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