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