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