# HG changeset patch # User Paul Boddie # Date 1490308592 -3600 # Node ID 41eddb32a6037b5418cd64add2041d89a929a833 # Parent b496ef9d5ee1446ff1f20ee2c094e812c3ca8704 Represent integers as __attr values with bit 0 set. Since pointers must be aligned (to four-byte boundaries on many modern systems, maybe two-byte boundaries on older or embedded systems, eight-byte boundaries on some 64-bit systems), any value with bit 0 set will not be referencing an object. This avoids allocating objects for integers and instead just allows them to be passed around. Bit 0 needs to be tested when attributes are accessed, and for integers, a common instance is employed to provide any instance attributes, an instance table reference and a reference to the integer class. diff -r b496ef9d5ee1 -r 41eddb32a603 generator.py --- a/generator.py Thu Mar 23 16:40:57 2017 +0100 +++ b/generator.py Thu Mar 23 23:36:32 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" @@ -359,6 +360,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) @@ -504,6 +510,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) @@ -526,13 +537,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. @@ -974,7 +995,7 @@ # Special internal size member. elif attrname == "__size__": - structure.append("{.intvalue=%d}" % attr) + structure.append("__INTVALUE(%d)" % attr) continue # Special internal key member. @@ -1081,6 +1102,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) @@ -1213,13 +1241,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(__ARGS(__NULL, __tmp_exc.arg)).value, + __VALUE(%s(__ARGS(__NULL, __tmp_exc.arg))), __data__).strvalue); return 1; } diff -r b496ef9d5ee1 -r 41eddb32a603 lib/__builtins__/character.py --- a/lib/__builtins__/character.py Thu Mar 23 16:40:57 2017 +0100 +++ b/lib/__builtins__/character.py Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 lib/__builtins__/int.py --- a/lib/__builtins__/int.py Thu Mar 23 16:40:57 2017 +0100 +++ b/lib/__builtins__/int.py Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 lib/__builtins__/str.py --- a/lib/__builtins__/str.py Thu Mar 23 16:40:57 2017 +0100 +++ b/lib/__builtins__/str.py Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 lib/native/__init__.py --- a/lib/native/__init__.py Thu Mar 23 16:40:57 2017 +0100 +++ b/lib/native/__init__.py Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 lib/native/int.py --- a/lib/native/int.py Thu Mar 23 16:40:57 2017 +0100 +++ b/lib/native/int.py Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 templates/native/buffer.c --- a/templates/native/buffer.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/buffer.c Thu Mar 23 23:36:32 2017 +0100 @@ -37,7 +37,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)); @@ -45,8 +45,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 b496ef9d5ee1 -r 41eddb32a603 templates/native/common.c --- a/templates/native/common.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/common.c Thu Mar 23 23:36:32 2017 +0100 @@ -26,20 +26,12 @@ /* Utility functions. */ -__attr __new_int(int i) -{ - /* Create a new integer and mutate the __data__ attribute. */ - __attr attr = __NEWINSTANCEIM(__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 b496ef9d5ee1 -r 41eddb32a603 templates/native/common.h --- a/templates/native/common.h Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/common.h Thu Mar 23 23:36:32 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 * const value); diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/iconv.c --- a/templates/native/iconv.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/iconv.c Thu Mar 23 23:36:32 2017 +0100 @@ -57,13 +57,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. */ @@ -142,9 +142,9 @@ __attr * const tocode = &__args[1]; __attr * const fromcode = &__args[2]; /* 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 b496ef9d5ee1 -r 41eddb32a603 templates/native/identity.c --- a/templates/native/identity.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/identity.c Thu Mar 23 23:36:32 2017 +0100 @@ -1,6 +1,6 @@ /* Native functions for identity operations. -Copyright (C) 2016 Paul Boddie +Copyright (C) 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 @@ -31,6 +31,8 @@ __attr * const x = &__args[1]; __attr * const y = &__args[2]; + /* NOTE: value member assumed equivalent to intvalue for comparison. */ + return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False; } @@ -39,6 +41,8 @@ __attr * const x = &__args[1]; __attr * const y = &__args[2]; + /* NOTE: value member assumed equivalent to intvalue for comparison. */ + return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False; } diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/int.c --- a/templates/native/int.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/int.c Thu Mar 23 23:36:32 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,24 +31,17 @@ /* Integer operations. */ -__attr __fn_native_int_int_new(__attr __args[]) -{ - __attr * const _data = &__args[1]; - - return __new_int(_data->intvalue); -} - __attr __fn_native_int_int_add(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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(); @@ -59,15 +51,15 @@ __attr __fn_native_int_int_sub(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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(); @@ -77,17 +69,17 @@ __attr __fn_native_int_int_mul(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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(); @@ -97,16 +89,16 @@ __attr __fn_native_int_int_div(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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. */ @@ -115,16 +107,16 @@ __attr __fn_native_int_int_mod(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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. */ @@ -133,12 +125,12 @@ __attr __fn_native_int_int_neg(__attr __args[]) { - __attr * const _data = &__args[1]; - /* _data interpreted as int */ - int i = _data->intvalue; + __attr * const self = &__args[1]; + /* 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. */ @@ -147,11 +139,11 @@ __attr __fn_native_int_int_pow(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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; @@ -168,11 +160,11 @@ __attr __fn_native_int_int_and(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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. */ @@ -181,9 +173,9 @@ __attr __fn_native_int_int_not(__attr __args[]) { - __attr * const _data = &__args[1]; - /* _data interpreted as int */ - int i = _data->intvalue; + __attr * const self = &__args[1]; + /* self interpreted as int */ + int i = __TOINT(*self); /* Return the new integer. */ return __new_int(~i); @@ -191,11 +183,11 @@ __attr __fn_native_int_int_or(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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. */ @@ -204,11 +196,11 @@ __attr __fn_native_int_int_xor(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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. */ @@ -217,11 +209,11 @@ __attr __fn_native_int_int_lt(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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; @@ -229,11 +221,11 @@ __attr __fn_native_int_int_gt(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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; @@ -241,11 +233,11 @@ __attr __fn_native_int_int_eq(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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; @@ -253,11 +245,11 @@ __attr __fn_native_int_int_ne(__attr __args[]) { - __attr * const _data = &__args[1]; + __attr * const self = &__args[1]; __attr * const other = &__args[2]; - /* _data and other interpreted as int */ - 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; @@ -265,12 +257,12 @@ __attr __fn_native_int_int_str(__attr __args[]) { - __attr * const _data = &__args[1]; - /* _data interpreted as int */ - int i = _data->intvalue; + __attr * const self = &__args[1]; + /* 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 b496ef9d5ee1 -r 41eddb32a603 templates/native/int.h --- a/templates/native/int.h Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/int.h Thu Mar 23 23:36:32 2017 +0100 @@ -23,8 +23,6 @@ /* Integer operations. */ -__attr __fn_native_int_int_new(__attr __args[]); - __attr __fn_native_int_int_add(__attr __args[]); __attr __fn_native_int_int_div(__attr __args[]); __attr __fn_native_int_int_mod(__attr __args[]); diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/introspection.c --- a/templates/native/introspection.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/introspection.c Thu Mar 23 23:36:32 2017 +0100 @@ -32,7 +32,7 @@ __attr * const name = &__args[2]; __attr * const _default = &__args[3]; /* name.__data__ 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)) @@ -40,13 +40,13 @@ /* 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. */ @@ -63,7 +63,7 @@ __attr * const cls = &__args[2]; /* 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; @@ -75,7 +75,7 @@ __attr * const cls = &__args[2]; /* 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 b496ef9d5ee1 -r 41eddb32a603 templates/native/io.c --- a/templates/native/io.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/io.c Thu Mar 23 23:36:32 2017 +0100 @@ -62,9 +62,9 @@ __attr * const filename = &__args[1]; __attr * const mode = &__args[2]; /* filename.__data__ interpreted as string */ - char *fn = __load_via_object(filename->value, __data__).strvalue; + char *fn = __load_via_object(__VALUE(*filename), __data__).strvalue; /* mode.__data__ interpreted as string */ - char *s = __load_via_object(mode->value, __data__).strvalue; + char *s = __load_via_object(__VALUE(*mode), __data__).strvalue; FILE *f; __attr attr; @@ -93,10 +93,10 @@ { __attr * const fd = &__args[1]; __attr * const mode = &__args[2]; - /* fd.__data__ interpreted as int */ - int i = __load_via_object(fd->value, __data__).intvalue; + /* fd interpreted as int */ + int i = __TOINT(*fd); /* mode.__data__ interpreted as string */ - char *s = __load_via_object(mode->value, __data__).strvalue; + char *s = __load_via_object(__VALUE(*mode), __data__).strvalue; FILE *f; __attr attr; @@ -127,8 +127,8 @@ __attr * const size = &__args[2]; /* fp interpreted as FILE reference */ FILE *f = (FILE *) fp->datavalue; - /* size.__data__ interpreted as int */ - int to_read = __load_via_object(size->value, __data__).intvalue; + /* size interpreted as int */ + int to_read = __TOINT(*size); char buf[to_read]; size_t have_read; int error; @@ -158,9 +158,9 @@ /* fp interpreted as FILE reference */ FILE *f = (FILE *) fp->datavalue; /* str.__data__ interpreted as string */ - char *s = __load_via_object(str->value, __data__).strvalue; + char *s = __load_via_object(__VALUE(*str), __data__).strvalue; /* str.__size__ interpreted as int */ - int to_write = __load_via_object(str->value, __size__).intvalue; + int to_write = __TOINT(__load_via_object(__VALUE(*str), __size__)); size_t have_written = fwrite(s, sizeof(char), to_write, f); int error; @@ -178,8 +178,8 @@ __attr __fn_native_io_close(__attr __args[]) { __attr * const fd = &__args[1]; - /* fd.__data__ interpreted as int */ - int i = __load_via_object(fd->value, __data__).intvalue; + /* fd interpreted as int */ + int i = __TOINT(*fd); errno = 0; if (close(i) == -1) @@ -192,10 +192,10 @@ { __attr * const fd = &__args[1]; __attr * const n = &__args[2]; - /* fd.__data__ interpreted as int */ - int i = __load_via_object(fd->value, __data__).intvalue; - /* n.__data__ interpreted as int */ - int to_read = __load_via_object(n->value, __data__).intvalue; + /* fd interpreted as int */ + int i = __TOINT(*fd); + /* n interpreted as int */ + int to_read = __TOINT(*n); char buf[to_read]; ssize_t have_read; char *s; @@ -217,12 +217,12 @@ { __attr * const fd = &__args[1]; __attr * const str = &__args[2]; - /* fd.__data__ interpreted as int */ - int i = __load_via_object(fd->value, __data__).intvalue; + /* fd interpreted as int */ + int i = __TOINT(*fd); /* str.__data__ interpreted as string */ - char *s = __load_via_object(str->value, __data__).strvalue; + char *s = __load_via_object(__VALUE(*str), __data__).strvalue; /* str.__size__ interpreted as int */ - int size = __load_via_object(str->value, __size__).intvalue; + int size = __TOINT(__load_via_object(__VALUE(*str), __size__)); ssize_t have_written; errno = 0; diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/limits.c --- a/templates/native/limits.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/limits.c Thu Mar 23 23:36:32 2017 +0100 @@ -1,6 +1,6 @@ /* Native functions for limit definition. -Copyright (C) 2016 Paul Boddie +Copyright (C) 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 @@ -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 __args[]) { - return __new_int(INT_MAX); + return __new_int(__MAXINT); } __attr __fn_native_limits_get_minint(__attr __args[]) { - return __new_int(INT_MIN); + return __new_int(__MININT); } /* Module initialisation. */ diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/list.c --- a/templates/native/list.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/list.c Thu Mar 23 23:36:32 2017 +0100 @@ -30,8 +30,8 @@ __attr __fn_native_list_list_init(__attr __args[]) { __attr * const size = &__args[1]; - /* size.__data__ interpreted as int */ - unsigned int n = __load_via_object(size->value, __data__).intvalue; + /* size interpreted as int */ + unsigned int n = __TOINT(*size); __attr attr = {.seqvalue=__new_fragment(n)}; /* Return the __data__ attribute. */ @@ -44,8 +44,8 @@ __attr * const size = &__args[2]; /* _data interpreted as list */ __fragment *data = _data->seqvalue; - /* size.__data__ interpreted as int */ - unsigned int n = __load_via_object(size->value, __data__).intvalue; + /* size interpreted as int */ + unsigned int n = __TOINT(*size); data->size = n; return __builtins___none_None; @@ -56,12 +56,12 @@ __attr * const self = &__args[1]; __attr * const value = &__args[2]; /* self.__data__ interpreted as list */ - __fragment *data = __load_via_object(self->value, __data__).seqvalue; + __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; } @@ -70,7 +70,7 @@ __attr * const self = &__args[1]; __attr * const other = &__args[2]; /* self.__data__, other interpreted as list */ - __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; @@ -91,7 +91,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; } @@ -118,8 +118,8 @@ __attr * const index = &__args[2]; /* _data interpreted as fragment */ __attr *elements = _data->seqvalue->attrs; - /* index.__data__ interpreted as int */ - int i = __load_via_object(index->value, __data__).intvalue; + /* index interpreted as int */ + int i = __TOINT(*index); return elements[i]; } @@ -131,8 +131,8 @@ __attr * const value = &__args[3]; /* _data interpreted as fragment */ __attr *elements = _data->seqvalue->attrs; - /* index.__data__ interpreted as int */ - int i = __load_via_object(index->value, __data__).intvalue; + /* index interpreted as int */ + int i = __TOINT(*index); /* Set the element. */ elements[i] = *value; diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/locale.c --- a/templates/native/locale.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/locale.c Thu Mar 23 23:36:32 2017 +0100 @@ -32,8 +32,8 @@ __attr __fn_native_locale_getlocale(__attr __args[]) { __attr * const category = &__args[1]; - /* category.__data__ interpreted as int */ - int cat = __load_via_object(category->value, __data__).intvalue; + /* category interpreted as int */ + int cat = __TOINT(*category); char *result, *out; size_t length; @@ -53,10 +53,10 @@ { __attr * const category = &__args[1]; __attr * const value = &__args[2]; - /* category.__data__ interpreted as int */ - int cat = __load_via_object(category->value, __data__).intvalue; + /* category interpreted as int */ + int cat = __TOINT(*category); /* value.__data__ 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 b496ef9d5ee1 -r 41eddb32a603 templates/native/str.c --- a/templates/native/str.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/str.c Thu Mar 23 23:36:32 2017 +0100 @@ -37,7 +37,7 @@ /* _data, other interpreted as string */ char *s = _data->strvalue; char *o = other->strvalue; - int ss = _size->intvalue, os = othersize->intvalue; + int ss = __TOINT(*_size), os = __TOINT(*othersize); int n = ss + os; char *r = (char *) __ALLOCATE(n + 1, sizeof(char)); @@ -50,9 +50,9 @@ __attr __fn_native_str_str_chr(__attr __args[]) { - __attr * const _data = &__args[1]; - /* _data interpreted as int */ - int n = _data->intvalue; + __attr * const data = &__args[1]; + /* data interpreted as int */ + int n = __TOINT(*data); char *s = (char *) __ALLOCATE(2, sizeof(char)); s[0] = (char) n; @@ -112,12 +112,12 @@ __attr * const step = &__args[4]; /* _data interpreted as string */ char *s = _data->strvalue, *sub; - /* start.__data__ interpreted as int */ - int istart = __load_via_object(start->value, __data__).intvalue; - /* end.__data__ interpreted as int */ - int iend = __load_via_object(end->value, __data__).intvalue; - /* step.__data__ interpreted as int */ - int istep = __load_via_object(step->value, __data__).intvalue; + /* start interpreted as int */ + int istart = __TOINT(*start); + /* end interpreted as int */ + int iend = __TOINT(*end); + /* step interpreted as int */ + int istep = __TOINT(*step); /* Calculate the size of the substring. */ size_t resultsize = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/system.c --- a/templates/native/system.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/system.c Thu Mar 23 23:36:32 2017 +0100 @@ -31,7 +31,7 @@ { __attr * const status = &__args[1]; - exit(__load_via_object(status->value, __data__).intvalue); + exit(__VALUE(*status)); return __builtins___none_None; } diff -r b496ef9d5ee1 -r 41eddb32a603 templates/native/unicode.c --- a/templates/native/unicode.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/native/unicode.c Thu Mar 23 23:36:32 2017 +0100 @@ -76,7 +76,7 @@ /* _data interpreted as string */ char *s = _data->strvalue; /* _size interpreted as int */ - int size = _size->intvalue; + int size = __TOINT(*_size); unsigned int i, c = 0; for (i = 0; i < size; i++) @@ -94,7 +94,7 @@ /* _data interpreted as string */ char *s = _data->strvalue; /* _size interpreted as int */ - int size = _size->intvalue; + int size = __TOINT(*_size); unsigned int i, c = 0, v; for (i = 0; i < size; i++) @@ -133,13 +133,13 @@ /* _data interpreted as string */ char *s = _data->strvalue, *sub; /* _size interpreted as int */ - int ss = _size->intvalue; - /* start.__data__ interpreted as int */ - int istart = __load_via_object(start->value, __data__).intvalue; - /* end.__data__ interpreted as int */ - int iend = __load_via_object(end->value, __data__).intvalue; - /* step.__data__ interpreted as int */ - int istep = __load_via_object(step->value, __data__).intvalue; + int ss = __TOINT(*_size); + /* start interpreted as int */ + int istart = __TOINT(*start); + /* end interpreted as int */ + int iend = __TOINT(*end); + /* step interpreted as int */ + int istep = __TOINT(*step); /* Calculate the number of characters. */ size_t nchar = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; @@ -206,7 +206,7 @@ { __attr * const value = &__args[1]; /* value interpreted as int */ - int i = value->intvalue; + int i = __TOINT(*value); unsigned int resultsize; char *s; diff -r b496ef9d5ee1 -r 41eddb32a603 templates/ops.c --- a/templates/ops.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/ops.c Thu Mar 23 23:36:32 2017 +0100 @@ -27,7 +27,10 @@ __ref __VALUE(__attr attr) { - return attr.value; + if (!__INTEGER(attr)) + return attr.value; + else + return &__common_integer_obj; } /* Basic structure tests. */ diff -r b496ef9d5ee1 -r 41eddb32a603 templates/progops.c --- a/templates/progops.c Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/progops.c Thu Mar 23 23:36:32 2017 +0100 @@ -73,7 +73,7 @@ /* Store a reference to the data in the object's __data__ attribute. */ - __store_via_object(args[0].value, __data__, attr); + __store_via_object(__VALUE(args[0]), __data__, attr); } #ifdef __HAVE___builtins___dict_dict @@ -221,7 +221,7 @@ /* Erase the remaining arguments. */ for (pos = nargs; pos < max; pos++) - allargs[pos].value = 0; + __SETNULL(allargs[pos]); /* Fill keyword arguments. */ @@ -246,7 +246,7 @@ for (pos = nargs; pos < max; pos++) { - if (allargs[pos].value == 0) + if (__ISNULL(allargs[pos])) allargs[pos] = __GETDEFAULT(__VALUE(target), pos - min); } } diff -r b496ef9d5ee1 -r 41eddb32a603 templates/types.h --- a/templates/types.h Thu Mar 23 16:40:57 2017 +0100 +++ b/templates/types.h Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 tests/numbers.py --- a/tests/numbers.py Thu Mar 23 16:40:57 2017 +0100 +++ b/tests/numbers.py Thu Mar 23 23:36:32 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 b496ef9d5ee1 -r 41eddb32a603 transresults.py --- a/transresults.py Thu Mar 23 16:40:57 2017 +0100 +++ b/transresults.py Thu Mar 23 23:36:32 2017 +0100 @@ -140,7 +140,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):