1.1 --- a/translator.py Thu Oct 20 22:43:48 2016 +0200
1.2 +++ b/translator.py Thu Oct 20 23:40:02 2016 +0200
1.3 @@ -128,6 +128,14 @@
1.4 def get_origin(self):
1.5 return self.refs and len(self.refs) == 1 and first(self.refs).get_origin()
1.6
1.7 + def has_kind(self, kinds):
1.8 + if not self.refs:
1.9 + return False
1.10 + for ref in self.refs:
1.11 + if ref.has_kind(kinds):
1.12 + return True
1.13 + return False
1.14 +
1.15 def __repr__(self):
1.16 return "AttrResult(%r, %r)" % (self.s, self.origin)
1.17
1.18 @@ -228,6 +236,14 @@
1.19 class_name, method_name = path.rsplit(".", 1)
1.20 return self.importer.classes.has_key(class_name) and class_name
1.21
1.22 + def reset_invocations(self):
1.23 +
1.24 + "Reset offsets within each namespace's arguments array."
1.25 +
1.26 + self.invocation_depth = 0
1.27 + self.invocation_argument_depth = 0
1.28 + self.invocation_kw_argument_depth = 0
1.29 +
1.30 # Namespace recording.
1.31
1.32 def record_namespaces(self, node):
1.33 @@ -329,9 +345,7 @@
1.34 self.process_function_body_node(node)
1.35 else:
1.36 self.in_function = False
1.37 - self.invocation_depth = 0
1.38 - self.invocation_argument_depth = 0
1.39 - self.invocation_kw_argument_depth = 0
1.40 + self.reset_invocations()
1.41 self.start_module()
1.42 self.process_structure(node)
1.43 self.end_module()
1.44 @@ -633,9 +647,7 @@
1.45
1.46 # Process the function body.
1.47
1.48 - self.invocation_depth = 0
1.49 - self.invocation_argument_depth = 0
1.50 - self.invocation_kw_argument_depth = 0
1.51 + self.reset_invocations()
1.52
1.53 in_conditional = self.in_conditional
1.54 self.in_conditional = False
1.55 @@ -756,14 +768,25 @@
1.56
1.57 expr = self.process_structure_node(n.node)
1.58 objpath = expr.get_origin()
1.59 + target = None
1.60
1.61 # Obtain details of the callable.
1.62
1.63 if objpath:
1.64 parameters = self.importer.function_parameters.get(objpath)
1.65 + if expr.has_kind("<class>"):
1.66 + target = encode_instantiator_pointer(objpath)
1.67 + elif expr.has_kind("<function>"):
1.68 + target = encode_function_pointer(objpath)
1.69 else:
1.70 parameters = None
1.71
1.72 + # Obtain details of the argument storage, updating the offsets to allow
1.73 + # calls in the argument list.
1.74 +
1.75 + argstart = self.invocation_argument_depth
1.76 + # self.invocation_argument_depth += len(parameters)
1.77 +
1.78 stages = []
1.79
1.80 # Arguments are presented in a temporary frame array at the current
1.81 @@ -771,15 +794,20 @@
1.82 # may be omitted for invocations where it would be unused).
1.83
1.84 stages.append("__tmp_target = %s" % expr)
1.85 - stages.append("__tmp_args[...] = __tmp_target.context")
1.86 + stages.append("__tmp_args[%d] = __tmp_target.context" % argstart)
1.87
1.88 # Keyword arguments are positioned within the frame.
1.89
1.90 # Defaults are added to the frame where arguments are missing.
1.91
1.92 - # The callable member of the callable is then obtained.
1.93 + # Any identified target is stated.
1.94
1.95 - if self.always_callable:
1.96 + if target:
1.97 + get_fn = "__tmp_target.fn"
1.98 +
1.99 + # The callable member of any callable is then obtained.
1.100 +
1.101 + elif self.always_callable:
1.102 get_fn = "__load_via_object(__tmp_target, %s).fn" % \
1.103 encode_symbol("pos", "__fn__")
1.104 else:
1.105 @@ -788,7 +816,7 @@
1.106
1.107 stages.append(get_fn)
1.108
1.109 - output = "(\n%s\n)(__tmp_frame)" % ",\n".join(stages)
1.110 + output = "(\n%s\n)(&__tmp_args[%d])" % (",\n".join(stages), argstart)
1.111
1.112 return make_expression("".join(output))
1.113