1.1 --- a/templates/types.h Sun Nov 14 00:37:32 2021 +0100
1.2 +++ b/templates/types.h Sun Nov 14 00:42:49 2021 +0100
1.3 @@ -130,12 +130,15 @@
1.4
1.5 /* Attribute interpretation. */
1.6
1.7 -#define __NUM_TAG_BITS 1
1.8 -#define __TAG_MUTABLE 0b1
1.9 -#define __TAG_MASK 0b1
1.10 +#define __NUM_TAG_BITS 2
1.11 +#define __TAG_COPYABLE 0b01UL
1.12 +#define __TAG_MUTABLE 0b10UL
1.13 +#define __TAG_MASK 0b11UL
1.14
1.15 -#define __MUTABLE(ATTR) (((ATTR).rawvalue & __TAG_MASK) == __TAG_MUTABLE)
1.16 -#define __TO_MUTABLE(ATTR) ((__attr) (((ATTR).rawvalue & (~__TAG_MASK)) | __TAG_MUTABLE))
1.17 +#define __COPYABLE(ATTR) ((ATTR).rawvalue & __TAG_COPYABLE)
1.18 +#define __MUTABLE(ATTR) ((ATTR).rawvalue & __TAG_MUTABLE)
1.19 +#define __TO_IMMUTABLE(ATTR) ((__attr) {.rawvalue=(ATTR).rawvalue & (~__TAG_MUTABLE)})
1.20 +#define __TO_MUTABLE(ATTR) ((__attr) {.rawvalue=(ATTR).rawvalue | __TAG_MASK})
1.21
1.22 /* Attribute value setting. */
1.23
2.1 --- a/translator.py Sun Nov 14 00:37:32 2021 +0100
2.2 +++ b/translator.py Sun Nov 14 00:42:49 2021 +0100
2.3 @@ -1324,6 +1324,13 @@
2.4 for i, arg in enumerate(n.args):
2.5 argexpr = self.process_structure_node(arg)
2.6
2.7 + # Obtain an appropriate argument representation. This prevents
2.8 + # copyable values from being mutable, but care must be taken to
2.9 + # prevent special internal attribute values represented using
2.10 + # attributes from being modified.
2.11 +
2.12 + argrepr = argexpr.as_arg()
2.13 +
2.14 # Store a keyword argument, either in the argument list or
2.15 # in a separate keyword argument list for subsequent lookup.
2.16
2.17 @@ -1338,12 +1345,12 @@
2.18 except ValueError:
2.19 raise TranslateError("Argument %s is not recognised." % arg.name,
2.20 self.get_namespace_path(), n)
2.21 - args[argnum + reserved_args] = str(argexpr)
2.22 + args[argnum + reserved_args] = argrepr
2.23
2.24 # Otherwise, store the details in a separate collection.
2.25
2.26 else:
2.27 - kwargs.append(str(argexpr))
2.28 + kwargs.append(argrepr)
2.29 kwcodes.append("{%s, %s}" % (
2.30 encode_ppos(arg.name), encode_pcode(arg.name)))
2.31
2.32 @@ -1352,7 +1359,7 @@
2.33
2.34 else:
2.35 try:
2.36 - args[i + reserved_args] = str(argexpr)
2.37 + args[i + reserved_args] = argrepr
2.38 except IndexError:
2.39 raise TranslateError("Too many arguments specified.",
2.40 self.get_namespace_path(), n)
3.1 --- a/transresults.py Sun Nov 14 00:37:32 2021 +0100
3.2 +++ b/transresults.py Sun Nov 14 00:42:49 2021 +0100
3.3 @@ -59,6 +59,12 @@
3.4 def __repr__(self):
3.5 return "Expression(%r)" % self.s
3.6
3.7 + def as_arg(self):
3.8 +
3.9 + "Return the expression without any mutable tag."
3.10 +
3.11 + return self.s
3.12 +
3.13 class TrResolvedNameRef(ResolvedNameRef):
3.14
3.15 "A reference to a name in the translation."
3.16 @@ -132,6 +138,21 @@
3.17 else:
3.18 return "(%s)" % self.attrname
3.19
3.20 + def as_arg(self):
3.21 +
3.22 + "Return the expression without any mutable tag."
3.23 +
3.24 + s = self.__str__()
3.25 +
3.26 + # NOTE: This is a superficial test for internal attributes that relies
3.27 + # NOTE: on such attributes being used directly and passed to native
3.28 + # NOTE: code.
3.29 +
3.30 + if self.attrname in ("__data__", "__size__"):
3.31 + return s
3.32 + else:
3.33 + return "__TO_IMMUTABLE(%s)" % s
3.34 +
3.35 class TrConstantValueRef(ConstantValueRef):
3.36
3.37 "A constant value reference in the translation."
3.38 @@ -139,6 +160,9 @@
3.39 def __str__(self):
3.40 return encode_literal_constant(self.number)
3.41
3.42 + def as_arg(self):
3.43 + return self.__str__()
3.44 +
3.45 class TrLiteralSequenceRef(LiteralSequenceRef):
3.46
3.47 "A reference representing a sequence of values."
3.48 @@ -146,6 +170,9 @@
3.49 def __str__(self):
3.50 return str(self.node)
3.51
3.52 + def as_arg(self):
3.53 + return self.__str__()
3.54 +
3.55 class TrInstanceRef(InstanceRef):
3.56
3.57 "A reference representing instantiation of a class."
3.58 @@ -166,6 +193,9 @@
3.59 def __repr__(self):
3.60 return "TrResolvedInstanceRef(%r, %r)" % (self.ref, self.expr)
3.61
3.62 + def as_arg(self):
3.63 + return self.__str__()
3.64 +
3.65 class AttrResult(Result, InstructionSequence):
3.66
3.67 "A translation result for an attribute access."
3.68 @@ -222,6 +252,9 @@
3.69 self.context_identity, self.context_identity_verified,
3.70 self.accessor_test, self.accessor_stored)
3.71
3.72 + def as_arg(self):
3.73 + return self.__str__()
3.74 +
3.75 class AliasResult(NameRef, Result):
3.76
3.77 "An alias for other values."
3.78 @@ -275,6 +308,9 @@
3.79 def __repr__(self):
3.80 return "AliasResult(%r, %r)" % (self.name_ref, self.refs)
3.81
3.82 + def as_arg(self):
3.83 + return self.__str__()
3.84 +
3.85 class InvocationResult(Result, InstructionSequence):
3.86
3.87 "A translation result for an invocation."
3.88 @@ -285,6 +321,9 @@
3.89 def __repr__(self):
3.90 return "InvocationResult(%r)" % self.instructions
3.91
3.92 + def as_arg(self):
3.93 + return self.__str__()
3.94 +
3.95 class InstantiationResult(InvocationResult, TrInstanceRef):
3.96
3.97 "An instantiation result acting like an invocation result."
3.98 @@ -325,6 +364,9 @@
3.99 def __repr__(self):
3.100 return "PredefinedConstantRef(%r)" % self.value
3.101
3.102 + def as_arg(self):
3.103 + return self.__str__()
3.104 +
3.105 class LogicalResult(Result):
3.106
3.107 "A logical expression result."
3.108 @@ -370,6 +412,9 @@
3.109 def __repr__(self):
3.110 return "NegationResult(%r)" % self.expr
3.111
3.112 + def as_arg(self):
3.113 + return self.__str__()
3.114 +
3.115 class LogicalOperationResult(LogicalResult):
3.116
3.117 "A logical operation result."
3.118 @@ -442,4 +487,7 @@
3.119 def __repr__(self):
3.120 return "LogicalOperationResult(%r, %r)" % (self.exprs, self.conjunction)
3.121
3.122 + def as_arg(self):
3.123 + return self.__str__()
3.124 +
3.125 # vim: tabstop=4 expandtab shiftwidth=4