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