diff dmd/BaseClass.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 7427ded8caf7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BaseClass.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,138 @@
+module dmd.BaseClass;
+
+import dmd.Type;
+import dmd.PROT;
+import dmd.ClassDeclaration;
+import dmd.Array;
+import dmd.TY;
+import dmd.TypeFunction;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.ArrayTypes;
+
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class BaseClass
+{
+    Type type;				// (before semantic processing)
+    PROT protection;		// protection for the base interface
+
+    ClassDeclaration base;
+    int offset;				// 'this' pointer offset
+    Array vtbl;				// for interfaces: Array of FuncDeclaration's
+					// making up the vtbl[]
+
+    //int baseInterfaces_dim;
+    BaseClass[] baseInterfaces;		// if BaseClass is an interface, these
+					// are a copy of the InterfaceDeclaration::interfaces
+
+    this()
+	{
+		vtbl = new Array();
+	}
+
+    this(Type type, PROT protection)
+	{
+		//printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
+		this.type = type;
+		this.protection = protection;
+		
+		vtbl = new Array();
+	}
+
+	/****************************************
+	 * Fill in vtbl[] for base class based on member functions of class cd.
+	 * Input:
+	 *	vtbl		if !=null, fill it in
+	 *	newinstance	!=0 means all entries must be filled in by members
+	 *			of cd, not members of any base classes of cd.
+	 * Returns:
+	 *	true if any entries were filled in by members of cd (not exclusively
+	 *	by base classes)
+	 */
+    bool fillVtbl(ClassDeclaration cd, Array vtbl, int newinstance)
+	{
+		ClassDeclaration id = base;
+		int j;
+		bool result = false;
+
+		//printf("BaseClass.fillVtbl(this='%s', cd='%s')\n", base.toChars(), cd.toChars());
+		if (vtbl)
+			vtbl.setDim(base.vtbl.dim);
+
+		// first entry is ClassInfo reference
+		for (j = base.vtblOffset(); j < base.vtbl.dim; j++)
+		{
+			FuncDeclaration ifd = (cast(Dsymbol)base.vtbl.data[j]).isFuncDeclaration();
+			FuncDeclaration fd;
+			TypeFunction tf;
+
+			//printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd.toChars() : "null");
+
+			assert(ifd);
+			// Find corresponding function in this class
+			tf = (ifd.type.ty == Tfunction) ? cast(TypeFunction)(ifd.type) : null;
+			fd = cd.findFunc(ifd.ident, tf);
+			if (fd && !fd.isAbstract())
+			{
+				//printf("            found\n");
+				// Check that calling conventions match
+				if (fd.linkage != ifd.linkage)
+					fd.error("linkage doesn't match interface function");
+
+				// Check that it is current
+				if (newinstance &&
+					fd.toParent() != cd &&
+					ifd.toParent() == base
+				)
+					cd.error("interface function %s.%s is not implemented",
+					id.toChars(), ifd.ident.toChars());
+
+				if (fd.toParent() == cd)
+					result = true;
+			}
+			else
+			{
+				//printf("            not found\n");
+				// BUG: should mark this class as abstract?
+				if (!cd.isAbstract())
+					cd.error("interface function %s.%s isn't implemented", id.toChars(), ifd.ident.toChars());
+				fd = null;
+			}
+			if (vtbl)
+				vtbl.data[j] = cast(void*)fd;
+		}
+
+		return result;
+	}
+	
+    void copyBaseInterfaces(BaseClasses vtblInterfaces)
+	{
+		//printf("+copyBaseInterfaces(), %s\n", base.toChars());
+	//    if (baseInterfaces_dim)
+	//	return;
+
+		baseInterfaces.length = base.interfaces_dim;
+
+		int size = BaseClass.classinfo.init.length;
+
+		//printf("%s.copyBaseInterfaces()\n", base.toChars());
+		for (int i = 0; i < baseInterfaces.length; i++)
+		{
+			BaseClass b2 = base.interfaces[i];
+			assert(b2.vtbl.dim == 0);	// should not be filled yet
+
+			void* mem = malloc(size);
+			memcpy(mem, cast(void*)b2, size);
+
+			BaseClass b = cast(BaseClass)mem;
+			baseInterfaces[i] = b;
+
+			if (i)				// single inheritance is i==0
+				vtblInterfaces.push(cast(void*)b);	// only need for M.I.
+			b.copyBaseInterfaces(vtblInterfaces);
+		}
+		//printf("-copyBaseInterfaces\n");
+	}
+}
\ No newline at end of file