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