Reflection.cpp
// Reflection.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2009
@import "Ceda/cxPython/cxPython.h"
@import "Ceda/cxObject/Object.h"
@import "Ceda/cxObject/WCSpace.h"
#include "Ceda/cxUtils/TracerUtils.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Illustrates how python can directly access reflection information about classes, interfaces
etc.
*/
namespace Reflection1
{
void Run()
{
ceda::TraceGroup g("Reflection example 1");
ceda::CSpaceCreator cspace;
ceda::CSpaceLock lock;
PyRun_SimpleString(
@strx
(
def GetBit(value,bitpos):
return (value & (1 << bitpos)) != 0
assert(ceda.EReflectedClassBits.RCF_CLASS == 0)
assert(ceda.EReflectedClassBits.RCF_PURE_MODEL == 1)
assert(ceda.EReflectedClassBits.RCF_HAS_EMBEDDED_MODEL == 2)
assert(ceda.EReflectedClassBits.RCF_REFERENCES_MODEL == 3)
assert(ceda.EReflectedClassBits.RCF_ADT == 4)
assert(ceda.EReflectedClassBits.RCF_ALLOW_PASS_BY_VALUE == 5)
assert(ceda.EReflectedClassBits.RCF_ALLOW_RETURN_BY_VALUE == 6)
assert(ceda.EReflectedClassBits.RCF_REPLICATE_ON_DEMAND == 7)
def PrintEnumInfo(e,indent):
print ' '*indent + '$enum ' + str(e.GetName())
print ' '*indent + '{'
for i in range(0,e.GetCount()):
s = ' '*indent + ' '
if not e.GetEnable(i):
s += '-'
s += str(e.GetString(i)) + ' = ' + str(e.GetValue(i))
print(s)
print ' '*indent + '}'
def GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,fn):
proto = ''
if rbcRet.IsNull():
proto = 'void'
else:
proto = str(rbcRet)
proto += ' ' + str(fn.GetName()) + '('
for j in range(0,fn.GetNumArgs()):
a = fn.GetArg(j)
rbc = getArgByteCode(a)
proto += str(rbc) + ' ' + str(a.GetName())
if j != fn.GetNumArgs()-1:
proto += ','
proto += ')'
if isMethod and fn.IsConst():
proto += ' const'
return proto
# Returns a string representation of the prototype of an interface method
def GetInterfaceMethodPrototype(ri,m):
rbcRet = ceda.GetInterfaceMethodReturnTypeByteCode(ri,m)
def getArgByteCode(a):
return ceda.GetInterfaceMethodArgByteCode(ri,a)
isMethod = 1
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,m)
# Returns a string representation of the prototype of a class method
def GetClassMethodPrototype(rc,m):
rbcRet = ceda.GetClassMethodReturnTypeByteCode(rc,m)
def getArgByteCode(a):
return ceda.GetClassMethodArgByteCode(rc,a)
isMethod = 1
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,m)
def GetGlobalFunctionPrototype(gf):
rbcRet = ceda.GetGlobalFunctionReturnTypeByteCode(gf)
def getArgByteCode(a):
return ceda.GetGlobalFunctionArgByteCode(gf,a)
isMethod = 0
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,gf)
def GetFunctorPrototype(f):
rbcRet = ceda.GetFunctorReturnTypeByteCode(f)
def getArgByteCode(a):
return ceda.GetFunctorArgByteCode(f,a)
isMethod = 0
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,f)
def PrintGlobalFunctionInfo(gf,indent):
print ' '*indent + '$function ' + GetGlobalFunctionPrototype(gf)
def PrintFunctorInfo(f,indent):
print ' '*indent + '$functor ' + GetFunctorPrototype(f)
def PrintGlobalVariableInfo(gv,indent):
rbc = ceda.GetGlobalVariableByteCode(gv)
print ' '*indent + '$var ' + str(rbc) + ' ' + str(gv.GetName())
def PrintTypedefInfo(t,indent):
rbc = ceda.GetTypeDefByteCode(t)
print ' '*indent + '$typedef ' + str(rbc) + ' ' + str(t.GetName())
def PrintInterfaceInfo(ri,indent):
print ' '*indent + '$interface ' + str(ri.GetName())
print ' '*indent + '{'
for i in range(0,ri.GetNumMethods()):
m = ri.GetMethod(i)
print ' '*indent + ' ' + GetInterfaceMethodPrototype(ri,m)
print ' '*indent + '}'
def PrintVariantInfo(rv,indent):
print ' '*indent + '$variant ' + str(rv.GetName())
print ' '*indent + '{'
for i in range(0,rv.GetNumFields()):
f = rv.GetField(i)
rbc = ceda.GetVariantFieldByteCode(rv,f)
s = '[' + str(f.GetOffset()) + ']'
s += ' '
s += str(rbc) + ' ' + str(f.GetName())
print ' '*indent + ' ' + s
print ' '*indent + '}'
def PrintClassInfo(c,indent):
assert(c.IsStruct() == (not GetBit(c.GetFlags(), ceda.EReflectedClassBits.RCF_CLASS)))
assert(c.IsPureModel() == GetBit(c.GetFlags(), ceda.EReflectedClassBits.RCF_PURE_MODEL))
assert(c.HasEmbeddedModel() == GetBit(c.GetFlags(), ceda.EReflectedClassBits.RCF_HAS_EMBEDDED_MODEL))
assert(c.ReferencesModel() == GetBit(c.GetFlags(), ceda.EReflectedClassBits.RCF_REFERENCES_MODEL))
assert(c.IsAdt() == GetBit(c.GetFlags(), ceda.EReflectedClassBits.RCF_ADT))
assert(c.ReplicateOnDemand() == GetBit(c.GetFlags(), ceda.EReflectedClassBits.RCF_REPLICATE_ON_DEMAND))
print ' '*indent + '$' + str(c.GetKeyWord()) + ' ' + str(c.GetName())
print ' '*indent + '{'
indent += 4
#print ' '*indent + 'Flags = ' + str(c.GetFlags())
print ' '*indent + 'Size = ' + str(c.GetSize()) + ' bytes'
print ' '*indent + 'CanCreate = ' + str(c.CanCreate())
if c.GetNumModelFields() > 0:
print ' '*indent + 'model'
print ' '*indent + '{'
for i in range(0,c.GetNumModelFields()):
f = c.GetModelField(i)
rbc = ceda.GetModelFieldByteCode(c,f)
s = '[' + str(f.GetOffset()) + ']'
s += ' '
s += str(rbc) + ' ' + str(f.GetName()) + ' '
s += '[' + str(f.GetRsn1()) + ',' + str(f.GetRsn2()) + ')'
if not f.Present():
s += '*'
print ' '*indent + ' ' + s
print ' '*indent + '}'
if c.GetNumFields() > 0:
print ' '*indent + 'fields'
print ' '*indent + '{'
for i in range(0,c.GetNumFields()):
f = c.GetField(i)
rbc = ceda.GetFieldByteCode(c,f)
s = '[' + str(f.GetOffset()) + ']'
s += ' '
s += str(rbc) + ' ' + str(f.GetName())
print ' '*indent + ' ' + s
print ' '*indent + '}'
if c.GetNumMethods() > 0:
print ' '*indent + 'methods'
print ' '*indent + '{'
for i in range(0,c.GetNumMethods()):
m = c.GetMethod(i)
print ' '*indent + ' ' + GetClassMethodPrototype(c,m)
print ' '*indent + '}'
if c.GetNumIndirectInterfaces() > 0:
print ' '*indent + 'indirect interfaces'
print ' '*indent + '{'
for i in range(0,c.GetNumIndirectInterfaces()):
nm = c.GetInterfaceName(i)
print ' '*indent + ' ' + str(nm)
print ' '*indent + '}'
if c.GetNumDirectInterfaces() > 0:
print ' '*indent + 'direct interfaces'
print ' '*indent + '{'
for i in range(c.GetNumIndirectInterfaces(),c.GetNumInterfaces()):
nm = c.GetInterfaceName(i)
print ' '*indent + ' ' + str(nm)
print ' '*indent + '}'
indent -= 4
print ' '*indent + '}'
def PrintNameSpaceElement(nse,indent):
tp = nse.GetType()
if tp == ceda.ENSType.NST_Interface:
PrintInterfaceInfo(nse.AsInterface(),indent)
elif tp == ceda.ENSType.NST_Class:
PrintClassInfo(nse.AsClass(),indent)
elif tp == ceda.ENSType.NST_GlobalFunction:
PrintGlobalFunctionInfo(nse.AsGlobalFunction(),indent)
elif tp == ceda.ENSType.NST_GlobalVariable:
PrintGlobalVariableInfo(nse.AsGlobalVariable(),indent)
elif tp == ceda.ENSType.NST_Typedef:
PrintTypedefInfo(nse.AsTypedef(),indent)
elif tp == ceda.ENSType.NST_Enum:
PrintEnumInfo(nse.AsEnum(),indent)
elif tp == ceda.ENSType.NST_Functor:
PrintFunctorInfo(nse.AsFunctor(),indent)
elif tp == ceda.ENSType.NST_Variant:
PrintVariantInfo(nse.AsVariant(),indent)
else:
print 'unrecognised namespace element type ' + str(tp)
Assert(False)
def DumpNameSpace(ns,indent):
# Show all elements in namespace ns
i = ns.GetElementIterator()
while not i.AtEnd():
nse = i.GetElement()
tp = nse.GetType()
PrintNameSpaceElement(nse,indent)
i.Next()
i.Close()
# Recurse into child namespaces
i = ns.GetChildNameSpaceIterator()
while not i.AtEnd():
print ' '*indent + 'namespace ' + str(i.GetName())
DumpNameSpace(i.GetNameSpace(),indent+4)
i.Next()
i.Close()
DumpNameSpace(rootnamespace.pizza, 0)
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Illustrates how python can recurse down through the namespaces of reflected classes, interfaces
etc.
*/
namespace NamespaceDemo
{
void Run()
{
ceda::TraceGroup g("Namespace example");
PyRun_SimpleString(
@strx
(
# Return the object associated with the given NameSpaceElement
def ConvertNameSpaceElement(nse):
tp = nse.GetType()
if tp == ceda.ENSType.NST_Interface:
return nse.AsInterface()
elif tp == ceda.ENSType.NST_Class:
return nse.AsClass()
elif tp == ceda.ENSType.NST_GlobalFunction:
return nse.AsGlobalFunction()
elif tp == ceda.ENSType.NST_GlobalVariable:
return nse.AsGlobalVariable()
elif tp == ceda.ENSType.NST_Typedef:
return nse.AsTypedef()
elif tp == ceda.ENSType.NST_Enum:
return nse.AsEnum()
elif tp == ceda.ENSType.NST_Functor:
return nse.AsFunctor()
elif tp == ceda.ENSType.NST_Variant:
return nse.AsVariant()
else:
Assert(False)
def DumpNameSpace(ns,indent):
# Show all elements in namespace ns
i = ns.GetElementIterator()
while not i.AtEnd():
nse = i.GetElement()
tp = nse.GetType()
print ConvertNameSpaceElement(nse)
if tp == ceda.ENSType.NST_Class:
print 'Class name = ' + `nse.AsClass().GetName()`
#print ' '*indent + str(ceda.ENSType.GetString(tp))[4:] + ' ' + `i.GetName()`
print ' '*indent + str(ceda.ENSType.GetString(tp)) + ' ' + `i.GetName()`
i.Next()
i.Close()
# Recurse into child namespaces
i = ns.GetChildNameSpaceIterator()
while not i.AtEnd():
print ' '*indent + 'Namespace ' + `i.GetName()`
DumpNameSpace(i.GetNameSpace(),indent+4)
i.Next()
i.Close()
DumpNameSpace(rootnamespace,0)
print 'End of NamespaceDemo example'
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace Reflection
{
void Run()
{
Reflection1::Run();
//NamespaceDemo::Run();
}
}