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