Commit f22704c1 authored by da-woods's avatar da-woods

Added "analyse_as_specialized_type"

parent 35ef5e01
...@@ -655,6 +655,19 @@ class ExprNode(Node): ...@@ -655,6 +655,19 @@ class ExprNode(Node):
# type, return that type, else None. # type, return that type, else None.
return None return None
def analyse_as_specialized_type(self, env):
type = self.analyse_as_type(env)
if type.is_fused and env.fused_to_specific:
# while it would be nice to test "if entry.type in env.fused_to_specific"
# rather than try/catch this doesn't work reliably (mainly for nested fused types)
try:
return type.specialize(env.fused_to_specific)
except KeyError:
pass
if type.is_fused:
error(self.pos, "Type is not specific")
return type
def analyse_as_extension_type(self, env): def analyse_as_extension_type(self, env):
# If this node can be interpreted as a reference to an # If this node can be interpreted as a reference to an
# extension type or builtin type, return its type, else None. # extension type or builtin type, return its type, else None.
...@@ -1961,11 +1974,6 @@ class NameNode(AtomicExprNode): ...@@ -1961,11 +1974,6 @@ class NameNode(AtomicExprNode):
if not entry: if not entry:
entry = env.lookup(self.name) entry = env.lookup(self.name)
if entry and entry.is_type: if entry and entry.is_type:
if entry.type.is_fused and env.fused_to_specific:
if entry.type in env.fused_to_specific:
return entry.type.specialize(env.fused_to_specific)
# else lots of valid reasons why we may not be able to get a specific type
# so don't fail
return entry.type return entry.type
else: else:
return None return None
...@@ -6906,19 +6914,14 @@ class AttributeNode(ExprNode): ...@@ -6906,19 +6914,14 @@ class AttributeNode(ExprNode):
return None return None
def analyse_as_type(self, env): def analyse_as_type(self, env):
tp = None
module_scope = self.obj.analyse_as_module(env) module_scope = self.obj.analyse_as_module(env)
if module_scope: if module_scope:
tp = module_scope.lookup_type(self.attribute) return module_scope.lookup_type(self.attribute)
elif not self.obj.is_string_literal: if not self.obj.is_string_literal:
base_type = self.obj.analyse_as_type(env) base_type = self.obj.analyse_as_type(env)
if base_type and hasattr(base_type, 'scope') and base_type.scope is not None: if base_type and hasattr(base_type, 'scope') and base_type.scope is not None:
tp = base_type.scope.lookup_type(self.attribute) return base_type.scope.lookup_type(self.attribute)
if tp and tp.is_fused and env.fused_to_specific: return None
if tp in env.fused_to_specific:
tp = tp.specialize(env.fused_to_specific)
# else just use unspecialized type
return tp
def analyse_as_extension_type(self, env): def analyse_as_extension_type(self, env):
# Try to interpret this as a reference to an extension type # Try to interpret this as a reference to an extension type
...@@ -10836,7 +10839,7 @@ class TypeidNode(ExprNode): ...@@ -10836,7 +10839,7 @@ class TypeidNode(ExprNode):
self.error("The 'libcpp.typeinfo' module must be cimported to use the typeid() operator") self.error("The 'libcpp.typeinfo' module must be cimported to use the typeid() operator")
return self return self
self.type = type_info self.type = type_info
as_type = self.operand.analyse_as_type(env) as_type = self.operand.analyse_as_specialized_type(env)
if as_type: if as_type:
self.arg_type = as_type self.arg_type = as_type
self.is_type = True self.is_type = True
......
...@@ -3279,12 +3279,7 @@ class ReplaceFusedTypeChecks(VisitorTransform): ...@@ -3279,12 +3279,7 @@ class ReplaceFusedTypeChecks(VisitorTransform):
def visit_PrimaryCmpNode(self, node): def visit_PrimaryCmpNode(self, node):
with Errors.local_errors(ignore=True): with Errors.local_errors(ignore=True):
type1 = node.operand1.analyse_as_type(self.local_scope) type1 = node.operand1.analyse_as_type(self.local_scope)
# type2 should not be specialized here as a special case
# we always want to check against the global fused type
fused_to_specific = self.local_scope.fused_to_specific
self.local_scope.fused_to_specific = None
type2 = node.operand2.analyse_as_type(self.local_scope) type2 = node.operand2.analyse_as_type(self.local_scope)
self.local_scope.fused_to_specific = fused_to_specific
if type1 and type2: if type1 and type2:
false_node = ExprNodes.BoolNode(node.pos, value=False) false_node = ExprNodes.BoolNode(node.pos, value=False)
......
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