60c08bccea0056fc6b386ce38704fb15c8cd8287
[swftools.git] / lib / as3 / expr.c
1 /* ast.c
2
3    Extension module for the rfxswf library.
4    Part of the swftools package.
5
6    Copyright (c) 2009 Matthias Kramm <kramm@quiss.org>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #include "expr.h"
23 #include "common.h"
24 #include "tokenizer.h"
25
26 #define IS_INT(a) (TYPE_IS_INT((a)) || TYPE_IS_UINT((a)))
27 #define BOTH_INT(a,b) (IS_INT(a) && IS_INT(b))
28
29 #define READ_HEADER_LEFTRIGHT \
30     typedcode_t left = n->child[0]->type->read(n->child[0]);\
31     typedcode_t right = n->child[1]->type->read(n->child[1]);\
32     code_t*c=0;\
33     classinfo_t*t=0;
34
35 #define READ_HEADER_ONE \
36     typedcode_t x = n->child[0]->type->read(n->child[0]);\
37     code_t*c=0;\
38     classinfo_t*t=0;
39
40 #define EXEC_HEADER_ONE \
41     code_t* x = n->child[0]->type->exec(n->child[0]);\
42     code_t*c=0;\
43     classinfo_t*t=0;
44
45 #define EXEC_HEADER_LEFTRIGHT \
46     code_t* left = n->child[0]->type->exec(n->child[0]);\
47     code_t* right = n->child[1]->type->exec(n->child[1]);\
48     code_t*c=0;\
49     classinfo_t*t=0;
50
51 #define EVAL_HEADER_LEFTRIGHT \
52     constant_t left = n->child[0]->type->eval(n->child[0]);\
53     constant_t right = n->child[1]->type->eval(n->child[1]);\
54     constant_t r; \
55     if(left.type==CONSTANT_UNKNOWN || right.type==CONSTANT_UNKNOWN) {\
56         r.type = CONSTANT_UNKNOWN;return r; \
57     }
58
59
60 #define RET \
61     typedcode_t r; \
62     r.c = c; \
63     r.t = t; \
64     return r;
65
66 static classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, nodetype_t*t)
67 {
68     if(!type1 || !type2)
69         return TYPE_ANY;
70     if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
71         return TYPE_ANY;
72     if(type1 == type2)
73         return type1;
74     return TYPE_ANY;
75 }
76 static char is_getlocal(code_t*c)
77 {
78     if(!c || c->prev || c->next)
79         return 0;
80     return(c->opcode == OPCODE_GETLOCAL
81         || c->opcode == OPCODE_GETLOCAL_0
82         || c->opcode == OPCODE_GETLOCAL_1
83         || c->opcode == OPCODE_GETLOCAL_2
84         || c->opcode == OPCODE_GETLOCAL_3);
85 }
86 static int getlocalnr(code_t*c)
87 {
88     if(c->opcode == OPCODE_GETLOCAL) {return (ptroff_t)c->data[0];}
89     else if(c->opcode == OPCODE_GETLOCAL_0) {return 0;}
90     else if(c->opcode == OPCODE_GETLOCAL_1) {return 1;}
91     else if(c->opcode == OPCODE_GETLOCAL_2) {return 2;}
92     else if(c->opcode == OPCODE_GETLOCAL_3) {return 3;}
93     else syntaxerror("Internal error: opcode %02x is not a getlocal call", c->opcode);
94     return 0;
95 }
96
97
98 int gettempvar(); /* FIXME: we should use a function pointer here */
99
100
101 static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore, char pushvalue)
102 {
103     /* converts this:
104
105        [prefix code] [read instruction]
106
107        to this:
108
109        [prefix code] ([dup]) [read instruction] [middlepart] [setvar] [write instruction] [getvar]
110     */
111     if(in && in->opcode == OPCODE_COERCE_A) {
112         in = code_cutlast(in);
113     }
114     if(in->next)
115         syntaxerror("internal error");
116
117     /* chop off read instruction */
118     code_t*prefix = in;
119     code_t*r = in;
120     if(r->prev) {
121         prefix = r->prev;r->prev = 0;
122         prefix->next=0;
123     } else {
124         prefix = 0;
125     }
126         
127     char use_temp_var = readbefore;
128
129     /* generate the write instruction, and maybe append a dup to the prefix code */
130     code_t* write = abc_nop(0);
131     if(r->opcode == OPCODE_GETPROPERTY) {
132         write->opcode = OPCODE_SETPROPERTY;
133         multiname_t*m = (multiname_t*)r->data[0];
134         write->data[0] = multiname_clone(m);
135         if(m->type == QNAME || m->type == MULTINAME) {
136             if(!justassign) {
137                 prefix = abc_dup(prefix); // we need the object, too
138             }
139             use_temp_var = 1;
140         } else if(m->type == MULTINAMEL) {
141             if(!justassign) {
142                 /* dupping two values on the stack requires 5 operations and one register- 
143                    couldn't adobe just have given us a dup2? */
144                 int temp = gettempvar();
145                 prefix = abc_setlocal(prefix, temp);
146                 prefix = abc_dup(prefix);
147                 prefix = abc_getlocal(prefix, temp);
148                 prefix = abc_swap(prefix);
149                 prefix = abc_getlocal(prefix, temp);
150                 if(!use_temp_var);
151                     prefix = abc_kill(prefix, temp);
152             }
153             use_temp_var = 1;
154         } else {
155             syntaxerror("illegal lvalue: can't assign a value to this expression (not a qname/multiname)");
156         }
157     } else if(r->opcode == OPCODE_GETSLOT) {
158         write->opcode = OPCODE_SETSLOT;
159         write->data[0] = r->data[0];
160         if(!justassign) {
161             prefix = abc_dup(prefix); // we need the object, too
162         }
163         use_temp_var = 1;
164     } else if(r->opcode == OPCODE_GETLOCAL) { 
165         write->opcode = OPCODE_SETLOCAL;
166         write->data[0] = r->data[0];
167     } else if(r->opcode == OPCODE_GETLOCAL_0) { 
168         write->opcode = OPCODE_SETLOCAL_0;
169     } else if(r->opcode == OPCODE_GETLOCAL_1) { 
170         write->opcode = OPCODE_SETLOCAL_1;
171     } else if(r->opcode == OPCODE_GETLOCAL_2) { 
172         write->opcode = OPCODE_SETLOCAL_2;
173     } else if(r->opcode == OPCODE_GETLOCAL_3) { 
174         write->opcode = OPCODE_SETLOCAL_3;
175     } else if(r->opcode == OPCODE_GETSUPER) { 
176         write->opcode = OPCODE_SETSUPER;
177         multiname_t*m = (multiname_t*)r->data[0];
178         write->data[0] = multiname_clone(m);
179     } else {
180         code_dump(r);
181         syntaxerror("illegal lvalue: can't assign a value to this expression");
182     }
183     code_t* c = 0;
184     
185     int temp = -1;
186     if(!justassign) {
187         if(use_temp_var) {
188             /* with getproperty/getslot, we have to be extra careful not
189                to execute the read code twice, as it might have side-effects
190                (e.g. if the property is in fact a setter/getter combination)
191
192                So read the value, modify it, and write it again,
193                using prefix only once and making sure (by using a temporary
194                register) that the return value is what we just wrote */
195             temp = gettempvar();
196             c = code_append(c, prefix);
197             c = code_append(c, r);
198             if(pushvalue && readbefore) {
199                 c = abc_dup(c);
200                 c = abc_setlocal(c, temp);
201             }
202             c = code_append(c, middlepart);
203             if(pushvalue && !readbefore) {
204                 c = abc_dup(c);
205                 c = abc_setlocal(c, temp);
206             }
207             c = code_append(c, write);
208             if(pushvalue) {
209                 c = abc_getlocal(c, temp);
210                 c = abc_kill(c, temp);
211             }
212         } else {
213             /* if we're allowed to execute the read code twice *and*
214                the middlepart doesn't modify the code, things are easier.
215             */
216             //c = code_append(c, prefix);
217             if(prefix) syntaxerror("internal error (prefix)");
218             code_t* r2 = 0;
219             if(pushvalue) {
220                 r2 = code_dup(r);
221             }
222             c = code_append(c, r);
223             c = code_append(c, middlepart);
224             c = code_append(c, write);
225             if(pushvalue) {
226                 c = code_append(c, r2);
227             }
228         }
229     } else {
230         /* even smaller version: overwrite the value without reading
231            it out first */
232         if(!use_temp_var) {
233             if(prefix) {
234                 c = code_append(c, prefix);
235                 c = abc_dup(c);
236             }
237             c = code_append(c, middlepart);
238             c = code_append(c, write);
239             if(pushvalue) {
240                 c = code_append(c, r);
241             }
242         } else {
243             code_free(r);r=0;
244             temp = gettempvar();
245             if(prefix) {
246                 c = code_append(c, prefix);
247             }
248             c = code_append(c, middlepart);
249             if(pushvalue) {
250                 c = abc_dup(c);
251                 c = abc_setlocal(c, temp);
252             }
253             c = code_append(c, write);
254             if(pushvalue) {
255                 c = abc_getlocal(c, temp);
256                 c = abc_kill(c, temp);
257             }
258         }
259     }
260     return c;
261 }
262
263 code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to);
264
265 int constant_to_int(constant_t*c) 
266 {
267     switch(c->type) {
268         case CONSTANT_INT:    return c->i;
269         case CONSTANT_UINT:   return (int)c->u;
270         case CONSTANT_FLOAT:  return c->f;
271         case CONSTANT_TRUE:   return 1;
272         case CONSTANT_FALSE:  return 0;
273         case CONSTANT_STRING: return atoi(c->s->str);
274         default: syntaxerror("can't convert this constant to an integer");
275     }
276 }
277
278 double constant_to_float(constant_t*c) 
279 {
280     switch(c->type) {
281         case CONSTANT_INT:    return (double)c->i;
282         case CONSTANT_UINT:   return (double)c->u;
283         case CONSTANT_FLOAT:  return c->f;
284         case CONSTANT_TRUE:   return (double)1;
285         case CONSTANT_FALSE:  return (double)0;
286         case CONSTANT_STRING: return atof(c->s->str);
287         default: syntaxerror("can't convert this constant to a float");
288     }
289 }
290
291 // -------------------------- x + y -----------------------------------
292
293 typedcode_t node_plus_write(node_t*n)
294 {
295     syntaxerror("can't assign to this expression");
296 }
297 typedcode_t node_plus_read(node_t*n)
298 {
299     READ_HEADER_LEFTRIGHT;
300     c = code_append(left.c, right.c);
301     if(BOTH_INT(left.t, right.t)) {
302        c = abc_add_i(c);
303        t = TYPE_INT;
304     } else {
305        c = abc_add(c);
306        t = join_types(left.t,right.t,n->type);
307     }
308     RET;
309 }
310 code_t* node_plus_exec(node_t*n)
311 {
312     EXEC_HEADER_LEFTRIGHT;
313     return code_append(left, right);
314 }
315 constant_t node_plus_eval(node_t*n)
316 {
317     EVAL_HEADER_LEFTRIGHT;
318     char left_int = left.type == CONSTANT_INT || left.type == CONSTANT_UINT;
319     if(left_int && (right.type == CONSTANT_INT || right.type == CONSTANT_UINT)) { 
320         /* FIXME: what to do about signed/unsigned overflows? */
321         int i = constant_to_int(&left) + constant_to_int(&right);
322         r.type = CONSTANT_INT;
323         r.i = i;
324     } else if(left_int && right.type == CONSTANT_FLOAT) {
325         double f = constant_to_int(&left) + constant_to_float(&right);
326         r.type = CONSTANT_FLOAT;
327         r.f = f;
328     } else if(left.type == CONSTANT_STRING) {
329         char*add = constant_tostring(&right);
330         int l1 = left.s->len;
331         int l2 = strlen(add);
332         char*s = malloc(l1+l2+1);
333         memcpy(s, left.s->str, l1);
334         memcpy(s+l1, add, l2);
335         s[l1+l2]=0;
336         r.type = CONSTANT_STRING;
337         r.s = malloc(sizeof(string_t));
338         r.s->str = s;
339         r.s->len = l1+l2;
340     } else {
341         r.type = CONSTANT_UNKNOWN;
342     }
343     return r;
344 }
345 nodetype_t node_plus =
346 {
347 name:"plus",
348 flags:NODE_HAS_CHILDREN,
349 eval:node_plus_eval,
350 write:node_plus_write,
351 read:node_plus_read,
352 exec:node_plus_exec,
353 };
354
355 // -------------------------- x - y -----------------------------------
356
357 typedcode_t node_minus_write(node_t*n)
358 {
359     syntaxerror("can't assign to this expression");
360 }
361 typedcode_t node_minus_read(node_t*n)
362 {
363     READ_HEADER_LEFTRIGHT;
364     c = code_append(left.c, right.c);
365     if(BOTH_INT(left.t,right.t)) {
366        c = abc_subtract_i(c);
367        t = TYPE_INT;
368     } else {
369        c = abc_subtract(c);
370        t = TYPE_NUMBER;
371     }
372     RET;
373 }
374 code_t* node_minus_exec(node_t*n)
375 {
376     EXEC_HEADER_LEFTRIGHT;
377     return code_append(left, right);
378 }
379 constant_t node_minus_eval(node_t*n)
380 {
381     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
382 }
383 nodetype_t node_minus =
384 {
385 name:"minus",
386 flags:NODE_HAS_CHILDREN,
387 eval: node_minus_eval,
388 write: node_minus_write,
389 read: node_minus_read,
390 exec: node_minus_exec
391 };
392
393 // ---------------------------- ++x -----------------------------------
394
395 typedcode_t node_lplusplus_write(node_t*n)
396 {
397     syntaxerror("can't assign to this expression");
398 }
399 typedcode_t node_lplusplus_read(node_t*n)
400 {
401     READ_HEADER_ONE;
402     t = x.t;
403     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
404         int nr = getlocalnr(x.c);
405         code_free(x.c);x.c=0;
406         if(TYPE_IS_INT(x.t)) {
407            c = abc_inclocal_i(c, nr);
408            c = abc_getlocal(c, nr);
409         } else if(TYPE_IS_NUMBER(x.t)) {
410            c = abc_inclocal(c, nr);
411            c = abc_getlocal(c, nr);
412         } else syntaxerror("internal error");
413     } else {
414         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
415             c = abc_increment_i(c);
416             t = TYPE_INT;
417         } else {
418             c = abc_increment(c);
419             t = TYPE_NUMBER;
420         }
421         c = converttype(c, t, x.t);
422         c = toreadwrite(x.c, c, 0, 0, 1);
423         t = x.t;
424     }
425     RET
426 }
427 code_t* node_lplusplus_exec(node_t*n)
428 {
429     typedcode_t x = n->child[0]->type->read(n->child[0]);
430     code_t*c=0;
431     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
432         int nr = getlocalnr(x.c);
433         code_free(x.c);x.c=0;
434         if(TYPE_IS_INT(x.t)) {
435            c = abc_inclocal_i(c, nr);
436         } else if(TYPE_IS_NUMBER(x.t)) {
437            c = abc_inclocal(c, nr);
438         } else syntaxerror("internal error");
439     } else {
440         classinfo_t*t;
441         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
442             c = abc_increment_i(c);
443             t = TYPE_INT;
444         } else {
445             c = abc_increment(c);
446             t = TYPE_NUMBER;
447         }
448         c = converttype(c, t, x.t); //convert back to original type
449         c = toreadwrite(x.c, c, 0, 0, 0);
450         t = x.t;
451     }
452     return c;
453 }
454 constant_t node_lplusplus_eval(node_t*n)
455 {
456     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
457 }
458 nodetype_t node_lplusplus =
459 {
460 name: "lplusplus",
461 flags:NODE_HAS_CHILDREN,
462 eval: node_lplusplus_eval,
463 write: node_lplusplus_write,
464 read: node_lplusplus_read,
465 exec: node_lplusplus_exec
466 };
467
468
469 // ---------------------------- --x -----------------------------------
470
471 typedcode_t node_lminusminus_write(node_t*n)
472 {
473     syntaxerror("can't assign to this expression");
474 }
475 typedcode_t node_lminusminus_read(node_t*n)
476 {
477     READ_HEADER_ONE;
478     t = x.t;
479     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
480         int nr = getlocalnr(x.c);
481         code_free(x.c);x.c=0;
482         if(TYPE_IS_INT(x.t)) {
483            c = abc_declocal_i(c, nr);
484            c = abc_getlocal(c, nr);
485         } else if(TYPE_IS_NUMBER(x.t)) {
486            c = abc_declocal(c, nr);
487            c = abc_getlocal(c, nr);
488         } else syntaxerror("internal error");
489     } else {
490         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
491             c = abc_decrement_i(c);
492             t = TYPE_INT;
493         } else {
494             c = abc_decrement(c);
495             t = TYPE_NUMBER;
496         }
497         c = converttype(c, t, x.t);
498         c = toreadwrite(x.c, c, 0, 0, 1);
499         t = x.t;
500     }
501     RET
502 }
503 code_t* node_lminusminus_exec(node_t*n)
504 {
505     typedcode_t x = n->child[0]->type->read(n->child[0]);
506     code_t*c=0;
507     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
508         int nr = getlocalnr(x.c);
509         code_free(x.c);x.c=0;
510         if(TYPE_IS_INT(x.t)) {
511            c = abc_declocal_i(c, nr);
512         } else if(TYPE_IS_NUMBER(x.t)) {
513            c = abc_declocal(c, nr);
514         } else syntaxerror("internal error");
515     } else {
516         classinfo_t*t;
517         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
518             c = abc_decrement_i(c);
519             t = TYPE_INT;
520         } else {
521             c = abc_decrement(c);
522             t = TYPE_NUMBER;
523         }
524         c = converttype(c, t, x.t); //convert back to original type
525         c = toreadwrite(x.c, c, 0, 0, 0);
526         t = x.t;
527     }
528     return c;
529 }
530 constant_t node_lminusminus_eval(node_t*n)
531 {
532     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
533 }
534 nodetype_t node_lminusminus =
535 {
536 name: "lminusminus",
537 flags:NODE_HAS_CHILDREN,
538 eval: node_lminusminus_eval,
539 write: node_lminusminus_write,
540 read: node_lminusminus_read,
541 exec: node_lminusminus_exec
542 };
543
544
545
546 // ---------------------------- x++ -----------------------------------
547
548 typedcode_t node_rplusplus_write(node_t*n)
549 {
550     syntaxerror("can't assign to this expression");
551 }
552 typedcode_t node_rplusplus_read(node_t*n)
553 {
554     READ_HEADER_ONE;
555     t = x.t;
556     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
557         int nr = getlocalnr(x.c);
558         code_free(x.c);x.c=0;
559         if(TYPE_IS_INT(x.t)) {
560            c = abc_getlocal(0, nr);
561            c = abc_inclocal_i(c, nr);
562         } else if(TYPE_IS_NUMBER(x.t)) {
563            c = abc_getlocal(0, nr);
564            c = abc_inclocal(c, nr);
565         } else syntaxerror("internal error");
566     } else {
567         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
568             c = abc_increment_i(c);
569             t = TYPE_INT;
570         } else {
571             c = abc_increment(c);
572             t = TYPE_NUMBER;
573         }
574         c = converttype(c, t, x.t);
575         c = toreadwrite(x.c, c, 0, 1, 1);
576         t = x.t;
577     }
578     RET
579 }
580 code_t* node_rplusplus_exec(node_t*n)
581 {
582     typedcode_t x = n->child[0]->type->read(n->child[0]);
583     code_t*c=0;
584     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
585         int nr = getlocalnr(x.c);
586         code_free(x.c);x.c=0;
587         if(TYPE_IS_INT(x.t)) {
588            c = abc_inclocal_i(c, nr);
589         } else if(TYPE_IS_NUMBER(x.t)) {
590            c = abc_inclocal(c, nr);
591         } else syntaxerror("internal error");
592     } else {
593         classinfo_t*t;
594         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
595             c = abc_increment_i(c);
596             t = TYPE_INT;
597         } else {
598             c = abc_increment(c);
599             t = TYPE_NUMBER;
600         }
601         c = converttype(c, t, x.t); //convert back to original type
602         c = toreadwrite(x.c, c, 0, 1, 0);
603         t = x.t;
604     }
605     return c;
606 }
607 constant_t node_rplusplus_eval(node_t*n)
608 {
609     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
610 }
611 nodetype_t node_rplusplus =
612 {
613 name: "rplusplus",
614 flags:NODE_HAS_CHILDREN,
615 eval: node_rplusplus_eval,
616 write: node_rplusplus_write,
617 read: node_rplusplus_read,
618 exec: node_rplusplus_exec
619 };
620
621 // ---------------------------- x-- -----------------------------------
622
623 typedcode_t node_rminusminus_write(node_t*n)
624 {
625     syntaxerror("can't assign to this expression");
626 }
627 typedcode_t node_rminusminus_read(node_t*n)
628 {
629     READ_HEADER_ONE;
630     t = x.t;
631     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
632         int nr = getlocalnr(x.c);
633         code_free(x.c);x.c=0;
634         if(TYPE_IS_INT(x.t)) {
635            c = abc_getlocal(0, nr);
636            c = abc_declocal_i(c, nr);
637         } else if(TYPE_IS_NUMBER(x.t)) {
638            c = abc_getlocal(0, nr);
639            c = abc_declocal(c, nr);
640         } else syntaxerror("internal error");
641     } else {
642         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
643             c = abc_decrement_i(c);
644             t = TYPE_INT;
645         } else {
646             c = abc_decrement(c);
647             t = TYPE_NUMBER;
648         }
649         c = converttype(c, t, x.t);
650         c = toreadwrite(x.c, c, 0, 1, 1);
651         t = x.t;
652     }
653     RET
654 }
655 code_t* node_rminusminus_exec(node_t*n)
656 {
657     typedcode_t x = n->child[0]->type->read(n->child[0]);
658     code_t*c=0;
659     if(is_getlocal(x.c) && (TYPE_IS_INT(x.t) || TYPE_IS_NUMBER(x.t))) {
660         int nr = getlocalnr(x.c);
661         code_free(x.c);x.c=0;
662         if(TYPE_IS_INT(x.t)) {
663            c = abc_declocal_i(c, nr);
664         } else if(TYPE_IS_NUMBER(x.t)) {
665            c = abc_declocal(c, nr);
666         } else syntaxerror("internal error");
667     } else {
668         classinfo_t*t;
669         if(TYPE_IS_INT(x.t) || TYPE_IS_UINT(x.t)) {
670             c = abc_decrement_i(c);
671             t = TYPE_INT;
672         } else {
673             c = abc_decrement(c);
674             t = TYPE_NUMBER;
675         }
676         c = converttype(c, t, x.t); //convert back to original type
677         c = toreadwrite(x.c, c, 0, 1, 0);
678         t = x.t;
679     }
680     return c;
681 }
682 constant_t node_rminusminus_eval(node_t*n)
683 {
684     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
685 }
686 nodetype_t node_rminusminus =
687 {
688 name: "rminusminus",
689 flags:NODE_HAS_CHILDREN,
690 eval: node_rminusminus_eval,
691 write: node_rminusminus_write,
692 read: node_rminusminus_read,
693 exec: node_rminusminus_exec
694 };
695
696 // ---------------------------- x*y -----------------------------------
697
698 typedcode_t node_multiply_write(node_t*n)
699 {
700     syntaxerror("can't assign to this expression");
701 }
702 typedcode_t node_multiply_read(node_t*n)
703 {
704     READ_HEADER_LEFTRIGHT;
705     c = code_append(left.c,right.c);
706     if(BOTH_INT(left.t,right.t)) {
707        c = abc_multiply_i(c);
708        t = TYPE_INT;
709     } else {
710        c = abc_multiply(c);
711        t = TYPE_NUMBER;
712     }
713     RET
714 }
715 code_t* node_multiply_exec(node_t*n)
716 {
717     EXEC_HEADER_LEFTRIGHT;
718     return code_append(left, right);
719 }
720 constant_t node_multiply_eval(node_t*n)
721 {
722     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
723 }
724 nodetype_t node_multiply =
725 {
726 name: "multiply",
727 flags:NODE_HAS_CHILDREN,
728 eval: node_multiply_eval,
729 write: node_multiply_write,
730 read: node_multiply_read,
731 exec: node_multiply_exec
732 };
733
734 // ---------------------------- x/y -----------------------------------
735
736 typedcode_t node_div_write(node_t*n)
737 {
738     syntaxerror("can't assign to this expression");
739 }
740 typedcode_t node_div_read(node_t*n)
741 {
742     READ_HEADER_LEFTRIGHT;
743     c = code_append(left.c, right.c);
744     c = abc_divide(c);
745     t = TYPE_NUMBER;
746     RET
747 }
748 code_t* node_div_exec(node_t*n)
749 {
750     EXEC_HEADER_LEFTRIGHT;
751     return code_append(left, right);
752 }
753 constant_t node_div_eval(node_t*n)
754 {
755     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
756 }
757 nodetype_t node_div =
758 {
759 name: "div",
760 flags:NODE_HAS_CHILDREN,
761 eval: node_div_eval,
762 write: node_div_write,
763 read: node_div_read,
764 exec: node_div_exec
765 };
766
767 // ---------------------------- x%y -----------------------------------
768
769 typedcode_t node_mod_write(node_t*n)
770 {
771     syntaxerror("can't assign to this expression");
772 }
773 typedcode_t node_mod_read(node_t*n)
774 {
775     READ_HEADER_LEFTRIGHT;
776     c = code_append(left.c, right.c);
777     c = abc_modulo(c);
778     t = TYPE_NUMBER;
779     RET
780 }
781 code_t* node_mod_exec(node_t*n)
782 {
783     EXEC_HEADER_LEFTRIGHT;
784     return code_append(left, right);
785 }
786 constant_t node_mod_eval(node_t*n)
787 {
788     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
789 }
790 nodetype_t node_mod =
791 {
792 name: "mod",
793 flags:NODE_HAS_CHILDREN,
794 eval: node_mod_eval,
795 write: node_mod_write,
796 read: node_mod_read,
797 exec: node_mod_exec
798 };
799
800 // ---------------------------- x<y -----------------------------------
801
802 typedcode_t node_lt_write(node_t*n)
803 {
804     syntaxerror("can't assign to this expression");
805 }
806 typedcode_t node_lt_read(node_t*n)
807 {
808     READ_HEADER_LEFTRIGHT;
809     c = code_append(left.c,right.c);
810     c = abc_lessthan(c);
811     t = TYPE_BOOLEAN;
812     RET;
813 }
814 code_t* node_lt_exec(node_t*n)
815 {
816     EXEC_HEADER_LEFTRIGHT;
817     return code_append(left, right);
818 }
819 constant_t node_lt_eval(node_t*n)
820 {
821     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
822 }
823 nodetype_t node_lt =
824 {
825 name: "lt",
826 flags:NODE_HAS_CHILDREN,
827 eval: node_lt_eval,
828 write: node_lt_write,
829 read: node_lt_read,
830 exec: node_lt_exec
831 };
832
833 // ---------------------------- x>y -----------------------------------
834
835 typedcode_t node_gt_write(node_t*n)
836 {
837     syntaxerror("can't assign to this expression");
838 }
839 typedcode_t node_gt_read(node_t*n)
840 {
841     READ_HEADER_LEFTRIGHT;
842     c = code_append(left.c,right.c);
843     c = abc_greaterthan(c);
844     t = TYPE_BOOLEAN;
845     RET;
846 }
847 code_t* node_gt_exec(node_t*n)
848 {
849     EXEC_HEADER_LEFTRIGHT;
850     return code_append(left, right);
851 }
852 constant_t node_gt_eval(node_t*n)
853 {
854     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
855 }
856 nodetype_t node_gt =
857 {
858 name: "gt",
859 flags:NODE_HAS_CHILDREN,
860 eval: node_gt_eval,
861 write: node_gt_write,
862 read: node_gt_read,
863 exec: node_gt_exec
864 };
865
866 // ---------------------------- x<=y ----------------------------------
867
868 typedcode_t node_le_write(node_t*n)
869 {
870     syntaxerror("can't assign to this expression");
871 }
872 typedcode_t node_le_read(node_t*n)
873 {
874     READ_HEADER_LEFTRIGHT;
875     c = code_append(left.c,right.c);
876     c = abc_lessequals(c);
877     t = TYPE_BOOLEAN;
878     RET;
879 }
880 code_t* node_le_exec(node_t*n)
881 {
882     EXEC_HEADER_LEFTRIGHT;
883     return code_append(left, right);
884 }
885 constant_t node_le_eval(node_t*n)
886 {
887     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
888 }
889 nodetype_t node_le = //<=
890 {
891 name: "le",
892 flags:NODE_HAS_CHILDREN,
893 eval: node_le_eval,
894 write: node_le_write,
895 read: node_le_read,
896 exec: node_le_exec
897 };
898
899 // ---------------------------- x>=y ----------------------------------
900
901 typedcode_t node_ge_write(node_t*n)
902 {
903     syntaxerror("can't assign to this expression");
904 }
905 typedcode_t node_ge_read(node_t*n)
906 {
907     READ_HEADER_LEFTRIGHT;
908     c = code_append(left.c,right.c);
909     c = abc_greaterequals(c);
910     t = TYPE_BOOLEAN;
911     RET;
912 }
913 code_t* node_ge_exec(node_t*n)
914 {
915     EXEC_HEADER_LEFTRIGHT;
916     return code_append(left, right);
917 }
918 constant_t node_ge_eval(node_t*n)
919 {
920     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
921 }
922 nodetype_t node_ge = //>=
923 {
924 name: "ge",
925 flags:NODE_HAS_CHILDREN,
926 eval: node_ge_eval,
927 write: node_ge_write,
928 read: node_ge_read,
929 exec: node_ge_exec
930 };
931
932 // ---------------------------- x==y ----------------------------------
933
934 typedcode_t node_eqeq_write(node_t*n)
935 {
936     syntaxerror("can't assign to this expression");
937 }
938 typedcode_t node_eqeq_read(node_t*n)
939 {
940     READ_HEADER_LEFTRIGHT;
941     c = code_append(left.c,right.c);
942     c = abc_equals(c);
943     t = TYPE_BOOLEAN;
944     RET;
945 }
946 code_t* node_eqeq_exec(node_t*n)
947 {
948     EXEC_HEADER_LEFTRIGHT;
949     return code_append(left, right);
950 }
951 constant_t node_eqeq_eval(node_t*n)
952 {
953     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
954 }
955 nodetype_t node_eqeq = //==
956 {
957 name: "eqeq",
958 flags:NODE_HAS_CHILDREN,
959 eval: node_eqeq_eval,
960 write: node_eqeq_write,
961 read: node_eqeq_read,
962 exec: node_eqeq_exec
963 };
964
965 // --------------------------- x===y ----------------------------------
966
967 typedcode_t node_eqeqeq_write(node_t*n)
968 {
969     syntaxerror("can't assign to this expression");
970 }
971 typedcode_t node_eqeqeq_read(node_t*n)
972 {
973     READ_HEADER_LEFTRIGHT;
974     c = code_append(left.c,right.c);
975     c = abc_strictequals(c);
976     t = TYPE_BOOLEAN;
977     RET;
978 }
979 code_t* node_eqeqeq_exec(node_t*n)
980 {
981     EXEC_HEADER_LEFTRIGHT;
982     return code_append(left, right);
983 }
984 constant_t node_eqeqeq_eval(node_t*n)
985 {
986     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
987 }
988 nodetype_t node_eqeqeq = //===
989 {
990 name: "eqeqeq",
991 flags:NODE_HAS_CHILDREN,
992 eval: node_eqeqeq_eval,
993 write: node_eqeqeq_write,
994 read: node_eqeqeq_read,
995 exec: node_eqeqeq_exec
996 };
997
998 // --------------------------- x!==y ----------------------------------
999
1000 typedcode_t node_noteqeq_write(node_t*n)
1001 {
1002     syntaxerror("can't assign to this expression");
1003 }
1004 typedcode_t node_noteqeq_read(node_t*n)
1005 {
1006     READ_HEADER_LEFTRIGHT;
1007     c = code_append(left.c,right.c);
1008     c = abc_strictequals(c);
1009     c = abc_not(c);
1010     t = TYPE_BOOLEAN;
1011     RET;
1012 }
1013 code_t* node_noteqeq_exec(node_t*n)
1014 {
1015     EXEC_HEADER_LEFTRIGHT;
1016     return code_append(left, right);
1017 }
1018 constant_t node_noteqeq_eval(node_t*n)
1019 {
1020     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1021 }
1022 nodetype_t node_noteqeq = //!==
1023 {
1024 name: "noteqeq",
1025 flags:NODE_HAS_CHILDREN,
1026 eval: node_noteqeq_eval,
1027 write: node_noteqeq_write,
1028 read: node_noteqeq_read,
1029 exec: node_noteqeq_exec
1030 };
1031
1032 // --------------------------- x!=y ----------------------------------
1033
1034 typedcode_t node_noteq_write(node_t*n)
1035 {
1036     syntaxerror("can't assign to this expression");
1037 }
1038 typedcode_t node_noteq_read(node_t*n)
1039 {
1040     READ_HEADER_LEFTRIGHT;
1041     c = code_append(left.c,right.c);
1042     c = abc_equals(c);
1043     c = abc_not(c);
1044     t = TYPE_BOOLEAN;
1045     RET;
1046 }
1047 code_t* node_noteq_exec(node_t*n)
1048 {
1049     EXEC_HEADER_LEFTRIGHT;
1050     return code_append(left, right);
1051 }
1052 constant_t node_noteq_eval(node_t*n)
1053 {
1054     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1055 }
1056 nodetype_t node_noteq = //!=
1057 {
1058 name: "noteq",
1059 flags:NODE_HAS_CHILDREN,
1060 eval: node_noteq_eval,
1061 write: node_noteq_write,
1062 read: node_noteq_read,
1063 exec: node_noteq_exec
1064 };
1065
1066 // --------------------------- x||y ----------------------------------
1067
1068 typedcode_t node_oror_write(node_t*n)
1069 {
1070     syntaxerror("can't assign to this expression");
1071 }
1072 typedcode_t node_oror_read(node_t*n)
1073 {
1074     READ_HEADER_LEFTRIGHT;
1075     t = join_types(left.t, right.t, n->type);
1076     c = left.c;
1077     c = converttype(c, left.t, t);
1078     c = abc_dup(c);
1079     code_t*jmp = c = abc_iftrue(c, 0);
1080     c = cut_last_push(c);
1081     c = code_append(c, right.c);
1082     c = converttype(c, right.t, t);
1083     code_t*label = c = abc_label(c);
1084     jmp->branch = label;
1085     RET;
1086 }
1087 code_t* node_oror_exec(node_t*n)
1088 {
1089     typedcode_t left = n->child[0]->type->read(n->child[0]);
1090     code_t* right = n->child[1]->type->exec(n->child[1]);
1091     code_t*c = left.c;
1092     code_t*jmp = c = abc_iftrue(c, 0);
1093     c = code_append(c, right);
1094     code_t*label = c = abc_label(c);
1095     jmp->branch = label;
1096     return c;
1097 }
1098 constant_t node_oror_eval(node_t*n)
1099 {
1100     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1101 }
1102 nodetype_t node_oror = //||
1103 {
1104 name: "oror",
1105 flags:NODE_HAS_CHILDREN,
1106 eval: node_oror_eval,
1107 write: node_oror_write,
1108 read: node_oror_read,
1109 exec: node_oror_exec
1110 };
1111
1112 // --------------------------- x&&y ----------------------------------
1113
1114 typedcode_t node_andand_write(node_t*n)
1115 {
1116     syntaxerror("can't assign to this expression");
1117 }
1118 typedcode_t node_andand_read(node_t*n)
1119 {
1120     READ_HEADER_LEFTRIGHT;
1121     t = join_types(left.t, right.t, &node_andand);
1122     c = left.c;
1123     c = converttype(c, left.t, t);
1124     c = abc_dup(c);
1125     code_t*jmp = c = abc_iffalse(c, 0);
1126     c = cut_last_push(c);
1127     c = code_append(c,right.c);
1128     c = converttype(c, right.t, t);
1129     code_t*label = c = abc_label(c);
1130     jmp->branch = label;
1131     RET;
1132 }
1133 code_t* node_andand_exec(node_t*n)
1134 {
1135     typedcode_t left = n->child[0]->type->read(n->child[0]);\
1136     code_t* right = n->child[1]->type->exec(n->child[1]);\
1137     code_t*c = left.c;
1138     code_t*jmp = c = abc_iffalse(c, 0);
1139     c = code_append(c, right);
1140     code_t*label = c = abc_label(c);
1141     jmp->branch = label;
1142     return c;
1143 }
1144 constant_t node_andand_eval(node_t*n)
1145 {
1146     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1147 }
1148 nodetype_t node_andand = //&&
1149 {
1150 name: "andand",
1151 flags:NODE_HAS_CHILDREN,
1152 eval: node_andand_eval,
1153 write: node_andand_write,
1154 read: node_andand_read,
1155 exec: node_andand_exec
1156 };
1157
1158 // ----------------------------- !x -----------------------------------
1159
1160 typedcode_t node_not_write(node_t*n)
1161 {
1162     syntaxerror("can't assign to this expression");
1163 }
1164 typedcode_t node_not_read(node_t*n)
1165 {
1166     READ_HEADER_ONE;
1167     c = x.c;
1168     c = abc_not(c);
1169     t = TYPE_BOOLEAN;
1170     RET;
1171 }
1172 code_t* node_not_exec(node_t*n)
1173 {
1174     EXEC_HEADER_ONE;
1175     return x;
1176 }
1177 constant_t node_not_eval(node_t*n)
1178 {
1179     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1180 }
1181 nodetype_t node_not =
1182 {
1183 name: "not",
1184 flags:NODE_HAS_CHILDREN,
1185 eval: node_not_eval,
1186 write: node_not_write,
1187 read: node_not_read,
1188 exec: node_not_exec
1189 };
1190
1191 // ----------------------------- ~x -----------------------------------
1192
1193 typedcode_t node_bitnot_write(node_t*n)
1194 {
1195     syntaxerror("can't assign to this expression");
1196 }
1197 typedcode_t node_bitnot_read(node_t*n)
1198 {
1199     READ_HEADER_ONE;
1200     c = x.c;
1201     c = abc_bitnot(c);
1202     t = TYPE_INT;
1203     RET;
1204 }
1205 code_t* node_bitnot_exec(node_t*n)
1206 {
1207     EXEC_HEADER_ONE;
1208     return x;
1209 }
1210 constant_t node_bitnot_eval(node_t*n)
1211 {
1212     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1213 }
1214 nodetype_t node_bitnot =
1215 {
1216 name: "bitnot",
1217 flags:NODE_HAS_CHILDREN,
1218 eval: node_bitnot_eval,
1219 write: node_bitnot_write,
1220 read: node_bitnot_read,
1221 exec: node_bitnot_exec
1222 };
1223
1224 // ----------------------------- x&y -----------------------------------
1225
1226 typedcode_t node_bitand_write(node_t*n)
1227 {
1228     syntaxerror("can't assign to this expression");
1229 }
1230 typedcode_t node_bitand_read(node_t*n)
1231 {
1232     READ_HEADER_LEFTRIGHT;
1233     c = code_append(left.c,right.c);
1234     c = abc_bitand(c);
1235     t = TYPE_INT;
1236     RET;
1237 }
1238 code_t* node_bitand_exec(node_t*n)
1239 {
1240     EXEC_HEADER_LEFTRIGHT;
1241     return code_append(left, right);
1242 }
1243 constant_t node_bitand_eval(node_t*n)
1244 {
1245     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1246 }
1247 nodetype_t node_bitand =
1248 {
1249 name: "bitand",
1250 flags:NODE_HAS_CHILDREN,
1251 eval: node_bitand_eval,
1252 write: node_bitand_write,
1253 read: node_bitand_read,
1254 exec: node_bitand_exec
1255 };
1256
1257 // ----------------------------- x^y -----------------------------------
1258
1259 typedcode_t node_bitxor_write(node_t*n)
1260 {
1261     syntaxerror("can't assign to this expression");
1262 }
1263 typedcode_t node_bitxor_read(node_t*n)
1264 {
1265     READ_HEADER_LEFTRIGHT;
1266     c = code_append(left.c,right.c);
1267     c = abc_bitxor(c);
1268     t = TYPE_INT;
1269     RET;
1270 }
1271 code_t* node_bitxor_exec(node_t*n)
1272 {
1273     EXEC_HEADER_LEFTRIGHT;
1274     return code_append(left, right);
1275 }
1276 constant_t node_bitxor_eval(node_t*n)
1277 {
1278     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1279 }
1280 nodetype_t node_bitxor =
1281 {
1282 name: "bitxor",
1283 flags:NODE_HAS_CHILDREN,
1284 eval: node_bitxor_eval,
1285 write: node_bitxor_write,
1286 read: node_bitxor_read,
1287 exec: node_bitxor_exec
1288 };
1289
1290 // ----------------------------- x|y -----------------------------------
1291
1292 typedcode_t node_bitor_write(node_t*n)
1293 {
1294     syntaxerror("can't assign to this expression");
1295 }
1296 typedcode_t node_bitor_read(node_t*n)
1297 {
1298     READ_HEADER_LEFTRIGHT;
1299     c = code_append(left.c,right.c);
1300     c = abc_bitor(c);
1301     t = TYPE_INT;
1302     RET;
1303 }
1304 code_t* node_bitor_exec(node_t*n)
1305 {
1306     EXEC_HEADER_LEFTRIGHT;
1307     return code_append(left, right);
1308 }
1309 constant_t node_bitor_eval(node_t*n)
1310 {
1311     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1312 }
1313 nodetype_t node_bitor =
1314 {
1315 name: "bitor",
1316 flags:NODE_HAS_CHILDREN,
1317 eval: node_bitor_eval,
1318 write: node_bitor_write,
1319 read: node_bitor_read,
1320 exec: node_bitor_exec
1321 };
1322
1323 // ---------------------------- x>>y -----------------------------------
1324
1325 typedcode_t node_shr_write(node_t*n)
1326 {
1327     syntaxerror("can't assign to this expression");
1328 }
1329 typedcode_t node_shr_read(node_t*n)
1330 {
1331     READ_HEADER_LEFTRIGHT;
1332     c = code_append(left.c,right.c);
1333     c = abc_rshift(c);
1334     t = TYPE_INT;
1335     RET;
1336 }
1337 code_t* node_shr_exec(node_t*n)
1338 {
1339     EXEC_HEADER_LEFTRIGHT;
1340     return code_append(left, right);
1341 }
1342 constant_t node_shr_eval(node_t*n)
1343 {
1344     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1345 }
1346 nodetype_t node_shr = //>>
1347 {
1348 name: "shr",
1349 flags:NODE_HAS_CHILDREN,
1350 eval: node_shr_eval,
1351 write: node_shr_write,
1352 read: node_shr_read,
1353 exec: node_shr_exec
1354 };
1355
1356 // ---------------------------- x<<y -----------------------------------
1357
1358 typedcode_t node_shl_write(node_t*n)
1359 {
1360     syntaxerror("can't assign to this expression");
1361 }
1362 typedcode_t node_shl_read(node_t*n)
1363 {
1364     READ_HEADER_LEFTRIGHT;
1365     c = code_append(left.c,right.c);
1366     c = abc_lshift(c);
1367     t = TYPE_INT;
1368     RET;
1369 }
1370 code_t* node_shl_exec(node_t*n)
1371 {
1372     EXEC_HEADER_LEFTRIGHT;
1373     return code_append(left, right);
1374 }
1375 constant_t node_shl_eval(node_t*n)
1376 {
1377     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1378 }
1379 nodetype_t node_shl = //<<
1380 {
1381 name: "shl",
1382 flags:NODE_HAS_CHILDREN,
1383 eval: node_shl_eval,
1384 write: node_shl_write,
1385 read: node_shl_read,
1386 exec: node_shl_exec
1387 };
1388
1389 // ---------------------------- x>>>y -----------------------------------
1390
1391 typedcode_t node_ushr_write(node_t*n)
1392 {
1393     syntaxerror("can't assign to this expression");
1394 }
1395 typedcode_t node_ushr_read(node_t*n)
1396 {
1397     READ_HEADER_LEFTRIGHT;
1398     c = code_append(left.c,right.c);
1399     c = abc_urshift(c);
1400     t = TYPE_INT;
1401     RET;
1402 }
1403 code_t* node_ushr_exec(node_t*n)
1404 {
1405     EXEC_HEADER_LEFTRIGHT;
1406     return code_append(left, right);
1407 }
1408 constant_t node_ushr_eval(node_t*n)
1409 {
1410     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1411 }
1412 nodetype_t node_ushr = //>>>
1413 {
1414 name: "ushr",
1415 flags:NODE_HAS_CHILDREN,
1416 eval: node_ushr_eval,
1417 write: node_ushr_write,
1418 read: node_ushr_read,
1419 exec: node_ushr_exec
1420 };
1421
1422 // ---------------------------- x in y ----------------------------------
1423
1424 typedcode_t node_in_write(node_t*n)
1425 {
1426     syntaxerror("can't assign to this expression");
1427 }
1428 typedcode_t node_in_read(node_t*n)
1429 {
1430     READ_HEADER_LEFTRIGHT;
1431     c = code_append(left.c,right.c);
1432     c = abc_in(c);
1433     t = TYPE_BOOLEAN;
1434     RET;
1435 }
1436 code_t* node_in_exec(node_t*n)
1437 {
1438     EXEC_HEADER_LEFTRIGHT;
1439     return code_append(left, right);
1440 }
1441 constant_t node_in_eval(node_t*n)
1442 {
1443     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1444 }
1445 nodetype_t node_in = //in
1446 {
1447 name: "in",
1448 flags:NODE_HAS_CHILDREN,
1449 eval: node_in_eval,
1450 write: node_in_write,
1451 read: node_in_read,
1452 exec: node_in_exec
1453 };
1454
1455 // ---------------------------- x as y ----------------------------------
1456
1457 typedcode_t node_as_write(node_t*n)
1458 {
1459     /* ? */
1460     syntaxerror("can't assign to this expression");
1461 }
1462 typedcode_t node_as_read(node_t*n)
1463 {
1464     READ_HEADER_LEFTRIGHT;
1465     c = code_append(left.c, right.c);
1466     c = abc_astypelate(c);
1467     t = TYPE_ANY;
1468     RET;
1469 }
1470 code_t* node_as_exec(node_t*n)
1471 {
1472     /* we assume here that "as" doesn't have side-effects (like
1473        early run time type checking) */
1474     EXEC_HEADER_LEFTRIGHT;
1475     return code_append(left, right);
1476 }
1477 constant_t node_as_eval(node_t*n)
1478 {
1479     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1480 }
1481 nodetype_t node_as = //as
1482 {
1483 name: "as",
1484 flags:NODE_HAS_CHILDREN,
1485 eval: node_as_eval,
1486 write: node_as_write,
1487 read: node_as_read,
1488 exec: node_as_exec
1489 };
1490
1491 // ------------------------- x instanceof y -----------------------------
1492
1493 typedcode_t node_instanceof_write(node_t*n)
1494 {
1495     syntaxerror("can't assign to this expression");
1496 }
1497 typedcode_t node_instanceof_read(node_t*n)
1498 {
1499     READ_HEADER_LEFTRIGHT;
1500     c = code_append(left.c, right.c);
1501     c = abc_instanceof(c);
1502     t = TYPE_BOOLEAN;
1503     RET;
1504 }
1505 code_t* node_instanceof_exec(node_t*n)
1506 {
1507     EXEC_HEADER_LEFTRIGHT;
1508     return code_append(left, right);
1509 }
1510 constant_t node_instanceof_eval(node_t*n)
1511 {
1512     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1513 }
1514 nodetype_t node_instanceof = //instanceof
1515 {
1516 name: "instanceof",
1517 flags:NODE_HAS_CHILDREN,
1518 eval: node_instanceof_eval,
1519 write: node_instanceof_write,
1520 read: node_instanceof_read,
1521 exec: node_instanceof_exec
1522 };
1523
1524 // ------------------------- x is y --------------------------------------
1525
1526 typedcode_t node_is_write(node_t*n)
1527 {
1528     syntaxerror("can't assign to this expression");
1529 }
1530 typedcode_t node_is_read(node_t*n)
1531 {
1532     READ_HEADER_LEFTRIGHT;
1533     c = code_append(left.c, right.c);
1534     c = abc_istypelate(c);
1535     t = TYPE_BOOLEAN;
1536     RET;
1537 }
1538 code_t* node_is_exec(node_t*n)
1539 {
1540     EXEC_HEADER_LEFTRIGHT;
1541     return code_append(left, right);
1542 }
1543 constant_t node_is_eval(node_t*n)
1544 {
1545     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1546 }
1547 nodetype_t node_is = //is
1548 {
1549 name: "is",
1550 flags:NODE_HAS_CHILDREN,
1551 eval: node_is_eval,
1552 write: node_is_write,
1553 read: node_is_read,
1554 exec: node_is_exec
1555 };
1556
1557 // ------------------------- x[y] --------------------------------------
1558
1559 typedcode_t node_arraylookup_write(node_t*n)
1560 {
1561     syntaxerror("not implemented yet");
1562 }
1563 typedcode_t node_arraylookup_read(node_t*n)
1564 {
1565     READ_HEADER_LEFTRIGHT;
1566     c = code_append(left.c, right.c);
1567    
1568     /* XXX not sure whether this access logic is correct */
1569     namespace_t ns = {left.t?left.t->access:ACCESS_PACKAGE, ""};
1570     namespace_set_t nsset;
1571     namespace_list_t l;l.next = 0;
1572     nsset.namespaces = &l;
1573     l.namespace = &ns;
1574     multiname_t m = {MULTINAMEL, 0, &nsset, 0};
1575
1576     c = abc_getproperty2(c, &m);
1577     t = 0; // array elements have unknown type
1578     RET;
1579 }
1580 code_t* node_arraylookup_exec(node_t*n)
1581 {
1582     EXEC_HEADER_LEFTRIGHT;
1583     return code_append(left, right);
1584 }
1585 constant_t node_arraylookup_eval(node_t*n)
1586 {
1587     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1588 }
1589 nodetype_t node_arraylookup =
1590 {
1591 name: "arraylookup",
1592 flags:NODE_HAS_CHILDREN,
1593 eval: node_arraylookup_eval,
1594 write: node_arraylookup_write,
1595 read: node_arraylookup_read,
1596 exec: node_arraylookup_exec
1597 };
1598
1599 // ------------------------- typeof(x) ------------------------------------
1600
1601 typedcode_t node_typeof_write(node_t*n)
1602 {
1603     syntaxerror("can't assign to this expression");
1604 }
1605 typedcode_t node_typeof_read(node_t*n)
1606 {
1607     READ_HEADER_ONE;
1608     c = x.c;
1609     c = abc_typeof(c);
1610     t = TYPE_BOOLEAN;
1611     RET;
1612 }
1613 code_t* node_typeof_exec(node_t*n)
1614 {
1615     EXEC_HEADER_ONE;
1616     return x;
1617 }
1618 constant_t node_typeof_eval(node_t*n)
1619 {
1620     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1621 }
1622 nodetype_t node_typeof = //typeof
1623 {
1624 name: "typeof",
1625 flags:NODE_HAS_CHILDREN,
1626 eval: node_typeof_eval,
1627 write: node_typeof_write,
1628 read: node_typeof_read,
1629 exec: node_typeof_exec
1630 };
1631
1632 // ------------------------- (void)(x) ------------------------------------
1633
1634 typedcode_t node_void_write(node_t*n)
1635 {
1636     syntaxerror("can't assign to this expression");
1637 }
1638 typedcode_t node_void_read(node_t*n)
1639 {
1640     code_t*c = n->type->exec(n);
1641     c = abc_pushundefined(c);
1642     classinfo_t*t = TYPE_ANY;
1643     RET;
1644 }
1645 code_t* node_void_exec(node_t*n)
1646 {
1647     EXEC_HEADER_ONE;
1648     return x;
1649 }
1650 constant_t node_void_eval(node_t*n)
1651 {
1652     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1653 }
1654 nodetype_t node_void = //void
1655 {
1656 name: "void",
1657 flags:NODE_HAS_CHILDREN,
1658 eval: node_void_eval,
1659 write: node_void_write,
1660 read: node_void_read,
1661 exec: node_void_exec
1662 };
1663
1664 // ---------------------------- -x ----------------------------------------
1665
1666 typedcode_t node_neg_write(node_t*n)
1667 {
1668     syntaxerror("can't assign to this expression");
1669 }
1670 typedcode_t node_neg_read(node_t*n)
1671 {
1672     READ_HEADER_ONE;
1673     c = x.c;
1674     if(IS_INT(x.t)) {
1675        c = abc_negate_i(c);
1676        t = TYPE_INT;
1677     } else {
1678        c = abc_negate(c);
1679        t = TYPE_NUMBER;
1680     }
1681     RET;
1682 }
1683 code_t* node_neg_exec(node_t*n)
1684 {
1685     EXEC_HEADER_ONE;
1686     return x;
1687 }
1688 constant_t node_neg_eval(node_t*n)
1689 {
1690     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1691 }
1692 nodetype_t node_neg = //-
1693 {
1694 name: "neg",
1695 flags:NODE_HAS_CHILDREN,
1696 eval: node_neg_eval,
1697 write: node_neg_write,
1698 read: node_neg_read,
1699 exec: node_neg_exec
1700 };
1701
1702 // ---------------------------- x*=y ----------------------------------------
1703
1704 typedcode_t node_muleq_write(node_t*n)
1705 {
1706     syntaxerror("can't assign to this expression");
1707 }
1708 typedcode_t node_muleq_read(node_t*n)
1709 {
1710     READ_HEADER_LEFTRIGHT;
1711     c = right.c;
1712     classinfo_t*f = 0;
1713     if(BOTH_INT(left.t,right.t)) {
1714        c=abc_multiply_i(c);
1715        f = TYPE_INT;
1716     } else {
1717        c=abc_multiply(c);
1718        f = TYPE_NUMBER;
1719     }
1720     c=converttype(c, f, left.t);
1721     c = toreadwrite(left.c, c, 0, 0, 1);
1722     t = left.t;
1723     RET;
1724 }
1725 code_t* node_muleq_exec(node_t*n)
1726 {
1727     READ_HEADER_LEFTRIGHT;
1728     c = right.c;
1729     classinfo_t*f = 0;
1730     if(BOTH_INT(left.t,right.t)) {
1731         c=abc_multiply_i(c);
1732         f = TYPE_INT;
1733     } else {
1734         c=abc_multiply(c);
1735         f = TYPE_NUMBER;
1736     }
1737     c = converttype(c, f, left.t);
1738     return toreadwrite(left.c, c, 0, 0, 0);
1739 }
1740 constant_t node_muleq_eval(node_t*n)
1741 {
1742     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1743 }
1744 nodetype_t node_muleq =
1745 {
1746 name: "muleq",
1747 flags:NODE_HAS_CHILDREN,
1748 eval: node_muleq_eval,
1749 write: node_muleq_write,
1750 read: node_muleq_read,
1751 exec: node_muleq_exec
1752 };
1753
1754 // ---------------------------- x%=y ----------------------------------------
1755
1756 typedcode_t node_modeq_write(node_t*n)
1757 {
1758     syntaxerror("can't assign to this expression");
1759 }
1760 typedcode_t node_modeq_read(node_t*n)
1761 {
1762     READ_HEADER_LEFTRIGHT;
1763     c = abc_modulo(right.c);
1764     c = converttype(c, TYPE_NUMBER, left.t);
1765     c = toreadwrite(left.c, c, 0, 0, 1);
1766     t = left.t;
1767     RET;
1768 }
1769 code_t* node_modeq_exec(node_t*n)
1770 {
1771     READ_HEADER_LEFTRIGHT;
1772     c = abc_modulo(right.c);
1773     c = converttype(c, TYPE_NUMBER, left.t);
1774     return toreadwrite(left.c, c, 0, 0, 0);
1775 }
1776 constant_t node_modeq_eval(node_t*n)
1777 {
1778     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1779 }
1780 nodetype_t node_modeq = //%=
1781 {
1782 name: "modeq",
1783 flags:NODE_HAS_CHILDREN,
1784 eval: node_modeq_eval,
1785 write: node_modeq_write,
1786 read: node_modeq_read,
1787 exec: node_modeq_exec
1788 };
1789
1790 // ---------------------------- x<<=y ----------------------------------------
1791
1792 typedcode_t node_shleq_write(node_t*n)
1793 {
1794     syntaxerror("can't assign to this expression");
1795 }
1796 typedcode_t node_shleq_read(node_t*n)
1797 {
1798     READ_HEADER_LEFTRIGHT;
1799     c = abc_lshift(right.c);
1800     c = converttype(c, TYPE_INT, left.t);
1801     c = toreadwrite(left.c, c, 0, 0, 1);
1802     t = left.t;
1803     RET;
1804 }
1805 code_t* node_shleq_exec(node_t*n)
1806 {
1807     READ_HEADER_LEFTRIGHT;
1808     c = abc_lshift(right.c);
1809     c = converttype(c, TYPE_INT, left.t);
1810     return toreadwrite(left.c, c, 0, 0, 0);
1811 }
1812 constant_t node_shleq_eval(node_t*n)
1813 {
1814     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1815 }
1816 nodetype_t node_shleq = //<<=
1817 {
1818 name: "shleq",
1819 flags:NODE_HAS_CHILDREN,
1820 eval: node_shleq_eval,
1821 write: node_shleq_write,
1822 read: node_shleq_read,
1823 exec: node_shleq_exec
1824 };
1825
1826 // ---------------------------- x>>=y ----------------------------------------
1827
1828 typedcode_t node_shreq_write(node_t*n)
1829 {
1830     syntaxerror("can't assign to this expression");
1831 }
1832 typedcode_t node_shreq_read(node_t*n)
1833 {
1834     READ_HEADER_LEFTRIGHT;
1835     c = abc_rshift(right.c);
1836     c = converttype(c, TYPE_INT, left.t);
1837     c = toreadwrite(left.c, c, 0, 0, 1);
1838     t = left.t;
1839     RET;
1840 }
1841 code_t* node_shreq_exec(node_t*n)
1842 {
1843     READ_HEADER_LEFTRIGHT;
1844     c = abc_rshift(right.c);
1845     c = converttype(c, TYPE_INT, left.t);
1846     return toreadwrite(left.c, c, 0, 0, 0);
1847 }
1848 constant_t node_shreq_eval(node_t*n)
1849 {
1850     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1851 }
1852 nodetype_t node_shreq = //>>=
1853 {
1854 name: "shreq",
1855 flags:NODE_HAS_CHILDREN,
1856 eval: node_shreq_eval,
1857 write: node_shreq_write,
1858 read: node_shreq_read,
1859 exec: node_shreq_exec
1860 };
1861
1862 // --------------------------- x>>>=y ----------------------------------------
1863
1864 typedcode_t node_ushreq_write(node_t*n)
1865 {
1866     syntaxerror("can't assign to this expression");
1867 }
1868 typedcode_t node_ushreq_read(node_t*n)
1869 {
1870     READ_HEADER_LEFTRIGHT;
1871     c = abc_urshift(right.c);
1872     c = converttype(c, TYPE_UINT, left.t);
1873     c = toreadwrite(left.c, c, 0, 0, 1);
1874     t = left.t;
1875     RET;
1876 }
1877 code_t* node_ushreq_exec(node_t*n)
1878 {
1879     READ_HEADER_LEFTRIGHT;
1880     c = abc_urshift(right.c);
1881     c = converttype(c, TYPE_UINT, left.t);
1882     return toreadwrite(left.c, c, 0, 0, 0);
1883 }
1884 constant_t node_ushreq_eval(node_t*n)
1885 {
1886     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1887 }
1888 nodetype_t node_ushreq = //>>>=
1889 {
1890 name: "ushreq",
1891 flags:NODE_HAS_CHILDREN,
1892 eval: node_ushreq_eval,
1893 write: node_ushreq_write,
1894 read: node_ushreq_read,
1895 exec: node_ushreq_exec
1896 };
1897
1898 // --------------------------- x/=y ----------------------------------------
1899
1900 typedcode_t node_diveq_write(node_t*n)
1901 {
1902     syntaxerror("can't assign to this expression");
1903 }
1904 typedcode_t node_diveq_read(node_t*n)
1905 {
1906     READ_HEADER_LEFTRIGHT;
1907     c = abc_divide(right.c);
1908     c = converttype(c, TYPE_NUMBER, left.t);
1909     c = toreadwrite(left.c, c, 0, 0, 1);
1910     t = left.t;
1911     RET;
1912 }
1913 code_t* node_diveq_exec(node_t*n)
1914 {
1915     READ_HEADER_LEFTRIGHT;
1916     c = abc_divide(right.c);
1917     c = converttype(c, TYPE_NUMBER, left.t);
1918     return toreadwrite(left.c, c, 0, 0, 0);
1919 }
1920 constant_t node_diveq_eval(node_t*n)
1921 {
1922     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1923 }
1924 nodetype_t node_diveq =
1925 {
1926 name: "diveq",
1927 flags:NODE_HAS_CHILDREN,
1928 eval: node_diveq_eval,
1929 write: node_diveq_write,
1930 read: node_diveq_read,
1931 exec: node_diveq_exec
1932 };
1933
1934 // --------------------------- x|=y ----------------------------------------
1935
1936 typedcode_t node_bitoreq_write(node_t*n)
1937 {
1938     syntaxerror("can't assign to this expression");
1939 }
1940 typedcode_t node_bitoreq_read(node_t*n)
1941 {
1942     READ_HEADER_LEFTRIGHT;
1943     c = abc_bitor(right.c);
1944     c = converttype(c, TYPE_INT, left.t);
1945     c = toreadwrite(left.c, c, 0, 0, 1);
1946     t = left.t;
1947     RET;
1948 }
1949 code_t* node_bitoreq_exec(node_t*n)
1950 {
1951     READ_HEADER_LEFTRIGHT;
1952     c = abc_bitor(right.c);
1953     c = converttype(c, TYPE_INT, left.t);
1954     return toreadwrite(left.c, c, 0, 0, 0);
1955 }
1956 constant_t node_bitoreq_eval(node_t*n)
1957 {
1958     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1959 }
1960 nodetype_t node_bitoreq = //|=
1961 {
1962 name: "bitoreq",
1963 flags:NODE_HAS_CHILDREN,
1964 eval: node_bitoreq_eval,
1965 write: node_bitoreq_write,
1966 read: node_bitoreq_read,
1967 exec: node_bitoreq_exec
1968 };
1969
1970 // --------------------------- x^=y ----------------------------------------
1971
1972 typedcode_t node_bitxoreq_write(node_t*n)
1973 {
1974     syntaxerror("can't assign to this expression");
1975 }
1976 typedcode_t node_bitxoreq_read(node_t*n)
1977 {
1978     READ_HEADER_LEFTRIGHT;
1979     c = abc_bitxor(right.c);
1980     c = converttype(c, TYPE_INT, left.t);
1981     c = toreadwrite(left.c, c, 0, 0, 1);
1982     t = left.t;
1983     RET;
1984 }
1985 code_t* node_bitxoreq_exec(node_t*n)
1986 {
1987     READ_HEADER_LEFTRIGHT;
1988     c = abc_bitxor(right.c);
1989     c = converttype(c, TYPE_INT, left.t);
1990     return toreadwrite(left.c, c, 0, 0, 0);
1991 }
1992 constant_t node_bitxoreq_eval(node_t*n)
1993 {
1994     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
1995 }
1996 nodetype_t node_bitxoreq = //^=
1997 {
1998 name: "bitxoreq",
1999 flags:NODE_HAS_CHILDREN,
2000 eval: node_bitxoreq_eval,
2001 write: node_bitxoreq_write,
2002 read: node_bitxoreq_read,
2003 exec: node_bitxoreq_exec
2004 };
2005
2006 // --------------------------- x&=y ----------------------------------------
2007
2008 typedcode_t node_bitandeq_write(node_t*n)
2009 {
2010     syntaxerror("can't assign to this expression");
2011 }
2012 typedcode_t node_bitandeq_read(node_t*n)
2013 {
2014     READ_HEADER_LEFTRIGHT;
2015     c = abc_bitand(right.c);
2016     c = converttype(c, TYPE_INT, left.t);
2017     c = toreadwrite(left.c, c, 0, 0, 1);
2018     t = left.t;
2019     RET;
2020 }
2021 code_t* node_bitandeq_exec(node_t*n)
2022 {
2023     READ_HEADER_LEFTRIGHT;
2024     c = abc_bitand(right.c);
2025     c = converttype(c, TYPE_INT, left.t);
2026     return toreadwrite(left.c, c, 0, 0, 0);
2027 }
2028 constant_t node_bitandeq_eval(node_t*n)
2029 {
2030     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2031 }
2032 nodetype_t node_bitandeq = //^=
2033 {
2034 name: "bitandeq",
2035 flags:NODE_HAS_CHILDREN,
2036 eval: node_bitandeq_eval,
2037 write: node_bitandeq_write,
2038 read: node_bitandeq_read,
2039 exec: node_bitandeq_exec
2040 };
2041
2042 // --------------------------- x+=y ----------------------------------------
2043
2044 typedcode_t node_pluseq_write(node_t*n)
2045 {
2046     syntaxerror("can't assign to this expression");
2047 }
2048 typedcode_t node_pluseq_read(node_t*n)
2049 {
2050     READ_HEADER_LEFTRIGHT;
2051     c = right.c;
2052     if(TYPE_IS_INT(left.t)) {
2053        c = abc_add_i(c);
2054     } else {
2055        c = abc_add(c);
2056        c = converttype(c, TYPE_NUMBER, left.t);
2057     }
2058     c = toreadwrite(left.c, c, 0, 0, 1);
2059     t = left.t;
2060     RET;
2061 }
2062 code_t* node_pluseq_exec(node_t*n)
2063 {
2064     READ_HEADER_LEFTRIGHT;
2065     c = right.c;
2066     if(TYPE_IS_INT(left.t)) {
2067        c = abc_add_i(c);
2068     } else {
2069        c = abc_add(c);
2070        c = converttype(c, TYPE_NUMBER, left.t);
2071     }
2072     return toreadwrite(left.c, c, 0, 0, 0);
2073 }
2074 constant_t node_pluseq_eval(node_t*n)
2075 {
2076     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2077 }
2078 nodetype_t node_pluseq = //+=
2079 {
2080 name: "pluseq",
2081 flags:NODE_HAS_CHILDREN,
2082 eval: node_pluseq_eval,
2083 write: node_pluseq_write,
2084 read: node_pluseq_read,
2085 exec: node_pluseq_exec
2086 };
2087
2088 // --------------------------- x-=y ----------------------------------------
2089
2090 typedcode_t node_minuseq_write(node_t*n)
2091 {
2092     syntaxerror("can't assign to this expression");
2093 }
2094 typedcode_t node_minuseq_read(node_t*n)
2095 {
2096     READ_HEADER_LEFTRIGHT;
2097     c = right.c;
2098     if(TYPE_IS_INT(left.t)) {
2099        c = abc_subtract_i(c);
2100     } else {
2101        c = abc_subtract(c);
2102        c = converttype(c, TYPE_NUMBER, left.t);
2103     }
2104     c = toreadwrite(left.c, c, 0, 0, 1);
2105     t = left.t;
2106     RET;
2107 }
2108 code_t* node_minuseq_exec(node_t*n)
2109 {
2110     READ_HEADER_LEFTRIGHT;
2111     c = right.c;
2112     if(TYPE_IS_INT(left.t)) {
2113        c = abc_subtract_i(c);
2114     } else {
2115        c = abc_subtract(c);
2116        c = converttype(c, TYPE_NUMBER, left.t);
2117     }
2118     return toreadwrite(left.c, c, 0, 0, 0);
2119 }
2120 constant_t node_minuseq_eval(node_t*n)
2121 {
2122     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2123 }
2124 nodetype_t node_minuseq = //-=
2125 {
2126 name: "minuseq",
2127 flags:NODE_HAS_CHILDREN,
2128 eval: node_minuseq_eval,
2129 write: node_minuseq_write,
2130 read: node_minuseq_read,
2131 exec: node_minuseq_exec
2132 };
2133
2134 // --------------------------- x=y -----------------------------------------
2135
2136 typedcode_t node_assign_write(node_t*n)
2137 {
2138     syntaxerror("can't assign to this expression");
2139 }
2140 typedcode_t node_assign_read(node_t*n)
2141 {
2142     READ_HEADER_LEFTRIGHT;
2143     c = right.c;
2144     c = converttype(c, right.t, left.t);
2145     c = toreadwrite(left.c, c, 1, 0, 1);
2146     t = left.t;
2147     RET;
2148 }
2149 code_t* node_assign_exec(node_t*n)
2150 {
2151     READ_HEADER_LEFTRIGHT;
2152     c = right.c;
2153     c = converttype(c, right.t, left.t);
2154     return toreadwrite(left.c, c, 1, 0, 0);
2155 }
2156 constant_t node_assign_eval(node_t*n)
2157 {
2158     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2159 }
2160 nodetype_t node_assign =
2161 {
2162 name: "assign",
2163 flags:NODE_HAS_CHILDREN,
2164 eval: node_assign_eval,
2165 write: node_assign_write,
2166 read: node_assign_read,
2167 exec: node_assign_exec
2168 };
2169
2170 // --------------------------- x?y1:y2 --------------------------------------
2171
2172 typedcode_t node_tenary_write(node_t*n)
2173 {
2174     /* TODO: this might actually be kinda useful.
2175        (global?global.x:this.x) = 3;
2176     */
2177     syntaxerror("can't assign to this expression");
2178 }
2179 typedcode_t node_tenary_read(node_t*n)
2180 {
2181     typedcode_t cond = n->child[0]->type->read(n->child[0]);
2182     typedcode_t left = n->child[1]->type->read(n->child[1]);
2183     typedcode_t right = n->child[2]->type->read(n->child[2]);
2184     classinfo_t*t = join_types(left.t,right.t,&node_tenary);
2185     code_t* c = cond.c;
2186     code_t*j1 = c = abc_iffalse(c, 0);
2187     c = code_append(c, left.c);
2188     c = converttype(c, left.t, t);
2189     code_t*j2 = c = abc_jump(c, 0);
2190     c = j1->branch = abc_label(c);
2191     c = code_append(c, right.c);
2192     c = converttype(c, right.t, t);
2193     c = j2->branch = abc_label(c);
2194     RET;
2195 }
2196 code_t* node_tenary_exec(node_t*n)
2197 {
2198     typedcode_t cond = n->child[0]->type->read(n->child[0]);
2199     code_t* left = n->child[1]->type->exec(n->child[1]);
2200     code_t* right = n->child[2]->type->exec(n->child[2]);
2201     code_t* c = cond.c;
2202     code_t*j1 = c = abc_iffalse(c, 0);
2203     c = code_append(c, left);
2204     code_t*j2 = c = abc_jump(c, 0);
2205     c = j1->branch = abc_label(c);
2206     c = code_append(c, right);
2207     c = j2->branch = abc_label(c);
2208     return c;
2209 }
2210 constant_t node_tenary_eval(node_t*n)
2211 {
2212     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2213 }
2214 nodetype_t node_tenary =
2215 {
2216 name: "tenary",
2217 flags:NODE_HAS_CHILDREN,
2218 eval: node_tenary_eval,
2219 write: node_tenary_write,
2220 read: node_tenary_read,
2221 exec: node_tenary_exec
2222 };
2223
2224 // ---------------------------- comma ----------------------------------------
2225
2226 typedcode_t node_comma_write(node_t*n)
2227 {
2228     syntaxerror("can't assign to this expression");
2229 }
2230 typedcode_t node_comma_read(node_t*n)
2231 {
2232     code_t*c = 0;
2233     classinfo_t*t = 0;
2234     int i;
2235     for(i=0;i<n->num_children-1;i++) {
2236         c = code_append(c, n->child[i]->type->exec(n->child[i]));
2237     }
2238     typedcode_t o = n->child[i]->type->read(n->child[i]);
2239     c = code_append(c, o.c);
2240     t = o.t;
2241     RET;
2242 }
2243 code_t* node_comma_exec(node_t*n)
2244 {
2245     int t;
2246     code_t*c = 0;
2247     for(t=0;t<n->num_children;t++) {
2248         c = code_append(c, n->child[t]->type->exec(n->child[t]));
2249     }
2250     return c;
2251 }
2252 constant_t node_comma_eval(node_t*n)
2253 {
2254     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2255 }
2256 nodetype_t node_comma =
2257 {
2258 name: "expr",
2259 flags: NODE_HAS_CHILDREN,
2260 eval: node_comma_eval,
2261 write: node_comma_write,
2262 read: node_comma_read,
2263 exec: node_comma_exec
2264 };
2265
2266
2267 #if 0
2268 // -------------------------- new x -----------------------------------
2269
2270 typedcode_t node_new_write(node_t*n)
2271 {
2272 }
2273 typedcode_t node_new_read(node_t*n)
2274 {
2275 }
2276 code_t* node_new_exec(node_t*n)
2277 {
2278 }
2279 constant_t node_new_eval(node_t*n)
2280 {
2281     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2282 }
2283 nodetype_t node_new = //new
2284 {
2285 write: node_new_write,
2286 read: node_new_read,
2287 eval: node_new_eval,
2288 exec: node_new_exec
2289 };
2290
2291 // ------------------------ delete x ----------------------------------
2292
2293 typedcode_t node_delete_write(node_t*n)
2294 {
2295 }
2296 typedcode_t node_delete_read(node_t*n)
2297 {
2298 }
2299 code_t* node_delete_exec(node_t*n)
2300 {
2301 }
2302 constant_t node_delete_eval(node_t*n)
2303 {
2304     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2305 }
2306 nodetype_t node_delete = //delete
2307 {
2308 write: node_delete_write,
2309 read: node_delete_read,
2310 eval: node_delete_eval,
2311 exec: node_delete_exec
2312 };
2313
2314 // ---------------------------- x.y -----------------------------------
2315
2316 typedcode_t node_dot_write(node_t*n)
2317 {
2318 }
2319 typedcode_t node_dot_read(node_t*n)
2320 {
2321 }
2322 code_t* node_dot_exec(node_t*n)
2323 {
2324 }
2325 constant_t node_dot_eval(node_t*n)
2326 {
2327     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2328 }
2329 nodetype_t node_dot =
2330 {
2331 write: node_dot_write,
2332 read: node_dot_read,
2333 eval: node_dot_eval,
2334 exec: node_dot_exec
2335 };
2336
2337 // --------------------------- x..y -----------------------------------
2338
2339 typedcode_t node_dotdot_write(node_t*n)
2340 {
2341 }
2342 typedcode_t node_dotdot_read(node_t*n)
2343 {
2344 }
2345 code_t* node_dotdot_exec(node_t*n)
2346 {
2347
2348 }
2349 constant_t node_dotdot_eval(node_t*n)
2350 {
2351     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2352 }
2353 nodetype_t node_dotdot = //..
2354 {
2355 write: node_dotdot_write,
2356 read: node_dotdot_read,
2357 eval: node_dotdot_eval,
2358 exec: node_dotdot_exec
2359 };
2360
2361 // --------------------------- x.@y -----------------------------------
2362
2363 typedcode_t node_dotat_write(node_t*n)
2364 {
2365 }
2366 typedcode_t node_dotat_read(node_t*n)
2367 {
2368 }
2369 code_t* node_dotat_exec(node_t*n)
2370 {
2371 }
2372 constant_t node_dotat_eval(node_t*n)
2373 {
2374     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2375 }
2376 nodetype_t node_dotat = //.@
2377 {
2378 write: node_dotat_write,
2379 read: node_dotat_read,
2380 eval: node_dotat_eval,
2381 exec: node_dotat_exec
2382 };
2383
2384 // --------------------------- x.*y -----------------------------------
2385
2386 typedcode_t node_dotstar_write(node_t*n)
2387 {
2388 }
2389 typedcode_t node_dotstar_read(node_t*n)
2390 {
2391 }
2392 code_t* node_dotstar_exec(node_t*n)
2393 {
2394 }
2395 constant_t node_dotstar_eval(node_t*n)
2396 {
2397     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2398 }
2399 nodetype_t node_dotstar = //.*
2400 {
2401 write: node_dotstar_write,
2402 read: node_dotstar_read,
2403 eval: node_dotstar_eval,
2404 exec: node_dotstar_exec
2405 };
2406
2407 // -------------------------- x.(y) -----------------------------------
2408
2409 typedcode_t node_filter_write(node_t*n)
2410 {
2411 }
2412 typedcode_t node_filter_read(node_t*n)
2413 {
2414 }
2415 code_t* node_filter_exec(node_t*n)
2416 {
2417 }
2418 constant_t node_filter_eval(node_t*n)
2419 {
2420     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2421 }
2422 nodetype_t node_filter = //.(
2423 {
2424 write: node_filter_write,
2425 read: node_filter_read,
2426 eval: node_filter_eval,
2427 exec: node_filter_exec
2428 };
2429
2430 // ------------------------ x(y1,...,yn) ------------------------------
2431
2432 typedcode_t node_call_write(node_t*n)
2433 {
2434 }
2435 typedcode_t node_call_read(node_t*n)
2436 {
2437 }
2438 code_t* node_call_exec(node_t*n)
2439 {
2440 }
2441 constant_t node_call_eval(node_t*n)
2442 {
2443     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2444 }
2445 nodetype_t node_call = //functioncall
2446 {
2447 write: node_call_write,
2448 read: node_call_read,
2449 eval: node_call_eval,
2450 exec: node_call_exec
2451 };
2452
2453 // ------------------------------ @x ----------------------------------------
2454
2455 typedcode_t node_at_write(node_t*n)
2456 {
2457 }
2458 typedcode_t node_at_read(node_t*n)
2459 {
2460 }
2461 code_t* node_at_exec(node_t*n)
2462 {
2463 }
2464 constant_t node_at_eval(node_t*n)
2465 {
2466     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2467 }
2468 nodetype_t node_at = //@
2469 {
2470 write: node_at_write,
2471 read: node_at_read,
2472 eval: node_at_eval,
2473 exec: node_at_exec
2474 };
2475
2476 // ---------------------------- x.ns::y ----------------------------------------
2477
2478 typedcode_t node_dotns_write(node_t*n)
2479 {
2480 }
2481 typedcode_t node_dotns_read(node_t*n)
2482 {
2483 }
2484 code_t* node_dotns_exec(node_t*n)
2485 {
2486 }
2487 constant_t node_dotns_eval(node_t*n)
2488 {
2489     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2490 }
2491 nodetype_t node_dotns = //.::
2492 {
2493 write: node_dotns_write,
2494 read: node_dotns_read,
2495 eval: node_dotns_eval,
2496 exec: node_dotns_exec
2497 };
2498 #endif
2499
2500 // ------------------------ constant ------------------------------
2501
2502 typedcode_t node_const_write(node_t*n)
2503 {
2504     syntaxerror("can't assign a value to a constant");
2505 }
2506 typedcode_t node_const_read(node_t*n)
2507 {
2508     constant_t*v = n->value;
2509     code_t*c=0;
2510     classinfo_t*t=0;
2511     switch(v->type) {
2512         case CONSTANT_INT:
2513             if(v->i>-128 && v->i<128) {
2514                 c = abc_pushbyte(0,v->i);
2515             } else if(v->i>=-32768 && v->i<32768) {
2516                 c = abc_pushshort(0,v->i);
2517             } else {
2518                 c = abc_pushint(0,v->i);
2519             }
2520             t = TYPE_INT;
2521         break;
2522         case CONSTANT_UINT:
2523             c = abc_pushuint(0,v->u);
2524             if(v->u<128) {
2525                 c = abc_pushbyte(0,v->u);
2526             } else if(v->u<32768) {
2527                 c = abc_pushshort(0,v->u);
2528             } else {
2529                 c = abc_pushint(0,v->u);
2530             }
2531             t = TYPE_UINT;
2532         break;
2533         case CONSTANT_FLOAT:
2534             c = abc_pushdouble(0,v->f);
2535             t = TYPE_FLOAT;
2536         break;
2537         case CONSTANT_TRUE:
2538             c = abc_pushtrue(0);
2539             t = TYPE_BOOLEAN;
2540         break;
2541         case CONSTANT_FALSE:
2542             c = abc_pushfalse(0);
2543             t = TYPE_BOOLEAN;
2544         break;
2545         case CONSTANT_NULL:
2546             c = abc_pushnull(0);
2547             t = TYPE_NULL;
2548         break;
2549         case CONSTANT_STRING:
2550             c = abc_pushstring2(0,v->s);
2551             t = TYPE_STRING;
2552         break;
2553         case CONSTANT_UNDEFINED:
2554             c = abc_pushundefined(0);
2555             t = 0;
2556         break;
2557         case CONSTANT_NAMESPACE:
2558         case CONSTANT_NAMESPACE_PACKAGE:
2559         case CONSTANT_NAMESPACE_PACKAGEINTERNAL:
2560         case CONSTANT_NAMESPACE_PROTECTED:
2561         case CONSTANT_NAMESPACE_EXPLICIT:
2562         case CONSTANT_NAMESPACE_STATICPROTECTED:
2563         case CONSTANT_NAMESPACE_PRIVATE:
2564             c = abc_pushnamespace(0, v->ns);
2565         break;
2566         default: syntaxerror("invalid constant");
2567     }
2568     RET;
2569 }
2570
2571 code_t* node_const_exec(node_t*n)
2572 {
2573     return 0;
2574 }
2575 constant_t node_const_eval(node_t*n)
2576 {
2577     constant_t*c = constant_clone(n->value);
2578     constant_t r = *c;
2579     free(c); //shallow free
2580     return r;
2581 }
2582 nodetype_t node_const =
2583 {
2584 name: "const",
2585 flags:0,
2586 eval: node_const_eval,
2587 write: node_const_write,
2588 read: node_const_read,
2589 exec: node_const_exec
2590 };
2591
2592 // ------------------------ code node ------------------------------
2593
2594 typedcode_t node_code_write(node_t*n)
2595 {
2596     syntaxerror("not implemented yet");
2597 }
2598 typedcode_t node_code_read(node_t*n)
2599 {
2600     /* TODO: this dup might be unnecessary- n->code.c is only read out once */
2601     typedcode_t t;
2602     t.c = code_dup(n->code.c);
2603     t.t = n->code.t;
2604     return t;
2605 }
2606 code_t* node_code_exec(node_t*n)
2607 {
2608     code_t*c = code_dup(n->code.c);
2609     c = cut_last_push(c);
2610     return c;
2611 }
2612 constant_t node_code_eval(node_t*n)
2613 {
2614     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2615 }
2616 nodetype_t node_code =
2617 {
2618 name: "code",
2619 flags:0,
2620 eval: node_code_eval,
2621 write: node_code_write,
2622 read: node_code_read,
2623 exec: node_code_exec
2624 };
2625
2626 // ------------------------ dummy node ------------------------------
2627               
2628 typedcode_t node_dummy_write(node_t*n)
2629 {
2630     syntaxerror("not implemented yet");
2631 }
2632 typedcode_t node_dummy_read(node_t*n)
2633 {
2634     typedcode_t t;
2635     t.c = abc_pushundefined(0);
2636     t.t = TYPE_ANY;
2637     return t;
2638 }
2639 code_t* node_dummy_exec(node_t*n)
2640 {
2641     return 0;
2642 }
2643 constant_t node_dummy_eval(node_t*n)
2644 {
2645     constant_t r;r.type=CONSTANT_UNKNOWN;return r;
2646 }
2647 nodetype_t node_dummy =
2648 {
2649 name: "dummy",
2650 flags:0,
2651 eval: node_dummy_eval,
2652 write: node_dummy_write,
2653 read: node_dummy_read,
2654 exec: node_dummy_exec
2655 };
2656
2657 // ======================== node handling ==============================
2658
2659 node_t* mkdummynode()
2660 {
2661     node_t*n = (node_t*)rfx_calloc(sizeof(node_t));
2662     n->type = &node_dummy;
2663     return n;
2664 }
2665
2666 node_t* mkconstnode(constant_t*c)
2667 {
2668     node_t*n = (node_t*)malloc(sizeof(node_t));
2669     n->type = &node_const;
2670     n->parent = 0;
2671     n->value = c;
2672     return n;
2673 }
2674
2675 node_t* mkcodenode(typedcode_t c)
2676 {
2677     node_t*n = (node_t*)malloc(sizeof(node_t));
2678     n->type = &node_code;
2679     n->parent = 0;
2680     n->code = c;
2681     return n;
2682 }
2683
2684 node_t* mkmultinode(nodetype_t*t, node_t*one)
2685 {
2686     node_t*n = (node_t*)malloc(sizeof(node_t));
2687     n->type = t;
2688     n->parent = 0;
2689     n->child = (node_t**)malloc(sizeof(node_t*)*1);
2690     n->child[0] = one;
2691     n->num_children = 1;
2692     return n;
2693 }
2694
2695 node_t* multinode_extend(node_t*n, node_t*add)
2696 {
2697     n->child = realloc(n->child, (n->num_children+1)*sizeof(node_t*));
2698     n->child[n->num_children] = add;
2699     n->num_children++;
2700     return n;
2701 }
2702
2703 node_t* mknode1(nodetype_t*t, node_t*node)
2704 {
2705     node_t*n = (node_t*)malloc(sizeof(node_t)+sizeof(node_t*)*2);
2706     node_t**x = (node_t**)&n[1];
2707     n->type = t;
2708     n->parent = 0;
2709     n->child = x;
2710     n->num_children = 1;
2711     x[0] = node;
2712     x[1] = 0;
2713     return n;
2714 };
2715
2716 node_t* mknode2(nodetype_t*t, node_t*left, node_t*right)
2717 {
2718     node_t*n = (node_t*)malloc(sizeof(node_t)+sizeof(node_t*)*3);
2719     node_t**x = (node_t**)&n[1];
2720     n->type = t;
2721     n->parent = 0;
2722     n->child = x;
2723     n->num_children = 2;
2724     x[0] = left;
2725     x[1] = right;
2726     x[2] = 0;
2727     return n;
2728 }
2729 node_t* mknode3(nodetype_t*t, node_t*one, node_t*two, node_t*three)
2730 {
2731     node_t*n = (node_t*)malloc(sizeof(node_t)+sizeof(node_t*)*4);
2732     node_t**x = (node_t**)&n[1];
2733     n->type = t;
2734     n->parent = 0;
2735     n->child = x;
2736     n->num_children = 3;
2737     x[0] = one;
2738     x[1] = two;
2739     x[2] = three;
2740     x[3] = 0;
2741     return n;
2742 }
2743
2744 void node_free(node_t*n)
2745 {
2746     int t;
2747     if(n->type == &node_const) {
2748         constant_free(n->value);n->value = 0;
2749     }
2750     else if(n->type == &node_code) {
2751         code_free(n->code.c);n->code.c = 0;
2752     }
2753     else for(t=0;t<n->num_children;t++) {
2754         node_free(n->child[t]);n->child[t] = 0;
2755     }
2756     free(n);
2757 }
2758
2759 typedcode_t node_read(node_t*n)
2760 {
2761     typedcode_t t = n->type->read(n);
2762     node_free(n);
2763     return t;
2764 }
2765 code_t* node_exec(node_t*n)
2766 {
2767     code_t*c = n->type->exec(n);
2768     node_free(n);
2769     return c;
2770 }
2771 constant_t node_eval(node_t*n)
2772 {
2773     constant_t c = n->type->eval(n);
2774     node_free(n);
2775     return c;
2776 }
2777
2778 /*
2779  |
2780  +-add
2781  | |
2782  | +-code
2783  | |
2784  | +-code
2785  |   |
2786  |   +
2787  | 
2788  +-div
2789
2790 */
2791 void node_dump2(node_t*n, const char*p1, const char*p2, FILE*fi)
2792 {
2793     if(n->type->flags&NODE_HAS_CHILDREN) {
2794         fprintf(fi, "%s%s\n", p1, n->type->name);
2795         int t;
2796         char*o2 = malloc(strlen(p2)+3);
2797         strcpy(o2, p2);strcat(o2, "| ");
2798         char*o3 = malloc(strlen(p2)+3);
2799         strcpy(o3, p2);strcat(o3, "+-");
2800         char*o4 = malloc(strlen(p2)+3);
2801         strcpy(o4, p2);strcat(o4, "  ");
2802
2803         for(t=0;t<n->num_children;t++) {
2804             fprintf(fi, "%s\n", o2);
2805             node_dump2(n->child[t], o3, t<n->num_children-1?o2:o4, fi);
2806         }
2807         free(o2);
2808         free(o3);
2809         free(o4);
2810     } else if(n->type == &node_const) {
2811         char*s = constant_tostring(n->value);
2812         fprintf(fi, "%s%s (%s)\n", p1, n->type->name, s);
2813         free(s);
2814     } else if(n->type == &node_code) {
2815         fprintf(fi, "%s%s\n", p1, n->type->name);
2816         code_dump2(n->code.c, 0, 0, (char*)p2, fi);
2817     } else {
2818         fprintf(fi, "%s%s\n", p1, n->type->name);
2819     }
2820 }
2821
2822 void node_dump(node_t*n)
2823 {
2824     printf("---------------------------VVVV\n");
2825     node_dump2(n,"","",stdout);
2826     printf("---------------------------^^^^\n");
2827 }
2828