1.1 --- a/results.py Mon Dec 05 13:01:21 2016 +0100
1.2 +++ b/results.py Mon Dec 05 16:03:06 2016 +0100
1.3 @@ -108,13 +108,9 @@
1.4 def __repr__(self):
1.5 return "LocalNameRef(%r, %r)" % (self.name, self.number)
1.6
1.7 -class ResolvedNameRef(NameRef):
1.8 -
1.9 - "A resolved name-based reference."
1.10 +class ResolvedRef:
1.11
1.12 - def __init__(self, name, ref, expr=None):
1.13 - NameRef.__init__(self, name, expr)
1.14 - self.ref = ref
1.15 + "A resolved reference mix-in."
1.16
1.17 def reference(self):
1.18 return self.ref
1.19 @@ -134,6 +130,14 @@
1.20 def has_kind(self, kinds):
1.21 return self.ref and self.ref.has_kind(kinds)
1.22
1.23 +class ResolvedNameRef(ResolvedRef, NameRef):
1.24 +
1.25 + "A resolved name-based reference."
1.26 +
1.27 + def __init__(self, name, ref, expr=None):
1.28 + NameRef.__init__(self, name, expr)
1.29 + self.ref = ref
1.30 +
1.31 def __repr__(self):
1.32 return "ResolvedNameRef(%r, %r, %r)" % (self.name, self.ref, self.expr)
1.33
1.34 @@ -149,7 +153,7 @@
1.35 def __repr__(self):
1.36 return "ConstantValueRef(%r, %r, %r, %r)" % (self.name, self.ref, self.value, self.number)
1.37
1.38 -class InstanceRef(Result):
1.39 +class InstanceRef(ResolvedRef, Result):
1.40
1.41 "An instance reference."
1.42
2.1 --- a/templates/progops.c Mon Dec 05 13:01:21 2016 +0100
2.2 +++ b/templates/progops.c Mon Dec 05 16:03:06 2016 +0100
2.3 @@ -109,6 +109,25 @@
2.4 __Raise(exc);
2.5 }
2.6
2.7 +/* Helper for raising exception instances. */
2.8 +
2.9 +__attr __ensure_instance(__attr arg)
2.10 +{
2.11 + /* Reserve space for the instance. */
2.12 +
2.13 + __attr args[1];
2.14 +
2.15 + /* Return instances as provided. */
2.16 +
2.17 + if (__is_instance(arg.value))
2.18 + return arg;
2.19 +
2.20 + /* Invoke non-instances to produce instances. */
2.21 +
2.22 + else
2.23 + return __invoke(arg, 0, 0, 0, 0, 1, args);
2.24 +}
2.25 +
2.26 /* Generic invocation operations. */
2.27
2.28 /* Invoke the given callable, supplying keyword argument details in the given
3.1 --- a/templates/progops.h Mon Dec 05 13:01:21 2016 +0100
3.2 +++ b/templates/progops.h Mon Dec 05 16:03:06 2016 +0100
3.3 @@ -13,10 +13,15 @@
3.4
3.5 void __newdata_mapping(__attr args[], unsigned int number);
3.6
3.7 +/* Exception raising. */
3.8 +
3.9 void __raise_memory_error();
3.10 void __raise_overflow_error();
3.11 void __raise_zero_division_error();
3.12 void __raise_type_error();
3.13 +__attr __ensure_instance(__attr arg);
3.14 +
3.15 +/* Generic invocation operations. */
3.16
3.17 __attr __invoke(__attr callable, int always_callable,
3.18 unsigned int nkwargs, __param kwcodes[], __attr kwargs[],
4.1 --- a/translator.py Mon Dec 05 13:01:21 2016 +0100
4.2 +++ b/translator.py Mon Dec 05 16:03:06 2016 +0100
4.3 @@ -154,6 +154,26 @@
4.4 def __str__(self):
4.5 return str(self.node)
4.6
4.7 +class TrInstanceRef(results.InstanceRef, TranslationResult):
4.8 +
4.9 + "A reference representing instantiation of a class."
4.10 +
4.11 + def __init__(self, ref, expr):
4.12 +
4.13 + """
4.14 + Initialise the reference with 'ref' indicating the nature of the
4.15 + reference and 'expr' being an expression used to create the instance.
4.16 + """
4.17 +
4.18 + results.InstanceRef.__init__(self, ref)
4.19 + self.expr = expr
4.20 +
4.21 + def __str__(self):
4.22 + return self.expr
4.23 +
4.24 + def __repr__(self):
4.25 + return "TrResolvedInstanceRef(%r, %r)" % (self.ref, self.expr)
4.26 +
4.27 class AttrResult(Expression, TranslationResult):
4.28
4.29 "A translation result for an attribute access."
4.30 @@ -1022,6 +1042,7 @@
4.31 objpath = expr.get_origin()
4.32 target = None
4.33 function = None
4.34 + instantiation = False
4.35 literal_instantiation = False
4.36 context_required = True
4.37
4.38 @@ -1030,7 +1051,7 @@
4.39 # Literals may be instantiated specially.
4.40
4.41 if expr.is_name() and expr.name.startswith("$L") and objpath:
4.42 - literal_instantiation = True
4.43 + instantiation = literal_instantiation = objpath
4.44 parameters = None
4.45 target = encode_literal_instantiator(objpath)
4.46 context_required = False
4.47 @@ -1043,6 +1064,7 @@
4.48 # Class invocation involves instantiators.
4.49
4.50 if expr.has_kind("<class>"):
4.51 + instantiation = objpath
4.52 target = encode_instantiator_pointer(objpath)
4.53 target_structure = "&%s" % encode_bound_reference("%s.__init__" % objpath)
4.54 context_required = False
4.55 @@ -1195,7 +1217,10 @@
4.56 len(kwargs), kwcodestr, kwargstr,
4.57 len(args), argstr)
4.58
4.59 - return make_expression(output)
4.60 + if instantiation:
4.61 + return TrInstanceRef(instantiation, output)
4.62 + else:
4.63 + return make_expression(output)
4.64
4.65 def always_callable(self, refs):
4.66
4.67 @@ -1342,7 +1367,15 @@
4.68 # NOTE: Determine which raise statement variants should be permitted.
4.69
4.70 if n.expr1:
4.71 - self.writestmt("__Raise(%s);" % self.process_structure_node(n.expr1))
4.72 + exc = self.process_structure_node(n.expr1)
4.73 +
4.74 + # Raise instances, testing the kind at run-time if necessary and
4.75 + # instantiating any non-instance.
4.76 +
4.77 + if isinstance(exc, TrInstanceRef):
4.78 + self.writestmt("__Raise(%s);" % exc)
4.79 + else:
4.80 + self.writestmt("__Raise(__ensure_instance(%s));" % exc)
4.81 else:
4.82 self.writestmt("__Complete;")
4.83