view dmd/TypeDelegate.d @ 135:af1bebfd96a4 dmd2037

dmd 2.038
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Mon, 13 Sep 2010 22:19:42 +0100
parents 60bb0fe4563e
children 14feb7ae01a6
line wrap: on
line source

module dmd.TypeDelegate;

import dmd.common;
import dmd.Type;
import dmd.TypeNext;
import dmd.MOD;
import dmd.OutBuffer;
import dmd.Id;
import dmd.AddExp;
import dmd.PtrExp;
import dmd.IntegerExp;
import dmd.MATCH;
import dmd.NullExp;
import dmd.TypeFunction;
import dmd.HdrGenState;
import dmd.Expression;
import dmd.Identifier;
import dmd.CppMangleState;
import dmd.Parameter;
import dmd.Loc;
import dmd.Scope;
import dmd.TypeInfoDeclaration;
import dmd.TypeInfoDelegateDeclaration;
import dmd.TY;
import dmd.Global;

import dmd.backend.TYPE;
import dmd.backend.Symbol;
import dmd.backend.Classsym;
import dmd.backend.TYM;
import dmd.backend.SC;
import dmd.backend.Util;
import dmd.backend.LIST;

class TypeDelegate : TypeNext
{
    // .next is a TypeFunction

    this(Type t)
	{
		super(TY.Tfunction, t);
		ty = TY.Tdelegate;
	}
	
version (DumbClone) {
} else {
	Type clone()
	{
		assert(false);
	}
}
    override Type syntaxCopy()
	{
		Type t = next.syntaxCopy();
		if (t == next)
			t = this;
		else
		{	
			t = new TypeDelegate(t);
			t.mod = mod;
		}
		return t;
	}
	
    override Type semantic(Loc loc, Scope sc)
	{
		if (deco)			// if semantic() already run
		{
			//printf("already done\n");
			return this;
		}

		next = next.semantic(loc, sc);
		return merge();
	}
	
    override ulong size(Loc loc)
	{
		return PTRSIZE * 2;
	}
	
	MATCH implicitConvTo(Type to)
	{
		//writef("TypeDelegate::implicitConvTo(this=%p, to=%p)\n", this, to);
		//writef("from: %s\n", toChars());
		//writef("to  : %s\n", to.toChars());
		if (this == to)
			return MATCHexact;
static if (false) // not allowing covariant conversions because it interferes with overriding
{
		if (to.ty == Tdelegate && this.nextOf().covariant(to.nextOf()) == 1)
			return MATCHconvert;
}
		return MATCHnomatch;
	}
    
    override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
	{
		if (mod != this.mod)
		{	
			toCBuffer3(buf, hgs, mod);
			return;
		}
		TypeFunction tf = cast(TypeFunction)next;

		tf.next.toCBuffer2(buf, hgs, MODundefined);
		buf.writestring(" delegate");
		Parameter.argsToCBuffer(buf, hgs, tf.parameters, tf.varargs);
	}
	
    override Expression defaultInit(Loc loc)
	{
	version (LOGDEFAULTINIT) {
		printf("TypeDelegate.defaultInit() '%s'\n", toChars());
	}
		return new NullExp(loc, this);
	}
	
    override bool isZeroInit(Loc loc)
	{
		return true;
	}
	
    override bool checkBoolean()
	{
		return true;
	}
	
    override TypeInfoDeclaration getTypeInfoDeclaration()
	{
		return new TypeInfoDelegateDeclaration(this);
	}
	
    override Expression dotExp(Scope sc, Expression e, Identifier ident)
	{
	version (LOGDOTEXP) {
		printf("TypeDelegate.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
	}
		if (ident == Id.ptr)
		{
			e.type = tvoidptr;
			return e;
		}
		else if (ident == Id.funcptr)
		{
			e = e.addressOf(sc);
			e.type = tvoidptr;
			e = new AddExp(e.loc, e, new IntegerExp(PTRSIZE));
			e.type = tvoidptr;
			e = new PtrExp(e.loc, e);
			e.type = next.pointerTo();
			return e;
		}
		else
		{
			e = Type.dotExp(sc, e, ident);
		}
		return e;
	}
	
    override bool hasPointers()
	{
		return true;
	}

version (CPP_MANGLE) {
    void toCppMangle(OutBuffer buf, CppMangleState* cms)
	{
		assert(false);
	}
}

    override type* toCtype()
	{
		type* t;

		if (ctype)
			return ctype;

		if (0 && global.params.symdebug)
		{
			/* A delegate consists of:
			 *    _Delegate { void* frameptr; Function *funcptr; }
			 */

			static Symbol* s;

			if (!s)
			{
				s = symbol_calloc("_Delegate");
				s.Sclass = SC.SCstruct;
				s.Sstruct = struct_calloc();
				s.Sstruct.Sflags |= 0;	/// huh?
				s.Sstruct.Salignsize = alignsize();
				s.Sstruct.Sstructalign = cast(ubyte)global.structalign;
				s.Sstruct.Sstructsize = cast(uint)size(Loc(0));
				slist_add(s);

				Symbol* s1 = symbol_name("frameptr", SC.SCmember, Type.tvoidptr.toCtype());
				list_append(&s.Sstruct.Sfldlst, s1);

				Symbol* s2 = symbol_name("funcptr", SC.SCmember, Type.tvoidptr.toCtype());
				s2.Smemoff = cast(uint)Type.tvoidptr.size();
				list_append(&s.Sstruct.Sfldlst, s2);
			}

			t = type_alloc(TYM.TYstruct);
			t.Ttag = cast(Classsym*)s;		// structure tag name
			t.Tcount++;
			s.Stype = t;
		}
		else
		{
			if (global.params.symdebug == 1)
			{
				// Generate D symbolic debug info, rather than C
				t = type_allocn(TYM.TYdelegate, next.toCtype());
			}
			else
				t = type_fake(TYM.TYdelegate);
		}

		t.Tcount++;
		ctype = t;
		return t;
	}
}