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