1.1 --- a/translator.py Sun Nov 14 00:50:17 2021 +0100
1.2 +++ b/translator.py Sun Nov 28 02:03:21 2021 +0100
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Translate programs.
1.6
1.7 -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2015-2018, 2021 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -37,7 +37,7 @@
1.13 AliasResult, AttrResult, Expression, InstantiationResult, \
1.14 InvocationResult, LogicalOperationResult, \
1.15 LogicalResult, NegationResult, PredefinedConstantRef, \
1.16 - ReturnRef
1.17 + ReturnRef, special_attributes
1.18 from StringIO import StringIO
1.19 import compiler
1.20 import sys
1.21 @@ -619,7 +619,8 @@
1.22 del self.attrs[0]
1.23 return AttrResult(output, refs, location,
1.24 context_identity, context_identity_verified,
1.25 - accessor_test, accessor_stored)
1.26 + accessor_test, accessor_stored, n.attrname,
1.27 + self.in_assignment)
1.28
1.29 def init_substitutions(self):
1.30
1.31 @@ -806,9 +807,23 @@
1.32 if ref and not ref.static():
1.33 parent, attrname = path.rsplit(".", 1)
1.34
1.35 - self.writestmt("__store_via_object(&%s, %s, __load_via_object(&%s, %s));" % (
1.36 - encode_path(class_name), name,
1.37 - encode_path(parent), attrname
1.38 + # NOTE: This is a superficial test for internal attributes that
1.39 + # NOTE: relies on such attributes being used directly and passed
1.40 + # NOTE: to native code.
1.41 +
1.42 + if name in special_attributes:
1.43 + store_op = "__store_via_object_internal"
1.44 + else:
1.45 + store_op = "__store_via_object"
1.46 +
1.47 + if attrname in special_attributes:
1.48 + load_op = "__load_via_object_internal"
1.49 + else:
1.50 + load_op = "__load_via_object"
1.51 +
1.52 + self.writestmt("%s(&%s, %s, %s(&%s, %s));" % (
1.53 + store_op, encode_path(class_name), name,
1.54 + load_op, encode_path(parent), attrname
1.55 ))
1.56
1.57 def process_from_node(self, n):
1.58 @@ -883,6 +898,11 @@
1.59 compiler.ast.AssAttr(compiler.ast.Name("self"), name, "OP_ASSIGN"),
1.60 compiler.ast.Name(name))
1.61
1.62 + # Record the value stack level.
1.63 +
1.64 + self.writestmt("__section *__stack_section = __stack.stackdesc->current;")
1.65 + self.writestmt("char *__stack_level = __stack_section->level; (void) __stack_level;")
1.66 +
1.67 # Produce the body and any additional return statement.
1.68
1.69 expr = self.process_structure_node(n.code) or \
1.70 @@ -1281,8 +1301,8 @@
1.71 self.record_temp("__tmp_values")
1.72
1.73 # Arguments are presented in a temporary frame array with any context
1.74 - # always being the first argument. Where it would be unused, it may be
1.75 - # set to null.
1.76 + # always being the first argument. Where the context would be unused, it
1.77 + # may be set to null.
1.78
1.79 if context_required:
1.80 if have_access_context:
1.81 @@ -1292,6 +1312,8 @@
1.82 else:
1.83 context_arg = "__NULL"
1.84
1.85 + # Introduce any context.
1.86 +
1.87 args = [context_arg]
1.88 reserved_args = 1
1.89
1.90 @@ -1324,12 +1346,9 @@
1.91 for i, arg in enumerate(n.args):
1.92 argexpr = self.process_structure_node(arg)
1.93
1.94 - # Obtain an appropriate argument representation. This prevents
1.95 - # copyable values from being mutable, but care must be taken to
1.96 - # prevent special internal attribute values represented using
1.97 - # attributes from being modified.
1.98 -
1.99 - argrepr = argexpr.as_arg()
1.100 + # Obtain an appropriate argument representation.
1.101 +
1.102 + argrepr = str(argexpr)
1.103
1.104 # Store a keyword argument, either in the argument list or
1.105 # in a separate keyword argument list for subsequent lookup.
1.106 @@ -1758,7 +1777,7 @@
1.107 if self.in_try_finally or self.in_try_except:
1.108 self.writestmt("__Return(%s);" % expr)
1.109 else:
1.110 - self.writestmt("return %s;" % expr)
1.111 + self.writestmt("return __return(%s, __stack_section, __stack_level);" % expr)
1.112
1.113 return ReturnRef()
1.114
1.115 @@ -2131,11 +2150,13 @@
1.116
1.117 if names:
1.118 names.sort()
1.119 - self.writeline("__attr %s;" % ", ".join(names))
1.120 + for n in names:
1.121 + self.writeline("__attr %s = (__attr) {.rawvalue = 0};" % n)
1.122
1.123 if volatile_names:
1.124 volatile_names.sort()
1.125 - self.writeline("volatile __attr %s;" % ", ".join(volatile_names))
1.126 + for n in volatile_names:
1.127 + self.writeline("volatile __attr %s = (__attr) {.rawvalue = 0};" % n)
1.128
1.129 self.flush_unit(name, out)
1.130