Mercurial > projects > ddmd
diff dmd/TypeStruct.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 8c2c7b7579f8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TypeStruct.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,589 @@ +module dmd.TypeStruct; + +import dmd.Type; +import dmd.StructDeclaration; +import dmd.Declaration; +import dmd.STC; +import dmd.MOD; +import dmd.OutBuffer; +import dmd.DotVarExp; +import dmd.TemplateMixin; +import dmd.DotTemplateExp; +import dmd.DsymbolExp; +import dmd.TypeExp; +import dmd.EnumMember; +import dmd.Id; +import dmd.DotIdExp; +import dmd.ScopeExp; +import dmd.TupleExp; +import dmd.TemplateDeclaration; +import dmd.OverloadSet; +import dmd.Import; +import dmd.DotExp; +import dmd.ErrorExp; +import dmd.Loc; +import dmd.Scope; +import dmd.Dsymbol; +import dmd.HdrGenState; +import dmd.Expression; +import dmd.Identifier; +import dmd.MATCH; +import dmd.ArrayTypes; +import dmd.TemplateInstance; +import dmd.FuncDeclaration; +import dmd.VarExp; +import dmd.CommaExp; +import dmd.ThisExp; +import dmd.SymbolDeclaration; +import dmd.TypeInfoDeclaration; +import dmd.TypeInfoStructDeclaration; +import dmd.TY; +import dmd.TOK; +import dmd.Global; +import dmd.VarDeclaration; +import dmd.Util; +import dmd.expression.Util; + +import dmd.backend.TYPE; +import dmd.backend.dt_t; +import dmd.backend.Symbol; +import dmd.backend.Util; +import dmd.backend.STR; +import dmd.backend.TYM; +import dmd.backend.Classsym; +import dmd.backend.SC; +import dmd.backend.LIST; + +import std.string : toStringz; + +class TypeStruct : Type +{ + StructDeclaration sym; + + this(StructDeclaration sym) + { + super(TY.Tstruct); + this.sym = sym; + } +version (DumbClone) { +} else { + final TypeStruct cloneTo(TypeStruct t) + { + super.cloneTo(t); + assert(t.sym is sym); + return t; + } + + TypeStruct clone() + { + assert(this.classinfo == TypeStruct.classinfo); + return cloneTo(new TypeStruct(sym)); + } +} + ulong size(Loc loc) + { + return sym.size(loc); + } + + uint alignsize() + { + uint sz; + + sym.size(Loc(0)); // give error for forward references + sz = sym.alignsize; + if (sz > sym.structalign) + sz = sym.structalign; + return sz; + } + + string toChars() + { + assert(false); + } + + Type syntaxCopy() + { + assert(false); + } + + Type semantic(Loc loc, Scope sc) + { + //printf("TypeStruct.semantic('%s')\n", sym.toChars()); + + /* Cannot do semantic for sym because scope chain may not + * be right. + */ + //sym.semantic(sc); + + return merge(); + } + + Dsymbol toDsymbol(Scope sc) + { + return sym; + } + + void toDecoBuffer(OutBuffer buf, int flag) + { + string name = sym.mangle(); + //printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", toChars(), name); + Type.toDecoBuffer(buf, flag); + buf.printf("%s", name); + } + + void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) + { + if (mod != this.mod) + { + toCBuffer3(buf, hgs, mod); + return; + } + TemplateInstance ti = sym.parent.isTemplateInstance(); + if (ti && ti.toAlias() == sym) + buf.writestring(ti.toChars()); + else + buf.writestring(sym.toChars()); + } + + Expression dotExp(Scope sc, Expression e, Identifier ident) + { + uint offset; + + VarDeclaration v; + Dsymbol s; + DotVarExp de; + Declaration d; + + version (LOGDOTEXP) { + printf("TypeStruct.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); + } + if (!sym.members) + { + error(e.loc, "struct %s is forward referenced", sym.toChars()); + return new ErrorExp(); + } + + /* If e.tupleof + */ + if (ident is Id.tupleof_) + { + /* Create a TupleExp out of the fields of the struct e: + * (e.field0, e.field1, e.field2, ...) + */ + e = e.semantic(sc); // do this before turning on noaccesscheck + Expressions exps = new Expressions; + exps.reserve(sym.fields.dim); + for (size_t i = 0; i < sym.fields.dim; i++) + { + VarDeclaration v2 = cast(VarDeclaration)sym.fields.data[i]; + Expression fe = new DotVarExp(e.loc, e, v2); + exps.push(cast(void*)fe); + } + e = new TupleExp(e.loc, exps); + sc = sc.push(); + sc.noaccesscheck = 1; + e = e.semantic(sc); + sc.pop(); + return e; + } + + if (e.op == TOK.TOKdotexp) + { + DotExp de2 = cast(DotExp)e; + + if (de2.e1.op == TOK.TOKimport) + { + assert(0); // cannot find a case where this happens; leave + // assert in until we do + ScopeExp se = cast(ScopeExp)de2.e1; + + s = se.sds.search(e.loc, ident, 0); + e = de2.e1; + goto L1; + } + } + + s = sym.search(e.loc, ident, 0); + L1: + if (!s) + { + if (ident !is Id.__sizeof && + ident !is Id.alignof_ && + ident !is Id.init_ && + ident !is Id.mangleof_ && + ident !is Id.stringof_ && + ident !is Id.offsetof) + { + /* See if we should forward to the alias this. + */ + if (sym.aliasthis) + { + /* Rewrite e.ident as: + * e.aliasthis.ident + */ + e = new DotIdExp(e.loc, e, sym.aliasthis.ident); + e = new DotIdExp(e.loc, e, ident); + return e.semantic(sc); + } + + /* Look for overloaded opDot() to see if we should forward request + * to it. + */ + Dsymbol fd = search_function(sym, Id.opDot); + if (fd) + { + /* Rewrite e.ident as: + * e.opId().ident + */ + e = build_overload(e.loc, sc, e, null, fd.ident); + e = new DotIdExp(e.loc, e, ident); + return e.semantic(sc); + } + } + + return Type.dotExp(sc, e, ident); + } + + if (!s.isFuncDeclaration()) // because of overloading + s.checkDeprecated(e.loc, sc); + + s = s.toAlias(); + + v = s.isVarDeclaration(); + if (v && !v.isDataseg()) + { + Expression ei = v.getConstInitializer(); + if (ei) + { + e = ei.copy(); // need to copy it if it's a StringExp + e = e.semantic(sc); + return e; + } + } + + if (s.getType()) + { + //return new DotTypeExp(e.loc, e, s); + return new TypeExp(e.loc, s.getType()); + } + + EnumMember em = s.isEnumMember(); + if (em) + { + assert(em.value); + return em.value.copy(); + } + + TemplateMixin tm = s.isTemplateMixin(); + if (tm) + { + Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); + de2.type = e.type; + return de2; + } + + TemplateDeclaration td = s.isTemplateDeclaration(); + if (td) + { + e = new DotTemplateExp(e.loc, e, td); + e.semantic(sc); + return e; + } + + TemplateInstance ti = s.isTemplateInstance(); + if (ti) + { + if (!ti.semanticRun) + ti.semantic(sc); + s = ti.inst.toAlias(); + if (!s.isTemplateInstance()) + goto L1; + Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); + de2.type = e.type; + return de2; + } + + Import timp = s.isImport(); + if (timp) + { + e = new DsymbolExp(e.loc, s, 0); + e = e.semantic(sc); + return e; + } + + OverloadSet o = s.isOverloadSet(); + if (o) + { + /* We really should allow this, triggered by: + * template c() + * { + * void a(); + * void b () { this.a(); } + * } + * struct S + * { + * mixin c; + * mixin c; + * } + * alias S e; + */ + error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars()); + return new ErrorExp(); + } + + d = s.isDeclaration(); + + debug { + if (!d) + writef("d = %s '%s'\n", s.kind(), s.toChars()); + } + assert(d); + + if (e.op == TOK.TOKtype) + { + FuncDeclaration fd = sc.func; + + if (d.isTupleDeclaration()) + { + e = new TupleExp(e.loc, d.isTupleDeclaration()); + e = e.semantic(sc); + return e; + } + + if (d.needThis() && fd && fd.vthis) + { + e = new DotVarExp(e.loc, new ThisExp(e.loc), d); + e = e.semantic(sc); + return e; + } + + return new VarExp(e.loc, d, 1); + } + + if (d.isDataseg()) + { + // (e, d) + accessCheck(e.loc, sc, e, d); + VarExp ve = new VarExp(e.loc, d); + e = new CommaExp(e.loc, e, ve); + e.type = d.type; + return e; + } + + if (v) + { + if (v.toParent() != sym) + sym.error(e.loc, "'%s' is not a member", v.toChars()); + + // *(&e + offset) + accessCheck(e.loc, sc, e, d); +static if (false) { + Expression b = new AddrExp(e.loc, e); + b.type = e.type.pointerTo(); + b = new AddExp(e.loc, b, new IntegerExp(e.loc, v.offset, Type.tint32)); + b.type = v.type.pointerTo(); + b = new PtrExp(e.loc, b); + b.type = v.type.addMod(e.type.mod); + return b; +} + } + + de = new DotVarExp(e.loc, e, d); + return de.semantic(sc); + } + + uint memalign(uint salign) + { + sym.size(Loc(0)); // give error for forward references + return sym.structalign; + } + + Expression defaultInit(Loc loc) + { + Symbol* s; + Declaration d; + + version (LOGDEFAULTINIT) { + printf("TypeStruct::defaultInit() '%s'\n", toChars()); + } + s = sym.toInitializer(); + d = new SymbolDeclaration(sym.loc, s, sym); + assert(d); + d.type = this; + return new VarExp(sym.loc, d); + } + + bool isZeroInit(Loc loc) + { + return sym.zeroInit; + } + + int isAssignable() + { + /* If any of the fields are const or invariant, + * then one cannot assign this struct. + */ + for (size_t i = 0; i < sym.fields.dim; i++) + { + VarDeclaration v = cast(VarDeclaration)sym.fields.data[i]; + if (v.isConst() || v.isInvariant()) + return false; + } + return true; + } + + bool checkBoolean() + { + return false; + } + + dt_t** toDt(dt_t** pdt) + { + sym.toDt(pdt); + return pdt; + } + + MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) + { + assert(false); + } + + TypeInfoDeclaration getTypeInfoDeclaration() + { + return new TypeInfoStructDeclaration(this); + } + + bool hasPointers() + { + StructDeclaration s = sym; + + sym.size(Loc(0)); // give error for forward references + for (size_t i = 0; i < s.fields.dim; i++) + { + Dsymbol sm = cast(Dsymbol)s.fields.data[i]; + Declaration d = sm.isDeclaration(); + if (d.storage_class & STC.STCref || d.hasPointers()) + return true; + } + + return false; + } + + MATCH implicitConvTo(Type to) + { + MATCH m; + + //printf("TypeStruct.implicitConvTo(%s => %s)\n", toChars(), to.toChars()); + if (ty == to.ty && sym == (cast(TypeStruct)to).sym) + { + m = MATCHexact; // exact match + if (mod != to.mod) + { + if (to.mod == MODconst) + m = MATCHconst; + else + { /* Check all the fields. If they can all be converted, + * allow the conversion. + */ + for (int i = 0; i < sym.fields.dim; i++) + { + Dsymbol s = cast(Dsymbol)sym.fields.data[i]; + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STCfield); + + // 'from' type + Type tvf = v.type.addMod(mod); + + // 'to' type + Type tv = v.type.castMod(to.mod); + + //printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), tvf.implicitConvTo(tv)); + if (tvf.implicitConvTo(tv) < MATCHconst) + return MATCHnomatch; + } + m = MATCHconst; + } + } + } + else if (sym.aliasthis) + { + m = MATCHnomatch; + Declaration d = sym.aliasthis.isDeclaration(); + if (d) + { + assert(d.type); + Type t = d.type.addMod(mod); + m = t.implicitConvTo(to); + } + } + else + m = MATCHnomatch; // no match + return m; + } + + MATCH constConv(Type to) + { + if (equals(to)) + return MATCHexact; + if (ty == to.ty && sym == (cast(TypeStruct)to).sym && to.mod == MODconst) + return MATCHconst; + return MATCHnomatch; + } + + Type toHeadMutable() + { + assert(false); + } + +version (CPP_MANGLE) { + void toCppMangle(OutBuffer buf, CppMangleState* cms) + { + assert(false); + } +} + + type* toCtype() + { + type* t; + Symbol* s; + + if (ctype) + return ctype; + + //printf("TypeStruct.toCtype() '%s'\n", sym.toChars()); + s = symbol_calloc(toStringz(sym.toPrettyChars())); + s.Sclass = SC.SCstruct; + s.Sstruct = struct_calloc(); + s.Sstruct.Sflags |= 0; /// huh? + s.Sstruct.Salignsize = sym.alignsize; + s.Sstruct.Sstructalign = cast(ubyte)sym.structalign; + s.Sstruct.Sstructsize = sym.structsize; + + if (sym.isUnionDeclaration()) + s.Sstruct.Sflags |= STR.STRunion; + + t = type_alloc(TYM.TYstruct); + t.Ttag = cast(Classsym*)s; // structure tag name + t.Tcount++; + s.Stype = t; + slist_add(s); + ctype = t; + + /* Add in fields of the struct + * (after setting ctype to avoid infinite recursion) + */ + if (global.params.symdebug) { + for (int i = 0; i < sym.fields.dim; i++) + { + VarDeclaration v = cast(VarDeclaration)sym.fields.data[i]; + + Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype()); + s2.Smemoff = v.offset; + list_append(&s.Sstruct.Sfldlst, s2); + } + } + + //printf("t = %p, Tflags = x%x\n", t, t.Tflags); + return t; + } +} \ No newline at end of file