Mercurial > projects > ddmd
diff dmd/VarExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | ccbc1e0bb3f0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/VarExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,258 @@ +module dmd.VarExp; + +import dmd.Expression; +import dmd.Declaration; +import dmd.InterState; +import dmd.OutBuffer; +import dmd.Loc; +import dmd.Scope; +import dmd.InlineCostState; +import dmd.FuncLiteralDeclaration; +import dmd.VarDeclaration; +import dmd.Dsymbol; +import dmd.FuncDeclaration; +import dmd.InlineDoState; +import dmd.HdrGenState; +import dmd.TOK; +import dmd.TY; +import dmd.STC; +import dmd.SymbolExp; +import dmd.Type; +import dmd.backend.dt_t; +import dmd.expression.Util; + +// Variable + +class VarExp : SymbolExp +{ + this(Loc loc, Declaration var, int hasOverloads = 0) + { + super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads); + + //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars()); + //if (strcmp(var.ident.toChars(), "func") == 0) halt(); + this.type = var.type; + } + + int equals(Object o) + { + assert(false); + } + + Expression semantic(Scope sc) + { + FuncLiteralDeclaration fd; + + version (LOGSEMANTIC) { + printf("VarExp.semantic(%s)\n", toChars()); + } + if (!type) + { + type = var.type; +static if (false) { + if (var.storage_class & STC.STClazy) + { + TypeFunction tf = new TypeFunction(null, type, 0, LINK.LINKd); + type = new TypeDelegate(tf); + type = type.semantic(loc, sc); + } +} + } + + /* Fix for 1161 doesn't work because it causes protection + * problems when instantiating imported templates passing private + * variables as alias template parameters. + */ + //accessCheck(loc, sc, null, var); + + VarDeclaration v = var.isVarDeclaration(); + if (v) + { +static if (false) { + if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init) + { + ExpInitializer ei = v.init.isExpInitializer(); + if (ei) + { + //ei.exp.implicitCastTo(sc, type).print(); + return ei.exp.implicitCastTo(sc, type); + } + } +} + v.checkNestedReference(sc, loc); +version (DMDV2) { + static if (true) { + if (sc.func) + { + /* Determine if sc.func is pure or if any function that + * encloses it is also pure. + */ + bool hasPureParent = false; + for (FuncDeclaration outerfunc = sc.func; outerfunc;) + { + if (outerfunc.isPure()) + { + hasPureParent = true; + break; + } + Dsymbol parent = outerfunc.toParent2(); + if (!parent) + break; + outerfunc = parent.isFuncDeclaration(); + } + + /* If ANY of its enclosing functions are pure, + * it cannot do anything impure. + * If it is pure, it cannot access any mutable variables other + * than those inside itself + */ + if (hasPureParent && !sc.intypeof && v.isDataseg() && !v.isInvariant()) + { + error("pure function '%s' cannot access mutable static data '%s'", + sc.func.toChars(), v.toChars()); + } + else if (sc.func.isPure() && sc.parent != v.parent && !sc.intypeof && !v.isInvariant() && !(v.storage_class & STC.STCmanifest)) + { + error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars()); + if (v.isEnumDeclaration()) + error("enum"); + } + } + } else { + if (sc.func && sc.func.isPure() && !sc.intypeof) + { + if (v.isDataseg() && !v.isInvariant()) + error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars()); + } + } +} + } + else + { +static if (false) { + if ((fd = var.isFuncLiteralDeclaration()) !is null) + { + Expression e = new FuncExp(loc, fd); + e.type = type; + return e; + } +} + } + + return this; + } + + Expression optimize(int result) + { + return fromConstInitializer(result, this); + } + + Expression interpret(InterState* istate) + { + assert(false); + } + + void dump(int indent) + { + assert(false); + } + + string toChars() + { + return var.toChars(); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring(var.toChars()); + } + + void checkEscape() + { + VarDeclaration v = var.isVarDeclaration(); + if (v) + { + Type tb = v.type.toBasetype(); + // if reference type + if (tb.ty == TY.Tarray || tb.ty == TY.Tsarray || tb.ty == TY.Tclass) + { + if ((v.isAuto() || v.isScope()) && !v.noauto) + error("escaping reference to scope local %s", v.toChars()); + else if (v.storage_class & STC.STCvariadic) + error("escaping reference to variadic parameter %s", v.toChars()); + } + } + } + +version (DMDV2) { + int isLvalue() + { + if (var.storage_class & STClazy) + return 0; + return 1; + } +} + Expression toLvalue(Scope sc, Expression e) + { +static if (false) { + tym = tybasic(e1.ET.Tty); + if (!(tyscalar(tym) || + tym == TYM.TYstruct || + tym == TYM.TYarray && e.Eoper == TOK.TOKaddr)) + { + synerr(EM_lvalue); // lvalue expected + } +} + if (var.storage_class & STC.STClazy) + error("lazy variables cannot be lvalues"); + + return this; + } + + Expression modifiableLvalue(Scope sc, Expression e) + { + //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); + if (type && type.toBasetype().ty == TY.Tsarray) + error("cannot change reference to static array '%s'", var.toChars()); + + var.checkModify(loc, sc, type); + + // See if this expression is a modifiable lvalue (i.e. not const) + return toLvalue(sc, e); + } + + dt_t** toDt(dt_t** pdt) + { + assert(false); + } + + void scanForNestedRef(Scope sc) + { + assert(false); + } + + int inlineCost(InlineCostState* ics) + { + //printf("VarExp.inlineCost() %s\n", toChars()); + return 1; + } + + Expression doInline(InlineDoState ids) + { + int i; + + //printf("VarExp.doInline(%s)\n", toChars()); + for (i = 0; i < ids.from.dim; i++) + { + if (var == cast(Declaration)ids.from.data[i]) + { + VarExp ve = cast(VarExp)copy(); + + ve.var = cast(Declaration)ids.to.data[i]; + return ve; + } + } + return this; + } +} +