[svn r117] Initial working implementation of interfaces.

Groundwork for all the different types of class/interface casts laid out.
This commit is contained in:
Tomas Lindquist Olsen
2007-11-24 06:33:00 +01:00
parent 0a8ff5931a
commit b43f5729b0
18 changed files with 867 additions and 145 deletions

View File

@@ -27,6 +27,10 @@ echo "compiling typeinfo 2"
rebuild typeinfos2.d -c -oqobj -dc=llvmdc-posix || exit 1
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo2.*.bc` ../lib/llvmdcore.bc || exit 1
echo "compiling object/interface casting runtime support"
llvmdc internal/cast.d -c -odobj || exit 1
llvm-link -f -o=../lib/llvmdcore.bc obj/cast.bc ../lib/llvmdcore.bc || exit 1
echo "compiling string foreach runtime support"
llvmdc internal/aApply.d -c -odobj || exit 1
llvmdc internal/aApplyR.d -c -odobj || exit 1

182
lphobos/internal/cast.d Normal file
View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
import object;
import std.c.stdio;
extern (C):
/******************************************
* Given a pointer:
* If it is an Object, return that Object.
* If it is an interface, return the Object implementing the interface.
* If it is null, return null.
* Else, undefined crash
*/
Object _d_toObject(void* p)
{ Object o;
if (p)
{
o = cast(Object)p;
//ClassInfo oc = o.classinfo;
Interface *pi = **cast(Interface ***)p;
/* Interface.offset lines up with ClassInfo.name.ptr,
* so we rely on pointers never being less than 64K,
* and Objects never being greater.
*/
if (pi.offset < 0x10000)
{
//printf("\tpi.offset = %d\n", pi.offset);
o = cast(Object)(p - pi.offset);
}
}
return o;
}
/*************************************
* Attempts to cast Object o to class c.
* Returns o if successful, null if not.
*/
Object _d_interface_cast(void* p, ClassInfo c)
{ Object o;
//printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
if (p)
{
Interface *pi = **cast(Interface ***)p;
//printf("\tpi.offset = %d\n", pi.offset);
o = cast(Object)(p - pi.offset);
return _d_dynamic_cast(o, c);
}
return o;
}
Object _d_dynamic_cast(Object o, ClassInfo c)
{ ClassInfo oc;
uint offset = 0;
//printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
if (o)
{
oc = o.classinfo;
if (_d_isbaseof2(oc, c, offset))
{
//printf("\toffset = %d\n", offset);
o = cast(Object)(cast(void*)o + offset);
}
else
o = null;
}
//printf("\tresult = %p\n", o);
return o;
}
int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset)
{ int i;
if (oc is c)
return 1;
do
{
if (oc.base is c)
return 1;
for (i = 0; i < oc.interfaces.length; i++)
{
ClassInfo ic;
ic = oc.interfaces[i].classinfo;
if (ic is c)
{ offset = oc.interfaces[i].offset;
return 1;
}
}
for (i = 0; i < oc.interfaces.length; i++)
{
ClassInfo ic;
ic = oc.interfaces[i].classinfo;
if (_d_isbaseof2(ic, c, offset))
{ offset = oc.interfaces[i].offset;
return 1;
}
}
oc = oc.base;
} while (oc);
return 0;
}
int _d_isbaseof(ClassInfo oc, ClassInfo c)
{ int i;
if (oc is c)
return 1;
do
{
if (oc.base is c)
return 1;
for (i = 0; i < oc.interfaces.length; i++)
{
ClassInfo ic;
ic = oc.interfaces[i].classinfo;
if (ic is c || _d_isbaseof(ic, c))
return 1;
}
oc = oc.base;
} while (oc);
return 0;
}
/*********************************
* Find the vtbl[] associated with Interface ic.
*/
void *_d_interface_vtbl(ClassInfo ic, Object o)
{ int i;
ClassInfo oc;
//printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
assert(o);
oc = o.classinfo;
for (i = 0; i < oc.interfaces.length; i++)
{
ClassInfo oic;
oic = oc.interfaces[i].classinfo;
if (oic is ic)
{
return cast(void *)oc.interfaces[i].vtbl;
}
}
assert(0);
}

View File

@@ -879,8 +879,6 @@ class TypeInfo_Class : TypeInfo
ClassInfo info;
}
/+
class TypeInfo_Interface : TypeInfo
{
char[] toString() { return info.name; }
@@ -944,8 +942,6 @@ class TypeInfo_Interface : TypeInfo
ClassInfo info;
}
+/
class TypeInfo_Struct : TypeInfo
{
char[] toString() { return name; }
@@ -1038,8 +1034,6 @@ class TypeInfo_Struct : TypeInfo
uint m_flags;
}
/+
class TypeInfo_Tuple : TypeInfo
{
TypeInfo[] elements;
@@ -1102,8 +1096,6 @@ class TypeInfo_Tuple : TypeInfo
}
}
+/
class TypeInfo_Const : TypeInfo
{
char[] toString() { return "const " ~ base.toString(); }