Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Reflection Using DDL

As DDL uses symbolic information to resolve references for dynamic binding, the D API ensures that the symbolic information carries a good deal of type information along with it. This type information can also be used to allow for some very rudimentary forms of reflection, thanks to this advantage of the D ABI.

The core concepts of using D's built-in Typeinfo, along with any dynamic info given by DDL, are displayed using the following concept:

// example abstract class tree for Reflection, using DDL and D's native Typeinfo.
class Symbol{
	Module module;
	uint line; // eventual line number support
	char[] name;
}

// covers scalars, enums, structs, pointers, delegates, functions and unions
class Field: Symbol{
	Typeinfo typeinfo();
	size_t size;
	void* getValue();
	void setValue(void* value);
}

class Member: Field{
	Class classtype;
	void* getValue();
	void setValue(void* value);
}

class Function: Symbol{
	TypeInfo[] parameterTypes();
	TypeInfo returntype;
	opCall call(...);
}

class Method: Function{
	Class classtype;
	opCall call(...);
}

class Constructor: Function{
	Class classtype;
	opCall call(...);
}

class Destructor: Function{
	Class classtype;
	opCall call(...);
}

class Interface: Symbol{
	ClassInfo classInfo();
	object.Interface interface();
	Function[] functions();
}

class Class: Symbol{
	ClassInfo classInfo();
	
	Class base;
	Interface[] baseInterfaces();
			
	Symbol[] symbols();
	
	Method[] methods();
	Members[] members();
	
	Function[] staticFunctions();
	Field[] staticFields();
	
	Constructor[] constructors();
	Destructor destructor();
	Function deallocator();
}

class Module{
	char[] name;
	ModuleInfo[] dependencies();
	Symbol[] symbols();
	Interface[] interfaces();
	Class[] classes();
	Function[] functions();
	Field[] fields();
}

class Reflection{
	Module getModule(char[] namespace);
	Class getClass(char[] namespace);
	Interface getInterface(char[] namespace);
	Struct getStruct(char[] namespace);
	Function getFunction(char[] namespace);
	Field getField(char[] namespace);
}

There are obviously a few D constructs that are missing, namely enums, structs, unions and typedefs. For the sake of usefulness, typedefs have been deliberately left out. The others, while used as parts of type ids and typeinfo, lack information beyond their names. Enums fields are compiled away to their respective constant values, and struct/union fields are converted to offsets.

The only constructs that give us any field/function reference capability are classes, interfaces and modules. These are all granted to us thanks to name mangling, and the symbol tables present in object files - DDL gets this data into our program for us.

Line number info is anticipated out past DDL v1.0. This has implications for the proposed Symbol class above.