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):
"""
Generate activate function for activable cypclass entries.
"""
active_self_entry = entry.type.scope.lookup_here("<active_self>")
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.
......@@ -985,30 +984,30 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("if (%s->%sn <= %s) {" %
(Naming.optional_args_cname,
Naming.pyrex_prefix, i))
code.putln("activated_instance = new %s::Activated(%s);" %
(entry.type.empty_declaration_code(),
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::Activated(%s);" %
(entry.type.empty_declaration_code(),
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 {")
code.putln("if (this->%s == NULL) {" % active_self_entry.cname)
code.putln("this->%s = new %s::Activated(this, %s);" %
(active_self_entry.cname,
entry.type.empty_declaration_code(),
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(this->%s);" % active_self_entry.cname)
code.putln("activated_instance = 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 = (%s *)(this->%s);" % (activate_class_decl, Naming.cypclass_active_self_cname))
code.putln("}")
code.putln("return activated_instance;")
code.putln("}")
......@@ -1051,8 +1050,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
passive_self_attr_cname
)
))
for reifying_class_entry in entry.type.scope.reifying_entries:
reified_function_entry = reifying_class_entry.reified_entry
for reified_function_entry in entry.type.scope.reified_entries:
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)
reified_arg_cname_list = []
reified_arg_decl_list = []
......@@ -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_code = ", ".join(message_constructor_args_list)
code.putln("%s = new %s(%s);" % (
reifying_class_entry.type.declaration_code("message"),
reifying_class_entry.type.empty_declaration_code(),
code.putln("%s * message = new %s(%s);" % (
reifying_class_full_name,
reifying_class_full_name,
message_constructor_args_code
))
......@@ -1147,9 +1148,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else:
code.decrease_indent()
for reifying_class_entry in entry.type.scope.reifying_entries:
reified_function_entry = reifying_class_entry.reified_entry
reifying_class_full_name = reifying_class_entry.type.empty_declaration_code()
for reified_function_entry in entry.type.scope.reified_entries:
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)
class_name = reifying_class_full_name.split('::')[-1]
code.putln("struct %s : public %s {" % (reifying_class_full_name, message_base_type.empty_declaration_code()))
# Declaring target object & reified method arguments
......@@ -1622,8 +1623,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
constructor = None
destructor = None
if entry.type.is_cyp_class and entry.type.activable:
activated_class_entry = scope.lookup_here("Activated")
code.putln("struct %s;" % activated_class_entry.cname)
code.putln("struct Activated;")
dunder_activate_entry = scope.lookup_here("__activate__")
code.putln("%s;" % dunder_activate_entry.type.declaration_code(dunder_activate_entry.cname))
for attr in scope.var_entries:
......@@ -1651,8 +1651,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
is_implementing = 'init_module' in code.globalstate.parts
for reified in scope.reifying_entries:
code.putln("struct %s;" % reified.cname)
for reified in scope.reified_entries:
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):
if is_implementing:
......
......@@ -170,6 +170,10 @@ api_name = pyrex_prefix + "capi__"
# cname for the type that defines the essential memory layout of a cypclass wrapper.
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:
# __PYX_HAVE__FILENAME (for ascii filenames)
# __PYX_HAVE_U_PUNYCODEFILENAME (for non-ascii filenames)
......
......@@ -4785,13 +4785,12 @@ class QualifiedCypclassType(BaseType):
self.qualifier = qualifier
if qualifier == 'active':
# TODO: raise a proper compilation error.
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:
from .Symtab import QualifiedCypclassScope
self.scope = QualifiedCypclassScope(base_type.scope, qualifier)
if base_type.scope is not None:
from .Symtab import qualified_cypclass_scope
self.scope = qualified_cypclass_scope(base_type.scope, qualifier)
def __repr__(self):
return "<QualifiedCypclassType %s%r>" % self.qual_base_type
......@@ -4804,10 +4803,12 @@ class QualifiedCypclassType(BaseType):
decl = self.qual_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref)
return "%s %s" % (self.qualifier, decl)
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:
decl_type = self.qual_base_type
return decl_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref)
return self.qual_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex, template_params, deref)
def empty_declaration_code(self):
if self._empty_declaration is None:
......
......@@ -177,6 +177,8 @@ class Entry(object):
# static_cname string The cname of a static method in a cypclass
#
# 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...
......@@ -254,6 +256,7 @@ class Entry(object):
from_type = None
static_cname = None
original_name = None
is_asyncable = False
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
......@@ -869,18 +872,13 @@ class Scope(object):
if entry.type.activable:
# === Acthon ===
# Declare activated class
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
#scope.declare_cpp_class("Activated", act_scope, pos)
act_entry = scope.declare(EncodedString("Activated"), "Activated", act_type, pos, visibility)
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)
# Declare dunder activate method (its definition is generated automatically)
from . import Builtin
queue_type = Builtin.acthon_queue_type
result_type = Builtin.acthon_result_type
......@@ -919,6 +917,7 @@ class Scope(object):
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)
activate_func_return = PyrexTypes.cyp_class_qualified_type(entry.type, 'active')
activate_func_type = PyrexTypes.CFuncType(activate_func_return, [activate_func_arg], nogil = 1)
......@@ -2806,7 +2805,7 @@ class CppClassScope(Scope):
self.directives = outer_scope.directives
self.inherited_var_entries = []
self.inherited_type_entries = []
self.reifying_entries = []
self.reified_entries = []
if templates is not None:
for T in templates:
template_entry = self.declare(
......@@ -2865,38 +2864,8 @@ class CppClassScope(Scope):
def reify_method(self, entry):
if entry.type.has_varargs:
error(entry.pos, "Could not reify method with ellipsis (you can use optional arguments)")
# Create the reifying class
reified_name = EncodedString("reified_" + entry.name)
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
self.reified_entries.append(entry)
entry.is_asyncable = True
# 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>".
......@@ -3298,7 +3267,7 @@ class QualifiedCypclassScope(Scope):
def __init__(self, base_type_scope, qualifier):
Scope.__init__(
self,
'cyp_qual_' + base_type_scope.name,
'%s_' % qualifier + base_type_scope.name,
base_type_scope.outer_scope,
base_type_scope.parent_scope)
self.base_type_scope = base_type_scope
......@@ -3309,8 +3278,54 @@ class QualifiedCypclassScope(Scope):
try:
return self.cached_qualified_entries[name]
except KeyError:
# TODO
pass
entry = self.resolve(name)
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):
def __init__(self, name, outer_scope):
......
......@@ -362,6 +362,7 @@
struct ActhonActivableClass : public CyObject {
ActhonQueueInterface *_active_queue_class = NULL;
void *_active_self = NULL;
ActhonResultInterface *(*_active_result_class)(void);
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));
......
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