Mercurial > projects > ddmd
diff dmd/DeclarationExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | cab4c37afb89 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/DeclarationExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,291 @@ +module dmd.DeclarationExp; + +import dmd.Expression; +import dmd.backend.elem; +import dmd.InterState; +import dmd.ExpInitializer; +import dmd.OutBuffer; +import dmd.Loc; +import dmd.Scope; +import dmd.InlineCostState; +import dmd.IRState; +import dmd.InlineDoState; +import dmd.HdrGenState; +import dmd.TupleDeclaration; +import dmd.InlineScanState; +import dmd.Dsymbol; +import dmd.AttribDeclaration; +import dmd.VarDeclaration; +import dmd.Global; +import dmd.TOK; +import dmd.VoidInitializer; +import dmd.Type; +import dmd.codegen.Util; + +// Declaration of a symbol + +class DeclarationExp : Expression +{ + Dsymbol declaration; + + this(Loc loc, Dsymbol declaration) + { + super(loc, TOK.TOKdeclaration, DeclarationExp.sizeof); + this.declaration = declaration; + } + + Expression syntaxCopy() + { + return new DeclarationExp(loc, declaration.syntaxCopy(null)); + } + + Expression semantic(Scope sc) + { + if (type) + return this; + +version (LOGSEMANTIC) { + printf("DeclarationExp.semantic() %s\n", toChars()); +} + + /* This is here to support extern(linkage) declaration, + * where the extern(linkage) winds up being an AttribDeclaration + * wrapper. + */ + Dsymbol s = declaration; + + AttribDeclaration ad = declaration.isAttribDeclaration(); + if (ad) + { + if (ad.decl && ad.decl.dim == 1) + s = cast(Dsymbol)ad.decl.data[0]; + } + + if (s.isVarDeclaration()) + { + // Do semantic() on initializer first, so: + // int a = a; + // will be illegal. + declaration.semantic(sc); + s.parent = sc.parent; + } + + //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc); + // Insert into both local scope and function scope. + // Must be unique in both. + if (s.ident) + { + if (!sc.insert(s)) + error("declaration %s is already defined", s.toPrettyChars()); + else if (sc.func) + { + VarDeclaration v = s.isVarDeclaration(); + if (s.isFuncDeclaration() && !sc.func.localsymtab.insert(s)) + error("declaration %s is already defined in another scope in %s", s.toPrettyChars(), sc.func.toChars()); + else if (!global.params.useDeprecated) + { + // Disallow shadowing + + for (Scope scx = sc.enclosing; scx && scx.func is sc.func; scx = scx.enclosing) + { + Dsymbol s2; + + if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s !is s2) + { + error("shadowing declaration %s is deprecated", s.toPrettyChars()); + } + } + } + } + } + if (!s.isVarDeclaration()) + { + declaration.semantic(sc); + s.parent = sc.parent; + } + if (!global.errors) + { + declaration.semantic2(sc); + if (!global.errors) + { + declaration.semantic3(sc); + + if (!global.errors && global.params.useInline) + declaration.inlineScan(); + } + } + + type = Type.tvoid; + return this; + } + + Expression interpret(InterState* istate) + { + assert(false); + } + + bool checkSideEffect(int flag) + { + return true; + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + declaration.toCBuffer(buf, hgs); + } + + elem* toElem(IRState* irs) + { + //printf("DeclarationExp::toElem() %s\n", toChars()); + elem* e = Dsymbol_toElem(declaration, irs); + return e; + } + + void scanForNestedRef(Scope sc) + { + assert(false); + } + +version (DMDV2) { + bool canThrow() + { + VarDeclaration v = declaration.isVarDeclaration(); + if (v && v.init) + { + ExpInitializer ie = v.init.isExpInitializer(); + return ie && ie.exp.canThrow(); + } + + return false; + } +} + int inlineCost(InlineCostState* ics) + { + int cost = 0; + VarDeclaration vd; + + //printf("DeclarationExp.inlineCost()\n"); + vd = declaration.isVarDeclaration(); + if (vd) + { + TupleDeclaration td = vd.toAlias().isTupleDeclaration(); + if (td) + { + static if (true) { + return COST_MAX; // finish DeclarationExp.doInline + } else { + for (size_t i = 0; i < td.objects.dim; i++) + { + Object o = cast(Object)td.objects.data[i]; + Expression eo = cast(Expression)o; + if (eo is null) + return COST_MAX; + + if (eo.op != TOKdsymbol) + return COST_MAX; + } + + return td.objects.dim; + } + } + if (!ics.hdrscan && vd.isDataseg()) + return COST_MAX; + + cost += 1; + + // Scan initializer (vd.init) + if (vd.init) + { + ExpInitializer ie = vd.init.isExpInitializer(); + + if (ie) + { + cost += ie.exp.inlineCost(ics); + } + } + } + + // These can contain functions, which when copied, get output twice. + if (declaration.isStructDeclaration() || + declaration.isClassDeclaration() || + declaration.isFuncDeclaration() || + declaration.isTypedefDeclaration() || + declaration.isTemplateMixin() + ) + return COST_MAX; + + //printf("DeclarationExp.inlineCost('%s')\n", toChars()); + return cost; + } + + Expression doInline(InlineDoState ids) + { + DeclarationExp de = cast(DeclarationExp)copy(); + VarDeclaration vd; + + //printf("DeclarationExp.doInline(%s)\n", toChars()); + vd = declaration.isVarDeclaration(); + if (vd) + { + static if (false) { + // Need to figure this out before inlining can work for tuples + TupleDeclaration td = vd.toAlias().isTupleDeclaration(); + if (td) + { + for (size_t i = 0; i < td.objects.dim; i++) + { + DsymbolExp se = cast(DsymbolExp)td.objects.data[i]; + assert(se.op == TOKdsymbol); + se.s; + } + return st.objects.dim; + } + } + if (vd.isStatic()) + { + ; + } + else + { + VarDeclaration vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init); + + ///*vto = *vd; + memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length); + + vto.parent = ids.parent; + vto.csym = null; + vto.isym = null; + + ids.from.push(cast(void*)vd); + ids.to.push(cast(void*)vto); + + if (vd.init) + { + if (vd.init.isVoidInitializer()) + { + vto.init = new VoidInitializer(vd.init.loc); + } + else + { + Expression e = vd.init.toExpression(); + assert(e); + vto.init = new ExpInitializer(e.loc, e.doInline(ids)); + } + } + de.declaration = vto; + } + } + /* This needs work, like DeclarationExp.toElem(), if we are + * to handle TemplateMixin's. For now, we just don't inline them. + */ + return de; + } + + Expression inlineScan(InlineScanState* iss) + { + //printf("DeclarationExp.inlineScan()\n"); + scanVar(declaration, iss); + return this; + } +} +