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