1.1 --- a/deducer.py Tue Jul 10 13:28:53 2018 +0200
1.2 +++ b/deducer.py Thu Jul 12 18:19:02 2018 +0200
1.3 @@ -2938,7 +2938,13 @@
1.4 # Produce an advisory instruction regarding the context.
1.5
1.6 if context_var:
1.7 - if context_test in ("ignore", "replace"):
1.8 +
1.9 + # Only verify the context for invocation purposes if a suitable
1.10 + # test has been performed.
1.11 +
1.12 + if context_test in ("ignore", "replace") or \
1.13 + final_method in ("access-invoke", "static-invoke"):
1.14 +
1.15 emit(("<context_identity_verified>", context_var))
1.16 else:
1.17 emit(("<context_identity>", context_var))
2.1 --- a/generator.py Tue Jul 10 13:28:53 2018 +0200
2.2 +++ b/generator.py Thu Jul 12 18:19:02 2018 +0200
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Generate C code from object layouts and other deduced information.
2.6
2.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -204,14 +204,12 @@
2.13 # Generate table and structure data.
2.14
2.15 function_instance_attrs = None
2.16 - objects = self.optimiser.attr_table.items()
2.17 + objects = self.optimiser.all_attrs.items()
2.18 objects.sort()
2.19
2.20 self.callables = {}
2.21
2.22 - for ref, indexes in objects:
2.23 - attrnames = self.get_attribute_names(indexes)
2.24 -
2.25 + for ref, attrnames in objects:
2.26 kind = ref.get_kind()
2.27 path = ref.get_origin()
2.28 table_name = encode_tablename(kind, path)
2.29 @@ -613,8 +611,7 @@
2.30 # Obtain the attributes.
2.31
2.32 cls = ref.get_origin()
2.33 - indexes = self.optimiser.attr_table[ref]
2.34 - attrnames = self.get_attribute_names(indexes)
2.35 + attrnames = self.optimiser.all_attrs[ref]
2.36 attrs = self.get_instance_attributes(cls, attrnames)
2.37
2.38 # Set the data, if provided.
2.39 @@ -867,22 +864,6 @@
2.40 num_parameters = len(parameters) + 1
2.41 return num_parameters - (defaults and len(defaults) or 0), num_parameters
2.42
2.43 - def get_attribute_names(self, indexes):
2.44 -
2.45 - """
2.46 - Given a list of attribute table 'indexes', return a list of attribute
2.47 - names.
2.48 - """
2.49 -
2.50 - all_attrnames = self.optimiser.all_attrnames
2.51 - attrnames = []
2.52 - for i in indexes:
2.53 - if i is None:
2.54 - attrnames.append(None)
2.55 - else:
2.56 - attrnames.append(all_attrnames[i])
2.57 - return attrnames
2.58 -
2.59 def get_static_attributes(self, kind, name, attrnames):
2.60
2.61 """
2.62 @@ -987,17 +968,8 @@
2.63 structure of the given 'kind', adding entries to the object 'structure'.
2.64 """
2.65
2.66 - # Populate function instance structures for functions.
2.67 -
2.68 - if ref.has_kind("<function>"):
2.69 - origin = self.function_type
2.70 - structure_ref = Reference("<instance>", self.function_type)
2.71 -
2.72 - # Otherwise, just populate the appropriate structures.
2.73 -
2.74 - else:
2.75 - origin = ref.get_origin()
2.76 - structure_ref = ref
2.77 + structure_ref = self.get_target_structure(ref)
2.78 + origin = structure_ref.get_origin()
2.79
2.80 for attrname in self.optimiser.structures[structure_ref]:
2.81
2.82 @@ -1129,6 +1101,20 @@
2.83
2.84 structure.append(self.encode_member(origin, attrname, attr, kind))
2.85
2.86 + def get_target_structure(self, ref):
2.87 +
2.88 + "Return the target structure type and reference for 'ref'."
2.89 +
2.90 + # Populate function instance structures for functions.
2.91 +
2.92 + if ref.has_kind("<function>"):
2.93 + return Reference("<instance>", self.function_type)
2.94 +
2.95 + # Otherwise, just populate the appropriate structures.
2.96 +
2.97 + else:
2.98 + return ref
2.99 +
2.100 def encode_member(self, path, name, ref, structure_type):
2.101
2.102 """
3.1 --- a/lib/__builtins__/int.py Tue Jul 10 13:28:53 2018 +0200
3.2 +++ b/lib/__builtins__/int.py Thu Jul 12 18:19:02 2018 +0200
3.3 @@ -3,7 +3,7 @@
3.4 """
3.5 Integer objects.
3.6
3.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
3.8 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
3.9
3.10 This program is free software; you can redistribute it and/or modify it under
3.11 the terms of the GNU General Public License as published by the Free Software
3.12 @@ -19,12 +19,12 @@
3.13 this program. If not, see <http://www.gnu.org/licenses/>.
3.14 """
3.15
3.16 -from __builtins__.operator import _negate
3.17 from __builtins__.unicode import utf8string
3.18 from native import get_maxint, get_minint, is_int, \
3.19 - int_add, int_and, int_div, int_eq, int_gt, int_lshift, \
3.20 - int_lt, int_mod, int_mul, int_ne, int_neg, int_not, \
3.21 - int_or, int_pow, int_rshift, int_str, int_sub, int_xor
3.22 + int_add, int_and, int_div, int_eq, int_ge, int_gt, \
3.23 + int_lshift, int_le, int_lt, int_mod, int_mul, int_ne, \
3.24 + int_neg, int_not, int_or, int_pow, int_rshift, int_str, \
3.25 + int_sub, int_xor
3.26
3.27 class int:
3.28
3.29 @@ -140,6 +140,8 @@
3.30
3.31 return self._binary_op_rev(int_div, other)
3.32
3.33 + # NOTE: To be implemented.
3.34 +
3.35 def __floordiv__(self, other): pass
3.36 def __rfloordiv__(self, other): pass
3.37 def __ifloordiv__(self, other): pass
3.38 @@ -189,7 +191,6 @@
3.39 return self._binary_op_rev(int_rshift, other)
3.40
3.41 __ilshift__ = __lshift__
3.42 -
3.43 __irshift__ = __rshift__
3.44
3.45 def __lt__(self, other):
3.46 @@ -208,13 +209,13 @@
3.47
3.48 "Return whether this int is less than or equal to 'other'."
3.49
3.50 - return _negate(self.__gt__(other))
3.51 + return self._binary_op(int_le, other)
3.52
3.53 def __ge__(self, other):
3.54
3.55 "Return whether this int is greater than or equal to 'other'."
3.56
3.57 - return _negate(self.__lt__(other))
3.58 + return self._binary_op(int_ge, other)
3.59
3.60 def __eq__(self, other):
3.61
3.62 @@ -226,7 +227,7 @@
3.63
3.64 "Return whether this int is not equal to 'other'."
3.65
3.66 - return _negate(self.__eq__(other))
3.67 + return self._binary_op(int_ne, other)
3.68
3.69 def __neg__(self):
3.70
4.1 --- a/optimiser.py Tue Jul 10 13:28:53 2018 +0200
4.2 +++ b/optimiser.py Thu Jul 12 18:19:02 2018 +0200
4.3 @@ -3,7 +3,7 @@
4.4 """
4.5 Optimise object layouts and generate access instruction plans.
4.6
4.7 -Copyright (C) 2014, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
4.8 +Copyright (C) 2014, 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
4.9
4.10 This program is free software; you can redistribute it and/or modify it under
4.11 the terms of the GNU General Public License as published by the Free Software
4.12 @@ -413,6 +413,12 @@
4.13 finally:
4.14 f.close()
4.15
4.16 + def is_allocated_attribute(self, attrname):
4.17 +
4.18 + "Return whether 'attrname' is to be allocated in an object."
4.19 +
4.20 + return not attrname.startswith("$t")
4.21 +
4.22 def populate_objects(self):
4.23
4.24 "Populate objects using attribute and usage information."
4.25 @@ -432,8 +438,8 @@
4.26
4.27 # Remove temporary names from structures.
4.28
4.29 - attrnames = filter(lambda x: not x.startswith("$t"), attrnames)
4.30 - self.all_attrs[(objkind, name)] = attrnames
4.31 + attrnames = filter(self.is_allocated_attribute, attrnames)
4.32 + self.all_attrs[Reference(objkind, name)] = attrnames
4.33
4.34 try:
4.35 self.locations = get_allocated_locations(self.all_attrs,
4.36 @@ -495,8 +501,7 @@
4.37
4.38 # Record the structures.
4.39
4.40 - for (objkind, name), attrnames in self.all_attrs.items():
4.41 - key = Reference(objkind, name)
4.42 + for key, attrnames in self.all_attrs.items():
4.43 l = self.structures[key] = [None] * len(attrnames)
4.44
4.45 for attrname in attrnames:
4.46 @@ -719,7 +724,7 @@
4.47
4.48 """
4.49 Get attribute and size information for the object attributes defined by 'd'
4.50 - providing a mapping from (object kind, type name) to attribute names.
4.51 + providing a mapping from object references to attribute names.
4.52
4.53 Return a matrix of attributes (each row entry consisting of column values
4.54 providing attribute names, with value positions corresponding to types
4.55 @@ -736,15 +741,15 @@
4.56 sizes = {}
4.57 objkinds = {}
4.58
4.59 - for objtype, attrnames in d.items():
4.60 - objkind, _name = objtype
4.61 + for ref, attrnames in d.items():
4.62 + objkind = ref.get_kind()
4.63
4.64 for attrname in attrnames:
4.65
4.66 # Record each type supporting the attribute.
4.67
4.68 init_item(attrs, attrname, set)
4.69 - attrs[attrname].add(objtype)
4.70 + attrs[attrname].add(ref)
4.71
4.72 # Maintain a record of the smallest object size supporting the given
4.73 # attribute.
4.74 @@ -761,13 +766,13 @@
4.75
4.76 # Obtain attribute details in order of size and occupancy.
4.77
4.78 - all_objtypes = d.keys()
4.79 + all_refs = d.keys()
4.80
4.81 rsizes = []
4.82 for attrname, size in sizes.items():
4.83 priority = "<instance>" in objkinds[attrname] and 0.5 or 1
4.84 occupied = len(attrs[attrname])
4.85 - key = (priority * size, size, len(all_objtypes) - occupied, attrname)
4.86 + key = (priority * size, size, len(all_refs) - occupied, attrname)
4.87 rsizes.append(key)
4.88
4.89 rsizes.sort()
4.90 @@ -775,20 +780,20 @@
4.91 # Make a matrix of attributes.
4.92
4.93 matrix = {}
4.94 - for attrname, objtypes in attrs.items():
4.95 + for attrname, refs in attrs.items():
4.96
4.97 # Traverse the object types, adding the attribute name if the object
4.98 # type supports the attribute, adding None otherwise.
4.99
4.100 row = []
4.101 - for objtype in all_objtypes:
4.102 - if objtype in objtypes:
4.103 + for ref in all_refs:
4.104 + if ref in refs:
4.105 row.append(attrname)
4.106 else:
4.107 row.append(None)
4.108 matrix[attrname] = row
4.109
4.110 - return matrix, all_objtypes, rsizes
4.111 + return matrix, all_refs, rsizes
4.112
4.113 def get_parameters_and_sizes(d):
4.114
5.1 --- a/templates/native/common.c Tue Jul 10 13:28:53 2018 +0200
5.2 +++ b/templates/native/common.c Thu Jul 12 18:19:02 2018 +0200
5.3 @@ -1,6 +1,6 @@
5.4 /* Common operations for native functions.
5.5
5.6 -Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
5.7 +Copyright (C) 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
5.8
5.9 This program is free software; you can redistribute it and/or modify it under
5.10 the terms of the GNU General Public License as published by the Free Software
5.11 @@ -30,9 +30,9 @@
5.12 {
5.13 /* Create a new string and mutate the __data__, __size__ and __key__ attributes. */
5.14 __attr attr = __NEWINSTANCE(__builtins___str_string);
5.15 - attr.value->attrs[__ATTRPOS(__data__)].strvalue = s;
5.16 - attr.value->attrs[__ATTRPOS(__size__)] = __INTVALUE(size);
5.17 - attr.value->attrs[__ATTRPOS(__key__)] = __NULL;
5.18 + __store_via_object(__VALUE(attr), __data__, (__attr) {.strvalue=s});
5.19 + __store_via_object(__VALUE(attr), __size__, __INTVALUE(size));
5.20 + __store_via_object(__VALUE(attr), __key__, __NULL);
5.21 return attr;
5.22 }
5.23
5.24 @@ -40,7 +40,7 @@
5.25 {
5.26 /* Create a new list and mutate the __data__ attribute. */
5.27 __attr attr = __NEWINSTANCE(__builtins___list_list);
5.28 - attr.value->attrs[__ATTRPOS(__data__)].seqvalue = f;
5.29 + __store_via_object(__VALUE(attr), __data__, (__attr) {.seqvalue=f});
5.30 return attr;
5.31 }
5.32
6.1 --- a/templates/ops.c Tue Jul 10 13:28:53 2018 +0200
6.2 +++ b/templates/ops.c Thu Jul 12 18:19:02 2018 +0200
6.3 @@ -1,6 +1,6 @@
6.4 /* Common operations.
6.5
6.6 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
6.7 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
6.8
6.9 This program is free software; you can redistribute it and/or modify it under
6.10 the terms of the GNU General Public License as published by the Free Software
6.11 @@ -231,7 +231,7 @@
6.12
6.13 /* Context-related operations. */
6.14
6.15 -int __test_context_update(__attr context, __attr attr)
6.16 +int __test_context_update(__attr context, __attr attr, int invoke)
6.17 {
6.18 /* Return whether the context should be updated for the attribute. */
6.19
6.20 @@ -258,6 +258,11 @@
6.21 __raise_type_error();
6.22 }
6.23
6.24 + /* Without a null or instance context, an invocation cannot be performed. */
6.25 +
6.26 + if (invoke)
6.27 + __raise_unbound_method_error();
6.28 +
6.29 /* Test for access to a type class attribute using a type instance. */
6.30
6.31 if (__test_specific_type(attrcontextvalue, &__TYPE_CLASS_TYPE) && __is_type_instance(__VALUE(context)))
6.32 @@ -272,7 +277,7 @@
6.33 {
6.34 /* Update the context or return the unchanged attribute. */
6.35
6.36 - if (__test_context_update(context, attr))
6.37 + if (__test_context_update(context, attr, 0))
6.38 return __update_context(context, attr);
6.39 else
6.40 return attr;
6.41 @@ -288,7 +293,7 @@
6.42 /* Revert the local context to that employed by the attribute if the
6.43 supplied context is not appropriate. */
6.44
6.45 - if (!__test_context_update(context, attr))
6.46 + if (!__test_context_update(context, attr, 1))
6.47 contexts[target] = __CONTEXT_AS_VALUE(attr);
6.48 return attr;
6.49 }
6.50 @@ -297,7 +302,7 @@
6.51 {
6.52 /* Set the local context to the specified context if appropriate. */
6.53
6.54 - if (__test_context_update(context, __ATTRVALUE(value)))
6.55 + if (__test_context_update(context, __ATTRVALUE(value), 1))
6.56 contexts[target] = context;
6.57 return __ATTRVALUE(value);
6.58 }
7.1 --- a/templates/ops.h Tue Jul 10 13:28:53 2018 +0200
7.2 +++ b/templates/ops.h Thu Jul 12 18:19:02 2018 +0200
7.3 @@ -101,7 +101,7 @@
7.4
7.5 /* Context-related operations. */
7.6
7.7 -int __test_context_update(__attr context, __attr attr);
7.8 +int __test_context_update(__attr context, __attr attr, int invoke);
7.9 __attr __test_context(__attr context, __attr attr);
7.10 __attr __update_context(__attr context, __attr attr);
7.11 __attr __test_context_revert(int target, __attr context, __attr attr, __attr contexts[]);
8.1 --- a/templates/progops.c Tue Jul 10 13:28:53 2018 +0200
8.2 +++ b/templates/progops.c Thu Jul 12 18:19:02 2018 +0200
8.3 @@ -151,6 +151,11 @@
8.4 __Raise(__new___builtins___core_OverflowError(__NULL));
8.5 }
8.6
8.7 +void __raise_unbound_method_error()
8.8 +{
8.9 + __Raise(__new___builtins___core_UnboundMethodInvocation(__NULL));
8.10 +}
8.11 +
8.12 void __raise_type_error()
8.13 {
8.14 __Raise(__new___builtins___core_TypeError(__NULL));
9.1 --- a/templates/progops.h Tue Jul 10 13:28:53 2018 +0200
9.2 +++ b/templates/progops.h Thu Jul 12 18:19:02 2018 +0200
9.3 @@ -1,6 +1,6 @@
9.4 /* Operations depending on program specifics.
9.5
9.6 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
9.7 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
9.8
9.9 This program is free software; you can redistribute it and/or modify it under
9.10 the terms of the GNU General Public License as published by the Free Software
9.11 @@ -55,6 +55,8 @@
9.12
9.13 void __raise_overflow_error();
9.14
9.15 +void __raise_unbound_method_error();
9.16 +
9.17 void __raise_zero_division_error();
9.18
9.19 void __raise_type_error();
11.1 --- a/translator.py Tue Jul 10 13:28:53 2018 +0200
11.2 +++ b/translator.py Thu Jul 12 18:19:02 2018 +0200
11.3 @@ -1070,9 +1070,21 @@
11.4
11.5 context_required = True
11.6 have_access_context = isinstance(expr, AttrResult)
11.7 +
11.8 + # The context identity is merely the thing providing the context.
11.9 + # A verified context is one that does not need further testing for
11.10 + # suitability.
11.11 +
11.12 context_identity = have_access_context and expr.context()
11.13 context_verified = have_access_context and expr.context_verified()
11.14 +
11.15 + # The presence of any test operations in the accessor expression.
11.16 + # With such operations present, the expression cannot be eliminated.
11.17 +
11.18 tests_accessor = have_access_context and expr.tests_accessor()
11.19 +
11.20 + # Parameter details and parameter list dimensions.
11.21 +
11.22 parameters = None
11.23 num_parameters = None
11.24 num_defaults = None
11.25 @@ -1252,11 +1264,13 @@
11.26
11.27 if context_required:
11.28 if have_access_context:
11.29 - args = [context_identity]
11.30 + context_arg = context_identity
11.31 else:
11.32 - args = ["__CONTEXT_AS_VALUE(%s)" % target_var]
11.33 + context_arg = "__CONTEXT_AS_VALUE(%s)" % target_var
11.34 else:
11.35 - args = ["__NULL"]
11.36 + context_arg = "__NULL"
11.37 +
11.38 + args = [context_arg]
11.39
11.40 # Complete the array with null values, permitting tests for a complete
11.41 # set of arguments.
11.42 @@ -1398,25 +1412,23 @@
11.43 elif function:
11.44 if context_required:
11.45
11.46 - # With context_verified or context_identity...
11.47 -
11.48 - if have_access_context:
11.49 + # Avoid further context testing if appropriate.
11.50 +
11.51 + if have_access_context and context_verified:
11.52 emit("__get_function_member(%s)" % target_expr)
11.53
11.54 # Otherwise, test the context for the function/method.
11.55
11.56 else:
11.57 - emit("__get_function(__CONTEXT_AS_VALUE(%s), %s)" % (
11.58 - target_var, target_expr))
11.59 + emit("__get_function(%s, %s)" % (context_arg, target_expr))
11.60 else:
11.61 emit("_get_function_member(%s)" % target_expr)
11.62
11.63 # With known parameters, the target can be tested.
11.64
11.65 elif known_parameters:
11.66 - context_arg = context_required and args[0] or "__NULL"
11.67 if self.always_callable(refs):
11.68 - if context_verified or context_identity:
11.69 + if context_verified:
11.70 emit("__get_function_member(%s)" % target_expr)
11.71 else:
11.72 emit("__get_function(%s, %s)" % (context_arg, target_expr))