Mercurial > projects > ldc
diff dmd2/traits.c @ 758:f04dde6e882c
Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 11 Nov 2008 01:38:48 +0100 |
parents | |
children | 638d16625da2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd2/traits.c Tue Nov 11 01:38:48 2008 +0100 @@ -0,0 +1,440 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2007 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <assert.h> +#include <complex.h> +#include <math.h> + +#if IN_GCC +// Issues with using -include total.h (defines integer_t) and then complex.h fails... +#undef integer_t +#endif + +#ifdef __APPLE__ +#define integer_t dmd_integer_t +#endif + +#if IN_GCC || IN_LLVM +#include "mem.h" +#elif _WIN32 +#include "..\root\mem.h" +#elif linux +#include "../root/mem.h" +#endif + +//#include "port.h" +#include "mtype.h" +#include "init.h" +#include "expression.h" +#include "template.h" +#include "utf.h" +#include "enum.h" +#include "scope.h" +#include "statement.h" +#include "declaration.h" +#include "aggregate.h" +#include "import.h" +#include "id.h" +#include "dsymbol.h" +#include "module.h" +#include "attrib.h" +#include "hdrgen.h" +#include "parse.h" + +#define LOGSEMANTIC 0 + +/************************************************ + * Delegate to be passed to overloadApply() that looks + * for virtual functions. + */ + +struct Pvirtuals +{ + Expression *e1; + Expressions *exps; +}; + +static int fpvirtuals(void *param, FuncDeclaration *f) +{ Pvirtuals *p = (Pvirtuals *)param; + + if (f->isVirtual()) + { Expression *e; + + if (p->e1->op == TOKdotvar) + { DotVarExp *dve = (DotVarExp *)p->e1; + e = new DotVarExp(0, dve->e1, f); + } + else + e = new DsymbolExp(0, f); + p->exps->push(e); + } + return 0; +} + +/************************ TraitsExp ************************************/ + +Expression *TraitsExp::semantic(Scope *sc) +{ +#if LOGSEMANTIC + printf("TraitsExp::semantic() %s\n", toChars()); +#endif + if (ident != Id::compiles && ident != Id::isSame) + TemplateInstance::semanticTiargs(loc, sc, args, 1); + size_t dim = args ? args->dim : 0; + Object *o; + FuncDeclaration *f; + +#define ISTYPE(cond) \ + for (size_t i = 0; i < dim; i++) \ + { Type *t = getType((Object *)args->data[i]); \ + if (!t) \ + goto Lfalse; \ + if (!(cond)) \ + goto Lfalse; \ + } \ + if (!dim) \ + goto Lfalse; \ + goto Ltrue; + +#define ISDSYMBOL(cond) \ + for (size_t i = 0; i < dim; i++) \ + { Dsymbol *s = getDsymbol((Object *)args->data[i]); \ + if (!s) \ + goto Lfalse; \ + if (!(cond)) \ + goto Lfalse; \ + } \ + if (!dim) \ + goto Lfalse; \ + goto Ltrue; + + + + if (ident == Id::isArithmetic) + { + ISTYPE(t->isintegral() || t->isfloating()) + } + else if (ident == Id::isFloating) + { + ISTYPE(t->isfloating()) + } + else if (ident == Id::isIntegral) + { + ISTYPE(t->isintegral()) + } + else if (ident == Id::isScalar) + { + ISTYPE(t->isscalar()) + } + else if (ident == Id::isUnsigned) + { + ISTYPE(t->isunsigned()) + } + else if (ident == Id::isAssociativeArray) + { + ISTYPE(t->toBasetype()->ty == Taarray) + } + else if (ident == Id::isStaticArray) + { + ISTYPE(t->toBasetype()->ty == Tsarray) + } + else if (ident == Id::isAbstractClass) + { + ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract()) + } + else if (ident == Id::isFinalClass) + { + ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) + } + else if (ident == Id::isAbstractFunction) + { + ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract()) + } + else if (ident == Id::isVirtualFunction) + { + ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual()) + } + else if (ident == Id::isFinalFunction) + { + ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal()) + } + else if (ident == Id::hasMember || + ident == Id::getMember || + ident == Id::getVirtualFunctions) + { + if (dim != 2) + goto Ldimerror; + Object *o = (Object *)args->data[0]; + Expression *e = isExpression((Object *)args->data[1]); + if (!e) + { error("expression expected as second argument of __traits %s", ident->toChars()); + goto Lfalse; + } + e = e->optimize(WANTvalue | WANTinterpret); + if (e->op != TOKstring) + { error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars()); + goto Lfalse; + } + StringExp *se = (StringExp *)e; + se = se->toUTF8(sc); + if (se->sz != 1) + { error("string must be chars"); + goto Lfalse; + } + Identifier *id = Lexer::idPool((char *)se->string); + + Type *t = isType(o); + e = isExpression(o); + Dsymbol *s = isDsymbol(o); + if (t) + e = new TypeDotIdExp(loc, t, id); + else if (e) + e = new DotIdExp(loc, e, id); + else if (s) + { e = new DsymbolExp(loc, s); + e = new DotIdExp(loc, e, id); + } + else + { error("invalid first argument"); + goto Lfalse; + } + + if (ident == Id::hasMember) + { /* Take any errors as meaning it wasn't found + */ + unsigned errors = global.errors; + global.gag++; + e = e->semantic(sc); + global.gag--; + if (errors != global.errors) + { if (global.gag == 0) + global.errors = errors; + goto Lfalse; + } + else + goto Ltrue; + } + else if (ident == Id::getMember) + { + e = e->semantic(sc); + return e; + } + else if (ident == Id::getVirtualFunctions) + { + unsigned errors = global.errors; + Expression *ex = e; + e = e->semantic(sc); + if (errors < global.errors) + error("%s cannot be resolved", ex->toChars()); + + /* Create tuple of virtual function overloads of e + */ + //e->dump(0); + Expressions *exps = new Expressions(); + FuncDeclaration *f; + if (e->op == TOKvar) + { VarExp *ve = (VarExp *)e; + f = ve->var->isFuncDeclaration(); + } + else if (e->op == TOKdotvar) + { DotVarExp *dve = (DotVarExp *)e; + f = dve->var->isFuncDeclaration(); + } + else + f = NULL; + Pvirtuals p; + p.exps = exps; + p.e1 = e; + overloadApply(f, fpvirtuals, &p); + + TupleExp *tup = new TupleExp(loc, exps); + return tup->semantic(sc); + } + else + assert(0); + } + else if (ident == Id::classInstanceSize) + { + if (dim != 1) + goto Ldimerror; + Object *o = (Object *)args->data[0]; + Dsymbol *s = getDsymbol(o); + ClassDeclaration *cd; + if (!s || (cd = s->isClassDeclaration()) == NULL) + { + error("first argument is not a class"); + goto Lfalse; + } + return new IntegerExp(loc, cd->structsize, Type::tsize_t); + } + else if (ident == Id::allMembers || ident == Id::derivedMembers) + { + if (dim != 1) + goto Ldimerror; + Object *o = (Object *)args->data[0]; + Dsymbol *s = getDsymbol(o); + ScopeDsymbol *sd; + if (!s) + { + error("argument has no members"); + goto Lfalse; + } + if ((sd = s->isScopeDsymbol()) == NULL) + { + error("%s %s has no members", s->kind(), s->toChars()); + goto Lfalse; + } + Expressions *exps = new Expressions; + while (1) + { size_t dim = ScopeDsymbol::dim(sd->members); + for (size_t i = 0; i < dim; i++) + { + Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i); + //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars()); + if (sm->ident) + { + //printf("\t%s\n", sm->ident->toChars()); + char *str = sm->ident->toChars(); + + /* Skip if already present in exps[] + */ + for (size_t j = 0; j < exps->dim; j++) + { StringExp *se2 = (StringExp *)exps->data[j]; + if (strcmp(str, (char *)se2->string) == 0) + goto Lnext; + } + + StringExp *se = new StringExp(loc, str); + exps->push(se); + } + Lnext: + ; + } + ClassDeclaration *cd = sd->isClassDeclaration(); + if (cd && cd->baseClass && ident == Id::allMembers) + sd = cd->baseClass; // do again with base class + else + break; + } + Expression *e = new ArrayLiteralExp(loc, exps); + e = e->semantic(sc); + return e; + } + else if (ident == Id::compiles) + { + /* Determine if all the objects - types, expressions, or symbols - + * compile without error + */ + if (!dim) + goto Lfalse; + + for (size_t i = 0; i < dim; i++) + { Object *o = (Object *)args->data[i]; + Type *t; + Expression *e; + Dsymbol *s; + + unsigned errors = global.errors; + global.gag++; + + t = isType(o); + if (t) + { t->resolve(loc, sc, &e, &t, &s); + if (t) + t->semantic(loc, sc); + else if (e) + e->semantic(sc); + } + else + { e = isExpression(o); + if (e) + e->semantic(sc); + } + + global.gag--; + if (errors != global.errors) + { if (global.gag == 0) + global.errors = errors; + goto Lfalse; + } + } + goto Ltrue; + } + else if (ident == Id::isSame) + { /* Determine if two symbols are the same + */ + if (dim != 2) + goto Ldimerror; + TemplateInstance::semanticTiargs(loc, sc, args, 0); + Object *o1 = (Object *)args->data[0]; + Object *o2 = (Object *)args->data[1]; + Dsymbol *s1 = getDsymbol(o1); + Dsymbol *s2 = getDsymbol(o2); + +#if 0 + printf("o1: %p\n", o1); + printf("o2: %p\n", o2); + if (!s1) + { Expression *ea = isExpression(o1); + if (ea) + printf("%s\n", ea->toChars()); + Type *ta = isType(o1); + if (ta) + printf("%s\n", ta->toChars()); + goto Lfalse; + } + else + printf("%s %s\n", s1->kind(), s1->toChars()); +#endif + if (!s1 && !s2) + { Expression *ea1 = isExpression(o1); + Expression *ea2 = isExpression(o2); + if (ea1 && ea2 && ea1->equals(ea2)) + goto Ltrue; + } + + if (!s1 || !s2) + goto Lfalse; + + s1 = s1->toAlias(); + s2 = s2->toAlias(); + + if (s1 == s2) + goto Ltrue; + else + goto Lfalse; + } + else + { error("unrecognized trait %s", ident->toChars()); + goto Lfalse; + } + + return NULL; + +Lnottype: + error("%s is not a type", o->toChars()); + goto Lfalse; + +Ldimerror: + error("wrong number of arguments %d", dim); + goto Lfalse; + + +Lfalse: + return new IntegerExp(loc, 0, Type::tbool); + +Ltrue: + return new IntegerExp(loc, 1, Type::tbool); +} + +