1.1 --- a/translator.py Fri Nov 25 18:36:10 2016 +0100
1.2 +++ b/translator.py Fri Nov 25 18:36:45 2016 +0100
1.3 @@ -245,9 +245,10 @@
1.4 self.in_try_finally = False
1.5 self.in_try_except = False
1.6
1.7 - # Attribute access counting.
1.8 + # Attribute access and accessor counting.
1.9
1.10 self.attr_accesses = {}
1.11 + self.attr_accessors = {}
1.12
1.13 def __repr__(self):
1.14 return "TranslatedModule(%r, %r)" % (self.name, self.importer)
1.15 @@ -710,6 +711,34 @@
1.16 init_item(self.attr_accesses[path], access, lambda: 0)
1.17 self.attr_accesses[path][access] += 1
1.18
1.19 + def get_accessor_location(self, name):
1.20 +
1.21 + """
1.22 + Using the current namespace and the given 'name', return the accessor
1.23 + location.
1.24 + """
1.25 +
1.26 + path = self.get_path_for_access()
1.27 +
1.28 + # Get the location used by the deducer and optimiser and find any
1.29 + # recorded accessor.
1.30 +
1.31 + access_number = self.get_accessor_number(path, name)
1.32 + self.update_accessor_number(path, name)
1.33 + return (path, name, None, access_number)
1.34 +
1.35 + def get_accessor_number(self, path, name):
1.36 + if self.attr_accessors.has_key(path) and self.attr_accessors[path].has_key(name):
1.37 + return self.attr_accessors[path][name]
1.38 + else:
1.39 + return 0
1.40 +
1.41 + def update_accessor_number(self, path, name):
1.42 + if name:
1.43 + init_item(self.attr_accessors, path, dict)
1.44 + init_item(self.attr_accessors[path], name, lambda: 0)
1.45 + self.attr_accessors[path][name] += 1
1.46 +
1.47 def process_class_node(self, n):
1.48
1.49 "Process the given class node 'n'."
1.50 @@ -740,6 +769,34 @@
1.51 self.in_conditional = False
1.52 self.function_target = 0
1.53
1.54 + # Process any guards defined for the parameters.
1.55 +
1.56 + for name in self.importer.function_parameters.get(function_name):
1.57 +
1.58 + # Get the accessor details and any guards defined for it.
1.59 +
1.60 + location = self.get_accessor_location(name)
1.61 + test = self.deducer.accessor_guard_tests.get(location)
1.62 + if test:
1.63 + guard, guard_type = test
1.64 +
1.65 + if guard == "specific":
1.66 + ref = first(self.deducer.accessor_all_types[location])
1.67 + argstr = "&%s" % encode_path(ref.get_origin())
1.68 + elif guard == "common":
1.69 + ref = first(self.deducer.accessor_all_general_types[location])
1.70 + typeattr = encode_type_attribute(ref.get_origin())
1.71 + argstr = "%s, %s" % (encode_symbol("pos", typeattr), encode_symbol("code", typeattr))
1.72 + else:
1.73 + continue
1.74 +
1.75 + # Write a test that raises a TypeError upon failure.
1.76 +
1.77 + self.writestmt("if (!__test_%s_%s(%s->value, %s)) __raise_type_error();" % (
1.78 + guard, guard_type, name, argstr))
1.79 +
1.80 + # Produce the body and any additional return statement.
1.81 +
1.82 expr = self.process_structure_node(n.code) or PredefinedConstantRef("None")
1.83 if not isinstance(expr, ReturnRef):
1.84 self.writestmt("return %s;" % expr)