Lichen

Changeset

900:c7eaa76e5b0f
2019-05-20 Paul Boddie raw files shortlog changelog graph Experiment with a temporary attribute on objects. This attribute must be cleared when assignments occur, but it should also be cleared when objects escape from functions (which is not yet done). Since the motivation for marking objects as temporary is their re-use in certain operations, the objective is to avoid objects being used in multiple places and still being marked as temporary and potentially undergoing re-use/mutation. Perhaps the only way of guaranteeing exclusive access to an object is if it is provided as a function result and is immediately passed to a function or operation, with this function either mutating the object or ensuring its direct propagation to another such function. temporary-object-experiment
generator.py (file) templates/native/common.c (file) templates/native/float.c (file) templates/native/list.c (file) templates/ops.c (file) templates/ops.h (file) templates/progops.c (file) templates/types.h (file) transresults.py (file)
     1.1 --- a/generator.py	Mon Feb 04 18:53:56 2019 +0100
     1.2 +++ b/generator.py	Mon May 20 13:12:25 2019 +0200
     1.3 @@ -854,6 +854,7 @@
     1.4  typedef struct {
     1.5      const __table * table;
     1.6      __pos pos;
     1.7 +    int temporary;
     1.8      __attr attrs[%s];
     1.9  %s
    1.10  } %s;
    1.11 @@ -882,6 +883,7 @@
    1.12  %s %s = {
    1.13      &%s,
    1.14      %s,
    1.15 +    0, /* not temporary */
    1.16      {
    1.17          %s
    1.18      },
     2.1 --- a/templates/native/common.c	Mon Feb 04 18:53:56 2019 +0100
     2.2 +++ b/templates/native/common.c	Mon May 20 13:12:25 2019 +0200
     2.3 @@ -1,6 +1,6 @@
     2.4  /* Common operations for native functions.
     2.5  
     2.6 -Copyright (C) 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
     2.7 +Copyright (C) 2016, 2017, 2018, 2019 Paul Boddie <paul@boddie.org.uk>
     2.8  
     2.9  This program is free software; you can redistribute it and/or modify it under
    2.10  the terms of the GNU General Public License as published by the Free Software
    2.11 @@ -30,9 +30,9 @@
    2.12  {
    2.13      /* Create a new string and mutate the __data__, __size__ and __key__ attributes. */
    2.14      __attr attr = __NEWINSTANCE(__builtins___str_string);
    2.15 -    __store_via_object(__VALUE(attr), __data__, (__attr) {.strvalue=s});
    2.16 -    __store_via_object(__VALUE(attr), __size__, __INTVALUE(size));
    2.17 -    __store_via_object(__VALUE(attr), __key__, __NULL);
    2.18 +    __store_member(__VALUE(attr), __data__, (__attr) {.strvalue=s});
    2.19 +    __store_member(__VALUE(attr), __size__, __INTVALUE(size));
    2.20 +    __store_member(__VALUE(attr), __key__, __NULL);
    2.21      return attr;
    2.22  }
    2.23  
    2.24 @@ -40,7 +40,7 @@
    2.25  {
    2.26      /* Create a new list and mutate the __data__ attribute. */
    2.27      __attr attr = __NEWINSTANCE(__builtins___list_list);
    2.28 -    __store_via_object(__VALUE(attr), __data__, (__attr) {.seqvalue=f});
    2.29 +    __store_member(__VALUE(attr), __data__, (__attr) {.seqvalue=f});
    2.30      return attr;
    2.31  }
    2.32  
     3.1 --- a/templates/native/float.c	Mon Feb 04 18:53:56 2019 +0100
     3.2 +++ b/templates/native/float.c	Mon May 20 13:12:25 2019 +0200
     3.3 @@ -63,6 +63,28 @@
     3.4      return __NULL;
     3.5  }
     3.6  
     3.7 +static __attr make_result(__attr self, __attr other, double value)
     3.8 +{
     3.9 +    __attr result;
    3.10 +
    3.11 +    if (self.value->temporary)
    3.12 +    {
    3.13 +        __set_trailing_data(self, __builtins___float_float, value);
    3.14 +        return self;
    3.15 +    }
    3.16 +    else if (other.value->temporary)
    3.17 +    {
    3.18 +        __set_trailing_data(other, __builtins___float_float, value);
    3.19 +        return other;
    3.20 +    }
    3.21 +    else
    3.22 +    {
    3.23 +        result = __new_float(value);
    3.24 +        result.value->temporary = 1;
    3.25 +        return result;
    3.26 +    }
    3.27 +}
    3.28 +
    3.29  /* Floating point operations. Exceptions are raised in the signal handler. */
    3.30  
    3.31  __attr __fn_native_float_float_add(__attr __self, __attr self, __attr other)
    3.32 @@ -70,7 +92,7 @@
    3.33      /* self and other interpreted as float */
    3.34      double i = __TOFLOAT(self);
    3.35      double j = __TOFLOAT(other);
    3.36 -    return __new_float(i + j);
    3.37 +    return make_result(self, other, i + j);
    3.38  }
    3.39  
    3.40  __attr __fn_native_float_float_sub(__attr __self, __attr self, __attr other)
    3.41 @@ -78,7 +100,7 @@
    3.42      /* self and other interpreted as float */
    3.43      double i = __TOFLOAT(self);
    3.44      double j = __TOFLOAT(other);
    3.45 -    return __new_float(i - j);
    3.46 +    return make_result(self, other, i - j);
    3.47  }
    3.48  
    3.49  __attr __fn_native_float_float_mul(__attr __self, __attr self, __attr other)
    3.50 @@ -86,7 +108,7 @@
    3.51      /* self and other interpreted as float */
    3.52      double i = __TOFLOAT(self);
    3.53      double j = __TOFLOAT(other);
    3.54 -    return __new_float(i * j);
    3.55 +    return make_result(self, other, i * j);
    3.56  }
    3.57  
    3.58  __attr __fn_native_float_float_div(__attr __self, __attr self, __attr other)
    3.59 @@ -94,7 +116,7 @@
    3.60      /* self and other interpreted as float */
    3.61      double i = __TOFLOAT(self);
    3.62      double j = __TOFLOAT(other);
    3.63 -    return __new_float(i / j);
    3.64 +    return make_result(self, other, i / j);
    3.65  }
    3.66  
    3.67  __attr __fn_native_float_float_mod(__attr __self, __attr self, __attr other)
    3.68 @@ -102,7 +124,7 @@
    3.69      /* self and other interpreted as float */
    3.70      double i = __TOFLOAT(self);
    3.71      double j = __TOFLOAT(other);
    3.72 -    return __new_float(fmod(i, j));
    3.73 +    return make_result(self, other, fmod(i, j));
    3.74  }
    3.75  
    3.76  __attr __fn_native_float_float_neg(__attr __self, __attr self)
    3.77 @@ -128,7 +150,7 @@
    3.78          __raise_overflow_error();
    3.79  
    3.80      /* Return the result. */
    3.81 -    return __new_float(result);
    3.82 +    return make_result(self, other, result);
    3.83  }
    3.84  
    3.85  __attr __fn_native_float_float_le(__attr __self, __attr self, __attr other)
     4.1 --- a/templates/native/list.c	Mon Feb 04 18:53:56 2019 +0100
     4.2 +++ b/templates/native/list.c	Mon May 20 13:12:25 2019 +0200
     4.3 @@ -1,6 +1,6 @@
     4.4  /* Native functions for list operations.
     4.5  
     4.6 -Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
     4.7 +Copyright (C) 2016, 2017, 2019 Paul Boddie <paul@boddie.org.uk>
     4.8  
     4.9  This program is free software; you can redistribute it and/or modify it under
    4.10  the terms of the GNU General Public License as published by the Free Software
    4.11 @@ -56,7 +56,7 @@
    4.12  
    4.13      /* Replace the __data__ attribute if appropriate. */
    4.14      if (newdata != data)
    4.15 -        __store_via_object(__VALUE(self), __data__, ((__attr) {.seqvalue=newdata}));
    4.16 +        __store_member(__VALUE(self), __data__, ((__attr) {.seqvalue=newdata}));
    4.17      return __builtins___none_None;
    4.18  }
    4.19  
    4.20 @@ -84,7 +84,7 @@
    4.21  
    4.22      /* Replace the __data__ attribute if appropriate. */
    4.23      if (newdata != data)
    4.24 -        __store_via_object(__VALUE(self), __data__, ((__attr) {.seqvalue=newdata}));
    4.25 +        __store_member(__VALUE(self), __data__, ((__attr) {.seqvalue=newdata}));
    4.26      return __builtins___none_None;
    4.27  }
    4.28  
     5.1 --- a/templates/ops.c	Mon Feb 04 18:53:56 2019 +0100
     5.2 +++ b/templates/ops.c	Mon May 20 13:12:25 2019 +0200
     5.3 @@ -79,12 +79,31 @@
     5.4  
     5.5  /* Direct storage operations. */
     5.6  
     5.7 -int __store_via_object__(__ref obj, int pos, __attr value)
     5.8 +__attr __store_attr__(__attr value)
     5.9 +{
    5.10 +    if (!__ISNULL(value) && !__INTEGER(value) && value.value->temporary)
    5.11 +        value.value->temporary = 0;
    5.12 +
    5.13 +    return value;
    5.14 +}
    5.15 +
    5.16 +int __store_member__(__ref obj, int pos, __attr value)
    5.17  {
    5.18      obj->attrs[pos] = value;
    5.19      return 1;
    5.20  }
    5.21  
    5.22 +int __store_via_object__(__ref obj, int pos, __attr value)
    5.23 +{
    5.24 +    /* NOTE: To be tested at compile-time, with dynamic attribute access
    5.25 +             forbidding special attributes. */
    5.26 +
    5.27 +    if ((pos != __ATTRPOS(__data__)) && (pos != __ATTRPOS(__key__)))
    5.28 +        __store_attr__(value);
    5.29 +
    5.30 +    return __store_member__(obj, pos, value);
    5.31 +}
    5.32 +
    5.33  int __store_via_class__(__ref obj, int pos, __attr value)
    5.34  {
    5.35      return __store_via_object__(__get_class(obj), pos, value);
     6.1 --- a/templates/ops.h	Mon Feb 04 18:53:56 2019 +0100
     6.2 +++ b/templates/ops.h	Mon May 20 13:12:25 2019 +0200
     6.3 @@ -1,6 +1,6 @@
     6.4  /* Common operations.
     6.5  
     6.6 -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
     6.7 +Copyright (C) 2015, 2016, 2017, 2018, 2019 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 @@ -42,8 +42,18 @@
    6.12  #define __load_via_object(OBJ, ATTRNAME) (__load_via_object__(OBJ, __ATTRPOS(ATTRNAME)))
    6.13  #define __get_class_and_load(OBJ, ATTRNAME) (__get_class_and_load__(OBJ, __ATTRPOS(ATTRNAME)))
    6.14  
    6.15 +/* Object state updating when assigning. */
    6.16 +
    6.17 +__attr __store_attr__(__attr value);
    6.18 +
    6.19  /* Direct storage operations. */
    6.20  
    6.21 +int __store_member__(__ref obj, int pos, __attr value);
    6.22 +
    6.23 +#define __store_local(NAME, VALUE) (NAME = __store_attr__(VALUE))
    6.24 +/* #define __store_local(NAME, VALUE) (NAME = VALUE) */
    6.25 +#define __store_member(OBJ, ATTRNAME, VALUE) (__store_member__(OBJ, __ATTRPOS(ATTRNAME), VALUE))
    6.26 +
    6.27  int __store_via_class__(__ref obj, int pos, __attr value);
    6.28  int __store_via_object__(__ref obj, int pos, __attr value);
    6.29  int __get_class_and_store__(__ref obj, int pos, __attr value);
     7.1 --- a/templates/progops.c	Mon Feb 04 18:53:56 2019 +0100
     7.2 +++ b/templates/progops.c	Mon May 20 13:12:25 2019 +0200
     7.3 @@ -32,7 +32,8 @@
     7.4  {
     7.5      obj->table = table;
     7.6      obj->pos = __INSTANCEPOS;
     7.7 -    __store_via_object(obj, __class__, __ATTRVALUE(cls));
     7.8 +    obj->temporary = 0;
     7.9 +    __store_member(obj, __class__, __ATTRVALUE(cls));
    7.10  }
    7.11  
    7.12  __attr __new(const __table * table, __ref cls, size_t size, int immutable)
    7.13 @@ -81,7 +82,7 @@
    7.14  
    7.15      /* Store a reference to the data in the object's __data__ attribute. */
    7.16  
    7.17 -    __store_via_object(__VALUE(self), __data__, (__attr) {.seqvalue=data});
    7.18 +    __store_member(__VALUE(self), __data__, (__attr) {.seqvalue=data});
    7.19      __newdata_sequence(number, data, args);
    7.20      return self;
    7.21  }
    7.22 @@ -97,7 +98,7 @@
    7.23  
    7.24      /* Store a reference to the data in the object's __data__ attribute. */
    7.25  
    7.26 -    __store_via_object(__VALUE(self), __data__, (__attr) {.seqvalue=data});
    7.27 +    __store_member(__VALUE(self), __data__, (__attr) {.seqvalue=data});
    7.28      __newdata_sequence(number, data, args);
    7.29      return self;
    7.30  }
     8.1 --- a/templates/types.h	Mon Feb 04 18:53:56 2019 +0100
     8.2 +++ b/templates/types.h	Mon May 20 13:12:25 2019 +0200
     8.3 @@ -94,6 +94,7 @@
     8.4  {
     8.5      const __table * table;      /* attribute table */
     8.6      __ppos pos;                 /* position of attribute indicating class */
     8.7 +    int temporary;              /* temporary state of the object */
     8.8      __attr attrs[];             /* attributes */
     8.9  
    8.10      /* Specialisations of this type may add other members.
     9.1 --- a/transresults.py	Mon Feb 04 18:53:56 2019 +0100
     9.2 +++ b/transresults.py	Mon May 20 13:12:25 2019 +0200
     9.3 @@ -114,7 +114,7 @@
     9.4              # All other assignments involve the names as they were given.
     9.5  
     9.6              else:
     9.7 -                return "%s = %s" % (attrname, self.expr)
     9.8 +                return "__store_local(%s, %s)" % (attrname, self.expr)
     9.9  
    9.10          # Expressions.
    9.11