Commit b13fbf8b authored by gsamain's avatar gsamain Committed by Xavier Thompson

Cleaner interface injection and code generation completion

parent 20efbd8d
......@@ -912,14 +912,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for wrapper_entry in wrapper.all_alternatives():
if wrapper_entry.used or entry.type.templates:
self.generate_cyp_class_wrapper_definition(entry.type, wrapper_entry, constructor, new, alloc, code)
self.generate_acthon_hacks(entry, code)
def generate_acthon_hacks(self, entry, code):
# HACK !!!
if entry.name == "ActhonResultInterface":
code.putln("ActhonResultInterface::operator int() {")
code.putln("return this->getIntResult();")
code.putln("}")
def generate_gcc33_hack(self, env, code):
# Workaround for spurious warning generation in gcc 3.3
......@@ -1012,7 +1004,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.put("struct %s" % type.cname)
if type.base_classes:
base_class_list = [base_class.empty_declaration_code() for base_class in type.base_classes]
if type.is_cyp_class and type.base_classes[-1] is cy_object_type:
if type.is_cyp_class and (type.base_classes[-1] is cy_object_type or type.base_classes[-1].name == "ActhonActivableClass"):
base_class_list[-1] = "virtual " + base_class_list[-1]
base_class_decl = ", public ".join(base_class_list)
code.put(" : public %s" % base_class_decl)
......@@ -1184,6 +1176,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("}")
def generate_cyp_class_activated_class(self, entry, code):
result_interface_entry = entry.scope.lookup_here("ActhonResultInterface")
# TODO: handle inheritance
code.putln("struct %s::Activated : public CyObject {" % entry.type.empty_declaration_code())
code.putln("%s * _passive_self;" % entry.type.empty_declaration_code())
......@@ -1195,12 +1188,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
arg_cname_list = [arg.cname for arg in reified_function_entry.type.args]
args_code = ", ".join([
arg.type.declaration_code(arg.cname) for arg in reified_function_entry.type.args
])
] + ["ActhonSyncInterface* sync_object"])
function_header = reified_function_entry.type.function_header_code(reified_function_entry.cname, args_code)
function_code = PyrexTypes.c_void_type.declaration_code(function_header)
# FIXME: it should return a ResultInterface
function_code = result_interface_entry.type.declaration_code(function_header)
code.putln("%s {" % function_code)
message_constructor_args_list = ["_passive_self"] + arg_cname_list
code.putln("%s = this->_passive_self->_active_result_class();" % result_interface_entry.type.declaration_code("result_object"))
message_constructor_args_list = ["this->_passive_self", "sync_object", "result_object"] + arg_cname_list
message_constructor_args_code = ", ".join(message_constructor_args_list)
code.putln("%s = new %s(%s);" % (
reifying_class_entry.type.declaration_code("message"),
......@@ -1208,6 +1201,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
message_constructor_args_code
))
code.putln("/* Push message in the queue */")
code.putln("if (this->_passive_self->_active_queue_class != NULL) {")
code.putln("this->_passive_self->_active_queue_class->push(message);")
code.putln("} else {")
code.putln("/* We should definitely shout here */")
code.putln("}")
code.putln("/* Return result object */")
code.putln("return result_object;")
code.putln("}")
code.putln("};")
......@@ -1221,11 +1221,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
reified_function_entry = reifying_class_entry.reified_entry
reifying_class_full_name = reifying_class_entry.type.empty_declaration_code()
constructor_name = reifying_class_full_name.split('::')[-1]
# FIXME: it should not inherit from CyObject but from MessageInterface
code.putln("struct %s : public CyObject {" % reifying_class_full_name)
code.putln("struct %s : public ActhonMessageInterface {" % reifying_class_full_name)
# Declaring target object & reified method arguments
code.putln("%s;" % target_object_code)
arg_codes = [target_object_argument_code]
arg_codes = [target_object_argument_code, "ActhonSyncInterface* sync_method", "ActhonResultInterface* result_object"]
arg_names = ["target_object"]
arg_cnames = [target_object_cname]
for arg in reified_function_entry.type.args:
......@@ -1240,14 +1239,23 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
initializer_list = ["%s(%s)" % (cname, name)
for name, cname in zip(arg_names, arg_cnames)]
constructor_initializer_list_declaration = ", ".join(initializer_list)
code.putln("%s(%s) : %s {}" % (
code.putln("%s(%s) : %s {" % (
constructor_name,
constructor_args_declaration,
constructor_initializer_list_declaration
))
code.putln("void activate() {")
# FIXME: it would be cleaner to be able to have a bare C++ two-args constructor for ActhonMessageInterface
code.putln("this->_sync_method = sync_method;")
code.putln("this->_result = result_object;")
code.putln("}")
code.putln("int activate() {")
code.putln("/* Activate only if its sync object agrees to do so */")
code.putln("if (this->_sync_method != NULL and !this->_sync_method->isActivable()) {")
code.putln("return 0;")
code.putln("}")
result_assignment = ""
if reified_function_entry.type.return_type is not PyrexTypes.c_void_type:
does_return = reified_function_entry.type.return_type is not PyrexTypes.c_void_type
if does_return:
result_assignment = "%s =" % reified_function_entry.type.return_type.declaration_code("result")
code.putln("%s this->%s->%s(%s);" % (
result_assignment,
......@@ -1257,6 +1265,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
)
)
code.putln("/* Push result in the result object */")
if reified_function_entry.type.return_type is PyrexTypes.c_int_type:
code.putln("this->_result->pushIntResult(result);")
elif does_return:
code.putln("this->_result->pushVoidStarResult((void*)result);")
code.putln("return 1;")
code.putln("}")
code.putln("};")
......
......@@ -1538,6 +1538,14 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
error(self.pos, "Base class '%s' not a struct or class." % base_class)
base_types_list = [b.analyse(scope or env) for b in self.base_classes]
if self.cypclass:
if self.activable:
activable_base = False
for base_type in base_types_list:
activable_base = activable_base or base_type.activable
if not activable_base:
activable_base_entry = env.lookup_here("ActhonActivableClass")
base_types_list.append(activable_base_entry.type)
cyobject_base = False
for base_type in base_types_list:
cyobject_base = cyobject_base or base_type.is_cyp_class
......
......@@ -1345,31 +1345,66 @@ class ModuleScope(Scope):
def inject_acthon_interfaces(self):
# XXX - Moving this to the builtin scope would make much more sense
# XXX - than redeclaring acthon builtins in every module.
#declare_cpp_class(self, name, scope,
# pos, cname = None, base_classes = (),
# visibility = 'extern', templates = None, cypclass=0, lock_mode=None, activable=False):
# def declare_cfunction(self, name, type, pos,
# cname=None, visibility='extern', api=0, in_pxd=0,
# defining=0, modifiers=(), utility_code=None, overridable=False):
# cypclass ActhonResultInterface(CyObject):
# void pushVoidStarResult(void* result){}
# void* getVoidStarResult(){}
# void pushIntResult(int result){}
# int getIntResult(){}
# operator int() { return this->getIntResult(); }
result_scope = CppClassScope("ActhonResultInterface", self)
result_type = PyrexTypes.CypClassType(
"ActhonResultInterface", result_scope, "ActhonResultInterface", (PyrexTypes.cy_object_type,),
lock_mode="nolock", activable=False)
result_scope.type = result_type
#result_type.set_scope is a little bit overkill here, because parent_type is only used when doing scope inheritance
result_entry = self.declare("ActhonResultInterface", None, result_type, "ActhonResultInterface", "extern")
result_entry.is_type = 1
result_pushVoidStar_arg_type = PyrexTypes.CFuncTypeArg("result", PyrexTypes.c_void_ptr_type, None)
result_pushVoidStar_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [result_pushVoidStar_arg_type], nogil = 1)
result_pushVoidStar_entry = result_scope.declare_cfunction("pushVoidStarResult", result_pushVoidStar_type,
None, cname="pushVoidStarResult", defining = 1)
result_getVoidStar_type = PyrexTypes.CFuncType(PyrexTypes.c_void_ptr_type, [], nogil = 1)
result_getVoidStar_entry = result_scope.declare_cfunction("getVoidStarResult", result_getVoidStar_type,
None, cname="getVoidStarResult", defining = 1)
result_pushInt_arg_type = PyrexTypes.CFuncTypeArg("result", PyrexTypes.c_int_type, None)
result_pushInt_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [result_pushInt_arg_type], nogil = 1)
result_pushInt_entry = result_scope.declare_cfunction("pushIntResult", result_pushInt_type,
None, cname="pushIntResult", defining = 1)
result_getInt_type = PyrexTypes.CFuncType(PyrexTypes.c_int_type, [], nogil = 1)
result_pushInt_entry = result_scope.declare_cfunction("getIntResult", result_getInt_type,
None, cname="getIntResult", defining = 1)
result_int_typecast_type = PyrexTypes.CFuncType(PyrexTypes.c_int_type, [], nogil = 1)
result_int_typecast_entry = result_scope.declare_cfunction("operator int", result_int_typecast_type,
None, cname="operator int", defining = 1)
# cypclass ActhonMessageInterface
forward_declared_message_entry = self.declare_cpp_class("ActhonMessageInterface",
None, None, cname="ActhonMessageInterface", base_classes = (PyrexTypes.cy_object_type,),
cypclass=1, lock_mode="nolock")
message_scope = CppClassScope("ActhonMessageInterface", self)
message_type = PyrexTypes.CypClassType(
"ActhonMessageInterface", message_scope, "ActhonMessageInterface", (PyrexTypes.cy_object_type,),
lock_mode="nolock", activable=False)
message_scope.type = message_type
# cypclass ActhonSyncInterface(CyObject):
# bool isActivable(){}
# bool isCompleted(){}
# void insertActivity(ActhonMessageInterface msg){}
# void removeActivity(ActhonMessageInterface msg){}
sync_scope = CppClassScope("ActhonSyncInterface", self)
sync_entry = self.declare_cpp_class("ActhonSyncInterface",
sync_scope, None, cname="ActhonSyncInterface", base_classes = (PyrexTypes.cy_object_type,),
cypclass=1, lock_mode="nolock")
sync_scope.type = sync_entry.type
sync_type = PyrexTypes.CypClassType(
"ActhonSyncInterface", sync_scope, "ActhonSyncInterface", (PyrexTypes.cy_object_type,),
lock_mode="nolock", activable=False)
sync_scope.type = sync_type
sync_entry = self.declare("ActhonSyncInterface", None, sync_type, "ActhonSyncInterface", "extern")
sync_entry.is_type = 1
sync_isActivable_type = PyrexTypes.CFuncType(PyrexTypes.c_bint_type, [], nogil = 1)
sync_isActivable_entry = sync_scope.declare_cfunction("isActivable", sync_isActivable_type,
......@@ -1379,7 +1414,7 @@ class ModuleScope(Scope):
sync_isCompleted_entry = sync_scope.declare_cfunction("isCompleted", sync_isCompleted_type,
None, cname="isCompleted", defining = 1)
sync_msg_arg = PyrexTypes.CFuncTypeArg("msg", forward_declared_message_entry.type, None)
sync_msg_arg = PyrexTypes.CFuncTypeArg("msg", message_type, None)
sync_insertActivity_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [sync_msg_arg], nogil = 1)
sync_removeActivity_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [sync_msg_arg], nogil = 1)
sync_insertActivity_entry = sync_scope.declare_cfunction("insertActivity", sync_insertActivity_type,
......@@ -1388,14 +1423,16 @@ class ModuleScope(Scope):
None, cname="removeActivity", defining = 1)
# cypclass ActhonMessageInterface(CyObject):
# SyncInterface _sync_method
# ActhonSyncInterface _sync_method
# ActhonResultInterface _result
# bool activate(){}
message_scope = CppClassScope("ActhonMessageInterface", self)
message_entry = self.declare_cpp_class("ActhonMessageInterface",
message_scope, None, cname="ActhonMessageInterface", base_classes = (PyrexTypes.cy_object_type,),
cypclass=1, lock_mode="nolock")
message_scope.type = message_entry.type
message_entry = self.declare("ActhonMessageInterface", None, message_type, "ActhonMessageInterface", "extern")
message_entry.is_type = 1
message_sync_attr_entry = message_scope.declare_var("_sync_method", sync_type, None)
message_result_attr_entry = message_scope.declare_var("_result", result_type, None)
message_activate_type = PyrexTypes.CFuncType(PyrexTypes.c_bint_type, [], nogil = 1)
message_activate_entry = message_scope.declare_cfunction("activate", message_activate_type,
......@@ -1406,12 +1443,14 @@ class ModuleScope(Scope):
# bool activate(){}
queue_scope = CppClassScope("ActhonQueueInterface", self)
queue_entry = self.declare_cpp_class("ActhonQueueInterface",
queue_scope, None, cname="ActhonQueueInterface", base_classes = (PyrexTypes.cy_object_type,),
cypclass=1, lock_mode="nolock")
queue_scope.type = queue_entry.type
queue_msg_arg = PyrexTypes.CFuncTypeArg("msg", message_entry.type, None)
queue_type = PyrexTypes.CypClassType(
"ActhonQueueInterface", queue_scope, "ActhonQueueInterface", (PyrexTypes.cy_object_type,),
lock_mode="nolock", activable=False)
queue_scope.type = queue_type
queue_entry = self.declare("ActhonQueueInterface", None, queue_type, "ActhonQueueInterface", "extern")
queue_entry.is_type = 1
queue_msg_arg = PyrexTypes.CFuncTypeArg("msg", message_type, None)
queue_push_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [queue_msg_arg], nogil = 1)
queue_push_entry = queue_scope.declare_cfunction("push", queue_push_type,
None, cname="push", defining = 1)
......@@ -1420,40 +1459,21 @@ class ModuleScope(Scope):
queue_activate_entry = queue_scope.declare_cfunction("activate", queue_activate_type,
None, cname="activate", defining = 1)
# cypclass ActhonResultInterface(CyObject):
# void pushVoidStarResult(void* result){}
# void* getVoidStarResult(){}
# void pushIntResult(int result){}
# int getIntResult(){}
# operator int() { return this->getIntResult(); }
# cdef cypclass ActivableClass:
# ResultInterface (*_active_result_class)()
# QueueInterface _active_queue_class
result_scope = CppClassScope("ActhonResultInterface", self)
result_entry = self.declare_cpp_class("ActhonResultInterface",
result_scope, None, cname="ActhonResultInterface", base_classes = (PyrexTypes.cy_object_type,),
cypclass=1, lock_mode="nolock")
result_scope.type = result_entry.type
activable_scope = CppClassScope("ActhonActivableClass", self)
activable_type = PyrexTypes.CypClassType(
"ActhonActivableClass", activable_scope, "ActhonActivableClass", (PyrexTypes.cy_object_type,),
lock_mode="nolock", activable=False)
activable_entry = self.declare("ActhonActivableClass", None, activable_type, "ActhonActivableClass", "extern")
activable_entry.is_type = 1
result_pushVoidStar_arg_type = PyrexTypes.CFuncTypeArg("result", PyrexTypes.c_void_ptr_type, None)
result_pushVoidStar_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [result_pushVoidStar_arg_type], nogil = 1)
result_pushVoidStar_entry = result_scope.declare_cfunction("pushVoidStarResult", result_pushVoidStar_type,
None, cname="pushVoidStarResult", defining = 1)
activable_result_attr_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(result_entry.type, []))
activable_result_attr_entry = activable_scope.declare_var("_active_result_class", activable_result_attr_type, None)
result_getVoidStar_type = PyrexTypes.CFuncType(PyrexTypes.c_void_ptr_type, [], nogil = 1)
result_getVoidStar_entry = result_scope.declare_cfunction("getVoidStarResult", result_getVoidStar_type,
None, cname="getVoidStarResult", defining = 1)
result_pushInt_arg_type = PyrexTypes.CFuncTypeArg("result", PyrexTypes.c_int_type, None)
result_pushInt_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [result_pushInt_arg_type], nogil = 1)
result_pushInt_entry = result_scope.declare_cfunction("pushIntResult", result_pushInt_type,
None, cname="pushIntResult", defining = 1)
result_getInt_type = PyrexTypes.CFuncType(PyrexTypes.c_int_type, [], nogil = 1)
result_pushInt_entry = result_scope.declare_cfunction("getIntResult", result_getInt_type,
None, cname="getIntResult", defining = 1)
result_int_typecast_type = PyrexTypes.CFuncType(PyrexTypes.c_int_type, [], nogil = 1)
result_int_typecast_entry = result_scope.declare_cfunction("operator int", result_int_typecast_type,
None, cname="operator int", defining = 1)
activable_queue_attr_entry = activable_scope.declare_var("_active_queue_class", queue_entry.type, None)
def qualifying_scope(self):
return self.parent_module
......@@ -2786,7 +2806,7 @@ class CppClassScope(Scope):
return wrapper_entry
def reify_method(self, entry):
# TODO: clean argument list
# Create the reifying class
reified_name = "reified_" + entry.name
reified_cname = Naming.builtin_prefix + reified_name
scope = CppClassScope(reified_name, self)
......@@ -2797,6 +2817,19 @@ class CppClassScope(Scope):
#reified_entry.is_cpp_class = 1
reifying_entry.reified_entry = entry
self.reifying_entries.append(reifying_entry)
# Add the base method to the Activated member class
activated_class_entry = self.lookup_here("Activated")
result_interface_entry = self.lookup("ActhonResultInterface")
sync_interface_entry = self.lookup("ActhonSyncInterface")
activated_method_sync_attr_type = PyrexTypes.CFuncTypeArg(
"sync_method", sync_interface_entry.type, entry.pos, "sync_method")
activated_method_type = PyrexTypes.CFuncType(result_interface_entry.type,
entry.type.args + [activated_method_sync_attr_type], nogil=entry.type.nogil)
activated_method_entry = activated_class_entry.type.scope.declare(entry.name, entry.cname,
activated_method_type, entry.pos, 'extern')
activated_method_entry.is_cfunction = 1
activated_method_entry.is_variable = 1
print activated_method_entry
def declare_cfunction(self, name, type, pos,
cname=None, visibility='extern', api=0, in_pxd=0,
......
......@@ -73,6 +73,42 @@
int CyObject_TRYWLOCK();
};
/* All this is made available by member injection inside the module scope */
struct ActhonResultInterface : CyObject {
virtual void pushVoidStarResult(void* result) = 0;
virtual void* getVoidStarResult() = 0;
virtual void pushIntResult(int result) = 0;
virtual int getIntResult() = 0;
operator int() { return this->getIntResult(); }
};
struct ActhonMessageInterface;
struct ActhonSyncInterface : CyObject {
virtual int isActivable() = 0;
virtual int isCompleted() = 0;
virtual void insertActivity(ActhonMessageInterface* msg) = 0;
virtual void removeActivity(ActhonMessageInterface* msg) = 0;
};
struct ActhonMessageInterface : CyObject {
ActhonSyncInterface* _sync_method;
ActhonResultInterface* _result;
virtual int activate() = 0;
};
struct ActhonQueueInterface : CyObject {
virtual void push(ActhonMessageInterface* message) = 0;
virtual int activate() = 0;
};
struct ActhonActivableClass : public CyObject {
ActhonResultInterface *(*_active_result_class)(void);
ActhonQueueInterface *_active_queue_class = NULL;
virtual ~ActhonActivableClass() {}
};
static inline int _Cy_DECREF(CyObject *op) {
return op->CyObject_DECREF();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment