# HG changeset patch # User Paul Boddie # Date 1490391577 -3600 # Node ID 9c393bfc03d5830b99104f9a89b2d3d22174b332 # Parent 59957b395bb15a730a881dd21cdcad12a3c842f3# Parent 41eddb32a6037b5418cd64add2041d89a929a833 Merged changes from the integers-as-tagged-attrs branch. diff -r 59957b395bb1 -r 9c393bfc03d5 deducer.py --- a/deducer.py Sun Mar 19 00:56:43 2017 +0100 +++ b/deducer.py Fri Mar 24 22:39:37 2017 +0100 @@ -1730,51 +1730,17 @@ attrs = self.get_references_for_access(access_location) - # Where no specific attributes are defined, do not attempt - # to refine the alias's types. - - if not attrs: - return False - - # Invocations converting class accessors to instances do not - # change the nature of class providers. - - provider_attrs = self.convert_invocation_providers(attrs, invocation) - - (class_types, instance_types, module_types, function_types, - var_types) = separate_types(provider_attrs) - - # Where non-accessor types are found, do not attempt to refine - # the defined accessor types. - - if function_types or var_types: - return False - - class_types = set(provider_class_types).intersection(class_types) - instance_types = set(provider_instance_types).intersection(instance_types) - module_types = set(provider_module_types).intersection(module_types) - - new_provider_class_types.update(class_types) - new_provider_instance_types.update(instance_types) - new_provider_module_types.update(module_types) - - # Accessors are updated separately, employing invocation - # result details. - - accessor_attrs = self.convert_invocations(attrs, invocation) - - (class_types, instance_types, module_types, function_types, - var_types) = separate_types(accessor_attrs) - - class_types = set(accessor_class_types).intersection(class_types) - instance_types = set(accessor_instance_types).intersection(instance_types) - module_types = set(accessor_module_types).intersection(module_types) - - new_accessor_class_types.update(class_types) - new_accessor_instance_types.update(instance_types) - new_accessor_module_types.update(module_types) - - refs.update(accessor_attrs) + if attrs: + + # Invocations converting class accessors to instances do + # not change the nature of class providers. + + provider_attrs = self.convert_invocation_providers(attrs, invocation) + + # Accessors are updated separately, employing invocation + # result details. + + accessor_attrs = self.convert_invocations(attrs, invocation) # Alias references a name, not an access. @@ -1791,35 +1757,41 @@ provider_attrs = self.get_provider_references(access_location) attrs = accessor_attrs = self.get_accessor_references(access_location) - # Where no further information is found, do not attempt to - # refine the defined accessor types. - - if not attrs: - return False - - (class_types, instance_types, module_types, function_types, - var_types) = separate_types(provider_attrs) - - class_types = set(provider_class_types).intersection(class_types) - instance_types = set(provider_instance_types).intersection(instance_types) - module_types = set(provider_module_types).intersection(module_types) - - new_provider_class_types.update(class_types) - new_provider_instance_types.update(instance_types) - new_provider_module_types.update(module_types) - - (class_types, instance_types, module_types, function_types, - var_types) = separate_types(accessor_attrs) - - class_types = set(accessor_class_types).intersection(class_types) - instance_types = set(accessor_instance_types).intersection(instance_types) - module_types = set(accessor_module_types).intersection(module_types) - - new_accessor_class_types.update(class_types) - new_accessor_instance_types.update(instance_types) - new_accessor_module_types.update(module_types) - - refs.update(accessor_attrs) + # Where no specific attributes are defined, do not attempt + # to refine the alias's types. + + if not attrs: + return False + + (class_types, instance_types, module_types, function_types, + var_types) = separate_types(provider_attrs) + + # Where non-accessor types are found, do not attempt to refine + # the defined accessor types. + + if function_types or var_types: + return False + + class_types = set(provider_class_types).intersection(class_types) + instance_types = set(provider_instance_types).intersection(instance_types) + module_types = set(provider_module_types).intersection(module_types) + + new_provider_class_types.update(class_types) + new_provider_instance_types.update(instance_types) + new_provider_module_types.update(module_types) + + (class_types, instance_types, module_types, function_types, + var_types) = separate_types(accessor_attrs) + + class_types = set(accessor_class_types).intersection(class_types) + instance_types = set(accessor_instance_types).intersection(instance_types) + module_types = set(accessor_module_types).intersection(module_types) + + new_accessor_class_types.update(class_types) + new_accessor_instance_types.update(instance_types) + new_accessor_module_types.update(module_types) + + refs.update(accessor_attrs) # Update the alias relationships for invocations. @@ -1868,14 +1840,6 @@ attrs = self.get_references_for_access(access_location) - # Where no further information is found, do not attempt to - # refine the defined accessor types. - - if not attrs: - return False - - refs.update(self.convert_invocations(attrs, invocation)) - # Alias references a name, not an access. else: @@ -1891,13 +1855,13 @@ provider_attrs = self.get_provider_references(access_location) attrs = accessor_attrs = self.get_accessor_references(access_location) - # Where no further information is found, do not attempt to - # refine the defined accessor types. - - if not attrs: - return False - - refs.update(self.convert_invocations(attrs, invocation)) + # Where no further information is found, do not attempt to + # refine the defined accessor types. + + if not attrs: + return False + + refs.update(self.convert_invocations(attrs, invocation)) # Update the alias relationships for invocations. @@ -2946,6 +2910,11 @@ if context_var: emit(("", context_var)) + # Produce an advisory instruction regarding the final attribute. + + if origin: + emit(("", origin)) + self.access_instructions[access_location] = instructions self.accessor_kinds[access_location] = accessor_kinds diff -r 59957b395bb1 -r 9c393bfc03d5 encoders.py --- a/encoders.py Sun Mar 19 00:56:43 2017 +0100 +++ b/encoders.py Fri Mar 24 22:39:37 2017 +0100 @@ -237,9 +237,13 @@ "", "", ) -reference_acting_ops = attribute_ops + checked_ops + typename_ops +reference_acting_ops = attribute_ops + checked_ops + type_ops + typename_ops attribute_producing_ops = attribute_loading_ops + checked_loading_ops +attribute_producing_variables = ( + "", "", "", "", "" + ) + def encode_access_instruction(instruction, subs, context_index): """ @@ -340,13 +344,7 @@ if isinstance(arg, tuple): encoded, substituted = encode_access_instruction(arg, subs, context_index) - - # Convert attribute results to references where required. - - if op and op in reference_acting_ops and arg[0] in attribute_producing_ops: - return "%s.value" % encoded, substituted - else: - return encoded, substituted + return attribute_to_reference(op, arg[0], encoded, substituted) # Special values only need replacing, not encoding. @@ -355,13 +353,18 @@ # Handle values modified by storage details. if arg in context_values: - return "%s(%s)" % (subs.get(arg), context_index), set([arg]) + encoded = "%s(%s)" % (subs.get(arg), context_index) else: - return subs.get(arg), set([arg]) + encoded = subs.get(arg) + + substituted = set([arg]) + return attribute_to_reference(op, arg, encoded, substituted) # Convert static references to the appropriate type. - elif op and op in reference_acting_ops and arg != "": + elif op and op in reference_acting_ops and \ + arg not in attribute_producing_variables: + return "&%s" % encode_path(arg), set() # Other values may need encoding. @@ -369,6 +372,18 @@ else: return encode_path(arg), set() +def attribute_to_reference(op, arg, encoded, substituted): + + # Convert attribute results to references where required. + + if op and op in reference_acting_ops and ( + arg in attribute_producing_ops or + arg in attribute_producing_variables): + + return "__VALUE(%s)" % encoded, substituted + else: + return encoded, substituted + def encode_function_pointer(path): "Encode 'path' as a reference to an output program function." diff -r 59957b395bb1 -r 9c393bfc03d5 generator.py --- a/generator.py Sun Mar 19 00:56:43 2017 +0100 +++ b/generator.py Fri Mar 24 22:39:37 2017 +0100 @@ -43,6 +43,7 @@ # NOTE: These must be synchronised with the library. function_type = "__builtins__.core.function" + int_type = "__builtins__.int.int" none_type = "__builtins__.none.NoneType" string_type = "__builtins__.str.string" type_type = "__builtins__.core.type" @@ -373,6 +374,11 @@ for constant, n in self.optimiser.constants.items(): self.make_literal_constant(f_decls, f_defs, n, constant) + # Generate a common integer instance object, referenced when integer + # attributes are accessed. + + self.make_common_integer(f_decls, f_defs) + # Finish the main source file. self.write_main_program(f_code, f_signatures) @@ -560,6 +566,11 @@ value, value_type, encoding = constant + # Do not generate individual integer constants. + + if value_type == self.int_type: + return + const_path = encode_literal_constant(n) structure_name = encode_literal_reference(n) @@ -582,13 +593,23 @@ self.make_constant(f_decls, f_defs, ref, attr_path, structure_name) + def make_common_integer(self, f_decls, f_defs): + + """ + Write common integer instance details to 'f_decls' (to declare a + structure) and to 'f_defs' (to define the contents). + """ + + ref = Reference("", self.int_type) + self.make_constant(f_decls, f_defs, ref, "__common_integer", "__common_integer_obj") + def make_constant(self, f_decls, f_defs, ref, const_path, structure_name, data=None, encoding=None): """ Write constant details to 'f_decls' (to declare a structure) and to 'f_defs' (to define the contents) for the constant described by 'ref' - having the given 'path' and 'structure_name' (for the constant structure - itself). + having the given 'const_path' (providing an attribute for the constant) + and 'structure_name' (for the constant structure itself). The additional 'data' and 'encoding' are used to describe specific values. @@ -1030,7 +1051,7 @@ # Special internal size member. elif attrname == "__size__": - structure.append("{.intvalue=%d}" % attr) + structure.append("__INTVALUE(%d)" % attr) continue # Special internal key member. @@ -1137,6 +1158,13 @@ # Obtain a constant value directly assigned to the attribute. if self.optimiser.constant_numbers.has_key(alias): + + # Encode integer constants differently. + + value, value_type, encoding = self.importer.all_constant_values[alias] + if value_type == self.int_type: + return "__INTVALUE(%s) /* %s */" % (value, name) + constant_number = self.optimiser.constant_numbers[alias] constant_value = encode_literal_constant(constant_number) return "%s /* %s */" % (constant_value, name) @@ -1264,13 +1292,11 @@ __Catch(__tmp_exc) { if (__ISINSTANCE(__tmp_exc.arg, __ATTRVALUE(&__builtins___exception_system_SystemExit))) - return __load_via_object( - __load_via_object(__tmp_exc.arg.value, __data__).value, - value).intvalue; + return __TOINT(__load_via_object(__VALUE(__tmp_exc.arg), value)); fprintf(stderr, "Program terminated due to exception: %%s.\\n", __load_via_object( - %s(__NULL, __tmp_exc.arg).value, + __VALUE(%s(__NULL, __tmp_exc.arg)), __data__).strvalue); return 1; } diff -r 59957b395bb1 -r 9c393bfc03d5 lib/__builtins__/character.py --- a/lib/__builtins__/character.py Sun Mar 19 00:56:43 2017 +0100 +++ b/lib/__builtins__/character.py Fri Mar 24 22:39:37 2017 +0100 @@ -29,7 +29,7 @@ check_int(i) if 0 <= i <= 255: - return str_chr(i.__data__) + return str_chr(i) else: raise ValueError, i @@ -94,7 +94,7 @@ check_int(i) if 0 <= i <= 2097151: - return utf8string(unicode_unichr(i.__data__)) + return utf8string(unicode_unichr(i)) else: raise ValueError, i diff -r 59957b395bb1 -r 9c393bfc03d5 lib/__builtins__/int.py --- a/lib/__builtins__/int.py Sun Mar 19 00:56:43 2017 +0100 +++ b/lib/__builtins__/int.py Fri Mar 24 22:39:37 2017 +0100 @@ -3,7 +3,7 @@ """ Integer objects. -Copyright (C) 2015, 2016 Paul Boddie +Copyright (C) 2015, 2016, 2017 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -34,11 +34,9 @@ "Initialise the integer with the given 'number_or_string'." - if _isinstance(number_or_string, int): - self.__data__ = number_or_string.__data__ - else: - # NOTE: To be implemented. - self.__data__ = None + # NOTE: To be implemented. + + pass def __hash__(self): @@ -51,7 +49,7 @@ "Perform 'op' on this int and 'other' if appropriate." if _isinstance(other, int): - return op(self.__data__, other.__data__) + return op(self, other) else: return NotImplemented @@ -60,7 +58,7 @@ "Perform 'op' on 'other' and this int if appropriate." if _isinstance(other, int): - return op(other.__data__, self.__data__) + return op(other, self) else: return NotImplemented @@ -122,7 +120,7 @@ "Return the inversion of this int." - return int_not(self.__data__) + return int_not(self) __add__ = __radd__ = __iadd__ __sub__ = __isub__ @@ -206,7 +204,7 @@ "Apply the unary negation operator." - return int_neg(self.__data__) + return int_neg(self) def __pos__(self): @@ -218,7 +216,7 @@ "Return a string representation." - return utf8string(int_str(self.__data__)) + return utf8string(int_str(self)) __repr__ = __str__ @@ -233,8 +231,7 @@ "Return whether this int is non-zero." - zero = 0 - return int_ne(self.__data__, zero.__data__) + return int_ne(self, 0) # Limits. diff -r 59957b395bb1 -r 9c393bfc03d5 lib/__builtins__/str.py --- a/lib/__builtins__/str.py Sun Mar 19 00:56:43 2017 +0100 +++ b/lib/__builtins__/str.py Fri Mar 24 22:39:37 2017 +0100 @@ -22,7 +22,7 @@ from __builtins__.operator import _negate from __builtins__.sequence import hashable, itemaccess from __builtins__.types import check_int -from native import int_new, str_add, str_lt, str_gt, str_eq, str_ord, \ +from native import str_add, str_lt, str_gt, str_eq, str_ord, \ str_substr WHITESPACE = (" ", "\f", "\n", "\r", "\t") @@ -53,7 +53,7 @@ else: self.__data__ = None self.__key__ = None - self.__size__ = None + self.__size__ = 0 # Internal methods. @@ -157,7 +157,7 @@ "Return the number of bytes in this string." - return int_new(self.__size__) + return self.__size__ # General type methods. @@ -165,7 +165,7 @@ "Return whether the string provides any data." - return int_new(self.__size__).__bool__() + return self.__size__.__bool__() def __contains__(self, value): diff -r 59957b395bb1 -r 9c393bfc03d5 lib/native/__init__.py --- a/lib/native/__init__.py Sun Mar 19 00:56:43 2017 +0100 +++ b/lib/native/__init__.py Fri Mar 24 22:39:37 2017 +0100 @@ -23,8 +23,7 @@ from native.identity import is_, is_not -from native.int import int_new, \ - int_add, int_div, int_mod, int_mul, int_neg, int_pow, \ +from native.int import int_add, int_div, int_mod, int_mul, int_neg, int_pow, \ int_sub, int_and, int_not, int_or, int_xor, int_lt, \ int_gt, int_eq, int_ne, int_str diff -r 59957b395bb1 -r 9c393bfc03d5 lib/native/int.py --- a/lib/native/int.py Sun Mar 19 00:56:43 2017 +0100 +++ b/lib/native/int.py Fri Mar 24 22:39:37 2017 +0100 @@ -24,8 +24,6 @@ this program. If not, see . """ -def int_new(data): pass - def int_add(self, other): pass def int_div(self, other): pass def int_mod(self, other): pass diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/buffer.c --- a/templates/native/buffer.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/buffer.c Fri Mar 24 22:39:37 2017 +0100 @@ -36,7 +36,7 @@ /* Calculate the size of the string. */ for (i = 0; i < data->size; i++) - size += __load_via_object(data->attrs[i].value, __size__).intvalue; + size += __TOINT(__load_via_object(__VALUE(data->attrs[i]), __size__)); /* Reserve space for a new string. */ s = (char *) __ALLOCATE(size + 1, sizeof(char)); @@ -44,8 +44,8 @@ /* Build a single string from the buffer contents. */ for (i = 0, j = 0; i < data->size; i++) { - o = __load_via_object(data->attrs[i].value, __data__); - n = __load_via_object(data->attrs[i].value, __size__).intvalue; + o = __load_via_object(__VALUE(data->attrs[i]), __data__); + n = __TOINT(__load_via_object(__VALUE(data->attrs[i]), __size__)); memcpy(s + j, o.strvalue, n); /* does not null terminate but final byte should be zero */ j += n; } diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/common.c --- a/templates/native/common.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/common.c Fri Mar 24 22:39:37 2017 +0100 @@ -26,20 +26,12 @@ /* Utility functions. */ -__attr __new_int(int i) -{ - /* Create a new integer and mutate the __data__ attribute. */ - __attr attr = __NEWINSTANCE(__builtins___int_int); - attr.value->attrs[__ATTRPOS(__data__)].intvalue = i; - return attr; -} - __attr __new_str(char *s, int size) { /* Create a new string and mutate the __data__, __size__ and __key__ attributes. */ __attr attr = __NEWINSTANCE(__builtins___str_string); attr.value->attrs[__ATTRPOS(__data__)].strvalue = s; - attr.value->attrs[__ATTRPOS(__size__)].intvalue = size; + attr.value->attrs[__ATTRPOS(__size__)] = __INTVALUE(size); attr.value->attrs[__ATTRPOS(__key__)] = __NULL; return attr; } diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/common.h --- a/templates/native/common.h Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/common.h Fri Mar 24 22:39:37 2017 +0100 @@ -23,7 +23,7 @@ /* Utility functions. */ -__attr __new_int(int i); +#define __new_int(VALUE) __INTVALUE(VALUE) __attr __new_str(char *s, int size); __attr __new_list(__fragment *f); __fragment *__fragment_append(__fragment *data, __attr value); diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/iconv.c --- a/templates/native/iconv.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/iconv.c Fri Mar 24 22:39:37 2017 +0100 @@ -51,13 +51,13 @@ /* cd interpreted as iconv_t */ iconv_t c = (iconv_t) cd.datavalue; /* state.__data__ interpreted as list */ - __fragment *f = __load_via_object(state.value, __data__).seqvalue; + __fragment *f = __load_via_object(__VALUE(state), __data__).seqvalue; /* Obtain the string, start position, and remaining bytes from the state. */ - char *inbuf = __load_via_object(f->attrs[0].value, __data__).strvalue; - int start = __load_via_object(f->attrs[1].value, __data__).intvalue; - int remaining = __load_via_object(f->attrs[2].value, __data__).intvalue; + char *inbuf = __load_via_object(__VALUE(f->attrs[0]), __data__).strvalue; + int start = __TOINT(f->attrs[1]); + int remaining = __TOINT(f->attrs[2]); /* Allocate a string for the output buffer using the remaining input size as a guide. */ @@ -133,9 +133,9 @@ __attr __fn_native_iconv_iconv_open(__attr __self, __attr tocode, __attr fromcode) { /* tocode.__data__ interpreted as string */ - char *t = __load_via_object(tocode.value, __data__).strvalue; + char *t = __load_via_object(__VALUE(tocode), __data__).strvalue; /* fromcode.__data__ interpreted as string */ - char *f = __load_via_object(fromcode.value, __data__).strvalue; + char *f = __load_via_object(__VALUE(fromcode), __data__).strvalue; iconv_t result; __attr attr; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/identity.c --- a/templates/native/identity.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/identity.c Fri Mar 24 22:39:37 2017 +0100 @@ -28,11 +28,15 @@ __attr __fn_native_identity_is_(__attr __self, __attr x, __attr y) { + /* NOTE: value member assumed equivalent to intvalue for comparison. */ + return x.value == y.value ? __builtins___boolean_True : __builtins___boolean_False; } __attr __fn_native_identity_is_not(__attr __self, __attr x, __attr y) { + /* NOTE: value member assumed equivalent to intvalue for comparison. */ + return x.value != y.value ? __builtins___boolean_True : __builtins___boolean_False; } diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/int.c --- a/templates/native/int.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/int.c Fri Mar 24 22:39:37 2017 +0100 @@ -16,7 +16,6 @@ this program. If not, see . */ -#include /* INT_MAX, INT_MIN */ #include /* ceil, log10, pow */ #include /* fdopen, snprintf */ #include /* errno */ @@ -32,20 +31,15 @@ /* Integer operations. */ -__attr __fn_native_int_int_new(__attr __self, __attr _data) +__attr __fn_native_int_int_add(__attr __self, __attr self, __attr other) { - return __new_int(_data.intvalue); -} - -__attr __fn_native_int_int_add(__attr __self, __attr _data, __attr other) -{ - /* _data and other interpreted as int.__data__ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Test for overflow. */ - if (((i > 0) && (j > 0) && (i > INT_MAX - j)) || - ((i < 0) && (j < 0) && (i < INT_MIN - j))) + if (((i > 0) && (j > 0) && (i > __MAXINT - j)) || + ((i < 0) && (j < 0) && (i < __MININT - j))) __raise_overflow_error(); @@ -53,15 +47,15 @@ return __new_int(i + j); } -__attr __fn_native_int_int_sub(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_sub(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data__ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Test for overflow. */ - if (((i < 0) && (j > 0) && (i < INT_MIN + j)) || - ((i > 0) && (j < 0) && (i > INT_MAX + j))) + if (((i < 0) && (j > 0) && (i < __MININT + j)) || + ((i > 0) && (j < 0) && (i > __MAXINT + j))) __raise_overflow_error(); @@ -69,17 +63,17 @@ return __new_int(i - j); } -__attr __fn_native_int_int_mul(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_mul(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data__ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Test for overflow. */ - if (((i > 0) && (j > 0) && (i > INT_MAX / j)) || - ((i < 0) && (j < 0) && (i > INT_MAX / j)) || - ((i < 0) && (j > 0) && (i < INT_MIN / j)) || - ((i > 0) && (j < 0) && (j < INT_MIN / i))) + if (((i > 0) && (j > 0) && (i > __MAXINT / j)) || + ((i < 0) && (j < 0) && (i > __MAXINT / j)) || + ((i < 0) && (j > 0) && (i < __MININT / j)) || + ((i > 0) && (j < 0) && (j < __MININT / i))) __raise_overflow_error(); @@ -87,56 +81,56 @@ return __new_int(i * j); } -__attr __fn_native_int_int_div(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_div(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data__ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Test for division by zero or overflow. */ if (j == 0) __raise_zero_division_error(); - else if ((j == -1) && (i == INT_MIN)) + else if ((j == -1) && (i == __MININT)) __raise_overflow_error(); /* Return the new integer. */ return __new_int(i / j); } -__attr __fn_native_int_int_mod(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_mod(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Test for division by zero or overflow. */ if (j == 0) __raise_zero_division_error(); - else if ((j == -1) && (i == INT_MIN)) + else if ((j == -1) && (i == __MININT)) __raise_overflow_error(); /* Return the new integer. */ return __new_int(i % j); } -__attr __fn_native_int_int_neg(__attr __self, __attr _data) +__attr __fn_native_int_int_neg(__attr __self, __attr self) { - /* _data interpreted as int.__data_ */ - int i = _data.intvalue; + /* self interpreted as int */ + int i = __TOINT(self); /* Test for overflow. */ - if (i == INT_MIN) + if (i == __MININT) __raise_overflow_error(); /* Return the new integer. */ return __new_int(-i); } -__attr __fn_native_int_int_pow(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_pow(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); int k; errno = 0; @@ -151,95 +145,96 @@ return __new_int(k); } -__attr __fn_native_int_int_and(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_and(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ return __new_int(i & j); } -__attr __fn_native_int_int_not(__attr __self, __attr _data) +__attr __fn_native_int_int_not(__attr __self, __attr self) { - /* _data interpreted as int.__data_ */ - int i = _data.intvalue; + /* self interpreted as int */ + int i = __TOINT(self); /* Return the new integer. */ return __new_int(~i); } -__attr __fn_native_int_int_or(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_or(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ return __new_int(i | j); } -__attr __fn_native_int_int_xor(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_xor(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ return __new_int(i ^ j); } -__attr __fn_native_int_int_lt(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_lt(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return a boolean result. */ return i < j ? __builtins___boolean_True : __builtins___boolean_False; } -__attr __fn_native_int_int_gt(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_gt(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return a boolean result. */ return i > j ? __builtins___boolean_True : __builtins___boolean_False; } -__attr __fn_native_int_int_eq(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_eq(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return a boolean result. */ return i == j ? __builtins___boolean_True : __builtins___boolean_False; } -__attr __fn_native_int_int_ne(__attr __self, __attr _data, __attr other) +__attr __fn_native_int_int_ne(__attr __self, __attr self, __attr other) { - /* _data and other interpreted as int.__data_ */ - int i = _data.intvalue; - int j = other.intvalue; + /* self and other interpreted as int */ + int i = __TOINT(self); + int j = __TOINT(other); /* Return a boolean result. */ return i != j ? __builtins___boolean_True : __builtins___boolean_False; } -__attr __fn_native_int_int_str(__attr __self, __attr _data) +__attr __fn_native_int_int_str(__attr __self, __attr self) { - /* _data interpreted as int.__data_ */ - int i = _data.intvalue; + /* self interpreted as int */ + int i = __TOINT(self); + /* Employ a buffer big enough to fit the largest integer plus an extra character, a minus sign, and the null terminator. */ - unsigned int n = (int) log10(INT_MAX) + 3; + unsigned int n = (int) log10(__MAXINT) + 3; char *s = (char *) __ALLOCATE(n, sizeof(char)); snprintf(s, n, "%d", i); diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/int.h --- a/templates/native/int.h Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/int.h Fri Mar 24 22:39:37 2017 +0100 @@ -23,8 +23,6 @@ /* Integer operations. */ -__attr __fn_native_int_int_new(__attr __self, __attr _data); - __attr __fn_native_int_int_add(__attr __self, __attr _data, __attr other); __attr __fn_native_int_int_sub(__attr __self, __attr _data, __attr other); __attr __fn_native_int_int_mul(__attr __self, __attr _data, __attr other); diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/introspection.c --- a/templates/native/introspection.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/introspection.c Fri Mar 24 22:39:37 2017 +0100 @@ -29,7 +29,7 @@ __attr __fn_native_introspection_object_getattr(__attr __self, __attr obj, __attr name, __attr _default) { /* name interpreted as string */ - __attr key = __load_via_object(name.value, __key__); + __attr key = __load_via_object(__VALUE(name), __key__); __attr out; if ((key.code == 0) && (key.pos == 0)) @@ -37,18 +37,18 @@ /* Attempt to get the attribute from the object. */ - out = __check_and_load_via_object_null(obj.value, key.pos, key.code); - if (out.value == 0) + out = __check_and_load_via_object_null(__VALUE(obj), key.pos, key.code); + if (__ISNULL(out)) { /* Inspect the object's class if this failed. */ - out = __check_and_load_via_class__(obj.value, key.pos, key.code); - if (out.value == 0) + out = __check_and_load_via_class__(__VALUE(obj), key.pos, key.code); + if (__ISNULL(out)) return _default; /* Update the context to the object if it is a method. */ - return __update_context(obj.value, out); + return __update_context(obj, out); } return out; @@ -57,7 +57,7 @@ __attr __fn_native_introspection_isinstance(__attr __self, __attr obj, __attr cls) { /* cls must be a class. */ - if (__is_instance_subclass(obj.value, cls)) + if (__is_instance_subclass(__VALUE(obj), cls)) return __builtins___boolean_True; else return __builtins___boolean_False; @@ -66,7 +66,7 @@ __attr __fn_native_introspection_issubclass(__attr __self, __attr obj, __attr cls) { /* obj and cls must be classes. */ - if (__is_subclass(obj.value, cls)) + if (__is_subclass(__VALUE(obj), cls)) return __builtins___boolean_True; else return __builtins___boolean_False; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/io.c --- a/templates/native/io.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/io.c Fri Mar 24 22:39:37 2017 +0100 @@ -57,10 +57,10 @@ __attr __fn_native_io_fopen(__attr __self, __attr filename, __attr mode) { - /* filename interpreted as string */ - char *fn = __load_via_object(filename.value, __data__).strvalue; - /* mode interpreted as string */ - char *s = __load_via_object(mode.value, __data__).strvalue; + /* filename.__data__ interpreted as string */ + char *fn = __load_via_object(__VALUE(filename), __data__).strvalue; + /* mode.__data__ interpreted as string */ + char *s = __load_via_object(__VALUE(mode), __data__).strvalue; FILE *f; __attr attr; @@ -88,9 +88,9 @@ __attr __fn_native_io_fdopen(__attr __self, __attr fd, __attr mode) { /* fd interpreted as int */ - int i = __load_via_object(fd.value, __data__).intvalue; - /* mode interpreted as string */ - char *s = __load_via_object(mode.value, __data__).strvalue; + int i = __TOINT(fd); + /* mode.__data__ interpreted as string */ + char *s = __load_via_object(__VALUE(mode), __data__).strvalue; FILE *f; __attr attr; @@ -120,7 +120,7 @@ /* fp interpreted as FILE reference */ FILE *f = (FILE *) fp.datavalue; /* size interpreted as int */ - int to_read = __load_via_object(size.value, __data__).intvalue; + int to_read = __TOINT(size); char buf[to_read]; size_t have_read; int error; @@ -147,9 +147,10 @@ { /* fp interpreted as FILE reference */ FILE *f = (FILE *) fp.datavalue; - /* str interpreted as string */ - char *s = __load_via_object(str.value, __data__).strvalue; - int to_write = __load_via_object(str.value, __size__).intvalue; + /* str.__data__ interpreted as string */ + char *s = __load_via_object(__VALUE(str), __data__).strvalue; + /* str.__size__ interpreted as int */ + int to_write = __TOINT(__load_via_object(__VALUE(str), __size__)); size_t have_written = fwrite(s, sizeof(char), to_write, f); int error; @@ -167,7 +168,7 @@ __attr __fn_native_io_close(__attr __self, __attr fd) { /* fd interpreted as int */ - int i = __load_via_object(fd.value, __data__).intvalue; + int i = __TOINT(fd); errno = 0; if (close(i) == -1) @@ -179,9 +180,9 @@ __attr __fn_native_io_read(__attr __self, __attr fd, __attr n) { /* fd interpreted as int */ - int i = __load_via_object(fd.value, __data__).intvalue; + int i = __TOINT(fd); /* n interpreted as int */ - int to_read = __load_via_object(n.value, __data__).intvalue; + int to_read = __TOINT(n); char buf[to_read]; ssize_t have_read; char *s; @@ -202,10 +203,11 @@ __attr __fn_native_io_write(__attr __self, __attr fd, __attr str) { /* fd interpreted as int */ - int i = __load_via_object(fd.value, __data__).intvalue; - /* str interpreted as string */ - char *s = __load_via_object(str.value, __data__).strvalue; - int size = __load_via_object(str.value, __size__).intvalue; + int i = __TOINT(fd); + /* str.__data__ interpreted as string */ + char *s = __load_via_object(__VALUE(str), __data__).strvalue; + /* str.__size__ interpreted as int */ + int size = __TOINT(__load_via_object(__VALUE(str), __size__)); ssize_t have_written; errno = 0; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/limits.c --- a/templates/native/limits.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/limits.c Fri Mar 24 22:39:37 2017 +0100 @@ -16,7 +16,6 @@ this program. If not, see . */ -#include /* INT_MAX, INT_MIN */ #include "native/common.h" #include "types.h" #include "exceptions.h" @@ -30,12 +29,12 @@ __attr __fn_native_limits_get_maxint(__attr __self) { - return __new_int(INT_MAX); + return __new_int(__MAXINT); } __attr __fn_native_limits_get_minint(__attr __self) { - return __new_int(INT_MIN); + return __new_int(__MININT); } /* Module initialisation. */ diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/list.c --- a/templates/native/list.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/list.c Fri Mar 24 22:39:37 2017 +0100 @@ -30,7 +30,7 @@ __attr __fn_native_list_list_init(__attr __self, __attr size) { /* size interpreted as int */ - unsigned int n = __load_via_object(size.value, __data__).intvalue; + unsigned int n = __TOINT(size); __attr attr = {.seqvalue=__new_fragment(n)}; /* Return the __data__ attribute. */ @@ -42,7 +42,7 @@ /* _data interpreted as list.__data__ */ __fragment *data = _data.seqvalue; /* size interpreted as int */ - unsigned int n = __load_via_object(size.value, __data__).intvalue; + unsigned int n = __TOINT(size); data->size = n; return __builtins___none_None; @@ -50,20 +50,20 @@ __attr __fn_native_list_list_append(__attr __self, __attr self, __attr value) { - /* self interpreted as list */ - __fragment *data = __load_via_object(self.value, __data__).seqvalue; + /* self.__data__ interpreted as list */ + __fragment *data = __load_via_object(__VALUE(self), __data__).seqvalue; __fragment *newdata = __fragment_append(data, value); /* Replace the __data__ attribute if appropriate. */ if (newdata != data) - __store_via_object(self.value, __data__, ((__attr) {.seqvalue=newdata})); + __store_via_object(__VALUE(self), __data__, ((__attr) {.seqvalue=newdata})); return __builtins___none_None; } __attr __fn_native_list_list_concat(__attr __self, __attr self, __attr other) { /* self, interpreted as list, other interpreted as list.__data__ */ - __fragment *data = __load_via_object(self.value, __data__).seqvalue; + __fragment *data = __load_via_object(__VALUE(self), __data__).seqvalue; __fragment *other_data = other.seqvalue; __fragment *newdata = data; unsigned int size = data->size, capacity = data->capacity; @@ -84,7 +84,7 @@ /* Replace the __data__ attribute if appropriate. */ if (newdata != data) - __store_via_object(self.value, __data__, ((__attr) {.seqvalue=newdata})); + __store_via_object(__VALUE(self), __data__, ((__attr) {.seqvalue=newdata})); return __builtins___none_None; } @@ -107,7 +107,7 @@ /* _data interpreted as list.__data__ */ __attr *elements = _data.seqvalue->attrs; /* index interpreted as int */ - int i = __load_via_object(index.value, __data__).intvalue; + int i = __TOINT(index); return elements[i]; } @@ -117,7 +117,7 @@ /* _data interpreted as list.__data__ */ __attr *elements = _data.seqvalue->attrs; /* index interpreted as int */ - int i = __load_via_object(index.value, __data__).intvalue; + int i = __TOINT(index); /* Set the element. */ elements[i] = value; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/locale.c --- a/templates/native/locale.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/locale.c Fri Mar 24 22:39:37 2017 +0100 @@ -32,7 +32,7 @@ __attr __fn_native_locale_getlocale(__attr __self, __attr category) { /* category interpreted as int */ - int cat = __load_via_object(category.value, __data__).intvalue; + int cat = __TOINT(category); char *result, *out; size_t length; @@ -51,9 +51,9 @@ __attr __fn_native_locale_setlocale(__attr __self, __attr category, __attr value) { /* category interpreted as int */ - int cat = __load_via_object(category.value, __data__).intvalue; + int cat = __TOINT(category); /* value interpreted as string */ - char *s = __load_via_object(value.value, __data__).strvalue; + char *s = __load_via_object(__VALUE(value), __data__).strvalue; char *result, *out; size_t length; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/program.c --- a/templates/native/program.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/program.c Fri Mar 24 22:39:37 2017 +0100 @@ -28,7 +28,7 @@ __attr __fn_native_program_get_using(__attr __self, __attr callable, __attr instance) { - return __test_context(instance.value, callable); + return __test_context(instance, callable); } /* Module initialisation. */ diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/str.c --- a/templates/native/str.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/str.c Fri Mar 24 22:39:37 2017 +0100 @@ -33,8 +33,8 @@ /* _data, other interpreted as string.__data__ */ char *s = _data.strvalue; char *o = other.strvalue; - /* _size, othersize interpreted as int.__data__ */ - int ss = _size.intvalue, os = othersize.intvalue; + /* _size, othersize interpreted as int */ + int ss = __TOINT(_size), os = __TOINT(othersize); int n = ss + os; char *r = (char *) __ALLOCATE(n + 1, sizeof(char)); @@ -47,8 +47,8 @@ __attr __fn_native_str_str_chr(__attr __self, __attr _data) { - /* _data interpreted as int.__data__ */ - int n = _data.intvalue; + /* data interpreted as int */ + int n = __TOINT(_data); char *s = (char *) __ALLOCATE(2, sizeof(char)); s[0] = (char) n; @@ -98,11 +98,11 @@ /* _data interpreted as string.__data__ */ char *s = _data.strvalue, *sub; /* start interpreted as int */ - int istart = __load_via_object(start.value, __data__).intvalue; + int istart = __TOINT(start); /* end interpreted as int */ - int iend = __load_via_object(end.value, __data__).intvalue; + int iend = __TOINT(end); /* step interpreted as int */ - int istep = __load_via_object(step.value, __data__).intvalue; + int istep = __TOINT(step); /* Calculate the size of the substring. */ size_t resultsize = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/system.c --- a/templates/native/system.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/system.c Fri Mar 24 22:39:37 2017 +0100 @@ -29,7 +29,7 @@ __attr __fn_native_system_exit(__attr __self, __attr status) { - exit(__load_via_object(status.value, __data__).intvalue); + exit(__VALUE(status)); return __builtins___none_None; } diff -r 59957b395bb1 -r 9c393bfc03d5 templates/native/unicode.c --- a/templates/native/unicode.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/native/unicode.c Fri Mar 24 22:39:37 2017 +0100 @@ -73,8 +73,8 @@ { /* _data interpreted as string.__data__ */ char *s = _data.strvalue; - /* _size interpreted as int.__data__ */ - int size = _size.intvalue; + /* _size interpreted as int */ + int size = __TOINT(_size); unsigned int i, c = 0; for (i = 0; i < size; i++) @@ -89,8 +89,8 @@ { /* _data interpreted as string.__data__ */ char *s = _data.strvalue; - /* _size interpreted as int.__data__ */ - int size = _size.intvalue; + /* _size interpreted as int */ + int size = __TOINT(_size); unsigned int i, c = 0, v; for (i = 0; i < size; i++) @@ -123,14 +123,14 @@ { /* _data interpreted as string.__data__ */ char *s = _data.strvalue, *sub; - /* _size interpreted as int.__data__ */ - int ss = _size.intvalue; + /* _size interpreted as int */ + int ss = __TOINT(_size); /* start interpreted as int */ - int istart = __load_via_object(start.value, __data__).intvalue; + int istart = __TOINT(start); /* end interpreted as int */ - int iend = __load_via_object(end.value, __data__).intvalue; + int iend = __TOINT(end); /* step interpreted as int */ - int istep = __load_via_object(step.value, __data__).intvalue; + int istep = __TOINT(step); /* Calculate the number of characters. */ size_t nchar = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; @@ -195,8 +195,8 @@ __attr __fn_native_unicode_unicode_unichr(__attr __self, __attr value) { - /* value interpreted as int.__data__ */ - int i = value.intvalue; + /* value interpreted as int */ + int i = __TOINT(value); unsigned int resultsize; char *s; diff -r 59957b395bb1 -r 9c393bfc03d5 templates/ops.c --- a/templates/ops.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/ops.c Fri Mar 24 22:39:37 2017 +0100 @@ -23,6 +23,16 @@ #include "progconsts.h" #include "progtypes.h" +/* Get object reference from attribute. */ + +__ref __VALUE(__attr attr) +{ + if (!__INTEGER(attr)) + return attr.value; + else + return &__common_integer_obj; +} + /* Basic structure tests. */ static inline int __HASATTR(__ref obj, int pos, int code) @@ -37,12 +47,12 @@ return __ATTRVALUE(obj); } -__attr __load_static_replace(__ref context, __ref obj) +__attr __load_static_replace(__attr context, __ref obj) { return __update_context(context, __ATTRVALUE(obj)); } -__attr __load_static_test(__ref context, __ref obj) +__attr __load_static_test(__attr context, __ref obj) { return __test_context(context, __ATTRVALUE(obj)); } @@ -92,12 +102,12 @@ int __is_subclass(__ref obj, __attr cls) { - return __HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)); + return __HASATTR(obj, __TYPEPOS(__VALUE(cls)), __TYPECODE(__VALUE(cls))); } int __is_instance_subclass(__ref obj, __attr cls) { - return __is_instance(obj) && __HASATTR(__get_class(obj), __TYPEPOS(cls.value), __TYPECODE(cls.value)); + return __is_instance(obj) && __HASATTR(__get_class(obj), __TYPEPOS(__VALUE(cls)), __TYPECODE(__VALUE(cls))); } int __is_type_instance(__ref obj) @@ -107,7 +117,7 @@ __ref __get_class(__ref obj) { - return __load_via_object(obj, __class__).value; + return __VALUE(__load_via_object(obj, __class__)); } __attr __get_class_attr(__ref obj) @@ -174,7 +184,7 @@ __attr __check_and_load_via_any__(__ref obj, int pos, int code) { __attr out = __check_and_load_via_object_null(obj, pos, code); - if (out.value == 0) + if (__ISNULL(out)) out = __check_and_load_via_class__(obj, pos, code); return out; } @@ -216,27 +226,28 @@ /* Context-related operations. */ -int __test_context_update(__ref context, __attr attr) +int __test_context_update(__attr context, __attr attr) { /* Return whether the context should be updated for the attribute. */ - __ref attrcontext = __CONTEXT_AS_VALUE(attr).value; + __attr attrcontext = __CONTEXT_AS_VALUE(attr); + __ref attrcontextvalue = __VALUE(attrcontext); /* Preserve any existing null or instance context. */ - if ((attrcontext == 0) || __is_instance(attrcontext)) + if (__ISNULL(attrcontext) || __is_instance(attrcontextvalue)) return 0; /* Test any instance context against the context employed by the attribute. */ - if (__is_instance(context)) + if (__is_instance(__VALUE(context))) { /* Obtain the special class attribute position and code identifying the attribute context's class, inspecting the context instance for compatibility. */ - if (__test_common_instance__(context, __TYPEPOS(attrcontext), __TYPECODE(attrcontext))) + if (__test_common_instance__(__VALUE(context), __TYPEPOS(attrcontextvalue), __TYPECODE(attrcontextvalue))) return 1; else __raise_type_error(); @@ -244,7 +255,7 @@ /* Test for access to a type class attribute using a type instance. */ - if (__test_specific_type(attrcontext, &__TYPE_CLASS_TYPE) && __is_type_instance(context)) + if (__test_specific_type(attrcontextvalue, &__TYPE_CLASS_TYPE) && __is_type_instance(__VALUE(context))) return 1; /* Otherwise, preserve the attribute as retrieved. */ @@ -252,7 +263,7 @@ return 0; } -__attr __test_context(__ref context, __attr attr) +__attr __test_context(__attr context, __attr attr) { /* Update the context or return the unchanged attribute. */ @@ -262,22 +273,22 @@ return attr; } -__attr __update_context(__ref context, __attr attr) +__attr __update_context(__attr context, __attr attr) { return __new_wrapper(context, attr); } -__attr __test_context_revert(int target, __ref context, __attr attr, __ref contexts[]) +__attr __test_context_revert(int target, __attr context, __attr attr, __attr contexts[]) { /* Revert the local context to that employed by the attribute if the supplied context is not appropriate. */ if (!__test_context_update(context, attr)) - contexts[target] = __CONTEXT_AS_VALUE(attr).value; + contexts[target] = __CONTEXT_AS_VALUE(attr); return attr; } -__attr __test_context_static(int target, __ref context, __ref value, __ref contexts[]) +__attr __test_context_static(int target, __attr context, __ref value, __attr contexts[]) { /* Set the local context to the specified context if appropriate. */ @@ -288,48 +299,53 @@ /* Context testing for invocations. */ -int __type_method_invocation(__ref context, __attr target) +int __type_method_invocation(__attr context, __attr target) { - __ref targetcontext = __CONTEXT_AS_VALUE(target).value; + __attr targetcontext = __CONTEXT_AS_VALUE(target); /* Require instances, not classes, where methods are function instances. */ - if (!__is_instance(target.value)) + if (!__is_instance(__VALUE(target))) return 0; /* Access the context of the callable and test if it is the type object. */ - return ((targetcontext != 0) && __test_specific_type(targetcontext, &__TYPE_CLASS_TYPE) && __is_type_instance(context)); + return (!__ISNULL(targetcontext) && __test_specific_type(__VALUE(targetcontext), &__TYPE_CLASS_TYPE) && __is_type_instance(__VALUE(context))); } __attr __unwrap_callable(__attr callable) { - __attr value = __check_and_load_via_object_null(callable.value, __ATTRPOS(__value__), __ATTRCODE(__value__)); - return value.value ? value : callable; + __attr value = __check_and_load_via_object_null(__VALUE(callable), __ATTRPOS(__value__), __ATTRCODE(__value__)); + return __VALUE(value) ? value : callable; } -__attr (*__get_function(__ref context, __attr target))() +__attr (*__get_function_unchecked(__attr target))() +{ + return __load_via_object(__VALUE(__unwrap_callable(target)), __fn__).fn; +} + +__attr (*__get_function(__attr context, __attr target))() { target = __unwrap_callable(target); /* Require null or instance contexts for functions and methods respectively, or type instance contexts for type methods. */ - if ((context == 0) || __is_instance(context) || __type_method_invocation(context, target)) - return __load_via_object(target.value, __fn__).fn; + if (__ISNULL(context) || __is_instance(__VALUE(context)) || __type_method_invocation(context, target)) + return __load_via_object(__VALUE(target), __fn__).fn; else return __unbound_method; } -__attr (*__check_and_get_function(__ref context, __attr target))() +__attr (*__check_and_get_function(__attr context, __attr target))() { target = __unwrap_callable(target); /* Require null or instance contexts for functions and methods respectively, or type instance contexts for type methods. */ - if ((context == 0) || __is_instance(context) || __type_method_invocation(context, target)) - return __check_and_load_via_object__(target.value, __ATTRPOS(__fn__), __ATTRCODE(__fn__)).fn; + if (__ISNULL(context) || __is_instance(__VALUE(context)) || __type_method_invocation(context, target)) + return __check_and_load_via_object__(__VALUE(target), __ATTRPOS(__fn__), __ATTRCODE(__fn__)).fn; else return __unbound_method; } @@ -354,7 +370,7 @@ __attr __CONTEXT_AS_VALUE(__attr attr) { - return __check_and_load_via_object_null(attr.value, __ATTRPOS(__context__), __ATTRCODE(__context__)); + return __check_and_load_via_object_null(__VALUE(attr), __ATTRPOS(__context__), __ATTRCODE(__context__)); } /* Type testing. */ @@ -391,6 +407,14 @@ return ptr; } +void *__ALLOCATEIM(size_t nmemb, size_t size) +{ + void *ptr = GC_MALLOC_ATOMIC(nmemb * size); /* sets memory to zero */ + if (ptr == NULL) + __raise_memory_error(); + return ptr; +} + void *__REALLOCATE(void *ptr, size_t size) { void *nptr = GC_REALLOC(ptr, size); diff -r 59957b395bb1 -r 9c393bfc03d5 templates/ops.h --- a/templates/ops.h Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/ops.h Fri Mar 24 22:39:37 2017 +0100 @@ -22,11 +22,15 @@ #include "types.h" #include /* for __COPY */ +/* Get object reference from attribute. */ + +__ref __VALUE(__attr attr); + /* Direct access and manipulation of static objects. */ __attr __load_static_ignore(__ref obj); -__attr __load_static_replace(__ref context, __ref obj); -__attr __load_static_test(__ref context, __ref obj); +__attr __load_static_replace(__attr context, __ref obj); +__attr __load_static_test(__attr context, __ref obj); /* Direct retrieval operations, returning attributes. */ @@ -93,23 +97,24 @@ /* Context-related operations. */ -int __test_context_update(__ref context, __attr attr); -__attr __test_context(__ref context, __attr attr); -__attr __update_context(__ref context, __attr attr); -__attr __test_context_revert(int target, __ref context, __attr attr, __ref contexts[]); -__attr __test_context_static(int target, __ref context, __ref value, __ref contexts[]); +int __test_context_update(__attr context, __attr attr); +__attr __test_context(__attr context, __attr attr); +__attr __update_context(__attr context, __attr attr); +__attr __test_context_revert(int target, __attr context, __attr attr, __attr contexts[]); +__attr __test_context_static(int target, __attr context, __ref value, __attr contexts[]); #define __get_context(__TARGET) (__tmp_contexts[__TARGET]) -#define __set_context(__TARGET, __ATTR) (__tmp_contexts[__TARGET] = (__ATTR).value) -#define __set_private_context(__ATTR) (__tmp_private_context = (__ATTR).value) -#define __set_accessor(__ATTR) (__tmp_value = (__ATTR).value) -#define __set_target_accessor(__ATTR) (__tmp_target_value = (__ATTR).value) +#define __set_context(__TARGET, __ATTR) (__tmp_contexts[__TARGET] = (__ATTR)) +#define __set_private_context(__ATTR) (__tmp_private_context = (__ATTR)) +#define __set_accessor(__ATTR) (__tmp_value = (__ATTR)) +#define __set_target_accessor(__ATTR) (__tmp_target_value = (__ATTR)) /* Context testing for invocations. */ __attr __unwrap_callable(__attr callable); -__attr (*__get_function(__ref context, __attr target))(); -__attr (*__check_and_get_function(__ref context, __attr target))(); +__attr (*__get_function_unchecked(__attr target))(); +__attr (*__get_function(__attr context, __attr target))(); +__attr (*__check_and_get_function(__attr context, __attr target))(); /* Parameter position operations. */ @@ -132,6 +137,7 @@ /* Memory allocation. */ void *__ALLOCATE(size_t nmemb, size_t size); +void *__ALLOCATEIM(size_t nmemb, size_t size); void *__REALLOCATE(void *ptr, size_t size); /* Copying of structures. */ diff -r 59957b395bb1 -r 9c393bfc03d5 templates/progops.c --- a/templates/progops.c Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/progops.c Fri Mar 24 22:39:37 2017 +0100 @@ -28,18 +28,18 @@ /* Generic instantiation operations, defining common members. */ -__attr __new(const __table * table, __ref cls, size_t size) +__attr __new(const __table * table, __ref cls, size_t size, int immutable) { - __ref obj = (__ref) __ALLOCATE(1, size); + __ref obj = (__ref) (immutable ? __ALLOCATEIM : __ALLOCATE)(1, size); obj->table = table; obj->pos = __INSTANCEPOS; __store_via_object(obj, __class__, __ATTRVALUE(cls)); - return (__attr) {.value=obj}; + return __ATTRVALUE(obj); } -__attr __new_wrapper(__ref context, __attr attr) +__attr __new_wrapper(__attr context, __attr attr) { - return __new___builtins___core_wrapper(__NULL, __ATTRVALUE(context), attr); + return __new___builtins___core_wrapper(__NULL, context, attr); } /* Generic internal data allocation. */ @@ -74,7 +74,7 @@ /* Store a reference to the data in the object's __data__ attribute. */ - __store_via_object(self.value, __data__, attr); + __store_via_object(__VALUE(self), __data__, attr); return self; } @@ -145,7 +145,7 @@ /* Return instances as provided. */ - if (__is_instance(arg.value)) + if (__is_instance(__VALUE(arg))) return arg; /* Invoke non-instances to produce instances. */ @@ -174,7 +174,7 @@ /* Obtain the __args__ special member, referencing the parameter table. */ /* Refer to the table and minimum/maximum. */ - const __ptable *ptable = __check_and_load_via_object(target.value, __args__).ptable; + const __ptable *ptable = __check_and_load_via_object(__VALUE(target), __args__).ptable; const unsigned int min = ptable->min, max = ptable->max; /* Reserve enough space for the arguments. */ @@ -203,7 +203,7 @@ /* Erase the remaining arguments. */ for (pos = nargs; pos < max; pos++) - allargs[pos].value = 0; + __SETNULL(allargs[pos]); /* Fill keyword arguments. */ @@ -228,8 +228,8 @@ for (pos = nargs; pos < max; pos++) { - if (allargs[pos].value == 0) - allargs[pos] = __GETDEFAULT(target.value, pos - min); + if (__ISNULL(allargs[pos])) + allargs[pos] = __GETDEFAULT(__VALUE(target), pos - min); } } @@ -238,8 +238,8 @@ return __call_with_args( always_callable ? - __get_function(allargs[0].value, target) : - __check_and_get_function(allargs[0].value, target), + __get_function(allargs[0], target) : + __check_and_get_function(allargs[0], target), allargs, max); } @@ -265,8 +265,10 @@ int __BOOL(__attr attr) { + __ref truevalue = __VALUE(__builtins___boolean_True); + /* Invoke the bool function with the object and test against True. */ - return (attr.value == __builtins___boolean_True.value) || - (__fn___builtins___boolean_bool(__NULL, attr).value == __builtins___boolean_True.value); + return (__VALUE(attr) == truevalue) || + (__VALUE(__fn___builtins___boolean_bool(__NULL, attr)) == truevalue); } diff -r 59957b395bb1 -r 9c393bfc03d5 templates/progops.h --- a/templates/progops.h Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/progops.h Fri Mar 24 22:39:37 2017 +0100 @@ -25,8 +25,8 @@ /* Generic instantiation operations, defining common members. */ -__attr __new(const __table *table, __ref cls, size_t size); -__attr __new_wrapper(__ref context, __attr attr); +__attr __new(const __table *table, __ref cls, size_t size, int immutable); +__attr __new_wrapper(__attr context, __attr attr); /* Generic internal data allocation. */ @@ -78,7 +78,8 @@ /* Convenience definitions. */ -#define __NEWINSTANCE(__CLS) __new(&__InstanceTable_##__CLS, &__CLS, sizeof(__obj_##__CLS)) +#define __NEWINSTANCE(__CLS) __new(&__InstanceTable_##__CLS, &__CLS, sizeof(__obj_##__CLS), 0) +#define __NEWINSTANCEIM(__CLS) __new(&__InstanceTable_##__CLS, &__CLS, sizeof(__obj_##__CLS), 1) #define __ISINSTANCE(__ATTR, __TYPE) __BOOL(__fn_native_introspection_isinstance(__NULL, __ATTR, __TYPE)) #endif /* __PROGOPS_H__ */ diff -r 59957b395bb1 -r 9c393bfc03d5 templates/types.h --- a/templates/types.h Sun Mar 19 00:56:43 2017 +0100 +++ b/templates/types.h Fri Mar 24 22:39:37 2017 +0100 @@ -72,14 +72,19 @@ typedef union __attr { + /* General attribute members. */ + __ref value; /* attribute value */ + int intvalue; /* integer value data ((integer << 1) | 1) */ + + /* Special case attribute members. */ + const __ptable * ptable; /* parameter table */ struct { __pcode code; /* parameter table code for key */ __ppos pos; /* parameter table position for key */ }; __attr (*fn)(); /* callable details */ - int intvalue; /* integer value */ float floatvalue; /* floating point value */ char * strvalue; /* string value */ __fragment * seqvalue; /* sequence data */ @@ -106,10 +111,22 @@ #define __FRAGMENT_SIZE(NUMBER) ((NUMBER) * sizeof(__attr) + 2 * sizeof(unsigned int)) +/* Attribute interpretation. */ + +#define __INTEGER(ATTR) ((ATTR).intvalue % 2) + /* Attribute value setting. */ #define __ATTRVALUE(VALUE) ((__attr) {.value=VALUE}) #define __NULL __ATTRVALUE(0) +#define __SETNULL(ATTR) ((ATTR).value = 0) + +/* Attribute as instance setting. */ + +#define __INTVALUE(VALUE) ((__attr) {.intvalue=((VALUE) << 1) | 1}) +#define __TOINT(ATTR) ((ATTR).intvalue >> 1) +#define __MAXINT ((1 << ((sizeof(__attr) * 8) - 2)) - 1) +#define __MININT (-(1 << ((sizeof(__attr) * 8) - 2))) /* Argument lists. */ diff -r 59957b395bb1 -r 9c393bfc03d5 tests/get_using.py --- a/tests/get_using.py Sun Mar 19 00:56:43 2017 +0100 +++ b/tests/get_using.py Fri Mar 24 22:39:37 2017 +0100 @@ -21,6 +21,11 @@ except UnboundMethodInvocation: print "fn(): method is unbound" +try: + print f() # fails +except UnboundMethodInvocation: + print "f(): method is unbound" + d = D() try: fn = get_using(C.f, d) diff -r 59957b395bb1 -r 9c393bfc03d5 tests/numbers.py --- a/tests/numbers.py Sun Mar 19 00:56:43 2017 +0100 +++ b/tests/numbers.py Fri Mar 24 22:39:37 2017 +0100 @@ -10,15 +10,15 @@ print "# sys.maxint + sys.minint:", print sys.maxint + sys.minint -i = 2 ** 30 -print i # 1073741824 -print hex(i) # 0x40000000 -print oct(i) # 010000000000 +i = 2 ** 29 +print i # 536870912 +print hex(i) # 0x20000000 +print oct(i) # 04000000000 -j = -2 ** 30 -print j # -1073741824 -print hex(j) # -0x40000000 -print oct(j) # -010000000000 +j = -2 ** 29 +print j # -536870912 +print hex(j) # -0x20000000 +print oct(j) # -05000000000 print i + j # 0 @@ -39,9 +39,9 @@ print i - i # 0 print j - j # 0 -print ~j # 1073741823 +print ~j # 536870911 print i & ~j # 0 -print i - 1 & ~j # 1073741823 +print i - 1 & ~j # 536870911 print hex(31) # 0x1f print oct(31) # 037 diff -r 59957b395bb1 -r 9c393bfc03d5 translator.py --- a/translator.py Sun Mar 19 00:56:43 2017 +0100 +++ b/translator.py Fri Mar 24 22:39:37 2017 +0100 @@ -29,7 +29,7 @@ from errors import InspectError, TranslateError from os.path import exists, join from os import makedirs -from referencing import Reference +from referencing import Reference, combine_types from results import Result from transresults import TrConstantValueRef, TrInstanceRef, \ TrLiteralSequenceRef, TrResolvedNameRef, \ @@ -542,7 +542,7 @@ subs = { "" : attr_expr, - "" : "%s.value" % attr_expr, + "" : attr_expr, "" : self.in_assignment, } @@ -557,6 +557,7 @@ context_index = self.function_target - 1 context_identity = None + final_identity = None # Obtain encoded versions of each instruction, accumulating temporary # variables. @@ -569,6 +570,13 @@ context_identity, _substituted = encode_access_instruction_arg(instruction[1], subs, instruction[0], context_index) continue + # Intercept a special instruction identifying the target. The value + # is not encoded since it is used internally. + + if instruction[0] == "": + final_identity = instruction[1] + continue + # Collect the encoded instruction, noting any temporary variables # required by it. @@ -582,6 +590,12 @@ if self.temp_subs.has_key(sub): self.record_temp(self.temp_subs[sub]) + # Get full final identity details. + + if final_identity and not refs: + ref = self.importer.identify(final_identity) + refs = [ref] + del self.attrs[0] return AttrResult(output, refs, location, context_identity) @@ -629,7 +643,18 @@ identified attributes. """ + # Determine whether any deduced references refer to the accessed + # attribute. + + path, accessor_name, attrnames, access_number = location + attrnames = attrnames and attrnames.split(".") + remaining = attrnames and len(attrnames) > 1 + access_location = self.deducer.const_accesses.get(location) + + if remaining and not access_location: + return [] + refs = [] l = self.deducer.referenced_attrs.get(access_location or location) if l: @@ -862,14 +887,10 @@ else: return - # Produce an appropriate access to an attribute's value. - - name_to_value = "%s.value" % encode_path(name) - # Write a test that raises a TypeError upon failure. - self.writestmt("if (!__test_%s_%s(%s, %s)) __raise_type_error();" % ( - guard, guard_type, name_to_value, argstr)) + self.writestmt("if (!__test_%s_%s(__VALUE(%s), %s)) __raise_type_error();" % ( + guard, guard_type, encode_path(name), argstr)) def process_function_node(self, n): @@ -939,6 +960,8 @@ if not instance_name: instance_name = "&%s" % encode_path(objpath) + else: + instance_name = "__VALUE(%s)" % instance_name # Where defaults are involved but cannot be identified, obtain a new # instance of the lambda and populate the defaults. @@ -1021,6 +1044,7 @@ objpath = expr.get_origin() location = expr.access_location() + refs = expr.references() # Identified target details. @@ -1042,6 +1066,8 @@ have_access_context = isinstance(expr, AttrResult) context_identity = have_access_context and expr.context() parameters = None + num_parameters = None + num_defaults = None # Obtain details of the callable and of its parameters. @@ -1056,6 +1082,9 @@ elif objpath: parameters = self.importer.function_parameters.get(objpath) + function_defaults = self.importer.function_defaults.get(objpath) + num_parameters = parameters and len(parameters) or 0 + num_defaults = function_defaults and len(function_defaults) or 0 # Class invocation involves instantiators. @@ -1091,22 +1120,71 @@ target_structure = "&%s" % encode_path(objpath) - # Other targets are retrieved at run-time. Some information about them - # may be available and be used to provide warnings about argument - # compatibility. - - elif self.importer.give_warning("args"): - unsuitable = self.get_referenced_attribute_invocations(location) - - if unsuitable: - for ref in unsuitable: - _objpath = ref.get_origin() - num_parameters = len(self.importer.function_parameters[_objpath]) - print >>sys.stderr, \ - "In %s, at line %d, inappropriate number of " \ - "arguments given. Need %d arguments to call %s." % ( - self.get_namespace_path(), n.lineno, num_parameters, - _objpath) + # Other targets are retrieved at run-time. + + else: + if location: + path, name, attrnames, access_number = location + attrname = attrnames and attrnames.rsplit(".", 1)[-1] + + # Determine any common aspects of any attribute. + + if attrname: + all_params = set() + all_defaults = set() + min_params = set() + max_params = set() + refs = set() + + # Obtain parameters and defaults for each possible target. + + for ref in self.get_attributes_for_attrname(attrname): + origin = ref.get_origin() + params = self.importer.function_parameters.get(origin) + + defaults = self.importer.function_defaults.get(origin) + if defaults is not None: + all_defaults.add(tuple(defaults)) + + if params is not None: + all_params.add(tuple(params)) + min_params.add(len(params) - (defaults and len(defaults) or 0)) + max_params.add(len(params)) + refs.add(ref) + else: + refs = set() + break + + # Where the parameters and defaults are always the same, + # permit populating them in advance. + + if refs: + if self.uses_keyword_arguments(n): + if len(all_params) == 1 and (not all_defaults or len(all_defaults) == 1): + parameters = first(all_params) + function_defaults = all_defaults and first(all_defaults) or [] + num_parameters = parameters and len(parameters) or 0 + num_defaults = function_defaults and len(function_defaults) or 0 + else: + if len(min_params) == 1 and len(max_params) == 1: + num_parameters = first(max_params) + num_defaults = first(max_params) - first(min_params) + + # Some information about the target may be available and be used to + # provide warnings about argument compatibility. + + if self.importer.give_warning("args"): + unsuitable = self.get_referenced_attribute_invocations(location) + + if unsuitable: + for ref in unsuitable: + _objpath = ref.get_origin() + print >>sys.stderr, \ + "In %s, at line %d, inappropriate number of " \ + "arguments given. Need %d arguments to call %s." % ( + self.get_namespace_path(), n.lineno, + len(self.importer.function_parameters[_objpath]), + _objpath) # Determine any readily-accessible target identity. @@ -1120,16 +1198,19 @@ if not target_identity: self.record_temp("__tmp_targets") - if context_identity and context_identity.startswith("__tmp_contexts"): - self.record_temp("__tmp_contexts") + if context_identity: + if context_identity.startswith("__tmp_contexts"): + self.record_temp("__tmp_contexts") # Arguments are presented in a temporary frame array with any context # always being the first argument. Where it would be unused, it may be # set to null. + known_parameters = num_parameters is not None + if context_required: if have_access_context: - args = ["__ATTRVALUE(%s)" % context_identity] + args = [context_identity] else: args = ["__CONTEXT_AS_VALUE(%s)" % context_var] else: @@ -1138,7 +1219,7 @@ # Complete the array with null values, permitting tests for a complete # set of arguments. - args += [None] * (parameters is None and len(n.args) or parameters is not None and len(parameters) or 0) + args += [None] * (num_parameters is None and len(n.args) or num_parameters is not None and num_parameters or 0) kwcodes = [] kwargs = [] @@ -1198,18 +1279,29 @@ # Defaults are added to the frame where arguments are missing. - if parameters: - function_defaults = self.importer.function_defaults.get(objpath) - if function_defaults: - - # Visit each default and set any missing arguments. - # Use the target structure to obtain defaults, as opposed to the - # actual function involved. - - for i, (argname, default) in enumerate(function_defaults): - argnum = parameters.index(argname) - if not args[argnum+1]: - args[argnum+1] = "__GETDEFAULT(%s, %d)" % (target_structure, i) + if parameters and function_defaults: + + # Visit each default and set any missing arguments. Where keyword + # arguments have been used, the defaults must be inspected and, if + # necessary, inserted into gaps in the argument list. + + for i, (argname, default) in enumerate(function_defaults): + argnum = parameters.index(argname) + if not args[argnum+1]: + args[argnum+1] = "__GETDEFAULT(%s, %d)" % (target_structure, i) + + elif known_parameters: + + # No specific parameter details are provided, but no keyword + # arguments are used. Thus, defaults can be supplied using position + # information only. + + i = len(n.args) + pos = i - (num_parameters - num_defaults) + while i < num_parameters: + args[i+1] = "__GETDEFAULT(%s.value, %d)" % (target_var, pos) + i += 1 + pos += 1 # Test for missing arguments. @@ -1264,10 +1356,19 @@ stages.append("__get_function(%s, %s)" % ( context_identity, target_var)) else: - stages.append("__get_function(__CONTEXT_AS_VALUE(%s).value, %s)" % ( + stages.append("__get_function(__CONTEXT_AS_VALUE(%s), %s)" % ( context_var, target_var)) else: - stages.append("__load_via_object(%s.value, __fn__).fn" % target_var) + stages.append("__load_via_object(__VALUE(%s), __fn__).fn" % target_var) + + # With known parameters, the target can be tested. + + elif known_parameters: + context_arg = context_required and args[0] or "__NULL" + if self.always_callable(refs): + stages.append("__get_function(%s, %s)" % (context_arg, target_var)) + else: + stages.append("__check_and_get_function(%s, %s)" % (context_arg, target_var)) # With a known target, the function is obtained directly and called. # By putting the invocation at the end of the final element in the @@ -1275,7 +1376,7 @@ # the sequence. Moreover, the parameters become part of the sequence # and thereby participate in a guaranteed evaluation order. - if target or function: + if target or function or known_parameters: stages[-1] += "(%s)" % argstr if instantiation: return InstantiationResult(instantiation, stages) @@ -1288,7 +1389,7 @@ else: stages.append("__invoke(\n%s,\n%d, %d, %s, %s,\n%d, %s\n)" % ( target_var, - self.always_callable and 1 or 0, + self.always_callable(refs) and 1 or 0, len(kwargs), kwcodestr, kwargstr, len(args), "__ARGS(%s)" % argstr)) return InvocationResult(stages) @@ -1304,13 +1405,13 @@ "Determine whether all 'refs' are callable." + if not refs: + return False + for ref in refs: - if not ref.static(): + if not ref.has_kind("") and not self.importer.get_attributes(ref, "__fn__"): return False - else: - origin = ref.final() - if not self.importer.get_attribute(origin, "__fn__"): - return False + return True def need_default_arguments(self, objpath, nargs): @@ -1323,6 +1424,31 @@ parameters = self.importer.function_parameters.get(objpath) return nargs < len(parameters) + def uses_keyword_arguments(self, n): + + "Return whether invocation node 'n' uses keyword arguments." + + for arg in enumerate(n.args): + if isinstance(arg, compiler.ast.Keyword): + return True + + return False + + def get_attributes_for_attrname(self, attrname): + + "Return a set of all attributes exposed by 'attrname'." + + usage = [(attrname, True, False)] + class_types = self.deducer.get_class_types_for_usage(usage) + instance_types = self.deducer.get_instance_types_for_usage(usage) + module_types = self.deducer.get_module_types_for_usage(usage) + attrs = set() + + for ref in combine_types(class_types, instance_types, module_types): + attrs.update(self.importer.get_attributes(ref, attrname)) + + return attrs + def process_lambda_node(self, n): "Process the given lambda node 'n'." @@ -1342,7 +1468,7 @@ else: self.record_temp("__tmp_value") - return make_expression("(__tmp_value = __COPY(&%s, sizeof(%s)), %s, __ATTRVALUE(__tmp_value))" % ( + return make_expression("(__tmp_value = __ATTRVALUE(__COPY(&%s, sizeof(%s))), %s, __tmp_value)" % ( encode_path(function_name), encode_symbol("obj", function_name), ", ".join(defaults))) @@ -1923,16 +2049,16 @@ if self.uses_temp(name, "__tmp_targets"): self.writeline("__attr __tmp_targets[%d];" % targets) if self.uses_temp(name, "__tmp_contexts"): - self.writeline("__ref __tmp_contexts[%d];" % targets) + self.writeline("__attr __tmp_contexts[%d];" % targets) # Add temporary variable usage details. if self.uses_temp(name, "__tmp_private_context"): - self.writeline("__ref __tmp_private_context;") + self.writeline("__attr __tmp_private_context;") if self.uses_temp(name, "__tmp_value"): - self.writeline("__ref __tmp_value;") + self.writeline("__attr __tmp_value;") if self.uses_temp(name, "__tmp_target_value"): - self.writeline("__ref __tmp_target_value;") + self.writeline("__attr __tmp_target_value;") if self.uses_temp(name, "__tmp_result"): self.writeline("__attr __tmp_result;") diff -r 59957b395bb1 -r 9c393bfc03d5 transresults.py --- a/transresults.py Sun Mar 19 00:56:43 2017 +0100 +++ b/transresults.py Fri Mar 24 22:39:37 2017 +0100 @@ -139,7 +139,13 @@ "A constant value reference in the translation." def __str__(self): - return encode_literal_constant(self.number) + + # NOTE: Should reference a common variable for the type name. + + if self.ref.get_origin() == "__builtins__.int.int": + return "__INTVALUE(%s)" % self.value + else: + return encode_literal_constant(self.number) class TrLiteralSequenceRef(LiteralSequenceRef): @@ -205,7 +211,7 @@ return encode_instructions(self.instructions) def __repr__(self): - return "AttrResult(%r, %r, %r)" % (self.instructions, self.refs, self.location) + return "AttrResult(%r, %r, %r, %r)" % (self.instructions, self.refs, self.location, self.context_identity) class AliasResult(NameRef, Result):