Commit 48a1e3f9 authored by Xavier Thompson's avatar Xavier Thompson

Allow qualified 'self' argument in cypclass methods

parent 69d0430d
......@@ -4,7 +4,7 @@
from __future__ import absolute_import
from .Symtab import BuiltinScope, StructOrUnionScope, Scope
from .Symtab import BuiltinScope, StructOrUnionScope, CppClassScope
from .Code import UtilityCode
from .TypeSlots import Signature
from . import PyrexTypes
......@@ -387,7 +387,7 @@ def inject_cy_object(self):
scope.inherited_var_entries = []
scope.inherited_type_entries = []
cy_object_scope = Scope("CyObject", self, None)
cy_object_scope = CppClassScope("CyObject", self, None)
init_scope(cy_object_scope)
cy_object_type = PyrexTypes.cy_object_type
cy_object_scope.type = PyrexTypes.cy_object_type
......@@ -411,7 +411,7 @@ def inject_acthon_interfaces(self):
# int getIntResult(){}
# operator int() { return this->getIntResult(); }
result_scope = Scope("ActhonResultInterface", self, None)
result_scope = CppClassScope("ActhonResultInterface", self, None)
init_scope(result_scope)
acthon_result_type = result_type = PyrexTypes.CypClassType(
"ActhonResultInterface", result_scope, "ActhonResultInterface", (PyrexTypes.cy_object_type,),
......@@ -470,7 +470,7 @@ def inject_acthon_interfaces(self):
# cypclass ActhonMessageInterface
message_scope = Scope("ActhonMessageInterface", self, None)
message_scope = CppClassScope("ActhonMessageInterface", self, None)
init_scope(message_scope)
acthon_message_type = message_type = PyrexTypes.CypClassType(
"ActhonMessageInterface", message_scope, "ActhonMessageInterface", (PyrexTypes.cy_object_type,),
......@@ -484,7 +484,7 @@ def inject_acthon_interfaces(self):
# void insertActivity(ActhonMessageInterface msg){}
# void removeActivity(ActhonMessageInterface msg){}
sync_scope = Scope("ActhonSyncInterface", self, None)
sync_scope = CppClassScope("ActhonSyncInterface", self, None)
init_scope(sync_scope)
acthon_sync_type = sync_type = PyrexTypes.CypClassType(
"ActhonSyncInterface", sync_scope, "ActhonSyncInterface", (PyrexTypes.cy_object_type,),
......@@ -553,7 +553,7 @@ def inject_acthon_interfaces(self):
# void push(ActhonMessageInterface message){}
# bool activate(){}
queue_scope = Scope("ActhonQueueInterface", self, None)
queue_scope = CppClassScope("ActhonQueueInterface", self, None)
init_scope(queue_scope)
acthon_queue_type = queue_type = PyrexTypes.CypClassType(
"ActhonQueueInterface", queue_scope, "ActhonQueueInterface", (PyrexTypes.cy_object_type,),
......@@ -590,7 +590,7 @@ def inject_acthon_interfaces(self):
# ResultInterface (*_active_result_class)()
# QueueInterface _active_queue_class
activable_scope = Scope("ActhonActivableClass", self, None)
activable_scope = CppClassScope("ActhonActivableClass", self, None)
init_scope(activable_scope)
acthon_activable_type = activable_type = PyrexTypes.CypClassType(
"ActhonActivableClass", activable_scope, "ActhonActivableClass", (PyrexTypes.cy_object_type,),
......
......@@ -302,6 +302,10 @@ def NAME(ARGDECLS):
method_type = method_entry.type
if method_type.self_qualifier:
# skip methods with qualified self
return
if method_type.optional_arg_count:
# for now skip methods with optional arguments
return
......
......@@ -612,12 +612,14 @@ class CFuncDeclaratorNode(CDeclaratorNode):
# nogil boolean Can be called without gil
# with_gil boolean Acquire gil around function body
# is_const_method boolean Whether this is a const method
# self_qualifier string The qualifier of 'self' argument, if any
child_attrs = ["base", "args", "exception_value"]
overridable = 0
optional_arg_count = 0
is_const_method = 0
self_qualifier = None
templates = None
skipped_self = None
......@@ -685,6 +687,10 @@ class CFuncDeclaratorNode(CDeclaratorNode):
if type.is_const_cyp_class:
self.is_const_method = True
unqualified_type = type.const_base_type
# Accept 'f(<qualifier> self, ...) syntax'
if type.is_qualified_cyp_class:
self.self_qualifier = type.qualifier
unqualified_type = type.qual_base_type
# check that the type of self is correct:
if not unqualified_type.same_as(env.parent_type):
error(self.pos, "Wrong type for self argument - expected %s, got %s" % (env.parent_type, type))
......@@ -784,6 +790,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
nogil=self.nogil, with_gil=self.with_gil, is_overridable=self.overridable,
is_const_method=self.is_const_method,
is_cyp_class_method = env.is_cyp_class_scope,
self_qualifier = self.self_qualifier,
templates=self.templates)
if self.optional_arg_count:
......@@ -913,6 +920,8 @@ class CArgDeclNode(Node):
self_base_type = self.base_type
if isinstance(self_base_type, CConstOrVolatileTypeNode):
self_base_type = self_base_type.base_type
if isinstance(self_base_type, QualifiedCypclassNode):
self_base_type = self_base_type.base_type
self_base_type.is_self_arg = self.is_self_arg = True
if self.type is None:
# The parser may misinterpret names as types. We fix that here.
......@@ -923,6 +932,9 @@ class CArgDeclNode(Node):
# and crashes when that assumption is broken.
if isinstance(name_as_type, CConstOrVolatileTypeNode):
name_as_type = name_as_type.base_type
# Support syntax like '<qualifier> self'
if isinstance(name_as_type, QualifiedCypclassNode):
name_as_type = name_as_type.base_type
if nonempty:
if name_as_type.is_basic_c_type:
# char, short, long called "int"
......
......@@ -3071,6 +3071,7 @@ class CFuncType(CType):
# is_const_method boolean
# is_static_method boolean
# is_cyp_class_method boolean
# self_qualifier string
is_cfunction = 1
original_sig = None
......@@ -3078,6 +3079,7 @@ class CFuncType(CType):
from_fused = False
is_const_method = False
is_cyp_class_method = False
self_qualifier = None
subtypes = ['return_type', 'args']
......@@ -3085,7 +3087,7 @@ class CFuncType(CType):
exception_value = None, exception_check = 0, calling_convention = "",
nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
is_const_method = False, is_static_method=False, is_cyp_class_method=False,
templates = None, is_strict_signature = False):
self_qualifier = None, templates = None, is_strict_signature = False):
self.return_type = return_type
self.args = args
self.has_varargs = has_varargs
......@@ -3099,6 +3101,7 @@ class CFuncType(CType):
self.is_const_method = is_const_method
self.is_static_method = is_static_method
self.is_cyp_class_method = is_cyp_class_method
self.self_qualifier = self_qualifier
self.templates = templates
self.is_strict_signature = is_strict_signature
......
......@@ -382,6 +382,7 @@ class Scope(object):
nogil = 0
fused_to_specific = None
return_type = None
directives = {}
def __init__(self, name, outer_scope, parent_scope):
# The outer_scope is the next scope in the lookup chain.
......@@ -1186,6 +1187,8 @@ class Scope(object):
# This is to support things like global __foo which makes a declaration for __foo
return self.entries.get(name, None)
lookup_here_unfiltered = lookup_here
def lookup_here_unmangled(self, name):
return self.entries.get(name, None)
......@@ -2894,7 +2897,7 @@ class CppClassScope(Scope):
# Remember the original name because it might change
original_name = name
reify = self.type.is_cyp_class and self.type.activable
reify = self.type.is_cyp_class and self.type.activable and type.self_qualifier is None
class_name = self.name.split('::')[-1]
if name in (class_name, '__init__') and cname is None:
reify = False
......@@ -3119,7 +3122,7 @@ class CppClassScope(Scope):
return scope
def lookup_here(self, name):
def adapt_name_lookup(self, name):
if name == "__init__":
name = "<init>"
elif name == "__dealloc__":
......@@ -3137,7 +3140,17 @@ class CppClassScope(Scope):
as_operator_name = self._as_type_operator(stripped_name)
if as_operator_name:
name = 'operator ' + as_operator_name
return super(CppClassScope,self).lookup_here(name)
return name
def lookup_here(self, name):
entry = super(CppClassScope,self).lookup_here(self.adapt_name_lookup(name))
if entry and self.is_cyp_class_scope and entry.is_cfunction and entry.type.self_qualifier:
# Cannot access self-qualified methods from unqualified cypclass.
return None
return entry
def lookup_here_unfiltered(self, name):
return super(CppClassScope,self).lookup_here(self.adapt_name_lookup(name))
class CppScopedEnumScope(Scope):
......@@ -3270,7 +3283,7 @@ class QualifiedCypclassScope(Scope):
return entry
def resolve(self, name):
base_entry = self.base_type_scope.lookup_here(name)
base_entry = self.base_type_scope.lookup_here_unfiltered(name)
if base_entry is None:
return None
alternatives = []
......@@ -3280,7 +3293,7 @@ class QualifiedCypclassScope(Scope):
continue
entry.overloaded_alternatives = alternatives
alternatives.append(entry)
return alternatives[0]
return alternatives[0] if alternatives else None
def adapt(self, base_entry):
return None
......@@ -3290,7 +3303,7 @@ def qualified_cypclass_scope(base_type_scope, qualifier):
if qualifier == 'active':
return ActiveCypclassScope(base_type_scope)
elif qualifier.startswith('iso'):
return IsoCypclassScope(base_type_scope)
return IsoCypclassScope(base_type_scope, qualifier)
elif qualifier == 'locked':
return IsoCypclassScope(base_type_scope, 'locked')
else:
......@@ -3301,6 +3314,8 @@ class ActiveCypclassScope(QualifiedCypclassScope):
qualifier = 'active'
def adapt(self, base_entry):
if base_entry.is_cfunction and base_entry.type.self_qualifier == 'active':
return base_entry
return base_entry.active_entry
......@@ -3313,10 +3328,16 @@ class IsoCypclassScope(QualifiedCypclassScope):
return arg
def adapt_method_entry(self, base_entry):
iso_method_type = copy.copy(base_entry.type)
return_type = viewpoint_adaptation(base_entry.type.return_type)
base_type = base_entry.type
if base_type.self_qualifier:
if self.qualifier in PyrexTypes.QualifiedCypclassType.assignable_to[base_type.self_qualifier]:
return base_entry
else:
return None
iso_method_type = copy.copy(base_type)
return_type = viewpoint_adaptation(base_type.return_type)
iso_method_type.return_type = return_type
iso_method_type.args = [self.adapt_arg_type(arg) for arg in base_entry.type.args]
iso_method_type.args = [self.adapt_arg_type(arg) for arg in base_type.args]
entry = copy.copy(base_entry)
entry.type = iso_method_type
return entry
......
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