1 /*
2     $Id: addressobj.c 2596 2021-04-18 18:52:11Z soci $
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 
18 */
19 #include "addressobj.h"
20 #include <string.h>
21 #include "error.h"
22 #include "eval.h"
23 #include "variables.h"
24 #include "arguments.h"
25 #include "instruction.h"
26 
27 #include "boolobj.h"
28 #include "strobj.h"
29 #include "intobj.h"
30 #include "typeobj.h"
31 #include "noneobj.h"
32 #include "errorobj.h"
33 #include "floatobj.h"
34 #include "bitsobj.h"
35 #include "bytesobj.h"
36 #include "registerobj.h"
37 
38 static Type obj;
39 
40 Type *const ADDRESS_OBJ = &obj;
41 
address_from_obj(Obj * v1,linepos_t epoint)42 static MUST_CHECK Obj *address_from_obj(Obj *v1, linepos_t epoint) {
43     switch (v1->obj->type) {
44     case T_BOOL:
45     case T_INT:
46     case T_BITS:
47     case T_FLOAT:
48     case T_BYTES:
49     case T_STR:
50         return new_address(val_reference(v1), A_NONE);
51     case T_NONE:
52     case T_ERROR:
53     case T_ADDRESS: return val_reference(v1);
54     default: break;
55     }
56     return new_error_conv(v1, ADDRESS_OBJ, epoint);
57 }
58 
convert(oper_t op)59 static MUST_CHECK Obj *convert(oper_t op) {
60     return address_from_obj(op->v2, op->epoint2);
61 }
62 
destroy(Obj * o1)63 static FAST_CALL void destroy(Obj *o1) {
64     Address *v1 = Address(o1);
65     val_destroy(v1->val);
66 }
67 
garbage(Obj * o1,int i)68 static FAST_CALL void garbage(Obj *o1, int i) {
69     Address *v1 = Address(o1);
70     Obj *v;
71     switch (i) {
72     case -1:
73         v1->val->refcount--;
74         return;
75     case 0:
76         return;
77     case 1:
78         v = v1->val;
79         if ((v->refcount & SIZE_MSB) != 0) {
80             v->refcount -= SIZE_MSB - 1;
81             v->obj->garbage(v, 1);
82         } else v->refcount++;
83         return;
84     }
85 }
86 
same(const Obj * o1,const Obj * o2)87 static FAST_CALL bool same(const Obj *o1, const Obj *o2) {
88     const Address *v1 = Address(o1), *v2 = Address(o2);
89     return o1->obj == o2->obj && v1->type == v2->type && v1->val->obj->same(v1->val, v2->val);
90 }
91 
truth(Obj * o1,Truth_types type,linepos_t epoint)92 static MUST_CHECK Obj *truth(Obj *o1, Truth_types type, linepos_t epoint) {
93     Address *v1 = Address(o1);
94     Obj *v;
95     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
96         return DEFAULT_OBJ->truth(o1, type, epoint);
97     }
98     v = v1->val;
99     return v->obj->truth(v, type, epoint);
100 }
101 
hash(Obj * o1,int * hs,linepos_t epoint)102 static MUST_CHECK Obj *hash(Obj *o1, int *hs, linepos_t epoint) {
103     Address *v1 = Address(o1);
104     Obj *v = v1->val;
105     Obj *err = v->obj->hash(v, hs, epoint);
106     if (err == NULL) {
107         *hs = ((unsigned int)*hs + v1->type) & ((~0U) >> 1);
108     }
109     return err;
110 }
111 
repr(Obj * o1,linepos_t epoint,size_t maxsize)112 static MUST_CHECK Obj *repr(Obj *o1, linepos_t epoint, size_t maxsize) {
113     Address *v1 = Address(o1);
114     uint8_t *s;
115     size_t len, chars;
116     char buffer[100], buffer2[100], *b2;
117     atype_t addrtype;
118     unsigned int ind, ind2;
119     Obj *tmp;
120     Str *v, *str;
121 
122     ind2 = 0;
123     addrtype = v1->type;
124     ind = 99;
125     buffer2[ind] = '\0';
126     if (addrtype == A_NONE) {
127         ind -= 8;
128         memcpy(&buffer2[ind], "address(", 8);
129         buffer[ind2++] = ')';
130     } else {
131         while ((addrtype & MAX_ADDRESS_MASK) != 0) {
132             uint32_t mode;
133             switch ((Address_types)((addrtype & 0xf000) >> 12)) {
134             case A_XR: mode = (',' << 16) + ('x' << 24);break;
135             case A_YR: mode = (',' << 16) + ('y' << 24);break;
136             case A_ZR: mode = (',' << 16) + ('z' << 24);break;
137             case A_SR: mode = (',' << 16) + ('s' << 24);break;
138             case A_RR: mode = (',' << 16) + ('r' << 24);break;
139             case A_DR: mode = (',' << 16) + ('d' << 24);break;
140             case A_BR: mode = (',' << 16) + ('b' << 24);break;
141             case A_KR: mode = (',' << 16) + ('k' << 24);break;
142             case A_I:  mode = ('(' << 8) + (')' << 16);break;
143             case A_LI: mode = ('[' << 8) + (']' << 16);break;
144             case A_IMMEDIATE_SIGNED: mode = ('#' << 8) + '+';break;
145             case A_IMMEDIATE: mode = '#' << 8;break;
146             default: mode = 0;
147             }
148             if ((char)mode != '\0') buffer2[--ind] = (char)mode;
149             mode >>= 8;
150             if ((char)mode != '\0') buffer2[--ind] = (char)mode;
151             mode >>= 8;
152             if ((char)mode != '\0') buffer[ind2++] = (char)mode;
153             mode >>= 8;
154             if ((char)mode != '\0') buffer[ind2++] = (char)mode;
155             addrtype <<= 4;
156         }
157     }
158     b2 = buffer2 + ind;
159     ind = 99 - ind;
160 
161     chars = ind + ind2;
162     if (chars > maxsize) return NULL;
163     tmp = v1->val->obj->repr(v1->val, epoint, maxsize - chars);
164     if (tmp == NULL || tmp->obj != STR_OBJ) return tmp;
165     str = Str(tmp);
166     len = chars + str->len;
167     if (len < chars) goto error; /* overflow */
168     chars += str->chars;
169     if (chars > maxsize) {
170     error:
171         val_destroy(tmp);
172         return NULL;
173     }
174 
175     v = new_str2(len);
176     if (v == NULL) goto error;
177     v->chars = chars;
178     s = v->data;
179     if (ind != 0) {
180         memcpy(s, b2, ind);
181         s += ind;
182     }
183     if (str->len != 0) {
184         memcpy(s, str->data, str->len);
185         s += str->len;
186     }
187     if (ind2 != 0) memcpy(s, buffer, ind2);
188     val_destroy(tmp);
189     return Obj(v);
190 }
191 
str(Obj * o1,linepos_t epoint,size_t maxsize)192 static MUST_CHECK Obj *str(Obj *o1, linepos_t epoint, size_t maxsize) {
193     Address *v1 = Address(o1);
194     if (v1->type == A_NONE) {
195         o1 = v1->val;
196         return o1->obj->repr(o1, epoint, maxsize);
197     }
198     return repr(o1, epoint, maxsize);
199 }
200 
check_addr(atype_t type)201 bool check_addr(atype_t type) {
202     while (type != A_NONE) {
203         switch ((Address_types)(type & 0xf)) {
204         case A_I:
205         case A_LI: return true;
206         case A_IMMEDIATE:
207         case A_IMMEDIATE_SIGNED:
208         case A_KR:
209         case A_DR:
210         case A_BR:
211         case A_XR:
212         case A_YR:
213         case A_ZR:
214         case A_RR:
215         case A_SR:
216         case A_NONE: break;
217         }
218         type >>= 4;
219     }
220     return false;
221 }
222 
check_addr2(atype_t type)223 static inline bool check_addr2(atype_t type) {
224     while (type != A_NONE) {
225         switch ((Address_types)(type & 0xf)) {
226         case A_KR:
227         case A_DR:
228         case A_BR:
229         case A_XR:
230         case A_YR:
231         case A_ZR:
232         case A_RR:
233         case A_SR:
234         case A_I:
235         case A_LI: return true;
236         case A_IMMEDIATE:
237         case A_IMMEDIATE_SIGNED:
238         case A_NONE: break;
239         }
240         type >>= 4;
241     }
242     return false;
243 }
244 
register_to_indexing(unsigned int c)245 Address_types register_to_indexing(unsigned int c) {
246     switch (c) {
247     case 's': return A_SR;
248     case 'r': return A_RR;
249     case 'z': return A_ZR;
250     case 'y': return A_YR;
251     case 'x': return A_XR;
252     case 'd': return A_DR;
253     case 'b': return A_BR;
254     case 'k': return A_KR;
255     default: return A_NONE;
256     }
257 }
258 
address(const Obj * o1)259 static FAST_CALL uint32_t address(const Obj *o1) {
260     const Address *v1 = Address(o1);
261     Obj *v = v1->val;
262     uint32_t am = v->obj->address(v);
263     atype_t type = v1->type;
264     while (type != A_NONE) {
265         am <<= 4;
266         type >>= 4;
267     }
268     return am | v1->type;
269 }
270 
ival(Obj * o1,ival_t * iv,unsigned int bits,linepos_t epoint)271 static MUST_CHECK Error *ival(Obj *o1, ival_t *iv, unsigned int bits, linepos_t epoint) {
272     Address *v1 = Address(o1);
273     Obj *v;
274     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
275         return DEFAULT_OBJ->ival(o1, iv, bits, epoint);
276     }
277     v = v1->val;
278     return v->obj->ival(v, iv, bits, epoint);
279 }
280 
uval(Obj * o1,uval_t * uv,unsigned int bits,linepos_t epoint)281 static MUST_CHECK Error *uval(Obj *o1, uval_t *uv, unsigned int bits, linepos_t epoint) {
282     Address *v1 = Address(o1);
283     Obj *v;
284     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
285         return DEFAULT_OBJ->uval(o1, uv, bits, epoint);
286     }
287     v = v1->val;
288     return v->obj->uval(v, uv, bits, epoint);
289 }
290 
uval2(Obj * o1,uval_t * uv,unsigned int bits,linepos_t epoint)291 static MUST_CHECK Error *uval2(Obj *o1, uval_t *uv, unsigned int bits, linepos_t epoint) {
292     Address *v1 = Address(o1);
293     Obj *v;
294     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
295         return DEFAULT_OBJ->uval2(o1, uv, bits, epoint);
296     }
297     v = v1->val;
298     return v->obj->uval2(v, uv, bits, epoint);
299 }
300 
iaddress(Obj * o1,ival_t * iv,unsigned int bits,linepos_t epoint)301 static MUST_CHECK Error *iaddress(Obj *o1, ival_t *iv, unsigned int bits, linepos_t epoint) {
302     Address *v1 = Address(o1);
303     Obj *v = v1->val;
304     return v->obj->iaddress(v, iv, bits, epoint);
305 }
306 
uaddress(Obj * o1,uval_t * uv,unsigned int bits,linepos_t epoint)307 static MUST_CHECK Error *uaddress(Obj *o1, uval_t *uv, unsigned int bits, linepos_t epoint) {
308     Address *v1 = Address(o1);
309     Obj *v = v1->val;
310     return v->obj->uaddress(v, uv, bits, epoint);
311 }
312 
float_from_address(Address * v1,linepos_t epoint)313 MUST_CHECK Obj *float_from_address(Address *v1, linepos_t epoint) {
314     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
315         return new_error_conv(Obj(v1), FLOAT_OBJ, epoint);
316     }
317     return float_from_obj(v1->val, epoint);
318 }
319 
int_from_address(Address * v1,linepos_t epoint)320 MUST_CHECK Obj *int_from_address(Address *v1, linepos_t epoint) {
321     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
322         return new_error_conv(Obj(v1), INT_OBJ, epoint);
323     }
324     return int_from_obj(v1->val, epoint);
325 }
326 
bits_from_address(Address * v1,linepos_t epoint)327 MUST_CHECK Obj *bits_from_address(Address *v1, linepos_t epoint) {
328     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
329         return new_error_conv(Obj(v1), BITS_OBJ, epoint);
330     }
331     return bits_from_obj(v1->val, epoint);
332 }
333 
bytes_from_address(Address * v1,linepos_t epoint)334 MUST_CHECK Obj *bytes_from_address(Address *v1, linepos_t epoint) {
335     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
336         return new_error_conv(Obj(v1), BYTES_OBJ, epoint);
337     }
338     return bytes_from_obj(v1->val, epoint);
339 }
340 
sign(Obj * o1,linepos_t epoint)341 static MUST_CHECK Obj *sign(Obj *o1, linepos_t epoint) {
342     Address *v1 = Address(o1);
343     Obj *v;
344     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
345         return DEFAULT_OBJ->sign(o1, epoint);
346     }
347     v = v1->val;
348     return v->obj->sign(v, epoint);
349 }
350 
function(oper_t op)351 static MUST_CHECK Obj *function(oper_t op) {
352     Address *v1 = Address(op->v2);
353     Obj *v;
354     if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
355         return DEFAULT_OBJ->function(op);
356     }
357     op->v2 = v = v1->val;
358     op->inplace = op->inplace == Obj(v1) && v->refcount == 1 ? v : NULL;
359     return v->obj->function(op);
360 }
361 
calc1(oper_t op)362 static MUST_CHECK Obj *calc1(oper_t op) {
363     Obj *result;
364     Address *v1 = Address(op->v1);
365     atype_t am = v1->type;
366     switch (op->op) {
367     case O_LNOT:
368     case O_STRING:
369         if (am != A_NONE) break;
370         /* fall through */
371     case O_BANK:
372     case O_HIGHER:
373     case O_LOWER:
374     case O_HWORD:
375     case O_WORD:
376     case O_BSWORD:
377     case O_INV:
378     case O_NEG:
379     case O_POS:
380         if (check_addr2(am)) break;
381         op->v1 = v1->val;
382         op->inplace = NULL;
383         result = op->v1->obj->calc1(op);
384         if (am == A_NONE) return result;
385         return new_address(result, am);
386     default: break;
387     }
388     if (v1->val == none_value || v1->val->obj == ERROR_OBJ) return val_reference(v1->val);
389     return obj_oper_error(op);
390 }
391 
slice(oper_t op,argcount_t indx)392 static MUST_CHECK Obj *slice(oper_t op, argcount_t indx) {
393     Obj *val = Address(op->v1)->val;
394     if (val == none_value || val->obj == ERROR_OBJ) {
395         return val_reference(val);
396     }
397     return DEFAULT_OBJ->slice(op, indx);
398 }
399 
calc2(oper_t op)400 static MUST_CHECK Obj *calc2(oper_t op) {
401     Obj *o2 = op->v2, *result;
402     Address *v1 = Address(op->v1);
403     atype_t am;
404     if (op->op == O_LAND || op->op == O_LOR) {
405         bool i;
406         result = truth(Obj(v1), TRUTH_BOOL, op->epoint);
407         if (result->obj != BOOL_OBJ) return result;
408         i = (result == true_value) != (op->op == O_LOR);
409         val_destroy(result);
410         if (diagnostics.strict_bool) err_msg_bool_oper(op);
411         return val_reference(i ? o2 : Obj(v1));
412     }
413     switch (o2->obj->type) {
414     case T_ADDRESS:
415         {
416             Address *v2 = Address(o2);
417             atype_t am2 = v2->type;
418             am = v1->type;
419             switch (op->op) {
420             case O_CMP:
421             case O_EQ:
422             case O_NE:
423             case O_MIN:
424             case O_LT:
425             case O_LE:
426             case O_MAX:
427             case O_GT:
428             case O_GE:
429                 if (am == am2) {
430                     op->v1 = v1->val;
431                     op->v2 = v2->val;
432                     op->inplace = NULL;
433                     return op->v1->obj->calc2(op);
434                 }
435                 return obj_oper_compare(op, (am < am2) ? -1 : 1);
436             case O_ADD:
437                 if (check_addr(am)) break;
438                 if (check_addr(am2)) break;
439                 op->v1 = v1->val;
440                 op->v2 = v2->val;
441                 op->inplace = NULL;
442                 result = op->v1->obj->calc2(op);
443                 if (am == A_NONE && v2->type == A_NONE) return result;
444                 while ((Address_types)(am2 & 0xf) != A_NONE) { am <<= 4; am2 >>= 4; }
445                 return new_address(result, am | v2->type);
446             case O_SUB:
447                 if (check_addr(am)) break;
448                 if (check_addr(am2)) break;
449                 {
450                     atype_t am1 = A_NONE;
451                     for (; (am & MAX_ADDRESS_MASK) != 0; am <<= 4) {
452                         atype_t amc = (am >> 12) & 0xf;
453                         atype_t am3, am4;
454                         if (amc == A_NONE) continue;
455                         am3 = A_NONE; am4 = am2;
456                         while (am4 != A_NONE) {
457                             atype_t am5 = (am4 & 0xf);
458                             if (amc == am5) amc = A_NONE;
459                             else am3 = (am3 << 4) | am5;
460                             am4 >>= 4;
461                         }
462                         am2 = am3;
463                         if (amc == A_NONE) continue;
464                         am1 = (am1 << 4) | amc;
465                     }
466                     if (am2 != A_NONE) break;
467                     op->v1 = v1->val;
468                     op->v2 = v2->val;
469                     op->inplace = NULL;
470                     result = op->v1->obj->calc2(op);
471                     if (am1 == A_NONE) return result;
472                     return new_address(result, am1);
473                 }
474             case O_XOR:
475                 if (check_addr(am)) break;
476                 if (check_addr(am2)) break;
477                 if (am == am2) {
478                     op->v1 = v1->val;
479                     op->v2 = v2->val;
480                     op->inplace = NULL;
481                     return op->v1->obj->calc2(op);
482                 }
483                 break;
484             default:
485                 break;
486             }
487             break;
488         }
489     case T_BOOL:
490     case T_INT:
491     case T_BITS:
492     case T_FLOAT:
493     case T_BYTES:
494     case T_STR:
495         am = v1->type;
496         switch (op->op) {
497         case O_CMP:
498         case O_EQ:
499         case O_NE:
500         case O_MIN:
501         case O_LT:
502         case O_LE:
503         case O_MAX:
504         case O_GT:
505         case O_GE:
506             if (am == A_NONE || (am == A_DR && dpage == 0) || (am == A_BR && databank == 0)) {
507                 op->v1 = v1->val;
508                 op->inplace = NULL;
509                 return op->v1->obj->calc2(op);
510             }
511             break;
512         default:
513             if (am == A_NONE) {
514                 op->v1 = v1->val;
515                 op->inplace = NULL;
516                 return op->v1->obj->calc2(op);
517             }
518             if (check_addr2(am)) break;
519             goto ok;
520         case O_ADD:
521         case O_SUB:
522             if (check_addr(am)) break;
523         ok:
524             op->v1 = v1->val;
525             op->inplace = NULL;
526             return new_address(op->v1->obj->calc2(op), am);
527         }
528         break;
529     case T_REGISTER:
530         if (Register(op->v2)->len == 1) {
531             Address_types am2 = register_to_indexing(Register(op->v2)->data[0]);
532             if (am2 == A_NONE) break;
533             if (op->op == O_ADD) {
534                 return new_address(val_reference(v1->val), v1->type << 4 | am2);
535             }
536             if (op->op == O_SUB) {
537                 atype_t am1 = A_NONE;
538                 for (am = v1->type; ; am >>= 4) {
539                     atype_t amc = am & 0xf;
540                     switch (amc) {
541                     case A_I:
542                     case A_LI:
543                     case A_IMMEDIATE:
544                     case A_IMMEDIATE_SIGNED:
545                         if (am2 == A_NONE) {
546                             am1 = (am1 >> 4) | (amc << 12);
547                             continue;
548                         }
549                         break;
550                     case A_KR:
551                     case A_DR:
552                     case A_BR:
553                     case A_XR:
554                     case A_YR:
555                     case A_ZR:
556                     case A_RR:
557                     case A_SR:
558                         if (amc == am2) {
559                             am2 = A_NONE;
560                             continue;
561                         }
562                         am1 = (am1 >> 4) | (amc << 12);
563                         continue;
564                     default: break;
565                     }
566                     break;
567                 }
568                 if (am2 != A_NONE) break;
569                 if (am1 != A_NONE) while ((am1 & 0xf) == A_NONE) am1 >>= 4;
570                 return new_address(val_reference(v1->val), am1);
571             }
572         }
573         break;
574     default:
575         if (op->op != O_MEMBER && op->op != O_X) {
576             return o2->obj->rcalc2(op);
577         }
578         if (o2 == none_value || o2->obj == ERROR_OBJ) return val_reference(o2);
579     }
580     if (v1->val == none_value || v1->val->obj == ERROR_OBJ) return val_reference(v1->val);
581     return obj_oper_error(op);
582 }
583 
rcalc2(oper_t op)584 static MUST_CHECK Obj *rcalc2(oper_t op) {
585     const Type *t1 = op->v1->obj;
586     Address *v2 = Address(op->v2);
587     atype_t am;
588     switch (t1->type) {
589     case T_BOOL:
590     case T_INT:
591     case T_BITS:
592     case T_FLOAT:
593     case T_BYTES:
594     case T_GAP:
595         am = v2->type;
596         switch (op->op) {
597         default:
598             if (am == A_NONE) {
599                 op->v2 = v2->val;
600                 op->inplace = NULL;
601                 return t1->calc2(op);
602             }
603             break;
604         case O_MUL:
605         case O_OR:
606         case O_XOR:
607         case O_AND:
608             if (check_addr2(am)) break;
609             goto ok;
610         case O_ADD:
611             if (check_addr(am)) break;
612         ok:
613             op->v2 = v2->val;
614             op->inplace = NULL;
615             return new_address(t1->calc2(op), am);
616         }
617         break;
618     case T_CODE:
619         if (op->op != O_IN) {
620             return t1->calc2(op);
621         }
622         break;
623     case T_REGISTER:
624         if (Register(op->v1)->len == 1) {
625             am = register_to_indexing(Register(op->v1)->data[0]);
626             if (am == A_NONE) break;
627             if (op->op == O_ADD) {
628                 return new_address(val_reference(v2->val), v2->type << 4 | am);
629             }
630             if (op->op == O_SUB) {
631                 if (am == v2->type) {
632                     op->v1 = int_value[0];
633                     op->v2 = v2->val;
634                     op->inplace = NULL;
635                     return INT_OBJ->calc2(op);
636                 }
637             }
638         }
639         break;
640     default: break;
641     }
642     if (v2->val == none_value || v2->val->obj == ERROR_OBJ) return val_reference(v2->val);
643     return obj_oper_error(op);
644 }
645 
addressobj_init(void)646 void addressobj_init(void) {
647     new_type(&obj, T_ADDRESS, "address", sizeof(Address));
648     obj.convert = convert;
649     obj.destroy = destroy;
650     obj.garbage = garbage;
651     obj.same = same;
652     obj.truth = truth;
653     obj.hash = hash;
654     obj.repr = repr;
655     obj.str = str;
656     obj.address = address;
657     obj.ival = ival;
658     obj.uval = uval;
659     obj.uval2 = uval2;
660     obj.iaddress = iaddress;
661     obj.uaddress = uaddress;
662     obj.sign = sign;
663     obj.function = function;
664     obj.calc1 = calc1;
665     obj.calc2 = calc2;
666     obj.rcalc2 = rcalc2;
667     obj.slice = slice;
668 }
669 
addressobj_names(void)670 void addressobj_names(void) {
671     new_builtin("address", val_reference(Obj(ADDRESS_OBJ)));
672 }
673