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

Allow qualified 'self' argument in cypclass methods

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