Commit acf56eff authored by Xavier Thompson's avatar Xavier Thompson

Refactor acthon implementation

parent 904b7eee
......@@ -968,48 +968,19 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"""
Generate activate function for activable cypclass entries.
"""
activate_class_decl = "%s::Activated" % entry.type.empty_declaration_code()
dunder_activate_entry = entry.type.scope.lookup_here("__activate__")
# Here we generate the function header like Nodes.CFuncDefNode would do,
# but we streamline the process because we know the exact prototype.
dunder_activate_arg = dunder_activate_entry.type.op_arg_struct.declaration_code(Naming.optional_args_cname)
dunder_activate_entity = dunder_activate_entry.type.function_header_code(dunder_activate_entry.func_cname, dunder_activate_arg)
dunder_activate_header = dunder_activate_entry.type.return_type.declaration_code(dunder_activate_entity)
code.putln("%s {" % dunder_activate_header)
code.putln("%s;" % dunder_activate_entry.type.return_type.declaration_code("activated_instance"))
code.putln('if (%s) {' % Naming.optional_args_cname)
activated_class_constructor_optargs_list = ["this"]
activated_class_constructor_defaultargs_list = ["this->_active_queue_class", "this->_active_result_class"]
for i, arg in enumerate(dunder_activate_entry.type.args):
code.putln("if (%s->%sn <= %s) {" %
(Naming.optional_args_cname,
Naming.pyrex_prefix, i))
code.putln("activated_instance = new %s(%s);" %
(activate_class_decl,
", ".join(activated_class_constructor_optargs_list + activated_class_constructor_defaultargs_list[i:])))
code.putln("} else {")
activated_class_constructor_optargs_list.append("%s->%s" %
(Naming.optional_args_cname,
dunder_activate_entry.type.opt_arg_cname(arg.name)))
# We're in the final else clause, corresponding to all optional arguments specified)
code.putln("activated_instance = new %s(%s);" %
(activate_class_decl,
", ".join(activated_class_constructor_optargs_list)))
for _ in dunder_activate_entry.type.args:
code.putln("}")
code.putln("}")
code.putln("else {")
class_decl = entry.type.empty_declaration_code()
activated_class_decl = "%s::Activated" % class_decl
code.putln("%s *%s::__activate__() {" % (activated_class_decl, class_decl))
code.putln("if (this->%s == NULL) {" % Naming.cypclass_active_self_cname)
code.putln("this->%s = new %s(this, %s);" %
(Naming.cypclass_active_self_cname,
activate_class_decl,
", ".join(activated_class_constructor_defaultargs_list))
)
code.putln("}")
code.putln("Cy_INCREF((%s *)(this->%s));" % (activate_class_decl, Naming.cypclass_active_self_cname))
code.putln("activated_instance = (%s *)(this->%s);" % (activate_class_decl, Naming.cypclass_active_self_cname))
code.putln("this->%s = new %s(this, %s);" % (
Naming.cypclass_active_self_cname,
activated_class_decl,
", ".join(["this->_active_queue_class", "this->_active_result_class"])
)
)
code.putln("}")
code.putln("return activated_instance;")
code.putln("Cy_INCREF((%s *)(this->%s));" % (activated_class_decl, Naming.cypclass_active_self_cname))
code.putln("return (%s *)(this->%s);" % (activated_class_decl, Naming.cypclass_active_self_cname))
code.putln("}")
......@@ -1040,15 +1011,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
initialize_code = "ActhonActivableClass(active_queue, active_result_constructor)"
code.putln("struct %s::Activated : %s {" % (entry.type.empty_declaration_code(), base_classes_code))
code.putln("%s;" % entry.type.declaration_code(passive_self_attr_cname))
result_constructor_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(result_interface_type, [], nogil = 1))
code.putln(("Activated(%s * passive_object, %s, %s)"
": %s, %s(passive_object){} // Used by _passive_self.__activate__()"
% (
": %s, %s(passive_object){} // Used by _passive_self.__activate__()" % (
entry.type.empty_declaration_code(),
queue_interface_type.declaration_code("active_queue"),
entry.type.scope.lookup_here("__activate__").type.args[1].type.declaration_code("active_result_constructor"),
result_constructor_type.declaration_code("active_result_constructor"),
initialize_code,
passive_self_attr_cname
)
)
))
for reified_function_entry in entry.type.scope.reified_entries:
reifying_class_name = "%s%s" % (Naming.cypclass_reified_prefix, reified_function_entry.name)
......@@ -1624,8 +1595,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
destructor = None
if entry.type.is_cyp_class and entry.type.activable:
code.putln("struct Activated;")
dunder_activate_entry = scope.lookup_here("__activate__")
code.putln("%s;" % dunder_activate_entry.type.declaration_code(dunder_activate_entry.cname))
code.putln("%s::Activated *__activate__();" % entry.type.empty_declaration_code())
for attr in scope.var_entries:
cname = attr.cname
if attr.is_mutable:
......
......@@ -872,50 +872,6 @@ class Scope(object):
if entry.type.activable:
# === Acthon ===
act_scope = CppClassScope("Activated", scope)
act_type = PyrexTypes.CypClassType(
EncodedString("Activated"), act_scope, "Activated", None, templates = templates, lock_mode=entry.type.lock_mode)
act_type.set_scope(act_scope)
act_type.namespace = entry.type
# Declare dunder activate method (its definition is generated automatically)
from . import Builtin
queue_type = Builtin.acthon_queue_type
result_type = Builtin.acthon_result_type
queue_arg = PyrexTypes.CFuncTypeArg(EncodedString("queue"), queue_type, pos)
result_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(result_type, [], nogil = 1))
result_arg = PyrexTypes.CFuncTypeArg(EncodedString("result"), result_type, pos)
activate_type = PyrexTypes.CFuncType(act_type, [queue_arg, result_arg], nogil = 1, optional_arg_count = 2)
# HACK !!! This is a dirty duplication of Nodes.CFuncDeclaratorNode.declare_optional_arg_struct
def declare_opt_arg_struct(func_type, name, env, pos):
scope = StructOrUnionScope()
arg_count_member = EncodedString('%sn' % Naming.pyrex_prefix)
scope.declare_var(arg_count_member, PyrexTypes.c_int_type, pos)
for arg in func_type.args[len(func_type.args) - func_type.optional_arg_count:]:
scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject=True, allow_memoryview=True)
struct_cname = env.mangle(Naming.opt_arg_prefix, name)
op_args_struct = env.global_scope().declare_struct_or_union(
name=EncodedString(struct_cname),
kind='struct',
scope=scope,
typedef_flag=0,
pos=pos,
cname=struct_cname)
op_args_struct.defined_in_pxd = 1
op_args_struct.used = 1
func_type.op_arg_struct = PyrexTypes.c_ptr_type(op_args_struct.type)
declare_opt_arg_struct(activate_type, name, self, pos)
activate_entry = scope.declare(EncodedString("__activate__"), "__activate__", activate_type, None, 'extern')
activate_entry.is_variable = activate_entry.is_cfunction = 1
activate_entry.func_cname = "%s::%s" % (entry.type.empty_declaration_code(), "__activate__")
# Declare 'activate' function for this class
activate_func_arg = PyrexTypes.CFuncTypeArg(EncodedString("o"), entry.type, pos)
......
......@@ -456,7 +456,7 @@
template <typename T>
static inline typename T::Activated * activate(T * ob) {
static_assert(std::is_convertible<T *, ActhonActivableClass *>::value, "wrong type for activate");
return ob->__activate__(NULL);
return ob->__activate__();
}
/*
......
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