Lichen

Changeset

579:d3811f95c60e
2017-02-13 Paul Boddie raw files shortlog changelog graph Moved minimum parameter information to parameter tables, adding maximum parameter information (also fixing tests in the __invoke function), and thus making parameter tables distinct according to minimum parameters and parameter member details. This changes the __attr size to a single word and thus reduces the program data volume even further. method-wrapper-for-context
generator.py (file) templates/progops.c (file) templates/types.h (file)
     1.1 --- a/generator.py	Mon Feb 13 16:03:52 2017 +0100
     1.2 +++ b/generator.py	Mon Feb 13 16:55:30 2017 +0100
     1.3 @@ -217,7 +217,7 @@
     1.4                          # Define special attributes.
     1.5  
     1.6                          attrs["__fn__"] = path
     1.7 -                        attrs["__args__"] = encode_size("pmin", path)
     1.8 +                        attrs["__args__"] = path
     1.9  
    1.10                      self.populate_structure(Reference(kind, path), attrs, kind, structure)
    1.11  
    1.12 @@ -270,7 +270,7 @@
    1.13                  # Set a special callable attribute on the instance.
    1.14  
    1.15                  function_instance_attrs["__fn__"] = path
    1.16 -                function_instance_attrs["__args__"] = encode_size("pmin", path)
    1.17 +                function_instance_attrs["__args__"] = path
    1.18  
    1.19                  structure = self.populate_function(path, function_instance_attrs)
    1.20                  self.write_structure(f_decls, f_defs, path, table_name, structure)
    1.21 @@ -286,22 +286,48 @@
    1.22  
    1.23                  print >>f_signatures, "__attr %s(__attr args[]);" % encode_function_pointer(path)
    1.24  
    1.25 +            # Generate parameter table size data.
    1.26 +
    1.27 +            min_parameters = {}
    1.28 +            max_parameters = {}
    1.29 +            size_parameters = {}
    1.30 +
    1.31              # Consolidate parameter tables for instantiators and functions.
    1.32  
    1.33              parameter_tables = set()
    1.34  
    1.35              for path, function_path in self.callables.items():
    1.36 +                argmin, argmax = self.get_argument_limits(function_path)
    1.37 +
    1.38 +                # Obtain the parameter table members.
    1.39 +
    1.40                  parameters = self.optimiser.parameters[function_path]
    1.41                  if not parameters:
    1.42                      parameters = ()
    1.43                  else:
    1.44                      parameters = tuple(parameters)
    1.45 -                parameter_tables.add(parameters)
    1.46 +
    1.47 +                # Define each table in terms of the members and the minimum
    1.48 +                # number of arguments.
    1.49 +
    1.50 +                parameter_tables.add((argmin, parameters))
    1.51 +                signature = self.get_parameter_signature(argmin, parameters)
    1.52 +
    1.53 +                # Record the minimum number of arguments, the maximum number,
    1.54 +                # and the size of the table.
    1.55 +
    1.56 +                min_parameters[signature] = argmin
    1.57 +                max_parameters[signature] = argmax
    1.58 +                size_parameters[signature] = len(parameters)
    1.59 +
    1.60 +            self.write_size_constants(f_consts, "pmin", min_parameters, 0)
    1.61 +            self.write_size_constants(f_consts, "pmax", max_parameters, 0)
    1.62 +            self.write_size_constants(f_consts, "psize", size_parameters, 0)
    1.63  
    1.64              # Generate parameter tables for distinct function signatures.
    1.65  
    1.66 -            for parameters in parameter_tables:
    1.67 -                self.make_parameter_table(f_decls, f_defs, parameters)
    1.68 +            for argmin, parameters in parameter_tables:
    1.69 +                self.make_parameter_table(f_decls, f_defs, argmin, parameters)
    1.70  
    1.71              # Generate predefined constants.
    1.72  
    1.73 @@ -340,27 +366,6 @@
    1.74              for kind, sizes in size_tables:
    1.75                  self.write_size_constants(f_consts, kind, sizes, 0)
    1.76  
    1.77 -            # Generate parameter table size data.
    1.78 -
    1.79 -            min_sizes = {}
    1.80 -            max_sizes = {}
    1.81 -
    1.82 -            # Determine the minimum number of parameters for each 
    1.83 -
    1.84 -            for path in self.optimiser.parameters.keys():
    1.85 -                argmin, argmax = self.get_argument_limits(path)
    1.86 -                min_sizes[path] = argmin
    1.87 -
    1.88 -            # Use the parameter table details to define the maximum number.
    1.89 -            # The context is already present in the collection.
    1.90 -
    1.91 -            for parameters in parameter_tables:
    1.92 -                signature = self.get_parameter_signature(parameters)
    1.93 -                max_sizes[signature] = len(parameters)
    1.94 -
    1.95 -            self.write_size_constants(f_consts, "pmin", min_sizes, 0)
    1.96 -            self.write_size_constants(f_consts, "pmax", max_sizes, 0)
    1.97 -
    1.98              # Generate parameter codes.
    1.99  
   1.100              self.write_code_constants(f_consts, self.optimiser.all_paramnames, self.optimiser.arg_locations, "pcode", "ppos")
   1.101 @@ -535,29 +540,32 @@
   1.102          attr_name = encode_path(const_path)
   1.103          print >>f_decls, "#define %s ((__attr) {.value=&%s})" % (attr_name, structure_name)
   1.104  
   1.105 -    def make_parameter_table(self, f_decls, f_defs, parameters):
   1.106 +    def make_parameter_table(self, f_decls, f_defs, argmin, parameters):
   1.107  
   1.108          """
   1.109          Write parameter table details to 'f_decls' (to declare a table) and to
   1.110 -        'f_defs' (to define the contents) for the given 'parameters'.
   1.111 +        'f_defs' (to define the contents) for the given 'argmin' and
   1.112 +        'parameters'.
   1.113          """
   1.114  
   1.115          # Use a signature for the table name instead of a separate name for each
   1.116          # function.
   1.117  
   1.118 -        signature = self.get_parameter_signature(parameters)
   1.119 +        signature = self.get_parameter_signature(argmin, parameters)
   1.120          table_name = encode_tablename("<function>", signature)
   1.121 -        structure_size = encode_size("pmax", signature)
   1.122 +        min_parameters = encode_size("pmin", signature)
   1.123 +        max_parameters = encode_size("pmax", signature)
   1.124 +        structure_size = encode_size("psize", signature)
   1.125  
   1.126          table = []
   1.127          self.populate_parameter_table(parameters, table)
   1.128 -        self.write_parameter_table(f_decls, f_defs, table_name, structure_size, table)
   1.129 +        self.write_parameter_table(f_decls, f_defs, table_name, min_parameters, max_parameters, structure_size, table)
   1.130  
   1.131 -    def get_parameter_signature(self, parameters):
   1.132 +    def get_parameter_signature(self, argmin, parameters):
   1.133  
   1.134 -        "Return a signature for the given 'parameters'."
   1.135 +        "Return a signature for the given 'argmin' and 'parameters'."
   1.136  
   1.137 -        l = []
   1.138 +        l = [str(argmin)]
   1.139          for parameter in parameters:
   1.140              if parameter is None:
   1.141                  l.append("")
   1.142 @@ -571,8 +579,9 @@
   1.143          "Return the signature for the callable with the given 'path'."
   1.144  
   1.145          function_path = self.callables[path]
   1.146 +        argmin, argmax = self.get_argument_limits(function_path)
   1.147          parameters = self.optimiser.parameters[function_path]
   1.148 -        return self.get_parameter_signature(parameters)
   1.149 +        return self.get_parameter_signature(argmin, parameters)
   1.150  
   1.151      def write_size_constants(self, f_consts, size_prefix, sizes, padding):
   1.152  
   1.153 @@ -639,19 +648,22 @@
   1.154          %s
   1.155      }
   1.156  };
   1.157 -""" % (table_name, structure_size, ",\n        ".join(table))
   1.158 +""" % (table_name, structure_size,
   1.159 +       ",\n        ".join(table))
   1.160  
   1.161 -    def write_parameter_table(self, f_decls, f_defs, table_name, structure_size, table):
   1.162 +    def write_parameter_table(self, f_decls, f_defs, table_name, min_parameters,
   1.163 +                              max_parameters, structure_size, table):
   1.164  
   1.165          """
   1.166          Write the declarations to 'f_decls' and definitions to 'f_defs' for
   1.167 -        the object having the given 'table_name' and the given 'structure_size',
   1.168 -        with 'table' details used to populate the definition.
   1.169 +        the object having the given 'table_name' and the given 'min_parameters',
   1.170 +        'max_parameters' and 'structure_size', with 'table' details used to
   1.171 +        populate the definition.
   1.172          """
   1.173  
   1.174          members = []
   1.175          for t in table:
   1.176 -            members.append("{%s, %s}" % t)
   1.177 +            members.append("{.code=%s, .pos=%s}" % t)
   1.178  
   1.179          print >>f_decls, "extern const __ptable %s;\n" % table_name
   1.180  
   1.181 @@ -659,12 +671,15 @@
   1.182  
   1.183          print >>f_defs, """\
   1.184  const __ptable %s = {
   1.185 -    %s,
   1.186 +    .min=%s,
   1.187 +    .max=%s,
   1.188 +    .size=%s,
   1.189      {
   1.190          %s
   1.191      }
   1.192  };
   1.193 -""" % (table_name, structure_size, ",\n        ".join(members))
   1.194 +""" % (table_name, min_parameters, max_parameters, structure_size,
   1.195 +       ",\n        ".join(members))
   1.196  
   1.197      def write_instance_structure(self, f_decls, path, structure_size):
   1.198  
   1.199 @@ -886,7 +901,7 @@
   1.200                      signature = self.get_signature_for_callable(ref.get_origin())
   1.201                      ptable = encode_tablename("<function>", signature)
   1.202  
   1.203 -                    structure.append("{.min=%s, .ptable=&%s}" % (attr, ptable))
   1.204 +                    structure.append("{.ptable=&%s}" % ptable)
   1.205                      continue
   1.206  
   1.207                  # Special internal data member.
     2.1 --- a/templates/progops.c	Mon Feb 13 16:03:52 2017 +0100
     2.2 +++ b/templates/progops.c	Mon Feb 13 16:55:30 2017 +0100
     2.3 @@ -189,13 +189,10 @@
     2.4      __attr target = __unwrap_callable(callable);
     2.5  
     2.6      /* Obtain the __args__ special member, referencing the parameter table. */
     2.7 -
     2.8 -    __attr minparams = __check_and_load_via_object(target.value, __ATTRPOS(__args__), __ATTRCODE(__args__));
     2.9 -
    2.10      /* Refer to the table and minimum/maximum. */
    2.11  
    2.12 -    const __ptable *ptable = minparams.ptable;
    2.13 -    const unsigned int min = minparams.min, max = ptable->size;
    2.14 +    const __ptable *ptable = __check_and_load_via_object(target.value, __ATTRPOS(__args__), __ATTRCODE(__args__)).ptable;
    2.15 +    const unsigned int min = ptable->min, max = ptable->max;
    2.16  
    2.17      /* Reserve enough space for the arguments. */
    2.18  
     3.1 --- a/templates/types.h	Mon Feb 13 16:03:52 2017 +0100
     3.2 +++ b/templates/types.h	Mon Feb 13 16:55:30 2017 +0100
     3.3 @@ -49,7 +49,7 @@
     3.4  
     3.5  typedef struct __ptable
     3.6  {
     3.7 -    const __ppos size;
     3.8 +    const __ppos min, max, size;
     3.9      const __param params[];
    3.10  } __ptable;
    3.11  
    3.12 @@ -65,23 +65,20 @@
    3.13  
    3.14  typedef union __attr
    3.15  {
    3.16 -    __ref value;                    /* attribute value */
    3.17 +    __ref value;                /* attribute value */
    3.18 +    const __ptable * ptable;    /* parameter table */
    3.19      struct {
    3.20 -        __ppos min;                 /* minimum number of parameters */
    3.21 -        const __ptable * ptable;    /* parameter table */
    3.22 +        __pcode code;           /* parameter table code for key */
    3.23 +        __ppos pos;             /* parameter table position for key */
    3.24      };
    3.25      struct {
    3.26 -        __pcode code;               /* parameter table code for key */
    3.27 -        __ppos pos;                 /* parameter table position for key */
    3.28 -    };
    3.29 -    struct {
    3.30 -        __attr (*fn)();             /* callable details */
    3.31 +        __attr (*fn)();         /* callable details */
    3.32      };
    3.33 -    int intvalue;                   /* integer value */
    3.34 -    float floatvalue;               /* floating point value */
    3.35 -    char * strvalue;                /* string value */
    3.36 -    __fragment * seqvalue;          /* sequence data */
    3.37 -    void * datavalue;               /* object-specific data */
    3.38 +    int intvalue;               /* integer value */
    3.39 +    float floatvalue;          	/* floating point value */
    3.40 +    char * strvalue;            /* string value */
    3.41 +    __fragment * seqvalue;      /* sequence data */
    3.42 +    void * datavalue;           /* object-specific data */
    3.43  } __attr;
    3.44  
    3.45  typedef struct __obj