1.1 --- a/encoders.py Wed Jul 11 23:53:09 2018 +0200
1.2 +++ b/encoders.py Thu Jul 12 00:15:16 2018 +0200
1.3 @@ -505,6 +505,15 @@
1.4
1.5 return "__constvalue%s" % n
1.6
1.7 +def encode_trailing_area(path):
1.8 +
1.9 + """
1.10 + Encode any reference to trailing data members for instances of the type
1.11 + given by 'path'.
1.12 + """
1.13 +
1.14 + return "__TRAILING_%s" % encode_path(path)
1.15 +
1.16
1.17
1.18 # Track all encoded paths, detecting and avoiding conflicts.
2.1 --- a/generator.py Wed Jul 11 23:53:09 2018 +0200
2.2 +++ b/generator.py Thu Jul 12 00:15:16 2018 +0200
2.3 @@ -29,6 +29,7 @@
2.4 encode_path, encode_pcode, encode_pos, encode_ppos, \
2.5 encode_predefined_reference, encode_size, \
2.6 encode_symbol, encode_tablename, \
2.7 + encode_trailing_area, \
2.8 encode_type_attribute, decode_type_attribute, \
2.9 is_type_attribute
2.10 from os import listdir, mkdir, remove
2.11 @@ -42,6 +43,7 @@
2.12 # NOTE: These must be synchronised with the library.
2.13
2.14 dict_type = "__builtins__.dict.dict"
2.15 + float_type = "__builtins__.float.float"
2.16 function_type = "__builtins__.core.function"
2.17 int_type = "__builtins__.int.int"
2.18 list_type = "__builtins__.list.list"
2.19 @@ -64,6 +66,12 @@
2.20 dict_type, list_type, tuple_type
2.21 )
2.22
2.23 + # Data types with a trailing data member of the given native types.
2.24 +
2.25 + trailing_data_types = {
2.26 + float_type : "double",
2.27 + }
2.28 +
2.29 def __init__(self, importer, optimiser, output):
2.30
2.31 """
2.32 @@ -219,6 +227,7 @@
2.33
2.34 if kind != "<instance>":
2.35 structure = []
2.36 + trailing = []
2.37 attrs = self.get_static_attributes(kind, path, attrnames)
2.38
2.39 # Set a special instantiator on the class.
2.40 @@ -244,12 +253,13 @@
2.41 attrs["__args__"] = path
2.42
2.43 self.populate_structure(Reference(kind, path), attrs, kind, structure)
2.44 + self.populate_trailing(Reference(kind, path), attrs, trailing)
2.45
2.46 if kind == "<class>":
2.47 self.write_instance_structure(f_decls, path, structure_size)
2.48
2.49 - self.write_structure(f_decls, f_defs, path, table_name, structure,
2.50 - kind == "<class>" and path)
2.51 + self.write_structure(f_decls, f_defs, path, table_name,
2.52 + structure, trailing, ref)
2.53
2.54 # Record function instance details for function generation below.
2.55
2.56 @@ -297,7 +307,7 @@
2.57 function_instance_attrs["__args__"] = path
2.58
2.59 structure = self.populate_function(path, function_instance_attrs)
2.60 - self.write_structure(f_decls, f_defs, path, table_name, structure)
2.61 + self.write_structure(f_decls, f_defs, path, table_name, structure, [], Reference("<function>", path))
2.62
2.63 # Functions with defaults need to declare instance structures.
2.64
2.65 @@ -411,6 +421,12 @@
2.66 self.optimiser.locations,
2.67 "code", "pos", encode_code, encode_pos)
2.68
2.69 + # Generate trailing data macros of the form...
2.70 + # #define __TRAILING_typename nativetype trailing;
2.71 +
2.72 + for name, member_type in self.trailing_data_types.items():
2.73 + print >>f_consts, "#define %s %s trailing;" % (encode_symbol("TRAILING", name), member_type)
2.74 +
2.75 # Generate macros for calls.
2.76
2.77 all_max_parameters = list(all_max_parameters)
2.78 @@ -617,7 +633,16 @@
2.79 # Set the data, if provided.
2.80
2.81 if data is not None:
2.82 - attrs["__data__"] = data
2.83 +
2.84 + # Data retained by special attribute.
2.85 +
2.86 + if attrs.has_key("__data__"):
2.87 + attrs["__data__"] = data
2.88 +
2.89 + # Data retained by a trailing data area.
2.90 +
2.91 + elif attrs.has_key("__trailing__"):
2.92 + attrs["__trailing__"] = data
2.93
2.94 # Also set a key for dynamic attribute lookup, if a string.
2.95
2.96 @@ -658,9 +683,12 @@
2.97 # the constant in the program.
2.98
2.99 structure = []
2.100 + trailing = []
2.101 table_name = encode_tablename("<instance>", cls)
2.102 self.populate_structure(ref, attrs, ref.get_kind(), structure)
2.103 - self.write_structure(f_decls, f_defs, structure_name, table_name, structure)
2.104 + self.populate_trailing(ref, attrs, trailing)
2.105 + self.write_structure(f_decls, f_defs, structure_name, table_name,
2.106 + structure, trailing, ref)
2.107
2.108 # Define a macro for the constant.
2.109
2.110 @@ -819,38 +847,51 @@
2.111 # Write an instance-specific type definition for instances of classes.
2.112 # See: templates/types.h
2.113
2.114 + trailing_area = path in self.trailing_data_types and encode_trailing_area(path) or ""
2.115 +
2.116 print >>f_decls, """\
2.117 typedef struct {
2.118 const __table * table;
2.119 __pos pos;
2.120 __attr attrs[%s];
2.121 +%s
2.122 } %s;
2.123 -""" % (structure_size, encode_symbol("obj", path))
2.124 +""" % (structure_size, trailing_area, encode_symbol("obj", path))
2.125
2.126 - def write_structure(self, f_decls, f_defs, structure_name, table_name, structure, path=None):
2.127 + def write_structure(self, f_decls, f_defs, structure_name, table_name,
2.128 + structure, trailing, ref):
2.129
2.130 """
2.131 Write the declarations to 'f_decls' and definitions to 'f_defs' for
2.132 the object having the given 'structure_name', the given 'table_name',
2.133 - and the given 'structure' details used to populate the definition.
2.134 + the given 'structure' details and any 'trailing' member details, used to
2.135 + populate the definition.
2.136 """
2.137
2.138 + origin = ref.get_origin()
2.139 + pos = ref.has_kind("<class>") and encode_pos(encode_type_attribute(origin)) or str(self.instancepos)
2.140 +
2.141 + obj_type = ref.has_kind("<instance>") and encode_symbol("obj", origin) or "__obj"
2.142 + obj_name = encode_path(structure_name)
2.143 +
2.144 if f_decls:
2.145 - print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name)
2.146 -
2.147 - is_class = path and self.importer.get_object(path).has_kind("<class>")
2.148 - pos = is_class and encode_pos(encode_type_attribute(path)) or str(self.instancepos)
2.149 + print >>f_decls, "extern %s %s;\n" % (obj_type, obj_name)
2.150
2.151 print >>f_defs, """\
2.152 -__obj %s = {
2.153 +%s %s = {
2.154 &%s,
2.155 %s,
2.156 {
2.157 %s
2.158 - }};
2.159 + },
2.160 + %s
2.161 + };
2.162 """ % (
2.163 - encode_path(structure_name), table_name, pos,
2.164 - ",\n ".join(structure))
2.165 + obj_type, obj_name,
2.166 + table_name,
2.167 + pos,
2.168 + ",\n ".join(structure),
2.169 + trailing and ",\n ".join(trailing) or "")
2.170
2.171 def get_argument_limits(self, path):
2.172
2.173 @@ -910,6 +951,12 @@
2.174 continue
2.175 const = consts.get(attrname)
2.176 attrs[attrname] = const or Reference("<var>", "%s.%s" % (name, attrname))
2.177 +
2.178 + # Instances with trailing data.
2.179 +
2.180 + if name in self.trailing_data_types:
2.181 + attrs["__trailing__"] = Reference("<var>", "%s.__trailing__" % name)
2.182 +
2.183 return attrs
2.184
2.185 def populate_table(self, path, table):
2.186 @@ -1101,6 +1148,21 @@
2.187
2.188 structure.append(self.encode_member(origin, attrname, attr, kind))
2.189
2.190 + def populate_trailing(self, ref, attrs, trailing):
2.191 +
2.192 + """
2.193 + For the structure having the given 'ref', whose members are provided by
2.194 + the 'attrs' mapping, adding entries to the 'trailing' member collection.
2.195 + """
2.196 +
2.197 + structure_ref = self.get_target_structure(ref)
2.198 +
2.199 + # Instances with trailing data.
2.200 +
2.201 + if structure_ref.get_kind() == "<instance>" and \
2.202 + structure_ref.get_origin() in self.trailing_data_types:
2.203 + trailing.append(encode_literal_constant_value(attrs["__trailing__"]))
2.204 +
2.205 def get_target_structure(self, ref):
2.206
2.207 "Return the target structure type and reference for 'ref'."
2.208 @@ -1154,22 +1216,22 @@
2.209
2.210 if kind == "<instance>" and origin == self.none_type:
2.211 attr_path = encode_predefined_reference(self.none_value)
2.212 - return "{.value=&%s} /* %s */" % (attr_path, name)
2.213 + return "{.value=(__ref) &%s} /* %s */" % (attr_path, name)
2.214
2.215 # Predefined constant members.
2.216
2.217 if (path, name) in self.predefined_constant_members:
2.218 attr_path = encode_predefined_reference("%s.%s" % (path, name))
2.219 - return "{.value=&%s} /* %s */" % (attr_path, name)
2.220 + return "{.value=(__ref) &%s} /* %s */" % (attr_path, name)
2.221
2.222 # General undetermined members.
2.223
2.224 if kind in ("<var>", "<instance>"):
2.225 attr_path = encode_predefined_reference(self.none_value)
2.226 - return "{.value=&%s} /* %s */" % (attr_path, name)
2.227 + return "{.value=(__ref) &%s} /* %s */" % (attr_path, name)
2.228
2.229 else:
2.230 - return "{.value=&%s}" % encode_path(origin)
2.231 + return "{.value=(__ref) &%s}" % encode_path(origin)
2.232
2.233 def append_defaults(self, path, structure):
2.234
3.1 --- a/lib/__builtins__/core.py Wed Jul 11 23:53:09 2018 +0200
3.2 +++ b/lib/__builtins__/core.py Thu Jul 12 00:15:16 2018 +0200
3.3 @@ -3,7 +3,7 @@
3.4 """
3.5 Core 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 @@ -189,6 +189,15 @@
3.13
3.14 pass
3.15
3.16 +class UnderflowError(ArithmeticError):
3.17 +
3.18 + """
3.19 + Indicates that an arithmetic operation produced a result that could not be
3.20 + represented.
3.21 + """
3.22 +
3.23 + pass
3.24 +
3.25 class ZeroDivisionError(ArithmeticError):
3.26
3.27 "An error occurring when an attempt was made to divide an operand by zero."
4.1 --- a/lib/__builtins__/float.py Wed Jul 11 23:53:09 2018 +0200
4.2 +++ b/lib/__builtins__/float.py Thu Jul 12 00:15:16 2018 +0200
4.3 @@ -1,9 +1,9 @@
4.4 #!/usr/bin/env python
4.5
4.6 """
4.7 -Floating point objects.
4.8 +Floating point number objects.
4.9
4.10 -Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
4.11 +Copyright (C) 2015, 2016, 2018 Paul Boddie <paul@boddie.org.uk>
4.12
4.13 This program is free software; you can redistribute it and/or modify it under
4.14 the terms of the GNU General Public License as published by the Free Software
4.15 @@ -19,36 +19,189 @@
4.16 this program. If not, see <http://www.gnu.org/licenses/>.
4.17 """
4.18
4.19 +from __builtins__.unicode import utf8string
4.20 +from native import isinstance as _isinstance, \
4.21 + int_float, is_int, \
4.22 + float_add, float_div, float_eq, float_ge, float_gt, \
4.23 + float_le, float_lt, float_mod, float_mul, float_ne, \
4.24 + float_neg, float_pow, float_str, float_sub,
4.25 +
4.26 class float:
4.27 +
4.28 + "A floating point number abstraction."
4.29 +
4.30 def __init__(self, number_or_string=None):
4.31 - # Note member.
4.32 - self.__data__ = 0.0
4.33 +
4.34 + "Initialise the integer with the given 'number_or_string'."
4.35 +
4.36 + # NOTE: To be implemented.
4.37 +
4.38 + pass
4.39 +
4.40 + def __hash__(self):
4.41 +
4.42 + "Return a value for hashing purposes."
4.43 +
4.44 + return self
4.45 +
4.46 + def _binary_op(self, op, other):
4.47 +
4.48 + "Perform 'op' on this float and 'other' if appropriate."
4.49 +
4.50 + if _isinstance(other, float):
4.51 + return op(self, other)
4.52 + elif is_int(other):
4.53 + return op(self, int_float(other))
4.54 + else:
4.55 + return NotImplemented
4.56 +
4.57 + def _binary_op_rev(self, op, other):
4.58 +
4.59 + "Perform 'op' on 'other' and this float if appropriate."
4.60 +
4.61 + if _isinstance(other, float):
4.62 + return op(other, self)
4.63 + elif is_int(other):
4.64 + return op(int_float(other), self)
4.65 + else:
4.66 + return NotImplemented
4.67 +
4.68 + def __iadd__(self, other):
4.69 +
4.70 + "Return a new float for the addition of this float and 'other'."
4.71
4.72 - def __iadd__(self, other): pass
4.73 - def __isub__(self, other): pass
4.74 - def __add__(self, other): pass
4.75 - def __radd__(self, other): pass
4.76 - def __sub__(self, other): pass
4.77 - def __rsub__(self, other): pass
4.78 - def __mul__(self, other): pass
4.79 - def __rmul__(self, other): pass
4.80 - def __div__(self, other): pass
4.81 - def __rdiv__(self, other): pass
4.82 + return self._binary_op(float_add, other)
4.83 +
4.84 + def __isub__(self, other):
4.85 +
4.86 + "Return a new float for the subtraction from this float of 'other'."
4.87 +
4.88 + return self._binary_op(float_sub, other)
4.89 +
4.90 + def __imul__(self, other):
4.91 +
4.92 + "Return a new float for the multiplication of this float and 'other'."
4.93 +
4.94 + return self._binary_op(float_mul, other)
4.95 +
4.96 + def __idiv__(self, other):
4.97 +
4.98 + "Return a new float for the division of this float by 'other'."
4.99 +
4.100 + return self._binary_op(float_div, other)
4.101 +
4.102 + def __imod__(self, other):
4.103 +
4.104 + "Return a new float for the modulo of this float by 'other'."
4.105 +
4.106 + return self._binary_op(float_mod, other)
4.107 +
4.108 + def __ipow__(self, other):
4.109 +
4.110 + "Return a new float for the exponentiation of this float by 'other'."
4.111 +
4.112 + return self._binary_op(float_pow, other)
4.113 +
4.114 + __add__ = __radd__ = __iadd__
4.115 + __sub__ = __isub__
4.116 +
4.117 + def __rsub__(self, other):
4.118 +
4.119 + "Return a new float for the subtraction of this float from 'other'."
4.120 +
4.121 + return self._binary_op_rev(float_sub, other)
4.122 +
4.123 + __mul__ = __rmul__ = __imul__
4.124 + __div__ = __idiv__
4.125 +
4.126 + def __rdiv__(self, other):
4.127 +
4.128 + "Return a new float for the division of 'other' by this float."
4.129 +
4.130 + return self._binary_op_rev(float_div, other)
4.131 +
4.132 + # NOTE: To be implemented.
4.133 +
4.134 def __floordiv__(self, other): pass
4.135 def __rfloordiv__(self, other): pass
4.136 - def __mod__(self, other): pass
4.137 - def __rmod__(self, other): pass
4.138 - def __pow__(self, other): pass
4.139 - def __rpow__(self, other): pass
4.140 - def __lt__(self, other): pass
4.141 - def __gt__(self, other): pass
4.142 - def __le__(self, other): pass
4.143 - def __ge__(self, other): pass
4.144 - def __eq__(self, other): pass
4.145 - def __ne__(self, other): pass
4.146 - def __neg__(self): pass
4.147 - def __pos__(self): pass
4.148 - def __str__(self): pass
4.149 - def __bool__(self): pass
4.150 + def __ifloordiv__(self, other): pass
4.151 +
4.152 + __mod__ = __imod__
4.153 +
4.154 + def __rmod__(self, other):
4.155 +
4.156 + "Return a new float for the modulo of 'other' by this float."
4.157 +
4.158 + return self._binary_op_rev(float_mod, other)
4.159 +
4.160 + __pow__ = __ipow__
4.161 +
4.162 + def __rpow__(self, other):
4.163 +
4.164 + "Return a new float for the exponentiation of 'other' by this float."
4.165 +
4.166 + return self._binary_op_rev(float_pow, other)
4.167 +
4.168 + def __lt__(self, other):
4.169 +
4.170 + "Return whether this float is less than 'other'."
4.171 +
4.172 + return self._binary_op(float_lt, other)
4.173 +
4.174 + def __gt__(self, other):
4.175 +
4.176 + "Return whether this float is greater than 'other'."
4.177 +
4.178 + return self._binary_op(float_gt, other)
4.179 +
4.180 + def __le__(self, other):
4.181 +
4.182 + "Return whether this float is less than or equal to 'other'."
4.183 +
4.184 + return self._binary_op(float_le, other)
4.185 +
4.186 + def __ge__(self, other):
4.187 +
4.188 + "Return whether this float is greater than or equal to 'other'."
4.189 +
4.190 + return self._binary_op(float_ge, other)
4.191 +
4.192 + def __eq__(self, other):
4.193 +
4.194 + "Return whether this float is equal to 'other'."
4.195 +
4.196 + return self._binary_op(float_eq, other)
4.197 +
4.198 + def __ne__(self, other):
4.199 +
4.200 + "Return whether this float is not equal to 'other'."
4.201 +
4.202 + return self._binary_op(float_ne, other)
4.203 +
4.204 + def __neg__(self):
4.205 +
4.206 + "Apply the unary negation operator."
4.207 +
4.208 + return float_neg(self)
4.209 +
4.210 + def __pos__(self):
4.211 +
4.212 + "Apply the unary positive operator."
4.213 +
4.214 + return self
4.215 +
4.216 + def __str__(self):
4.217 +
4.218 + "Return a string representation."
4.219 +
4.220 + return utf8string(float_str(self))
4.221 +
4.222 + __repr__ = __str__
4.223 +
4.224 + def __bool__(self):
4.225 +
4.226 + "Return whether this float is non-zero."
4.227 +
4.228 + return float_ne(self, 0)
4.229
4.230 # vim: tabstop=4 expandtab shiftwidth=4
5.1 --- a/lib/native/__init__.py Wed Jul 11 23:53:09 2018 +0200
5.2 +++ b/lib/native/__init__.py Thu Jul 12 00:15:16 2018 +0200
5.3 @@ -3,7 +3,7 @@
5.4 """
5.5 Native library functions.
5.6
5.7 -Copyright (C) 2011, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
5.8 +Copyright (C) 2011, 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
5.9
5.10 This program is free software; you can redistribute it and/or modify it under
5.11 the terms of the GNU General Public License as published by the Free Software
5.12 @@ -21,13 +21,19 @@
5.13
5.14 from native.buffer import buffer_str
5.15
5.16 +from native.float import float_add, float_div, float_mod, float_mul, \
5.17 + float_neg, float_pow, float_sub, \
5.18 + float_eq, float_ge, float_gt, float_le, float_lt, \
5.19 + float_ne, \
5.20 + float_int, float_str
5.21 +
5.22 from native.identity import is_, is_not
5.23
5.24 from native.int import int_add, int_div, int_mod, int_mul, int_neg, int_pow, \
5.25 int_sub, int_and, int_not, int_or, int_xor, \
5.26 int_lshift, int_rshift, \
5.27 int_eq, int_ge, int_gt, int_le, int_lt, int_ne, \
5.28 - int_str, is_int
5.29 + int_float, int_str, is_int
5.30
5.31 from native.introspection import object_getattr, isinstance, issubclass
5.32
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/lib/native/float.py Thu Jul 12 00:15:16 2018 +0200
6.3 @@ -0,0 +1,45 @@
6.4 +#!/usr/bin/env python
6.5 +
6.6 +"""
6.7 +Native library functions for floating point numbers.
6.8 +
6.9 +None of these are actually defined here. Instead, native implementations are
6.10 +substituted when each program is built. It is, however, important to declare
6.11 +non-core exceptions used by the native functions because they need to be
6.12 +identified as being needed by the program.
6.13 +
6.14 +Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
6.15 +
6.16 +This program is free software; you can redistribute it and/or modify it under
6.17 +the terms of the GNU General Public License as published by the Free Software
6.18 +Foundation; either version 3 of the License, or (at your option) any later
6.19 +version.
6.20 +
6.21 +This program is distributed in the hope that it will be useful, but WITHOUT
6.22 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6.23 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
6.24 +details.
6.25 +
6.26 +You should have received a copy of the GNU General Public License along with
6.27 +this program. If not, see <http://www.gnu.org/licenses/>.
6.28 +"""
6.29 +
6.30 +def float_add(self, other): return 0.0
6.31 +def float_div(self, other): return 0.0
6.32 +def float_mod(self, other): return 0.0
6.33 +def float_mul(self, other): return 0.0
6.34 +def float_neg(self): return 0.0
6.35 +def float_pow(self, other): return 0.0
6.36 +def float_sub(self, other): return 0.0
6.37 +
6.38 +def float_eq(self, other): return True or False
6.39 +def float_ge(self, other): return True or False
6.40 +def float_gt(self, other): return True or False
6.41 +def float_le(self, other): return True or False
6.42 +def float_lt(self, other): return True or False
6.43 +def float_ne(self, other): return True or False
6.44 +
6.45 +def float_str(self): return ""
6.46 +def float_int(self): return 0
6.47 +
6.48 +# vim: tabstop=4 expandtab shiftwidth=4
7.1 --- a/lib/native/int.py Wed Jul 11 23:53:09 2018 +0200
7.2 +++ b/lib/native/int.py Thu Jul 12 00:15:16 2018 +0200
7.3 @@ -8,7 +8,7 @@
7.4 non-core exceptions used by the native functions because they need to be
7.5 identified as being needed by the program.
7.6
7.7 -Copyright (C) 2011, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
7.8 +Copyright (C) 2011, 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
7.9
7.10 This program is free software; you can redistribute it and/or modify it under
7.11 the terms of the GNU General Public License as published by the Free Software
7.12 @@ -53,5 +53,6 @@
7.13 def int_ne(self, other): return True or False
7.14
7.15 def int_str(self): return ""
7.16 +def int_float(self): return 0.0
7.17
7.18 # vim: tabstop=4 expandtab shiftwidth=4
8.1 --- a/templates/native/common.c Wed Jul 11 23:53:09 2018 +0200
8.2 +++ b/templates/native/common.c Thu Jul 12 00:15:16 2018 +0200
8.3 @@ -44,6 +44,14 @@
8.4 return attr;
8.5 }
8.6
8.7 +__attr __new_float(double n)
8.8 +{
8.9 + /* Create a new float and set the trailing data. */
8.10 + __attr attr = __NEWINSTANCE(__builtins___float_float);
8.11 + __set_trailing_data(attr, __builtins___float_float, n);
8.12 + return attr;
8.13 +}
8.14 +
8.15 __fragment *__fragment_append(__fragment *data, __attr value)
8.16 {
8.17 __fragment *newdata = data;
9.1 --- a/templates/native/common.h Wed Jul 11 23:53:09 2018 +0200
9.2 +++ b/templates/native/common.h Thu Jul 12 00:15:16 2018 +0200
9.3 @@ -1,6 +1,6 @@
9.4 /* Common operations for native functions.
9.5
9.6 -Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
9.7 +Copyright (C) 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 @@ -21,11 +21,15 @@
9.12
9.13 #include "types.h"
9.14
9.15 -/* Utility functions. */
9.16 +/* Utility macro for the special integer representation. */
9.17
9.18 #define __new_int(VALUE) __INTVALUE(VALUE)
9.19 +
9.20 +/* Utility functions. */
9.21 +
9.22 __attr __new_str(char *s, int size);
9.23 __attr __new_list(__fragment *f);
9.24 +__attr __new_float(double n);
9.25 __fragment *__fragment_append(__fragment *data, __attr value);
9.26
9.27 #endif /* __NATIVE_COMMON_H__ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/templates/native/float.c Thu Jul 12 00:15:16 2018 +0200
10.3 @@ -0,0 +1,345 @@
10.4 +/* Native functions for floating point operations.
10.5 +
10.6 +Copyright (C) 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
10.7 +
10.8 +This program is free software; you can redistribute it and/or modify it under
10.9 +the terms of the GNU General Public License as published by the Free Software
10.10 +Foundation; either version 3 of the License, or (at your option) any later
10.11 +version.
10.12 +
10.13 +This program is distributed in the hope that it will be useful, but WITHOUT
10.14 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10.15 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10.16 +details.
10.17 +
10.18 +You should have received a copy of the GNU General Public License along with
10.19 +this program. If not, see <http://www.gnu.org/licenses/>.
10.20 +*/
10.21 +
10.22 +#include <fenv.h> /* feclearexcept, fetestexcept */
10.23 +#include <math.h> /* pow */
10.24 +#include <stdio.h> /* snprintf */
10.25 +#include <errno.h> /* errno */
10.26 +#include "native/common.h"
10.27 +#include "types.h"
10.28 +#include "exceptions.h"
10.29 +#include "ops.h"
10.30 +#include "progconsts.h"
10.31 +#include "progops.h"
10.32 +#include "progtypes.h"
10.33 +#include "main.h"
10.34 +
10.35 +/* Conversion from a pair of consecutive attributes to a double-precision
10.36 + floating point number. */
10.37 +
10.38 +static double __TOFLOAT(__attr attr)
10.39 +{
10.40 + return __get_trailing_data(attr, __builtins___float_float);
10.41 +}
10.42 +
10.43 +/* Numeric formatting using snprintf.
10.44 + NOTE: This might be moved elsewhere and used by other types. */
10.45 +
10.46 +static __attr format_number(double n, int size)
10.47 +{
10.48 + char *s = (char *) __ALLOCATE(size, sizeof(char));
10.49 + int digits;
10.50 +
10.51 + /* Allocation should raise a memory error if it fails, so this loop should
10.52 + terminate via the return statement or an allocation failure. */
10.53 +
10.54 + while (1)
10.55 + {
10.56 + digits = snprintf(s, size, "%f", n);
10.57 +
10.58 + if (digits < size)
10.59 + {
10.60 + s = (char *) __REALLOCATE(s, (digits + 1) * sizeof(char));
10.61 + return __new_str(s, digits);
10.62 + }
10.63 +
10.64 + size = digits + 1;
10.65 + s = (char *) __REALLOCATE(s, size * sizeof(char));
10.66 + }
10.67 +
10.68 + return __NULL;
10.69 +}
10.70 +
10.71 +/* Floating point exception handling. */
10.72 +
10.73 +static void init_env(fenv_t *envp, int excepts)
10.74 +{
10.75 + fegetenv(envp);
10.76 + feclearexcept(excepts);
10.77 +}
10.78 +
10.79 +static int test_env(fenv_t *envp, int excepts)
10.80 +{
10.81 + if (fetestexcept(excepts))
10.82 + {
10.83 + fesetenv(envp);
10.84 + return 1;
10.85 + }
10.86 + return 0;
10.87 +}
10.88 +
10.89 +static int have_result(fenv_t *envp, int excepts)
10.90 +{
10.91 + return !fetestexcept(excepts);
10.92 +}
10.93 +
10.94 +static __attr make_result(fenv_t *envp, double result)
10.95 +{
10.96 + fesetenv(envp);
10.97 + return __new_float(result);
10.98 +}
10.99 +
10.100 +/* Floating point operations. */
10.101 +
10.102 +__attr __fn_native_float_float_add(__attr __self, __attr self, __attr other)
10.103 +{
10.104 + /* self and other interpreted as float */
10.105 + double i = __TOFLOAT(self);
10.106 + double j = __TOFLOAT(other);
10.107 + double result;
10.108 +
10.109 + /* Preserve environment, clear exception state. */
10.110 + fenv_t env;
10.111 + init_env(&env, FE_OVERFLOW);
10.112 +
10.113 + result = i + j;
10.114 +
10.115 + /* Test for result, restore state, return the new float. */
10.116 + if (have_result(&env, FE_OVERFLOW))
10.117 + return make_result(&env, result);
10.118 +
10.119 + /* Restore state, raise exception. */
10.120 + if (test_env(&env, FE_OVERFLOW))
10.121 + __raise_overflow_error();
10.122 + return __NULL;
10.123 +}
10.124 +
10.125 +__attr __fn_native_float_float_sub(__attr __self, __attr self, __attr other)
10.126 +{
10.127 + /* self and other interpreted as float */
10.128 + double i = __TOFLOAT(self);
10.129 + double j = __TOFLOAT(other);
10.130 + double result;
10.131 +
10.132 + /* Preserve environment, clear exception state. */
10.133 + fenv_t env;
10.134 + init_env(&env, FE_OVERFLOW);
10.135 +
10.136 + result = i - j;
10.137 +
10.138 + /* Test for result, restore state, return the new float. */
10.139 + if (have_result(&env, FE_OVERFLOW))
10.140 + return make_result(&env, result);
10.141 +
10.142 + /* Restore state, raise exception. */
10.143 + if (test_env(&env, FE_OVERFLOW))
10.144 + __raise_overflow_error();
10.145 + return __NULL;
10.146 +}
10.147 +
10.148 +__attr __fn_native_float_float_mul(__attr __self, __attr self, __attr other)
10.149 +{
10.150 + /* self and other interpreted as float */
10.151 + double i = __TOFLOAT(self);
10.152 + double j = __TOFLOAT(other);
10.153 + double result;
10.154 +
10.155 + /* Preserve environment, clear exception state. */
10.156 + fenv_t env;
10.157 + init_env(&env, FE_OVERFLOW | FE_UNDERFLOW);
10.158 +
10.159 + result = i * j;
10.160 +
10.161 + /* Test for result, restore state, return the new float. */
10.162 + if (have_result(&env, FE_OVERFLOW | FE_UNDERFLOW))
10.163 + return make_result(&env, result);
10.164 +
10.165 + /* Restore state, raise exception. */
10.166 + if (test_env(&env, FE_OVERFLOW))
10.167 + __raise_overflow_error();
10.168 + if (test_env(&env, FE_UNDERFLOW))
10.169 + __raise_underflow_error();
10.170 + return __NULL;
10.171 +}
10.172 +
10.173 +__attr __fn_native_float_float_div(__attr __self, __attr self, __attr other)
10.174 +{
10.175 + /* self and other interpreted as float */
10.176 + double i = __TOFLOAT(self);
10.177 + double j = __TOFLOAT(other);
10.178 + double result;
10.179 +
10.180 + /* Preserve environment, clear exception state. */
10.181 + fenv_t env;
10.182 + init_env(&env, FE_OVERFLOW | FE_UNDERFLOW | FE_DIVBYZERO);
10.183 +
10.184 + result = i / j;
10.185 +
10.186 + /* Test for result, restore state, return the new float. */
10.187 + if (have_result(&env, FE_OVERFLOW | FE_UNDERFLOW | FE_DIVBYZERO))
10.188 + return make_result(&env, result);
10.189 +
10.190 + /* Restore state, raise exception. */
10.191 + if (test_env(&env, FE_OVERFLOW))
10.192 + __raise_overflow_error();
10.193 + if (test_env(&env, FE_UNDERFLOW))
10.194 + __raise_underflow_error();
10.195 + if (test_env(&env, FE_DIVBYZERO))
10.196 + __raise_zero_division_error();
10.197 + return __NULL;
10.198 +}
10.199 +
10.200 +__attr __fn_native_float_float_mod(__attr __self, __attr self, __attr other)
10.201 +{
10.202 + /* self and other interpreted as float */
10.203 + double i = __TOFLOAT(self);
10.204 + double j = __TOFLOAT(other);
10.205 + double result;
10.206 +
10.207 + /* Preserve environment, clear exception state. */
10.208 + fenv_t env;
10.209 + init_env(&env, FE_OVERFLOW | FE_DIVBYZERO);
10.210 +
10.211 + result = fmod(i, j);
10.212 +
10.213 + /* Test for result, restore state, return the new float. */
10.214 + if (have_result(&env, FE_OVERFLOW | FE_DIVBYZERO))
10.215 + return make_result(&env, result);
10.216 +
10.217 + /* Restore state, raise exception. */
10.218 + if (test_env(&env, FE_OVERFLOW))
10.219 + __raise_overflow_error();
10.220 + if (test_env(&env, FE_DIVBYZERO))
10.221 + __raise_zero_division_error();
10.222 + return __NULL;
10.223 +}
10.224 +
10.225 +__attr __fn_native_float_float_neg(__attr __self, __attr self)
10.226 +{
10.227 + /* self interpreted as float */
10.228 + double i = __TOFLOAT(self);
10.229 + double result;
10.230 +
10.231 + /* Preserve environment, clear exception state. */
10.232 + fenv_t env;
10.233 + init_env(&env, FE_OVERFLOW);
10.234 +
10.235 + result = -i;
10.236 +
10.237 + /* Test for result, restore state, return the new float. */
10.238 + if (have_result(&env, FE_OVERFLOW))
10.239 + return make_result(&env, result);
10.240 +
10.241 + /* Restore state, raise exception. */
10.242 + if (test_env(&env, FE_OVERFLOW))
10.243 + __raise_overflow_error();
10.244 + return __NULL;
10.245 +}
10.246 +
10.247 +__attr __fn_native_float_float_pow(__attr __self, __attr self, __attr other)
10.248 +{
10.249 + /* self and other interpreted as float */
10.250 + double i = __TOFLOAT(self);
10.251 + double j = __TOFLOAT(other);
10.252 + double result;
10.253 +
10.254 + errno = 0;
10.255 + result = pow(i, j);
10.256 +
10.257 + /* Test for overflow. */
10.258 +
10.259 + if (errno == ERANGE)
10.260 + __raise_overflow_error();
10.261 +
10.262 + /* Return the result. */
10.263 + return __new_float(result);
10.264 +}
10.265 +
10.266 +__attr __fn_native_float_float_le(__attr __self, __attr self, __attr other)
10.267 +{
10.268 + /* self and other interpreted as float */
10.269 + double i = __TOFLOAT(self);
10.270 + double j = __TOFLOAT(other);
10.271 +
10.272 + /* Return a boolean result. */
10.273 + return i <= j ? __builtins___boolean_True : __builtins___boolean_False;
10.274 +}
10.275 +
10.276 +__attr __fn_native_float_float_lt(__attr __self, __attr self, __attr other)
10.277 +{
10.278 + /* self and other interpreted as float */
10.279 + double i = __TOFLOAT(self);
10.280 + double j = __TOFLOAT(other);
10.281 +
10.282 + /* Return a boolean result. */
10.283 + return i < j ? __builtins___boolean_True : __builtins___boolean_False;
10.284 +}
10.285 +
10.286 +__attr __fn_native_float_float_ge(__attr __self, __attr self, __attr other)
10.287 +{
10.288 + /* self and other interpreted as float */
10.289 + double i = __TOFLOAT(self);
10.290 + double j = __TOFLOAT(other);
10.291 +
10.292 + /* Return a boolean result. */
10.293 + return i >= j ? __builtins___boolean_True : __builtins___boolean_False;
10.294 +}
10.295 +
10.296 +__attr __fn_native_float_float_gt(__attr __self, __attr self, __attr other)
10.297 +{
10.298 + /* self and other interpreted as float */
10.299 + double i = __TOFLOAT(self);
10.300 + double j = __TOFLOAT(other);
10.301 +
10.302 + /* Return a boolean result. */
10.303 + return i > j ? __builtins___boolean_True : __builtins___boolean_False;
10.304 +}
10.305 +
10.306 +__attr __fn_native_float_float_eq(__attr __self, __attr self, __attr other)
10.307 +{
10.308 + /* self and other interpreted as float */
10.309 + double i = __TOFLOAT(self);
10.310 + double j = __TOFLOAT(other);
10.311 +
10.312 + /* Return a boolean result. */
10.313 + return i == j ? __builtins___boolean_True : __builtins___boolean_False;
10.314 +}
10.315 +
10.316 +__attr __fn_native_float_float_ne(__attr __self, __attr self, __attr other)
10.317 +{
10.318 + /* self and other interpreted as float */
10.319 + double i = __TOFLOAT(self);
10.320 + double j = __TOFLOAT(other);
10.321 +
10.322 + /* Return a boolean result. */
10.323 + return i != j ? __builtins___boolean_True : __builtins___boolean_False;
10.324 +}
10.325 +
10.326 +__attr __fn_native_float_float_str(__attr __self, __attr self)
10.327 +{
10.328 + /* self interpreted as float */
10.329 + double i = __TOFLOAT(self);
10.330 +
10.331 + /* Return a new string. */
10.332 + return format_number(i, 64);
10.333 +}
10.334 +
10.335 +__attr __fn_native_float_float_int(__attr __self, __attr self)
10.336 +{
10.337 + /* self interpreted as float */
10.338 + double i = __TOFLOAT(self);
10.339 +
10.340 + /* NOTE: Test for conversion failure. */
10.341 + return __new_int((int) i);
10.342 +}
10.343 +
10.344 +/* Module initialisation. */
10.345 +
10.346 +void __main_native_float()
10.347 +{
10.348 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/templates/native/float.h Thu Jul 12 00:15:16 2018 +0200
11.3 @@ -0,0 +1,48 @@
11.4 +/* Native functions for floating point operations.
11.5 +
11.6 +Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
11.7 +
11.8 +This program is free software; you can redistribute it and/or modify it under
11.9 +the terms of the GNU General Public License as published by the Free Software
11.10 +Foundation; either version 3 of the License, or (at your option) any later
11.11 +version.
11.12 +
11.13 +This program is distributed in the hope that it will be useful, but WITHOUT
11.14 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11.15 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11.16 +details.
11.17 +
11.18 +You should have received a copy of the GNU General Public License along with
11.19 +this program. If not, see <http://www.gnu.org/licenses/>.
11.20 +*/
11.21 +
11.22 +#ifndef __NATIVE_FLOAT_H__
11.23 +#define __NATIVE_FLOAT_H__
11.24 +
11.25 +#include "types.h"
11.26 +
11.27 +/* Floating point operations. */
11.28 +
11.29 +__attr __fn_native_float_float_add(__attr __self, __attr self, __attr other);
11.30 +__attr __fn_native_float_float_sub(__attr __self, __attr self, __attr other);
11.31 +__attr __fn_native_float_float_mul(__attr __self, __attr self, __attr other);
11.32 +__attr __fn_native_float_float_div(__attr __self, __attr self, __attr other);
11.33 +__attr __fn_native_float_float_mod(__attr __self, __attr self, __attr other);
11.34 +__attr __fn_native_float_float_neg(__attr __self, __attr self);
11.35 +__attr __fn_native_float_float_pow(__attr __self, __attr self, __attr other);
11.36 +
11.37 +__attr __fn_native_float_float_le(__attr __self, __attr self, __attr other);
11.38 +__attr __fn_native_float_float_lt(__attr __self, __attr self, __attr other);
11.39 +__attr __fn_native_float_float_ge(__attr __self, __attr self, __attr other);
11.40 +__attr __fn_native_float_float_gt(__attr __self, __attr self, __attr other);
11.41 +__attr __fn_native_float_float_eq(__attr __self, __attr self, __attr other);
11.42 +__attr __fn_native_float_float_ne(__attr __self, __attr self, __attr other);
11.43 +
11.44 +__attr __fn_native_float_float_str(__attr __self, __attr self);
11.45 +__attr __fn_native_float_float_int(__attr __self, __attr self);
11.46 +
11.47 +/* Module initialisation. */
11.48 +
11.49 +void __main_native_float();
11.50 +
11.51 +#endif /* __NATIVE_FLOAT_H__ */
12.1 --- a/templates/native/int.c Wed Jul 11 23:53:09 2018 +0200
12.2 +++ b/templates/native/int.c Thu Jul 12 00:15:16 2018 +0200
12.3 @@ -1,6 +1,6 @@
12.4 /* Native functions for integer operations.
12.5
12.6 -Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
12.7 +Copyright (C) 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
12.8
12.9 This program is free software; you can redistribute it and/or modify it under
12.10 the terms of the GNU General Public License as published by the Free Software
12.11 @@ -290,6 +290,14 @@
12.12 return __new_str(s, strlen(s));
12.13 }
12.14
12.15 +__attr __fn_native_int_int_float(__attr __self, __attr self)
12.16 +{
12.17 + /* self interpreted as int */
12.18 + int i = __TOINT(self);
12.19 +
12.20 + return __new_float((double) i);
12.21 +}
12.22 +
12.23 /* Module initialisation. */
12.24
12.25 void __main_native_int()
13.1 --- a/templates/native/int.h Wed Jul 11 23:53:09 2018 +0200
13.2 +++ b/templates/native/int.h Thu Jul 12 00:15:16 2018 +0200
13.3 @@ -1,6 +1,6 @@
13.4 /* Native functions for integer operations.
13.5
13.6 -Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
13.7 +Copyright (C) 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
13.8
13.9 This program is free software; you can redistribute it and/or modify it under
13.10 the terms of the GNU General Public License as published by the Free Software
13.11 @@ -48,6 +48,7 @@
13.12 __attr __fn_native_int_int_ne(__attr __self, __attr _data, __attr other);
13.13
13.14 __attr __fn_native_int_int_str(__attr __self, __attr _data);
13.15 +__attr __fn_native_int_int_float(__attr __self, __attr _data);
13.16
13.17 /* Module initialisation. */
13.18
14.1 --- a/templates/ops.c Wed Jul 11 23:53:09 2018 +0200
14.2 +++ b/templates/ops.c Thu Jul 12 00:15:16 2018 +0200
14.3 @@ -1,6 +1,6 @@
14.4 /* Common operations.
14.5
14.6 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
14.7 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
14.8
14.9 This program is free software; you can redistribute it and/or modify it under
14.10 the terms of the GNU General Public License as published by the Free Software
14.11 @@ -30,7 +30,7 @@
14.12 if (!__INTEGER(attr))
14.13 return attr.value;
14.14 else
14.15 - return &__common_integer_obj;
14.16 + return (__ref) &__common_integer_obj;
14.17 }
14.18
14.19 /* Basic structure tests. */
15.1 --- a/templates/progops.c Wed Jul 11 23:53:09 2018 +0200
15.2 +++ b/templates/progops.c Thu Jul 12 00:15:16 2018 +0200
15.3 @@ -156,6 +156,11 @@
15.4 __Raise(__new___builtins___core_TypeError(__NULL));
15.5 }
15.6
15.7 +void __raise_underflow_error()
15.8 +{
15.9 + __Raise(__new___builtins___core_UnderflowError(__NULL));
15.10 +}
15.11 +
15.12 void __raise_zero_division_error()
15.13 {
15.14 __Raise(__new___builtins___core_ZeroDivisionError(__NULL));
15.15 @@ -303,7 +308,7 @@
15.16
15.17 __ref value = __VALUE(attr);
15.18
15.19 - return value == &__predefined___builtins___boolean_True ? 1 :
15.20 - value == &__predefined___builtins___boolean_False ? 0 :
15.21 - __VALUE(__fn___builtins___boolean_bool(__NULL, attr)) == &__predefined___builtins___boolean_True;
15.22 + return value == (__ref) &__predefined___builtins___boolean_True ? 1 :
15.23 + value == (__ref) &__predefined___builtins___boolean_False ? 0 :
15.24 + __VALUE(__fn___builtins___boolean_bool(__NULL, attr)) == (__ref) &__predefined___builtins___boolean_True;
15.25 }
16.1 --- a/templates/progops.h Wed Jul 11 23:53:09 2018 +0200
16.2 +++ b/templates/progops.h Thu Jul 12 00:15:16 2018 +0200
16.3 @@ -1,6 +1,6 @@
16.4 /* Operations depending on program specifics.
16.5
16.6 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
16.7 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
16.8
16.9 This program is free software; you can redistribute it and/or modify it under
16.10 the terms of the GNU General Public License as published by the Free Software
16.11 @@ -38,25 +38,22 @@
16.12 #define __newliteral___builtins___list_list(NUM, ...) __newdata_list(NUM, __ARGS(__VA_ARGS__))
16.13 #define __newliteral___builtins___tuple_tuple(NUM, ...) __newdata_tuple(NUM, __ARGS(__VA_ARGS__))
16.14
16.15 +/* Potentially superfluous operations. */
16.16 +
16.17 #ifdef __HAVE___builtins___dict_dict
16.18 __attr __newdata_dict(unsigned int number, __attr args[]);
16.19 #define __newliteral___builtins___dict_dict(NUM, ...) __newdata_dict(NUM, __ARGS(__VA_ARGS__))
16.20 -#endif /* __HAVE___builtins___dict_dict */
16.21 +#endif
16.22
16.23 /* Helpers for raising errors within common operations. */
16.24
16.25 void __raise_eof_error();
16.26 -
16.27 void __raise_io_error(__attr value);
16.28 -
16.29 void __raise_memory_error();
16.30 -
16.31 void __raise_os_error(__attr value, __attr arg);
16.32 -
16.33 void __raise_overflow_error();
16.34 -
16.35 +void __raise_underflow_error();
16.36 void __raise_zero_division_error();
16.37 -
16.38 void __raise_type_error();
16.39
16.40 /* Helper for raising exception instances. */
16.41 @@ -76,17 +73,21 @@
16.42 /* Generic operations depending on specific program details. */
16.43
16.44 void __SETDEFAULT(__ref obj, int pos, __attr value);
16.45 -
16.46 __attr __GETDEFAULT(__ref obj, int pos);
16.47 -
16.48 int __BOOL(__attr attr);
16.49
16.50 /* Convenience definitions. */
16.51
16.52 -#define __INSTANCESIZE(CLS) sizeof(__obj_##CLS)
16.53 +#define __OBJTYPE(CLS) __obj_##CLS
16.54 +#define __INSTANCESIZE(CLS) sizeof(__OBJTYPE(CLS))
16.55 #define __INSTANCETABLE(CLS) (__InstanceTable_##CLS)
16.56 #define __NEWINSTANCE(CLS) __new(&__INSTANCETABLE(CLS), &CLS, __INSTANCESIZE(CLS), 0)
16.57 #define __NEWINSTANCEIM(CLS) __new(&__INSTANCETABLE(CLS), &CLS, __INSTANCESIZE(CLS), 1)
16.58 #define __ISINSTANCE(ATTR, TYPE) __BOOL(__fn_native_introspection_isinstance(__NULL, ATTR, TYPE))
16.59
16.60 +/* Operations for accessing trailing data. */
16.61 +
16.62 +#define __get_trailing_data(ATTR, TYPE) (((__OBJTYPE(TYPE) *) ((ATTR).value))->trailing)
16.63 +#define __set_trailing_data(ATTR, TYPE, VALUE) ((__OBJTYPE(TYPE) *) ((ATTR).value))->trailing = VALUE;
16.64 +
16.65 #endif /* __PROGOPS_H__ */
17.1 --- a/templates/types.h Wed Jul 11 23:53:09 2018 +0200
17.2 +++ b/templates/types.h Thu Jul 12 00:15:16 2018 +0200
17.3 @@ -1,6 +1,6 @@
17.4 /* Runtime types.
17.5
17.6 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
17.7 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
17.8
17.9 This program is free software; you can redistribute it and/or modify it under
17.10 the terms of the GNU General Public License as published by the Free Software
17.11 @@ -85,7 +85,6 @@
17.12 __ppos pos; /* parameter table position for key */
17.13 };
17.14 __attr (*fn)(); /* callable details */
17.15 - float floatvalue; /* floating point value */
17.16 char * strvalue; /* string value */
17.17 __fragment * seqvalue; /* sequence data */
17.18 void * datavalue; /* object-specific data */
17.19 @@ -96,6 +95,11 @@
17.20 const __table * table; /* attribute table */
17.21 __ppos pos; /* position of attribute indicating class */
17.22 __attr attrs[]; /* attributes */
17.23 +
17.24 + /* Specialisations of this type may add other members.
17.25 + See generator.py for type generation, progops.h for definitions, and
17.26 + the generated progtypes.h for the final details. */
17.27 +
17.28 } __obj;
17.29
17.30 #define __INSTANCE_SIZE(NUMBER) ((NUMBER) * sizeof(__attr) + sizeof(__table *) + sizeof(__ppos))
17.31 @@ -117,7 +121,7 @@
17.32
17.33 /* Attribute value setting. */
17.34
17.35 -#define __ATTRVALUE(VALUE) ((__attr) {.value=VALUE})
17.36 +#define __ATTRVALUE(VALUE) ((__attr) {.value=(__ref) VALUE})
17.37 #define __NULL __ATTRVALUE(0)
17.38 #define __SETNULL(ATTR) ((ATTR).value = 0)
17.39
18.1 --- a/tests/numbers.py Wed Jul 11 23:53:09 2018 +0200
18.2 +++ b/tests/numbers.py Thu Jul 12 00:15:16 2018 +0200
18.3 @@ -55,6 +55,21 @@
18.4 print "# hash((sys.maxint - 1, 0)):",
18.5 print hash((sys.maxint - 1, 0))
18.6
18.7 +# Floating point numbers.
18.8 +
18.9 +i = 2.0 ** 29
18.10 +print i # 536870912.0
18.11 +j = -2.0 ** 29
18.12 +print j # -536870912.0
18.13 +print i + j # 0
18.14 +print i - j # -1073741824.0
18.15 +print i * i # 2.8823037615171174e+17
18.16 +
18.17 +try:
18.18 + print i ** i
18.19 +except OverflowError:
18.20 + print "i ** i: overflow occurred"
18.21 +
18.22 # Test combining numbers with strings.
18.23
18.24 s = "Number is " + str(123)