1.1 --- a/templates/ops.c Sun Nov 14 00:50:17 2021 +0100
1.2 +++ b/templates/ops.c Sun Nov 28 02:03:21 2021 +0100
1.3 @@ -37,6 +37,24 @@
1.4 return (pos < obj->table->size) && (obj->table->attrs[pos] == code);
1.5 }
1.6
1.7 +/* Generic load wrapper employing temporary stack storage. */
1.8 +
1.9 +__attr __load(__attr value)
1.10 +{
1.11 + /* Copy values where appropriate. */
1.12 +
1.13 + if (__COPYABLE(value))
1.14 + {
1.15 + size_t value_size = __INSTANCE_SIZE(__VALUE(value));
1.16 + __attr target = __stack_allocate(__stack, value_size);
1.17 +
1.18 + __COPY_TO(__VALUE(value), __VALUE(target), value_size);
1.19 + return __TO_MUTABLE(target);
1.20 + }
1.21 + else
1.22 + return value;
1.23 +}
1.24 +
1.25 /* Direct access and manipulation of static objects. */
1.26
1.27 __attr __load_static_ignore(__ref obj)
1.28 @@ -76,8 +94,71 @@
1.29
1.30 /* Direct storage operations. */
1.31
1.32 +__attr __store_local(__attr target, __attr value)
1.33 +{
1.34 + /* Copy values where appropriate. */
1.35 +
1.36 + if (__COPYABLE(value))
1.37 + {
1.38 + size_t value_size = __INSTANCE_SIZE(__VALUE(value));
1.39 +
1.40 + /* Allocate new space for values if the target is not a mutable value
1.41 + or refers to an object that is too small for the value. */
1.42 +
1.43 + if ((__VALUE(target) == NULL) || !__MUTABLE(target) || (value_size > __INSTANCE_SIZE(__VALUE(target))))
1.44 + target = __stack_allocate(__stack, value_size);
1.45 +
1.46 + __COPY_TO(__VALUE(value), __VALUE(target), value_size);
1.47 + return __TO_MUTABLE(target);
1.48 + }
1.49 + else
1.50 + return value;
1.51 +}
1.52 +
1.53 +void __store_target(__attr *target, __attr value)
1.54 +{
1.55 + /* Copy values where appropriate. */
1.56 +
1.57 + if (__COPYABLE(value))
1.58 + {
1.59 + size_t value_size = __INSTANCE_SIZE(__VALUE(value));
1.60 +
1.61 + if ((__VALUE(*target) == NULL) || (!__MUTABLE(*target)) || (value_size > __INSTANCE_SIZE(__VALUE(*target))))
1.62 + *target = __ATTRVALUE(__ALLOCATEIM(1, value_size));
1.63 +
1.64 + __COPY_TO(__VALUE(value), __VALUE(*target), value_size);
1.65 + *target = __TO_MUTABLE(*target);
1.66 + }
1.67 + else
1.68 + *target = value;
1.69 +}
1.70 +
1.71 int __store_via_object__(__ref obj, int pos, __attr value)
1.72 {
1.73 + /* Copy values where appropriate. */
1.74 +
1.75 + if (__COPYABLE(value))
1.76 + {
1.77 + size_t value_size = __INSTANCE_SIZE(__VALUE(value));
1.78 + __attr target = obj->attrs[pos];
1.79 +
1.80 + /* Allocate new space for values if the target is not a mutable value
1.81 + or refers to an object that is too small for the value. */
1.82 +
1.83 + if ((__VALUE(target) == NULL) || (!__MUTABLE(target)) || (value_size > __INSTANCE_SIZE(__VALUE(target))))
1.84 + target = __ATTRVALUE(__ALLOCATEIM(1, value_size));
1.85 +
1.86 + __COPY_TO(__VALUE(value), __VALUE(target), value_size);
1.87 + obj->attrs[pos] = __TO_MUTABLE(target);
1.88 + }
1.89 + else
1.90 + obj->attrs[pos] = value;
1.91 +
1.92 + return 1;
1.93 +}
1.94 +
1.95 +int __store_via_object_internal__(__ref obj, int pos, __attr value)
1.96 +{
1.97 obj->attrs[pos] = value;
1.98 return 1;
1.99 }
1.100 @@ -215,6 +296,20 @@
1.101 return 0;
1.102 }
1.103
1.104 +int __check_and_store_via_object_internal__(__ref obj, int pos, int code, __attr value)
1.105 +{
1.106 + if (__HASATTR(obj, pos, code))
1.107 + {
1.108 + __store_via_object_internal__(obj, pos, value);
1.109 + return 1;
1.110 + }
1.111 +
1.112 + /* No suitable attribute. */
1.113 +
1.114 + __raise_type_error();
1.115 + return 0;
1.116 +}
1.117 +
1.118 int __check_and_store_via_any__(__ref obj, int pos, int code, __attr value)
1.119 {
1.120 if (__check_and_store_via_object__(obj, pos, code, value))
1.121 @@ -438,9 +533,95 @@
1.122
1.123 /* Copying of structures. */
1.124
1.125 -__ref __COPY(__ref obj, int size)
1.126 +__ref __COPY(__ref obj, size_t size)
1.127 {
1.128 __ref copy = (__ref) __ALLOCATE(1, size);
1.129 memcpy(copy, obj, size);
1.130 return copy;
1.131 }
1.132 +
1.133 +void __COPY_TO(__ref source, __ref target, size_t size)
1.134 +{
1.135 + memcpy(target, source, size);
1.136 +}
1.137 +
1.138 +/* Stack management. */
1.139 +
1.140 +__attr __stack_init()
1.141 +{
1.142 + __attr __stack;
1.143 +
1.144 + __stack.stackdesc = (__stackdesc *) __ALLOCATE(1, sizeof(__stackdesc));
1.145 + __stack.stackdesc->current = NULL;
1.146 + __stack_expand(__stack);
1.147 +
1.148 + return __stack;
1.149 +}
1.150 +
1.151 +__attr __stack_allocate(__attr __stack, size_t size)
1.152 +{
1.153 + char *result;
1.154 + __section *section = __stack.stackdesc->current;
1.155 +
1.156 + if (section->limit - section->level < size)
1.157 + {
1.158 + __stack_expand(__stack);
1.159 + section = __stack.stackdesc->current;
1.160 + }
1.161 +
1.162 + result = section->level;
1.163 + section->level += size;
1.164 +
1.165 + return __ATTRVALUE(result);
1.166 +}
1.167 +
1.168 +void __stack_expand(__attr __stack)
1.169 +{
1.170 + __section *current = __stack.stackdesc->current;
1.171 + __section *section = (__section *) __ALLOCATE(1, sizeof(__section));
1.172 + char *base = (char *) __ALLOCATEIM(1, __STACK_SECTION_SIZE);
1.173 +
1.174 + section->base = base;
1.175 + section->level = base;
1.176 + section->limit = base + __STACK_SECTION_SIZE;
1.177 + section->previous = current;
1.178 +
1.179 + __stack.stackdesc->current = section;
1.180 +}
1.181 +
1.182 +__attr __return(__attr result, __section *section, char *level)
1.183 +{
1.184 + __ref obj = __VALUE(result);
1.185 + char *target = level;
1.186 + size_t size;
1.187 +
1.188 + if (__COPYABLE(result))
1.189 + {
1.190 + size = __INSTANCE_SIZE(obj);
1.191 +
1.192 + /* Test for space in the section. */
1.193 +
1.194 + if (size > section->limit - level)
1.195 + {
1.196 + __stack_expand(__stack);
1.197 + section = __stack.stackdesc->current;
1.198 + target = section->base;
1.199 + }
1.200 +
1.201 + /* Copy into the stack and adjust the level. */
1.202 +
1.203 + __COPY_TO(obj, (__ref) target, size);
1.204 + level = target + size;
1.205 +
1.206 + /* Reference the new location of the object. */
1.207 +
1.208 + result = __MUTABLEVALUE(target);
1.209 + }
1.210 +
1.211 + /* Set the level and current section.*/
1.212 +
1.213 + section->level = level;
1.214 + __stack.stackdesc->current = section;
1.215 +
1.216 + return result;
1.217 +}