Commit 904b7eee authored by Xavier Thompson's avatar Xavier Thompson

Refactor acthon implementation

parent a4bc6221
...@@ -968,8 +968,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -968,8 +968,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
""" """
Generate activate function for activable cypclass entries. Generate activate function for activable cypclass entries.
""" """
activate_class_decl = "%s::Activated" % entry.type.empty_declaration_code()
active_self_entry = entry.type.scope.lookup_here("<active_self>")
dunder_activate_entry = entry.type.scope.lookup_here("__activate__") dunder_activate_entry = entry.type.scope.lookup_here("__activate__")
# Here we generate the function header like Nodes.CFuncDefNode would do, # Here we generate the function header like Nodes.CFuncDefNode would do,
# but we streamline the process because we know the exact prototype. # but we streamline the process because we know the exact prototype.
...@@ -985,30 +984,30 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -985,30 +984,30 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("if (%s->%sn <= %s) {" % code.putln("if (%s->%sn <= %s) {" %
(Naming.optional_args_cname, (Naming.optional_args_cname,
Naming.pyrex_prefix, i)) Naming.pyrex_prefix, i))
code.putln("activated_instance = new %s::Activated(%s);" % code.putln("activated_instance = new %s(%s);" %
(entry.type.empty_declaration_code(), (activate_class_decl,
", ".join(activated_class_constructor_optargs_list + activated_class_constructor_defaultargs_list[i:]))) ", ".join(activated_class_constructor_optargs_list + activated_class_constructor_defaultargs_list[i:])))
code.putln("} else {") code.putln("} else {")
activated_class_constructor_optargs_list.append("%s->%s" % activated_class_constructor_optargs_list.append("%s->%s" %
(Naming.optional_args_cname, (Naming.optional_args_cname,
dunder_activate_entry.type.opt_arg_cname(arg.name))) dunder_activate_entry.type.opt_arg_cname(arg.name)))
# We're in the final else clause, corresponding to all optional arguments specified) # We're in the final else clause, corresponding to all optional arguments specified)
code.putln("activated_instance = new %s::Activated(%s);" % code.putln("activated_instance = new %s(%s);" %
(entry.type.empty_declaration_code(), (activate_class_decl,
", ".join(activated_class_constructor_optargs_list))) ", ".join(activated_class_constructor_optargs_list)))
for _ in dunder_activate_entry.type.args: for _ in dunder_activate_entry.type.args:
code.putln("}") code.putln("}")
code.putln("}") code.putln("}")
code.putln("else {") code.putln("else {")
code.putln("if (this->%s == NULL) {" % active_self_entry.cname) code.putln("if (this->%s == NULL) {" % Naming.cypclass_active_self_cname)
code.putln("this->%s = new %s::Activated(this, %s);" % code.putln("this->%s = new %s(this, %s);" %
(active_self_entry.cname, (Naming.cypclass_active_self_cname,
entry.type.empty_declaration_code(), activate_class_decl,
", ".join(activated_class_constructor_defaultargs_list)) ", ".join(activated_class_constructor_defaultargs_list))
) )
code.putln("}") code.putln("}")
code.putln("Cy_INCREF(this->%s);" % active_self_entry.cname) code.putln("Cy_INCREF((%s *)(this->%s));" % (activate_class_decl, Naming.cypclass_active_self_cname))
code.putln("activated_instance = this->%s;" % active_self_entry.cname) code.putln("activated_instance = (%s *)(this->%s);" % (activate_class_decl, Naming.cypclass_active_self_cname))
code.putln("}") code.putln("}")
code.putln("return activated_instance;") code.putln("return activated_instance;")
code.putln("}") code.putln("}")
...@@ -1051,8 +1050,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1051,8 +1050,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
passive_self_attr_cname passive_self_attr_cname
) )
)) ))
for reifying_class_entry in entry.type.scope.reifying_entries: for reified_function_entry in entry.type.scope.reified_entries:
reified_function_entry = reifying_class_entry.reified_entry reifying_class_name = "%s%s" % (Naming.cypclass_reified_prefix, reified_function_entry.name)
reifying_class_full_name = "%s::%s" % (PyrexTypes.namespace_declaration_code(entry.type), reifying_class_name)
code.putln("// generating reified of %s" % reified_function_entry.name) code.putln("// generating reified of %s" % reified_function_entry.name)
reified_arg_cname_list = [] reified_arg_cname_list = []
reified_arg_decl_list = [] reified_arg_decl_list = []
...@@ -1075,9 +1076,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1075,9 +1076,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
message_constructor_args_list = ["this->%s" % passive_self_attr_cname, "sync_object", "result_object"] + reified_arg_cname_list message_constructor_args_list = ["this->%s" % passive_self_attr_cname, "sync_object", "result_object"] + reified_arg_cname_list
message_constructor_args_code = ", ".join(message_constructor_args_list) message_constructor_args_code = ", ".join(message_constructor_args_list)
code.putln("%s = new %s(%s);" % ( code.putln("%s * message = new %s(%s);" % (
reifying_class_entry.type.declaration_code("message"), reifying_class_full_name,
reifying_class_entry.type.empty_declaration_code(), reifying_class_full_name,
message_constructor_args_code message_constructor_args_code
)) ))
...@@ -1147,9 +1148,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1147,9 +1148,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else: else:
code.decrease_indent() code.decrease_indent()
for reifying_class_entry in entry.type.scope.reifying_entries: for reified_function_entry in entry.type.scope.reified_entries:
reified_function_entry = reifying_class_entry.reified_entry reifying_class_name = "%s%s" % (Naming.cypclass_reified_prefix, reified_function_entry.name)
reifying_class_full_name = reifying_class_entry.type.empty_declaration_code() reifying_class_full_name = "%s::%s" % (PyrexTypes.namespace_declaration_code(entry.type), reifying_class_name)
class_name = reifying_class_full_name.split('::')[-1] class_name = reifying_class_full_name.split('::')[-1]
code.putln("struct %s : public %s {" % (reifying_class_full_name, message_base_type.empty_declaration_code())) code.putln("struct %s : public %s {" % (reifying_class_full_name, message_base_type.empty_declaration_code()))
# Declaring target object & reified method arguments # Declaring target object & reified method arguments
...@@ -1622,8 +1623,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1622,8 +1623,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
constructor = None constructor = None
destructor = None destructor = None
if entry.type.is_cyp_class and entry.type.activable: if entry.type.is_cyp_class and entry.type.activable:
activated_class_entry = scope.lookup_here("Activated") code.putln("struct Activated;")
code.putln("struct %s;" % activated_class_entry.cname)
dunder_activate_entry = scope.lookup_here("__activate__") dunder_activate_entry = scope.lookup_here("__activate__")
code.putln("%s;" % dunder_activate_entry.type.declaration_code(dunder_activate_entry.cname)) code.putln("%s;" % dunder_activate_entry.type.declaration_code(dunder_activate_entry.cname))
for attr in scope.var_entries: for attr in scope.var_entries:
...@@ -1651,8 +1651,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1651,8 +1651,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
is_implementing = 'init_module' in code.globalstate.parts is_implementing = 'init_module' in code.globalstate.parts
for reified in scope.reifying_entries: for reified in scope.reified_entries:
code.putln("struct %s;" % reified.cname) reifying_class_name = "%s%s" % (Naming.cypclass_reified_prefix, reified.name)
code.putln("struct %s;" % reifying_class_name)
def generate_cpp_constructor_code(arg_decls, arg_names, is_implementing, py_attrs, constructor): def generate_cpp_constructor_code(arg_decls, arg_names, is_implementing, py_attrs, constructor):
if is_implementing: if is_implementing:
......
...@@ -170,6 +170,10 @@ api_name = pyrex_prefix + "capi__" ...@@ -170,6 +170,10 @@ api_name = pyrex_prefix + "capi__"
# cname for the type that defines the essential memory layout of a cypclass wrapper. # cname for the type that defines the essential memory layout of a cypclass wrapper.
cypclass_wrapper_layout_type = "CyPyObject" cypclass_wrapper_layout_type = "CyPyObject"
# active cypclass
cypclass_reified_prefix = builtin_prefix + 'active_'
cypclass_active_self_cname = "_active_self"
# the h and api guards get changed to: # the h and api guards get changed to:
# __PYX_HAVE__FILENAME (for ascii filenames) # __PYX_HAVE__FILENAME (for ascii filenames)
# __PYX_HAVE_U_PUNYCODEFILENAME (for non-ascii filenames) # __PYX_HAVE_U_PUNYCODEFILENAME (for non-ascii filenames)
......
...@@ -4785,13 +4785,12 @@ class QualifiedCypclassType(BaseType): ...@@ -4785,13 +4785,12 @@ class QualifiedCypclassType(BaseType):
self.qualifier = qualifier self.qualifier = qualifier
if qualifier == 'active': if qualifier == 'active':
# TODO: raise a proper compilation error.
assert base_type.activable assert base_type.activable
# For now just redirect to the nested "Activated" cypclass scope
self.scope = self.qual_base_type.scope.lookup_here("Activated").type.scope
elif base_type.has_attributes and base_type.scope is not None: if base_type.scope is not None:
from .Symtab import QualifiedCypclassScope from .Symtab import qualified_cypclass_scope
self.scope = QualifiedCypclassScope(base_type.scope, qualifier) self.scope = qualified_cypclass_scope(base_type.scope, qualifier)
def __repr__(self): def __repr__(self):
return "<QualifiedCypclassType %s%r>" % self.qual_base_type return "<QualifiedCypclassType %s%r>" % self.qual_base_type
...@@ -4804,10 +4803,12 @@ class QualifiedCypclassType(BaseType): ...@@ -4804,10 +4803,12 @@ class QualifiedCypclassType(BaseType):
decl = self.qual_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref) decl = self.qual_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref)
return "%s %s" % (self.qualifier, decl) return "%s %s" % (self.qualifier, decl)
if self.qualifier == 'active': if self.qualifier == 'active':
decl_type = self.qual_base_type.scope.lookup_here("Activated").type if not deref:
entity_code = "*%s" % entity_code
namespace_decl = namespace_declaration_code(self.qual_base_type)
return "%s::Activated %s" % (namespace_decl, entity_code)
else: else:
decl_type = self.qual_base_type return self.qual_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref)
return decl_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref)
def empty_declaration_code(self): def empty_declaration_code(self):
if self._empty_declaration is None: if self._empty_declaration is None:
......
...@@ -177,6 +177,8 @@ class Entry(object): ...@@ -177,6 +177,8 @@ class Entry(object):
# static_cname string The cname of a static method in a cypclass # static_cname string The cname of a static method in a cypclass
# #
# original_name string The original name of a cpp or cypclass method # original_name string The original name of a cpp or cypclass method
#
# is_asyncable boolean Is a cypclass method that can be called asynchronously
# TODO: utility_code and utility_code_definition serves the same purpose... # TODO: utility_code and utility_code_definition serves the same purpose...
...@@ -254,6 +256,7 @@ class Entry(object): ...@@ -254,6 +256,7 @@ class Entry(object):
from_type = None from_type = None
static_cname = None static_cname = None
original_name = None original_name = None
is_asyncable = False
def __init__(self, name, cname, type, pos = None, init = None): def __init__(self, name, cname, type, pos = None, init = None):
self.name = name self.name = name
...@@ -869,18 +872,13 @@ class Scope(object): ...@@ -869,18 +872,13 @@ class Scope(object):
if entry.type.activable: if entry.type.activable:
# === Acthon === # === Acthon ===
# Declare activated class
act_scope = CppClassScope("Activated", scope) act_scope = CppClassScope("Activated", scope)
act_type = PyrexTypes.CypClassType( act_type = PyrexTypes.CypClassType(
EncodedString("Activated"), act_scope, "Activated", None, templates = templates, lock_mode=entry.type.lock_mode) EncodedString("Activated"), act_scope, "Activated", None, templates = templates, lock_mode=entry.type.lock_mode)
act_type.set_scope(act_scope) act_type.set_scope(act_scope)
act_type.namespace = entry.type act_type.namespace = entry.type
#scope.declare_cpp_class("Activated", act_scope, pos)
act_entry = scope.declare(EncodedString("Activated"), "Activated", act_type, pos, visibility) # Declare dunder activate method (its definition is generated automatically)
act_entry.is_type = 1
# Declaring active_self member and activate function (its definition is generated automatically)
act_attr_name = EncodedString(Naming.builtin_prefix + "_active_self")
scope.declare_var(EncodedString("<active_self>"), act_type, pos, cname=act_attr_name)
from . import Builtin from . import Builtin
queue_type = Builtin.acthon_queue_type queue_type = Builtin.acthon_queue_type
result_type = Builtin.acthon_result_type result_type = Builtin.acthon_result_type
...@@ -919,6 +917,7 @@ class Scope(object): ...@@ -919,6 +917,7 @@ class Scope(object):
activate_entry.is_variable = activate_entry.is_cfunction = 1 activate_entry.is_variable = activate_entry.is_cfunction = 1
activate_entry.func_cname = "%s::%s" % (entry.type.empty_declaration_code(), "__activate__") 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) activate_func_arg = PyrexTypes.CFuncTypeArg(EncodedString("o"), entry.type, pos)
activate_func_return = PyrexTypes.cyp_class_qualified_type(entry.type, 'active') activate_func_return = PyrexTypes.cyp_class_qualified_type(entry.type, 'active')
activate_func_type = PyrexTypes.CFuncType(activate_func_return, [activate_func_arg], nogil = 1) activate_func_type = PyrexTypes.CFuncType(activate_func_return, [activate_func_arg], nogil = 1)
...@@ -2806,7 +2805,7 @@ class CppClassScope(Scope): ...@@ -2806,7 +2805,7 @@ class CppClassScope(Scope):
self.directives = outer_scope.directives self.directives = outer_scope.directives
self.inherited_var_entries = [] self.inherited_var_entries = []
self.inherited_type_entries = [] self.inherited_type_entries = []
self.reifying_entries = [] self.reified_entries = []
if templates is not None: if templates is not None:
for T in templates: for T in templates:
template_entry = self.declare( template_entry = self.declare(
...@@ -2865,38 +2864,8 @@ class CppClassScope(Scope): ...@@ -2865,38 +2864,8 @@ class CppClassScope(Scope):
def reify_method(self, entry): def reify_method(self, entry):
if entry.type.has_varargs: if entry.type.has_varargs:
error(entry.pos, "Could not reify method with ellipsis (you can use optional arguments)") error(entry.pos, "Could not reify method with ellipsis (you can use optional arguments)")
# Create the reifying class self.reified_entries.append(entry)
reified_name = EncodedString("reified_" + entry.name) entry.is_asyncable = True
reified_cname = Naming.builtin_prefix + reified_name
scope = CppClassScope(reified_name, self)
reified_type = PyrexTypes.CypClassType(reified_name, scope, reified_cname, None, templates = None, lock_mode="nolock")
reified_type.namespace = self.type
#reify_base_classes = ()
reifying_entry = self.declare(reified_name, reified_cname, reified_type, entry.pos, 'extern') # FIXME: visibility
#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
from . import Builtin
activated_class_entry = self.lookup_here("Activated")
result_type = Builtin.acthon_result_type
sync_type = Builtin.acthon_sync_type
activated_method_sync_attr_type = PyrexTypes.CFuncTypeArg(
"sync_method", PyrexTypes.CConstOrVolatileType(sync_type, is_const=1), entry.pos, "sync_method")
activated_method_type = PyrexTypes.CFuncType(result_type,
[activated_method_sync_attr_type] + entry.type.args, nogil=entry.type.nogil,
has_varargs = entry.type.has_varargs,
optional_arg_count = entry.type.optional_arg_count)
if hasattr(entry.type, 'op_arg_struct'):
activated_method_type.op_arg_struct = entry.type.op_arg_struct
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
# Return the type declaration string if stripped_name corresponds to a known type, None otherwise. # Return the type declaration string if stripped_name corresponds to a known type, None otherwise.
# The returned string is intended to be used to build an operator of the form "operator <type name>". # The returned string is intended to be used to build an operator of the form "operator <type name>".
...@@ -3298,7 +3267,7 @@ class QualifiedCypclassScope(Scope): ...@@ -3298,7 +3267,7 @@ class QualifiedCypclassScope(Scope):
def __init__(self, base_type_scope, qualifier): def __init__(self, base_type_scope, qualifier):
Scope.__init__( Scope.__init__(
self, self,
'cyp_qual_' + base_type_scope.name, '%s_' % qualifier + base_type_scope.name,
base_type_scope.outer_scope, base_type_scope.outer_scope,
base_type_scope.parent_scope) base_type_scope.parent_scope)
self.base_type_scope = base_type_scope self.base_type_scope = base_type_scope
...@@ -3309,8 +3278,54 @@ class QualifiedCypclassScope(Scope): ...@@ -3309,8 +3278,54 @@ class QualifiedCypclassScope(Scope):
try: try:
return self.cached_qualified_entries[name] return self.cached_qualified_entries[name]
except KeyError: except KeyError:
# TODO entry = self.resolve(name)
pass self.cached_qualified_entries[name] = entry
return entry
def resolve(self, name):
return None
def qualified_cypclass_scope(base_type_scope, qualifier):
if qualifier == 'active':
return ActiveCypclassScope(base_type_scope)
else:
return QualifiedCypclassScope(base_type_scope, qualifier)
class ActiveCypclassScope(QualifiedCypclassScope):
def __init__(self, base_type_scope):
QualifiedCypclassScope.__init__(self, base_type_scope, 'active')
def resolve(self, name):
base_entry = self.base_type_scope.lookup_here(name)
if base_entry is None or not base_entry.is_asyncable:
return None
from . import Builtin
result_type = Builtin.acthon_result_type
sync_type = Builtin.acthon_sync_type
activated_method_sync_attr_type = PyrexTypes.CFuncTypeArg(
EncodedString("sync_method"),
PyrexTypes.CConstOrVolatileType(sync_type, is_const=1),
base_entry.pos,
"sync_method",
)
activated_method_type = PyrexTypes.CFuncType(
result_type,
[activated_method_sync_attr_type] + base_entry.type.args,
nogil=base_entry.type.nogil,
has_varargs = base_entry.type.has_varargs,
optional_arg_count = base_entry.type.optional_arg_count,
)
if hasattr(base_entry.type, 'op_arg_struct'):
activated_method_type.op_arg_struct = base_entry.type.op_arg_struct
activated_method_entry = Entry(base_entry.name, base_entry.cname, activated_method_type, base_entry.pos)
activated_method_entry.visibility = 'extern'
activated_method_entry.scope = self
activated_method_entry.is_cfunction = 1
activated_method_entry.is_variable = 1
return activated_method_entry
class TemplateScope(Scope): class TemplateScope(Scope):
def __init__(self, name, outer_scope): def __init__(self, name, outer_scope):
......
...@@ -362,6 +362,7 @@ ...@@ -362,6 +362,7 @@
struct ActhonActivableClass : public CyObject { struct ActhonActivableClass : public CyObject {
ActhonQueueInterface *_active_queue_class = NULL; ActhonQueueInterface *_active_queue_class = NULL;
void *_active_self = NULL;
ActhonResultInterface *(*_active_result_class)(void); ActhonResultInterface *(*_active_result_class)(void);
ActhonActivableClass(){} // Used in Activated classes inheritance chain (base Activated calls this, derived calls the 2 args version below) ActhonActivableClass(){} // Used in Activated classes inheritance chain (base Activated calls this, derived calls the 2 args version below)
ActhonActivableClass(ActhonQueueInterface * queue_object, ActhonResultInterface *(*result_constructor)(void)); ActhonActivableClass(ActhonQueueInterface * queue_object, ActhonResultInterface *(*result_constructor)(void));
......
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