source: cpp/frams/vm/framscript.y @ 341

Last change on this file since 341 was 341, checked in by Maciej Komosinski, 7 years ago

Fixed using null as object reference

  • Property svn:eol-style set to native
File size: 43.9 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5%{
6#include "framscript-defs.h"
7#include "common/framsg.h"
8#include <math.h>
9#include <ctype.h>
10#include <stdio.h>
11
12#define YYERROR_VERBOSE
13#define YYPRINT(file,type,value) yyprint (file,type,value)
14
15static void yyprint (FILE *file,int type,YYSTYPE value);
16void handleTwoArg(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
17                  int optoken,const char* opname, bool negarg2, bool uniq);
18bool handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
19                   ExtValue::CmpOperator,const char* opname);
20bool handleAssignOp(YYSTYPE& result,const YYSTYPE& var,const YYSTYPE& arg,const char* opname);
21bool handleAssignOp2(YYSTYPE& result,const char *var,const YYSTYPE& arg,const char* opname,int stackpos,bool push);
22bool variableOk(TokenValue &tok, const TokenValue& var,int &loc);
23bool globalOk(const TokenValue& var);
24void badVariable(TokenValue &tok, const TokenValue &var);
25bool evalVariable(TokenValue &tok, const TokenValue &var);
26bool doBreak(int level);
27bool doContinue(int level);
28void warnTruthValue(const TokenValue& t);
29void outFunName(const TokenValue& t);
30static bool resultIsRelaxedEqual(ExtValue::CompareResult res);
31
32static const char* assign_op_names[]={"add","sub","mul","div","mod"};
33
34%}
35
36%token_table
37
38%token CONSTANT
39
40%nonassoc ASSIGN_ADD ASSIGN_SUB ASSIGN_MUL ASSIGN_DIV ASSIGN_MOD
41%nonassoc PLUSPLUS MINUSMINUS
42%left LOGIC_AND LOGIC_OR '!'
43%left EQUAL NOT_EQUAL GEQUAL LEQUAL '>' '<'
44%left '|' '&' '^'
45%left '-' '+'
46%left '*' '/' '%'
47%left NEG     /* negation--unary minus */
48%left TYPEOF
49%left INT_TYPE
50%left FLOAT_TYPE
51%left STRING_TYPE
52
53%token IDENT
54%token OBJNAME
55
56%token IF      "if"
57%token ELSE    "else"
58%token FOR     "for"
59%token INNN    "in"
60%token WHILE   "while"
61%token DO      "do"
62%token GOTO    "goto"
63%token RETURN  "return"
64%token BREAK    "break"
65%token CONTINUE "continue"
66%token SWITCH   "switch"
67%token CASE     "case"
68%token DEFAULT  "default"
69
70%token TYPEOF      "typeof"
71%token INT_TYPE    "int"
72%token FLOAT_TYPE  "float"
73%token STRING_TYPE "string"
74
75%token ASM     
76%token ASMLINE
77             
78%token VAR      "var"
79%token GLOBAL   "global"
80%token FUNCTION "function"
81
82%token CALL    "call"
83
84%token ASSIGN
85%token ASSIGN_ADD
86%token ASSIGN_SUB
87%token ASSIGN_MUL
88%token ASSIGN_DIV
89
90%token EQUAL
91%token NOT_EQUAL
92%token GEQUAL
93%token LEQUAL
94
95%token LOGIC_AND
96%token LOGIC_OR
97
98%token PLUSPLUS
99%token MINUSMINUS
100
101%token LSHIFT
102%token RSHIFT
103
104%%
105code: {$$.setInt(trstack.currentPos());} recurcode
106{
107int pos=$1.getInt();
108if (pos!=trstack.currentPos()) trctx.out->printf("add %d,m0\n",pos-trstack.currentPos());
109}
110;
111
112recurcode:    /* empty string */
113       | recurcode statement
114;
115     
116statement: ';'
117      | VAR vardeflist ';'
118      | GLOBAL globaldeflist ';'
119      | IDENT ':'     {trctx.out->printf(":%s\n",str($1));}
120      | expr ';'      {if (!$1.constant) { trctx.out->printf("inc m0\n"); trstack.adjust(+1); } trctx.emitLine(); }
121      | functiondef
122      | blok
123      | if_statement
124      | goto_statement
125      | return_statement
126      | for_statement
127      | while_statement
128      | dowhile_statement
129      | break_statement
130      | continue_statement
131      | switch_statement
132//      | error ';'
133      | asmblock
134;
135
136asmblock: ASM asmlines '}'
137;
138
139asmlines: /* empty */
140        | ASMLINE            {fputs(str($1),trctx.out);fputc('\n',trctx.out);}
141        | asmlines ASMLINE   {fputs(str($2),trctx.out);fputc('\n',trctx.out);}
142;
143
144goto_statement: GOTO IDENT ';'
145 {
146#ifdef FRAMSCRIPT_GOTO
147trctx.out->printf("jump :%s\n",str($2)); FMprintf("FramScriptCompiler","translate",FMLV_WARN,"goto is not recommended"); trctx.emitLine();
148#else
149trctx.err->printf("goto is not supported\n");return 1;
150#endif
151 }
152;
153
154return_statement: RETURN expr ';'
155{
156int offset;
157if (trctx.functionstackpos==999)
158        offset=-trstack.currentPos();
159else
160        offset=trctx.functionstackpos-trstack.currentPos();
161if (!offset)
162        {
163        if ($2.constant)
164                trctx.out->printf("move %s,s0\nreturn\n",litstr($2));
165        else
166                {
167                trctx.out->printf("move m[m0++],s0\nreturn\n");
168                trstack.adjust(+1);
169                }
170        }
171else
172        {
173        if ($2.constant)
174                {
175                trctx.out->printf("add %d,m0\nmove %s,s0\nreturn\n",offset,litstr($2));
176                trstack.adjust(offset);
177                }
178        else
179                {
180                trctx.out->printf("move s0,s%d\nadd %d,m0\nreturn\n",offset,offset);
181                trstack.adjust(offset);
182                }
183        }
184}
185          | RETURN ';'
186{
187int offset;
188if (trctx.functionstackpos==999)
189        offset=-trstack.currentPos();
190else
191        offset=trctx.functionstackpos-trstack.currentPos();
192trctx.emitLine();
193if (!offset)
194        trctx.out->printf("move invalid,s0\nreturn\n");
195else
196        trctx.out->printf("add %d,m0\nmove invalid,s0\nreturn\n",offset);
197}
198;
199
200vardeflist: vardef
201          | vardeflist ',' vardef
202;
203
204vardef: IDENT               { trctx.emitLine(); trstack.addVariable($1.getString()); trctx.out->printf("push invalid\n");}
205      | IDENT '=' stackexpr { trctx.emitLine(); trstack.adjust(1); trstack.addVariable($1.getString());}
206;
207
208globaldeflist: globaldef
209          | globaldeflist ',' globaldef
210;
211
212globaldef: IDENT     {trstack.globals.add($1.getString(),0);
213                      trctx.out->printf("global %s\n",str($1));}
214;
215
216funparam: IDENT { trstack.addVariable($1.getString()); };
217
218paramlist: /* empty */             {$$.setInt(0); }
219         | funparam                {$$.setInt(1); }
220         | paramlist ',' funparam  {$$.setInt($1.getInt()+1);}
221;
222
223funnamelist:
224         IDENT {outFunName($1);}
225         | funnamelist ',' IDENT {outFunName($3);}
226;
227
228functiondef:                FUNCTION funnamelist
229{
230trctx.emitLine();
231int pos=trstack.currentPos();
232$$.setInt(pos);
233if (trctx.functionstackpos!=999)
234        {trctx.err->printf("functions cannot be nested\n");return 1;}
235}
236                            '(' paramlist ')'
237{
238trctx.functionstackpos=trstack.currentPos();
239}
240                            blok
241{trctx.out->printf("move invalid,s0\nreturn\n");
242int pos=$3.getInt();
243trstack.dropToPos(pos);
244trctx.functionstackpos=999;
245trctx.out->printf(":_skipfun_%d\n",trctx.functiontmplabel);
246trctx.functiontmplabel=-1;
247trctx.emitLine();
248};
249
250break_statement: BREAK ';'         {if (!doBreak(1)) return 1;}
251               | BREAK expr ';'
252{
253trctx.emitLine();
254if (!$2.constant)
255        {trctx.err->printf("break level must be a constant expression\n");return 1;}
256int level=$2.getInt();
257if (level<1)
258        {trctx.err->printf("break level must be a positive integer\n");return 1;}
259if (!doBreak(level)) return 1;
260trctx.emitLine();
261};
262
263continue_statement: CONTINUE ';'         {if (!doContinue(1)) return 1;}
264                  | CONTINUE expr ';'
265{
266if (!$2.constant)
267        {trctx.err->printf("continue level must be a constant expression\n");return 1;}
268int level=$2.getInt();
269if (level<1)
270        {trctx.err->printf("continue level must be a positive integer\n");return 1;}
271if (!doContinue(level)) return 1;
272trctx.emitLine();
273};
274
275while_statement: WHILE '('
276{
277int c=trctx.labelcounter++; $$.setInt(c);
278$$.stack=trstack.currentPos();
279trstack.loops.addLoop(c,$$.stack);
280trctx.out->printf(":_loop_%d\n",c);}
281                              expr ')'
282{
283int c=$3.getInt();
284warnTruthValue($4);
285if ($4.constant)
286        {if (!$4.getInt()) trctx.out->printf("jump :_loop_end_%d\n",c);}
287else
288        {
289        trctx.out->printf("if ~=,m[m0++],:_loop_end_%d\n",c,c);
290        trstack.adjust(+1);
291        }
292}
293                 pseudoblok_statement
294{
295trctx.out->printf("jump :_loop_%d\n:_loop_end_%d\n",$3.getInt(),$3.getInt());
296trstack.adjust($3.stack-trstack.currentPos());
297trstack.loops.drop();
298}
299;
300
301dowhile_statement: DO
302{
303trctx.emitLine();
304int c=trctx.labelcounter++; $$.setInt(c);
305$$.stack=trstack.currentPos();
306trstack.loops.addLoop(c,$$.stack);
307trctx.out->printf(":_loop_%d\n",c);} //2
308
309pseudoblok_statement WHILE '(' expr ')'
310
311{//8
312int c=$2.getInt();
313warnTruthValue($6);
314if ($6.constant)
315        {if ($6.getInt()) trctx.out->printf("jump :_loop_%d\n",c);}
316else
317        {
318        trctx.out->printf("if !~,m[m0++],:_loop_%d\n",c);
319        trstack.adjust(+1);
320        }
321trctx.out->printf(":_loop_end_%d\n",c);
322trstack.adjust($2.stack-trstack.currentPos());
323trstack.loops.drop();
324trctx.emitLine();
325}
326;
327
328switch_statement: SWITCH '('
329{
330int c=trctx.labelcounter++; $1.setInt(c);
331trstack.loops.addLoop(c,trstack.currentPos());}
332       stackexpr ')'
333{trctx.emitLine(); trctx.out->printf("dec m0\n"); trstack.adjust(-1);}
334 '{' inside_switch '}'
335{
336trctx.emitLine();
337LoopInfo *li=trstack.loops.getLoop(0);
338trctx.out->printf(":_case_after_%d_%d\n"
339                  "add 2,m0\n"
340                  ":_loop_end_%d\n",
341                  li->id,li->casecounter,
342                  li->id);
343trstack.adjust(+2);
344trstack.loops.drop();
345}
346;
347
348inside_switch: /* empty */
349       | case_label
350       | inside_switch case_label
351;
352
353case_label: CASE expr ':'
354{
355LoopInfo *li=trstack.loops.getLoop(0);
356if ($2.constant)
357        trctx.out->printf("if s1,!=,%s,:_case_before_%d_%d\n",
358                          litstr($2),
359                          li->id,li->casecounter+1);
360else
361        {
362        trctx.out->printf("if s2,!=,m[m0++],:_case_before_%d_%d\n",
363                          li->id,li->casecounter+1);
364        trstack.adjust(+1);
365        }
366trctx.out->printf(":_case_after_%d_%d\n",
367                  li->id,li->casecounter);
368int pos=trstack.currentPos(); $$.setInt(pos);
369}
370 recurcode
371{
372trctx.emitLine();
373LoopInfo *li=trstack.loops.getLoop(0);
374int pos=$4.getInt();
375if (pos!=trstack.currentPos()) trctx.out->printf("add %d,m0\n",pos-trstack.currentPos());
376trstack.dropToPos(pos);
377li->casecounter++;
378trctx.out->printf("jump :_case_after_%d_%d\n"
379                  ":_case_before_%d_%d\n",
380                  li->id,li->casecounter,
381                  li->id,li->casecounter);
382}
383      |  DEFAULT ':'
384  {
385  LoopInfo *li=trstack.loops.getLoop(0);
386  trctx.out->printf(":_case_after_%d_%d\n",li->id,li->casecounter);
387  }
388  recurcode
389  {
390  LoopInfo *li=trstack.loops.getLoop(0);
391  li->casecounter++;
392  }
393;
394
395newvar_or_expr:
396              VAR IDENT { $$.setInt(trstack.addVariable($2.getString())); trctx.out->printf("push invalid\n"); $$.ident=true; $$.var=true; }
397
398              |
399              VAR IDENT '=' stackexpr
400              {
401              //trctx.out->printf("# VAR IDENT '=' stackexpr pos=%d\n",trstack.currentPos());
402              trstack.adjust(+1);
403              $$.setInt(trstack.addVariable($2.getString()));
404              $$.ident=true; $$.var=true;
405              }
406
407              |
408              expr_special_ident
409              {
410              $$=$1;
411              }
412
413              | //nic
414              {
415              $$.setInt(1); $$.assign=false; $$.ident=false; $$.var=false; $$.constant=true;
416              }
417;
418
419expr_or_objname:
420              expr { $$=$1; $$.objname=false; }
421              |
422              OBJNAME { $$.setString($1.getString()); $$.objname=true; }
423;
424
425for_statement_begin: FOR '('
426{
427int c=trctx.labelcounter++; $$.counter=c; $$.stack=trstack.currentPos();
428}
429newvar_or_expr
430{
431$$=$4; $$.counter=$3.counter; $$.stack=$3.stack;
432};
433
434for_statement:
435
436           ///////////  for(in) ...  ////////////
437           for_statement_begin INNN
438           {//3
439           if (!$1.ident)
440                   {
441                   trctx.err->printf("for(... in ...) requires an variable\n");
442                   return 1;
443                   }
444           int loc;
445           if ($1.var) // for(var x[=expr] in
446                   $$.setInt($1.getInt());
447           else
448                   {  // for(x in
449                   if (variableOk($$,$1,loc))
450                           $$.setInt(loc);
451                   else if (globalOk($1))
452                           {
453                           trctx.err->printf("global '%s' can't be iterating variable in for\n",str($1));
454                           return 1;
455                           }
456                   else
457                           {
458                           badVariable($$,$1);
459                           return 1;
460                           }
461                   }
462           }
463           expr_or_objname ')'
464           {//6
465           trctx.emitLine();
466           if ($4.constant)
467                   {trctx.err->printf("%s can't be iterated\n",str($4)); return 1;}
468           if ($4.objname)
469                   trctx.out->printf("move %s.iterator,m[--m0]\n",(const char*)$4.getString());
470           else
471                   trctx.out->printf("move s%d,m1\nmove [m1].\"iterator\",m[--m0]\n",0);
472           trstack.adjust(-1);
473           // s0=iterator s1=obj (=obj.iterator)
474           trstack.loops.addLoop($1.counter,trstack.currentPos());
475           trctx.out->printf(":_loop1_%d\n",$1.counter);
476           trctx.out->printf(":_loop_%d\n",$1.counter);
477           trctx.out->printf("move s0,m1\nmove [m1].\"next\",m2\n");
478           trctx.out->printf("if m2,==,0,:_loop_end_%d\n",$1.counter);
479           trctx.out->printf("move [m1].\"value\",s%d\n",$3.getInt()-trstack.currentPos());
480           }
481           pseudoblok_statement
482           {
483           trctx.out->printf("jump :_loop1_%d\n",$1.counter);
484           trctx.out->printf(":_loop_end_%d\n",$1.counter);
485           trstack.loops.drop();
486           if ($1.stack != trstack.currentPos())
487                   trctx.out->printf("add %d,m0\n",$1.stack-trstack.currentPos());
488           trstack.adjust($1.stack-trstack.currentPos());
489           }
490           
491|
492
493           ///////////  for(;;) ...  ////////////
494           for_statement_begin ';'
495           { //3
496           trctx.emitLine();
497           //trctx.out->printf("# for_statement_begin pos=%d ident=%d var=%d\n",trstack.currentPos(),$1.ident,$1.var);
498           if ((!$1.var) && ($1.ident))
499                   {  // for(x;
500                   int loc;
501                   if ((!variableOk($$,$1,loc)) || (globalOk($1)))
502                           {
503                           badVariable($$,$1);
504                           return 1;
505                           }
506                   }
507           if (!$1.constant && !$1.ident)
508                   {
509                   trctx.out->printf("inc m0\n");
510                   trstack.adjust(+1);
511                   }
512           trstack.loops.addLoop($1.counter,trstack.currentPos());
513           trctx.out->printf(":_loop1_%d\n",$1.counter);
514           //trctx.out->printf("# expr#2\n");
515           }
516           expr_or_empty ';'
517           { //6
518           trctx.emitLine();
519           int c=$1.counter;
520           warnTruthValue($4);
521           if ($4.constant)
522                   {if (!$4.getInt()) trctx.out->printf("jump :_loop_end_%d\n",c);}
523           else
524                   {
525                   trctx.out->printf("if m[m0++],==,0,:_loop_end_%d\n",c,c);
526                   trstack.adjust(+1);
527                   }
528           trctx.tmp=0;
529           trctx.divertOut();
530           //trctx.out->printf("# expr#3\n");
531           }
532           expr_or_empty ')'
533           { //9
534           trctx.emitLine();
535           if (!$7.constant) { trctx.out->printf("inc m0\n"); trstack.adjust(+1); }
536           trctx.restoreOut();
537           $$.setString(trctx.tmp);
538           //trctx.out->printf("# pseudoblok_statement pos=%d\n",trstack.currentPos());
539           }
540           pseudoblok_statement
541           {//11
542           trctx.out->printf(":_loop_%d\n",$1.counter);
543           LoopInfo* li=trstack.loops.getLoop(0);
544           if (li->location != trstack.currentPos())
545                   trctx.out->printf("add %d,m0\n",li->location-trstack.currentPos());
546           trctx.out->printf(str($9));
547           if (li->location != trstack.currentPos())
548                   trctx.out->printf("sub %d,m0\n",li->location-trstack.currentPos());
549           trctx.out->printf("jump :_loop1_%d\n:_loop_end_%d\n",$1.counter,$1.counter);
550           if ($1.stack != trstack.currentPos())
551                   trctx.out->printf("add %d,m0\n",$1.stack-trstack.currentPos());
552           trstack.adjust($1.stack-trstack.currentPos());
553           trstack.loops.drop();
554           }
555;
556
557pseudoblok_statement:
558{trctx.emitLine(); int pos=trstack.currentPos(); $$.setInt(pos);}
559  statement
560{
561int pos=$1.getInt();
562if (pos!=trstack.currentPos()) trctx.out->printf("add %d,m0\n",pos-trstack.currentPos());
563trstack.dropToPos(pos);
564trctx.emitLine();
565};
566
567if_statement:
568 if_condition pseudoblok_statement
569                       {
570                       if ($1.stack!=trstack.currentPos())
571                               trctx.out->printf("add %d,m0\n",$1.stack-trstack.currentPos());
572                       trstack.adjust(trstack.currentPos()-$1.stack);
573                       trctx.out->printf("jump :_if_end_%d\n:_if_else_%d\n",$1.getInt(),$1.getInt());
574                       }
575         ELSE
576                       {trstack.adjust($1.stack-trstack.currentPos());}
577         pseudoblok_statement
578                       {
579                       if ($1.stack!=trstack.currentPos())
580                               trctx.out->printf("add %d,m0\n",$1.stack-trstack.currentPos());
581                       trstack.adjust(trstack.currentPos()-$1.stack);
582                       trctx.out->printf(":_if_end_%d\n",$1.getInt());
583                       }
584|
585 if_condition pseudoblok_statement
586                       {
587                       if ($1.stack!=trstack.currentPos())
588                               trctx.out->printf("add %d,m0\n",$1.stack-trstack.currentPos());
589                       trstack.dropToPos($1.stack);
590                       trctx.out->printf(":_if_else_%d\n",$1.getInt());
591                       }
592;
593
594if_condition: IF
595{$$.stack=trstack.currentPos();trctx.emitLine();}
596
597 '(' expr ')'
598{
599trctx.emitLine();
600int c=trctx.labelcounter++;
601$$.setInt(c);
602warnTruthValue($4);
603if ($4.constant)
604        {
605        if (!$4.getInt()) trctx.out->printf("jump :_if_else_%d\n",c);
606        }
607else
608        {
609        trctx.out->printf("if ~=,m[m0++],:_if_else_%d\n",c);
610        trstack.adjust(+1);
611        }
612$$.stack=$2.stack;
613};
614
615blok:    '{'
616{ int pos=trstack.currentPos();
617$$.setInt(pos);
618}
619         recurcode '}'
620{
621int pos=$2.getInt();
622if (pos!=trstack.currentPos()) trctx.out->printf("add %d,m0\n",pos-trstack.currentPos());
623trstack.dropToPos(pos);
624}
625
626assign_op: ASSIGN_ADD {$$.setInt(0);}
627         | ASSIGN_SUB {$$.setInt(1);}
628         | ASSIGN_MUL {$$.setInt(2);}
629         | ASSIGN_DIV {$$.setInt(3);}
630         | ASSIGN_MOD {$$.setInt(4);}
631
632plusminus: PLUSPLUS {$$.setInt(1);} | MINUSMINUS {$$.setInt(0);}
633
634expr: expr_special_ident
635  {
636  //trctx.out->printf("# expr: ident=%d str=%s\n",$1.ident,(const char*)$1.getString());
637  if ($1.ident)
638          {
639          if (evalVariable($$,$1))
640                  $$.constant=false;
641          else
642                  return 1;
643          }
644  else
645          {$$=$1; $$.ident=false;}
646  trctx.emitLine();
647  }
648;
649
650expr_or_empty:
651         expr {$$=$1;}
652
653         | //nic
654         { $$.setInt(1); $$.assign=false; $$.constant=true; $$.ident=false; $$.ident=false; }
655;
656
657expr_special_ident:    CONSTANT             { $$=$1; $$.constant=1; $$.ident=0; }
658
659       | IDENT                { $$.ident=true; $$.setString($1.getString()); }
660
661       | OBJNAME ':' IDENT    {$$.constant=0; $$.ident=0;
662                              trctx.out->printf("push %s:%s\n",(const char*)$1.getString(),
663                                                 (const char*)$3.getString());
664                              trstack.adjust(-1);
665                              }
666       | plusminus IDENT
667{
668trctx.emitLine();
669$$.ident=0;
670int loc; if (variableOk($$,$2,loc))
671        { loc-=trstack.currentPos();
672        trctx.out->printf("%s s%d\npush s%d\n",$1.getInt()?"inc":"dec",loc,loc);
673        trstack.adjust(-1);}
674        else if (globalOk($2))
675        { trctx.out->printf("%s @%s\npush @%s\n",$1.getInt()?"inc":"dec",str($2),str($2));
676        trstack.adjust(-1);}
677        else {badVariable($$,$2); return 1;}
678}
679
680       | IDENT plusminus
681{
682trctx.emitLine();
683$$.ident=0;
684int loc; if (variableOk($$,$1,loc))
685        {loc-=trstack.currentPos(); trctx.out->printf("push s%d\n%s s%d\n",loc,$2.getInt()?"inc":"dec",loc+1);
686        trstack.adjust(-1);}
687        else if (globalOk($1))
688        { trctx.out->printf("push @%s\n%s @%s\n",(const char*)$1.getString(),
689                            $2.getInt()?"inc":"dec",(const char*)$1.getString());
690        trstack.adjust(-1);}
691        else {badVariable($$,$1); return 1;}
692}
693
694       | IDENT assign_op expr { trctx.emitLine(); $$.ident=0;
695                                if (!handleAssignOp($$,$1,$3,assign_op_names[$2.getInt()]))
696                                if (globalOk($1)) {SString t="@"; t+=$1.getString();
697                                  handleAssignOp2($$,(const char*)t,$3,assign_op_names[$2.getInt()],0,1);}
698                                else { badVariable($$,$1); return 1; }
699                              }
700
701       | TYPEOF '(' expr ')' { trctx.emitLine(); $$.ident=0;
702                       if ($3.constant)
703                             {$$.constant=1; $$=$3.getExtType();}
704                       else
705                             {trctx.out->printf("type s0,s0\n");}
706                     }
707       | INT_TYPE '(' expr ')' { trctx.emitLine(); $$.ident=0;
708                       if ($3.constant)
709                             {$$.constant=1; $$=ExtValue($3.getInt());}
710                       else
711                             {trctx.out->printf("conv 1,s0\n");}
712                     }
713       | FLOAT_TYPE '(' expr ')' { trctx.emitLine(); $$.ident=0;
714                       if ($3.constant)
715                             {$$.constant=1; $$=ExtValue($3.getDouble());}
716                       else
717                             {trctx.out->printf("conv 2,s0\n");}
718                     }
719       | STRING_TYPE '(' expr ')' { trctx.emitLine(); $$.ident=0;
720                       if ($3.constant)
721                             {$$.constant=1; $$=ExtValue($3.getString());}
722                       else
723                             {trctx.out->printf("conv 3,s0\n");}
724                     }
725
726       | expr '+' expr { handleTwoArg($$,$1,$3,'+',"add",0,1); }
727       | expr '-' expr { handleTwoArg($$,$1,$3,'-',"sub",0,0); }
728       | expr '*' expr { handleTwoArg($$,$1,$3,'*',"mul",0,1); }
729       | expr '/' expr { handleTwoArg($$,$1,$3,'/',"div",0,0); }
730       | expr '&' expr { handleTwoArg($$,$1,$3,'&',"and",0,0); }
731       | expr '|' expr { handleTwoArg($$,$1,$3,'|',"or",0,0); }
732       | expr '%' expr { handleTwoArg($$,$1,$3,'%',"mod",0,0); }
733
734       | expr LOGIC_AND
735 {
736 // a && b:
737 //   push a
738 //   if (a)
739 //     pop; goto and_b
740 //   else
741 //     pop; push 0; goto and_end
742 // and_b:
743 //   push b
744 // and_end:
745 trctx.emitLine();
746// trctx.out->printf("\n####### logic AND\n");
747 int c=trctx.labelcounter++;
748 $$.setInt(c);
749 if ($1.constant)
750         {
751         ExtValue::CompareResult cond=$1.compare(ExtValue::zero());
752         if (resultIsRelaxedEqual(cond))
753                 {
754                 $1.counter=0;
755                 // no stack adjust - next tokens are processed in a different context
756                 trctx.out->printf("push 0\njump :_and_end_%d\n",c);
757                 }
758         else
759                 $1.counter=1;
760         }
761 else
762         {
763         trstack.adjust(+1); // stack as if (a==true), b expr is processed
764         trctx.out->printf("if !~,m[m0++],:_and_b_%d\n"
765                           "push 0\n"
766                           "jump :_and_end_%d\n"
767                           ":_and_b_%d\n"
768                           ,c,c,c);
769         }
770 }
771         expr
772 {
773 $$.ident=false;
774 $$.constant=0;
775 if ($4.constant)
776         {
777         if (!($1.constant && $1.counter==0))
778                 {
779                 ExtValue::CompareResult  cond=$4.compare(ExtValue::zero());
780                 bool value=!resultIsRelaxedEqual(cond);
781                 trstack.adjust(-1);
782                 trctx.out->printf("push %d\n",value);
783                 }
784         }
785 trctx.out->printf(":_and_end_%d\n",$3.getInt());
786// trctx.out->printf("#################\n\n");
787 }
788
789       | expr LOGIC_OR
790 {
791 // a || b:
792 //   push a
793 //   if (!a)
794 //     pop; goto and_b
795 //   else
796 //     pop; push 1; goto and_end
797 // and_b:
798 //   push b
799 // and_end:
800 trctx.emitLine();
801// trctx.out->printf("\n####### logic AND\n");
802 int c=trctx.labelcounter++;
803 $$.setInt(c);
804 if ($1.constant)
805         {
806         ExtValue::CompareResult  cond=$1.compare(ExtValue::zero());
807         if (!resultIsRelaxedEqual(cond))
808                 {
809                 $1.counter=1;
810                 // no stack adjust - next tokens are processed in a different context
811                 trctx.out->printf("push 1\njump :_or_end_%d\n",c);
812                 }
813         else
814                 $1.counter=0;
815         }
816 else
817         {
818         trstack.adjust(+1); // stack for (a==false)
819         trctx.out->printf("if ~=,m[m0++],:_or_b_%d\n"
820                           "push 1\n"
821                           "jump :_or_end_%d\n"
822                           ":_or_b_%d\n"
823                           ,c,c,c);
824         }
825 }
826         expr
827 {
828 $$.ident=false;
829 $$.constant=0;
830 if ($4.constant)
831         {
832         if (!($1.constant && $1.counter==1))
833                 {
834                 ExtValue::CompareResult cond=$4.compare(ExtValue::zero());
835                 bool value=!resultIsRelaxedEqual(cond);
836                 trstack.adjust(-1);
837                 trctx.out->printf("push %d\n",value);
838                 }
839         }
840 trctx.out->printf(":_or_end_%d\n",$3.getInt());
841// trctx.out->printf("#################\n\n");
842 }
843
844
845       | expr LSHIFT expr { handleTwoArg($$,$1,$3,LSHIFT,"shift",0,0); }
846       | expr RSHIFT expr { handleTwoArg($$,$1,$3,RSHIFT,"shift",1,0); }
847       | expr EQUAL expr     { if (!handleCompare($$,$1,$3,ExtValue::CmpEQ,"==")) return 1; }
848       | expr NOT_EQUAL expr { if (!handleCompare($$,$1,$3,ExtValue::CmpNE,"!=")) return 1; }
849       | expr GEQUAL expr    { if (!handleCompare($$,$1,$3,ExtValue::CmpGE,">=")) return 1; }
850       | expr LEQUAL expr    { if (!handleCompare($$,$1,$3,ExtValue::CmpLE,"<=")) return 1; }
851       | expr '>' expr       { if (!handleCompare($$,$1,$3,ExtValue::CmpGT,">")) return 1; }
852       | expr '<' expr       { if (!handleCompare($$,$1,$3,ExtValue::CmpLT,"<")) return 1; }
853
854       | '!' expr        {
855                         trctx.emitLine(); $$.assign=$2.assign; $$.parens=0; $$.ident=0;
856                         if ($2.constant)
857                                 {$$.constant=1; ExtValue::CompareResult res=$2.compare(ExtValue((paInt)0)); $$.setInt(resultIsRelaxedEqual(res));}
858                         else
859                                {trctx.out->printf("setif ~=,s0,s0\n");}
860                         }
861
862     | '-' expr %prec NEG {
863                          trctx.emitLine(); $$.assign=$2.assign; $$.parens=0; $$.ident=0;
864                          if ($2.constant)
865                                  { $$.constant=$2.constant;
866                                   if ($2.type==TInt) $$.setInt(-$2.getInt());
867                                   else if ($2.type==TDouble) $$.setDouble(-$2.getDouble());
868                                   else $$=$2;
869                                  }
870                             else
871                                  {
872                                  $$.constant=0; SString t="-"; t+=$2.getString(); $$.setString(t);
873                                  trctx.out->printf("mul -1,s0\n");
874                                  }
875                          }
876
877     | '(' expr ')'    { trctx.emitLine(); $$ = $2; $$.assign=$2.assign?(!$2.parens):0; $$.parens=1; $$.ident=0; }
878
879     | OBJNAME '.' member {
880                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
881                        if ($3.constant)
882                                {
883                                trctx.out->printf("push %s.%s\n",str($1),str($3)); trstack.adjust(-1);
884                                }
885                        else
886                                {
887                                trctx.out->printf("move s0,m1\nmove %s.[m1],s0\n",str($1));
888                                }
889                        }
890
891     | OBJNAME '.' member assign_op expr
892                  { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
893                  if ($3.constant)
894                          {
895                          handleAssignOp2($$,(const char*)t,$5,assign_op_names[$4.getInt()],0,1);
896                          }
897                  else
898                          {
899                          int sp=($5.constant)?0:1;
900                          t=$1.getString();t+=".[m1]";
901                          trctx.out->printf("move s0,m1\n",str($1));
902                          handleAssignOp2($$,(const char*)t,$5,assign_op_names[$4.getInt()],sp,0);
903                          if (sp) {trctx.out->printf("inc m0\n"); trstack.adjust(1);}
904                          }
905                  }
906
907     | plusminus OBJNAME '.' member {
908                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$2.getString(); t+="."; t+=$4.getString(); $$.setString(t);
909                        if ($4.constant)
910                                {
911                                trctx.out->printf("%s %s.%s\npush %s.%s\n",$1.getInt()?"inc":"dec",
912                                                  str($2),str($4),str($2),str($4));
913                                trstack.adjust(-1);
914                                }
915                        else
916                                {
917                                trctx.out->printf("move s0,m1\n%s %s.[m1]\nmove %s.[m1],s0\n",
918                                                  $1.getInt()?"inc":"dec",str($2),str($2));
919                                }
920                        }
921
922     | OBJNAME '.' member plusminus {
923                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
924                        if ($3.constant)
925                                {
926                                trctx.out->printf("push %s.%s\n%s %s.%s\n",
927                                                  str($1),str($3),$4.getInt()?"inc":"dec",str($1),str($3));
928                                trstack.adjust(-1);
929                                }
930                        else
931                                {
932                                trctx.out->printf("move s0,m1\nmove %s.[m1],s0\n%s %s.[m1]\n",
933                                                  str($1),$4.getInt()?"inc":"dec",str($1));
934                                }
935                        }
936
937     | OBJNAME '.' '*'    {
938                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".*"; $$.setString(t);
939                        trctx.out->printf("push %s.*\n",str($1)); trstack.adjust(-1);
940                        }
941
942
943     | OBJNAME '.' member '=' expr {
944                        trctx.emitLine(); $$=$5; $$.assign=1; $$.parens=0; $$.ident=0;
945                        if ($3.constant)
946                                {
947                                if ($$.constant)
948                                        trctx.out->printf("move %s,%s.%s\n",litstr($5),str($1),str($3));
949                                else
950                                        trctx.out->printf("move s0,%s.%s\n",str($1),str($3));
951                                }
952                        else
953                                {
954                                if ($$.constant)
955                                        {
956                                        trctx.out->printf("move m[m0++],m1\nmove %s,%s.[m1]\n",
957                                                          litstr($5),str($1));
958                                        trstack.adjust(1);
959                                        }
960                                else
961                                        {
962                                        trctx.out->printf("move s1,m1\nmove m[m0++],s0\nmove s0,%s.[m1]\n",
963                                                          str($1));
964                                        trstack.adjust(1);
965                                        }
966                                }
967                        }
968
969     | OBJNAME '.' member '(' arguments ')'
970                        {
971                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
972                        int adj=0,adj2=0;
973                        if ($5.getInt()==0)
974                                {trctx.out->printf("dec m0\n");trstack.adjust(-1);adj=1;}
975                        if ($3.constant)
976                                trctx.out->printf("call %s.%s\n",str($1),str($3));
977                        else
978                                {
979                                trctx.out->printf("move s%d,m1\ncall %s.[m1]\n",$5.getInt()+adj,str($1));
980                                adj2=1;
981                                }
982                        adj2+=$5.getInt()-1+adj;
983                        if (adj2>0)
984                                {
985                                trctx.out->printf("add %d,m0\nxmove s%d,s0\n",adj2,-adj2);
986                                trstack.adjust(adj2);
987                                }
988                        }
989
990     | CALL expr '(' arguments ')'
991             { trctx.emitLine(); $$.constant=0; $$.ident=0; $$.setString($2.getString());
992             short adj=0;
993             if ($4.getInt()==0)
994                     {trctx.out->printf("dec m0\n");trstack.adjust(-1);adj=1;}
995             if ($2.constant)
996                     trctx.out->printf("call %s\n",litstr($2));
997             else
998                     trctx.out->printf("call s%d\n",$4.getInt()+adj);
999             if (($4.getInt()+adj) > 0)
1000                     {
1001                     trctx.out->printf("add %d,m0\nxmove s%d,s0\n",$4.getInt()+adj,-($4.getInt()+adj));
1002                     trstack.adjust($4.getInt()+adj);
1003                     }
1004             }
1005
1006     | FUNCTION IDENT
1007             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=":"; t+=$1.getString(); $$.setString(t);
1008             trctx.out->printf("push :%s\n",(const char*)$2.getString());
1009             trstack.adjust(-1);
1010             }
1011
1012     | stackexpr '.' member
1013             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
1014             if ($3.constant)
1015                     trctx.out->printf("move s0,m1\nmove [m1].%s,s0\n",str($3));
1016             else
1017//                   trctx.out->printf("move s1,m1\nmove m[m0++],m2\nmove [m1].[m2],s0\n");
1018                     {trctx.out->printf("move s1,m1\nmove m[m0++],m2\nmove [m1].[m2],s0\n");trstack.adjust(1);}
1019             }
1020
1021     | plusminus stackexpr '.' member
1022             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$2.getString(); t+="."; t+=$4.getString(); $$.setString(t);
1023             if ($4.constant)
1024                     trctx.out->printf("move s0,m1\n%s [m1].%s\nmove [m1].%s,s0\n",
1025                                       $1.getInt()?"inc":"dec",str($4),str($4));
1026             else
1027//                   trctx.out->printf("move s1,m1\nmove m[m0++],m2\nmove [m1].[m2],s0\n");
1028                     {trctx.out->printf("move s1,m1\nmove m[m0++],m2\n%s [m1].[m2]\nmove [m1].[m2],s0\n",
1029                                        $1.getInt()?"inc":"dec");trstack.adjust(1);}
1030             }
1031
1032     | stackexpr '.' member plusminus
1033             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
1034             if ($3.constant)
1035                     trctx.out->printf("move s0,m1\nmove [m1].%s,s0\n%s [m1].%s\n",
1036                                       str($3),$4.getInt()?"inc":"dec",str($3));
1037             else
1038//                   trctx.out->printf("move s1,m1\nmove m[m0++],m2\nmove [m1].[m2],s0\n");
1039                     {trctx.out->printf("move s1,m1\nmove m[m0++],m2\nmove [m1].[m2],s0\n%s [m1].[m2]\n",
1040                                        $4.getInt()?"inc":"dec");trstack.adjust(1);}
1041             }
1042
1043     | stackexpr '.' member assign_op expr
1044             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
1045             if ($3.constant)
1046                     {
1047                     int sp;
1048                     if ($5.constant)
1049                             {sp=0; trctx.out->printf("move s0,m1\n");}
1050                     else
1051                             {sp=1; trctx.out->printf("move s1,m1\n");}
1052                     t="[m1]."; t+=str($3);
1053                     handleAssignOp2($$,(const char*)t,$5,assign_op_names[$4.getInt()],sp,0);
1054                     if (sp) {trctx.out->printf("inc m0\n");trstack.adjust(1);}
1055                     }
1056             else
1057                     {
1058                     int sp;
1059                     char *t;
1060                     if ($5.constant)
1061                             {sp=1; t="move s1,m1\nmove s0,m2\n";}
1062                     else
1063                             {sp=2; t="move s2,m1\nmove s1,m2\n";}
1064                     trctx.out->printf(t);
1065                     handleAssignOp2($$,"[m1].[m2]",$5,assign_op_names[$4.getInt()],sp,0);
1066                     trctx.out->printf("add %d,m0\n",sp);
1067                     trstack.adjust(sp);
1068                     }
1069             }
1070
1071     | stackexpr '.' member '=' stackexpr
1072             { trctx.emitLine(); $$=$5; $$.assign=1; $$.parens=0; $$.ident=0;
1073             if ($3.constant)
1074                     {
1075                     trctx.out->printf("move s1,m1\nmove m[m0++],s0\nmove s0,[m1].%s\n",str($3));
1076                     trstack.adjust(1);
1077                     }
1078             else
1079                     {
1080                     trctx.out->printf("move s2,m1\nmove s1,m2\nmove s0,[m1].[m2]\nadd 2,m0\nmove s-2,s0\n");
1081                     trstack.adjust(2);
1082                     }
1083             }
1084
1085     | stackexpr '.' member '(' arguments ')'
1086             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
1087             int adj=0;
1088             if ($5.getInt()==0)
1089                     {trctx.out->printf("dec m0\n");trstack.adjust(-1);adj=1;}
1090             if ($3.constant)
1091                     {
1092                     trctx.out->printf("move s%d,m1\ncall [m1].%s\n",$5.getInt()+adj,str($3));
1093                     adj+=1;
1094                     }
1095             else
1096                     {
1097                     trctx.out->printf("move s%d,m2\nmove s%d,m1\ncall [m2].[m1]\n",
1098                                       $5.getInt()+adj+1,$5.getInt()+adj);
1099                     adj+=2;
1100                     }
1101             if (($5.getInt()+adj) > 1)
1102                     {
1103                     trctx.out->printf("add %d,m0\nxmove s%d,s0\n",$5.getInt()-1+adj,-($5.getInt()-1+adj));
1104                     trstack.adjust($5.getInt()-1+adj);
1105                     }
1106             }
1107
1108      | stackexpr '[' expr ']' '=' expr    // shortcut: expr.set(expr,expr)
1109             { trctx.emitLine(); $$=$6; $$.assign=1; $$.parens=0; $$.ident=0;
1110             if ($3.constant)
1111                     {
1112                     if ($6.constant)
1113                             {trctx.out->printf("move s0,m1\ncall [m1].\"set\",%s,%s\ninc m0\n",litstr($3),litstr($6));$$=$6;trstack.adjust(+1);}
1114                     else
1115                             {trctx.out->printf("move s1,m1\npush s0\nmove %s,s1\ncall [m1].\"set\"\nadd 2,m0\nmove s-2,s0\n",litstr($3));trstack.adjust(+1);}
1116                     }
1117             else
1118                     {
1119                     if ($6.constant)
1120                             {trctx.out->printf("move s1,m1\npush %s\ncall [m1].\"set\"\nadd 3,m0\n",litstr($6)); trstack.adjust(+2);}
1121                     else
1122                             {trctx.out->printf("move s2,m1\ncall [m1].\"set\"\nadd 2,m0\nmove s-2,s0\n"); trstack.adjust(+2);}
1123                     }
1124             }
1125
1126      | stackexpr '[' expr ']'    /* shortcut: expr.get(expr) */
1127             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".get"; $$.setString(t);
1128             if ($3.constant)
1129                     {
1130                     trctx.out->printf("move s0,m1\ncall [m1].\"get\",%s\n",litstr($3));
1131                     }
1132             else
1133                     {
1134                     trctx.out->printf("move s1,m1\ncall [m1].\"get\"\ninc m0\nmove s-1,s0\n");
1135                     trstack.adjust(+1);
1136                     }
1137             }
1138
1139     | IDENT '=' expr { trctx.emitLine(); $$=$3; $$.assign=1; $$.ident=0;
1140                        int loc=trstack.getVariableLocation($1.getString());
1141                        if (loc!=TranslatorStack::NOTFOUND)
1142                            {
1143                            if ($3.constant)
1144                              trctx.out->printf("move %s,s%d\n",litstr($3),loc-trstack.currentPos());
1145                            else
1146                              trctx.out->printf("move s0,s%d\n",loc-trstack.currentPos());
1147                            }
1148                        else if (globalOk($1)) { $$=$3; $$.ident=0; $$.assign=1;
1149                          if ($3.constant) trctx.out->printf("move %s,@%s\n",litstr($3),str($1));
1150                          else trctx.out->printf("move s0,@%s\n",str($1));}
1151                        else {trctx.err->printf("undefined variable: '%s'\n",str($1)); return 1;}
1152                      }
1153
1154      | OBJNAME '[' expr ']'    /* shortcut: OBJNAME.get(expr) */
1155             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".get"; $$.setString(t);
1156             if ($3.constant)
1157                     {
1158                     trctx.out->printf("dec m0\ncall %s.get,%s\n",str($1),litstr($3));
1159                     trstack.adjust(-1);
1160                     }
1161             else
1162                     {
1163                     trctx.out->printf("call %s.get\n",str($1));
1164                     }
1165             }
1166
1167      | IDENT '(' arguments ')'
1168{
1169trctx.emitLine(); $$.constant=0; $$.ident=0; $$.setString("function call");
1170if ($3.getInt()==0)
1171        {trctx.out->printf("dec m0\n");trstack.adjust(-1);}
1172trctx.out->printf("call :%s\n",str($1));
1173if ($3.getInt()>1)
1174        {
1175        trctx.out->printf("add %d,m0\nxmove s%d,s0\n",$3.getInt()-1,-($3.getInt()-1));
1176        trstack.adjust($3.getInt()-1);
1177        }
1178}
1179
1180| '[' {trctx.emitLine(); $$.ident=0; trctx.out->printf("add -2,m0\ncall Vector.new\nmove s0,s1\n");trstack.adjust(-2);} // s1=vector, s0=nieuzywane ale zarezerwowane zeby nie przesuwac stosu przy kazdym elemencie (trafia tu wartosc zwracana przez add/set)
1181        v_elements ']'
1182        {$$.constant=0; trctx.out->printf("inc m0\n");trstack.adjust(1);}
1183
1184| '{' {trctx.emitLine(); $$.ident=0; trctx.out->printf("add -2,m0\ncall Dictionary.new\nmove s0,s1\n");trstack.adjust(-2);} // s1=dict, s0=nieuzywane ale zarezerwowane zeby nie przesuwac stosu przy kazdym elemencie (trafia tu wartosc zwracana przez add/set)
1185        d_elements '}'
1186        {$$.constant=0; trctx.out->printf("inc m0\n"); trstack.adjust(1);}
1187
1188//      | '&' stackexpr {trctx.out->printf("call Ref.new\n");}
1189
1190      | '&' IDENT {
1191        trctx.emitLine(); $$.ident=0;
1192        int loc=trstack.getVariableLocation($2.getString());
1193        if (loc!=TranslatorStack::NOTFOUND)
1194                {
1195                trctx.out->printf("push &%d\n",loc-trstack.currentPos());trstack.adjust(-1);
1196                }
1197        else if (globalOk($2))
1198                {
1199                trctx.out->printf("gpush &@%s\ncall Ref.newO\ninc m0\nmove s-1,s0\n",str($2));
1200                trstack.adjust(-1);
1201                }
1202        else {trctx.err->printf("undefined variable: '%s'\n",str($1)); return 1;}
1203            }
1204
1205      | '&' OBJNAME '.' member {
1206      trctx.emitLine(); $$.ident=0;
1207      if ($4.constant)
1208              {
1209              trctx.out->printf("dec m0\ncall Ref.newO,%s.*,%s:%s\n",str($2),str($2),str($4));
1210              trstack.adjust(-1);
1211              }
1212      else
1213              {
1214              trctx.out->printf("call Ref.newO,%s.*,s0\n",str($2));
1215              }
1216      }
1217
1218      | '&' '(' stackexpr ')' '.' member {
1219      trctx.emitLine(); $$.ident=0;
1220      if ($6.constant)
1221              {
1222              trctx.out->printf("call Ref.newO,s0,%s\n",litstr($6));
1223              }
1224      else
1225              {
1226              trctx.out->printf("call Ref.newO,s1,s0\ninc m0\nmove s-1,s0\n");
1227              trstack.adjust(1);
1228              }
1229      }
1230
1231      | '(' stackexpr ',' stackexpr ',' stackexpr ')' {
1232      trctx.emitLine(); $$.ident=0;
1233      trctx.out->printf("call XYZ.new\nadd 2,m0\nmove s-2,s0\n");trstack.adjust(2);}
1234;
1235
1236v_elements: /* empty */
1237      | v_element
1238      | v_elements ',' v_element
1239;
1240
1241d_elements: /* empty */
1242      | d_element
1243      | d_elements ',' d_element
1244;
1245
1246v_element: expr
1247{
1248if ($1.constant)
1249        trctx.out->printf("move s1,m1\ncall [m1].Vector:add,%s\n",litstr($1));
1250else
1251        {trctx.out->printf("move s2,m1\ncall [m1].Vector:add\ninc m0\n");trstack.adjust(1);}
1252}
1253;
1254
1255d_element: expr ':' expr
1256{
1257if ($1.constant)
1258        {
1259        if ($3.constant)
1260                trctx.out->printf("move s1,m1\ncall [m1].Dictionary:set,%s,%s\n",litstr($1),litstr($3));
1261        else
1262                {trctx.out->printf("move s2,m1\nmove %s,s1\ncall [m1].Dictionary:set\ninc m0\n",litstr($1));trstack.adjust(1);}
1263        }
1264else
1265        {
1266        if ($3.constant)
1267                {trctx.out->printf("move s2,m1\nmove s0,s1\nmove %s,s0\ncall [m1].Dictionary:set\ninc m0\n",litstr($3));trstack.adjust(1);}
1268        else
1269                {trctx.out->printf("move s3,m1\ncall [m1].Dictionary:set\nadd 2,m0\n");trstack.adjust(2);}
1270        }
1271}
1272;
1273
1274member:    IDENT { $$=$1; $$.constant=1;}
1275         | OBJNAME ':' IDENT { SString t=$1.getString();t+=":";t+=$3.getString();
1276                               $$.setString(t);$$.constant=1;}
1277         | '[' stackexpr ']' { SString t="["; t+=$2.getString(); t+="]";
1278                               $$.setString(t); $$.constant=0;}
1279
1280stackexpr: expr {if ($1.constant) {trctx.out->printf("push %s\n",litstr($1)); trstack.adjust(-1); $$.constant=0;} }
1281
1282arguments: /* empty */         { $$.setInt(0); }
1283         |  stackexpr               { $$.setInt(1); }
1284         |  arguments ',' stackexpr  {$$.setInt($1.getInt()+1);}
1285;
1286
1287%%
1288
1289SString makeLitString(const ExtValue& val)
1290{
1291if (val.type!=TString)
1292        return val.getString();
1293SString s=val.getString();
1294int len=s.len();
1295SString ret((len*11)/10+10);
1296ret+='\"';
1297const char*t=(const char*)s;
1298while(len>0)
1299        {
1300        switch(*t)
1301                {
1302                case '\n': ret+="\\n"; break;
1303                case '\r': ret+="\\r"; break;
1304                case '\t': ret+="\\t"; break;
1305                default: ret+=*t;
1306                }
1307        t++; len--;
1308        }
1309ret+='\"';
1310return ret;
1311}
1312
1313static void yyprint (FILE *file,int type,YYSTYPE value)
1314{
1315fprintf(file,"(%s)%s",str(value),value.constant?"c":"");
1316}
1317
1318int yyerror (const char *s)  /* Called by yyparse on error */
1319{
1320trctx.err->printf ("%s\n",s);
1321return 0; // w przykladach do bisona tez nie dali returna...
1322}
1323
1324void handleTwoArg(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
1325                  int optoken,const char* opname,bool negarg2,bool uniq)
1326{
1327trctx.emitLine();
1328result.ident=false;
1329if (arg1.constant && arg2.constant)
1330        {
1331        result=arg1;
1332        switch(optoken)
1333                {
1334                case '+': result+=arg2; break;
1335                case '-': result-=arg2; break;
1336                case '*': result*=arg2; break;
1337                case '/': result/=arg2; break;
1338                case '%': result%=arg2; break;
1339                case '&': result.setInt(arg1.getInt() & arg2.getInt()); break;
1340                case '|': result.setInt(arg1.getInt() | arg2.getInt()); break;
1341                case LSHIFT: result.setInt(arg1.getInt() << arg2.getInt()); break;
1342                case RSHIFT: result.setInt(arg1.getInt() >> arg2.getInt()); break;
1343                }
1344        }
1345else
1346        {
1347        //TODO: prawie kazde uzycie uniq jest niepotrzebne bo typem rzadko bedzie vector, ale w wiekszosci miejsc okreslenie typu wartosci
1348        // byloby bardzo trudne lub niemozliwe. mozna byloby natomiast zapamietywac przy parsowaniu czy dana wartosc na stosie jest
1349        // skopiowana ze zmiennej/pola czy jest wynikiem wczesniejszej operacji co pozwoliloby na likwidacje bardzo wielu uniq
1350        result.constant=0;
1351        result.assign=arg1.assign || arg2.assign;
1352        result.parens=0;
1353        result.setString(opname);
1354        if (arg1.constant)
1355                trctx.out->printf("move %s,m1\n%s%s s0,m1\nmove m1,s0\n",litstr(arg1),
1356                                  negarg2?"neg s0\n":"",
1357                                  opname);
1358        else if (arg2.constant)
1359                {
1360                if (negarg2)
1361                        trctx.out->printf("%s %d,s0\n",opname,-arg2.getInt());
1362                else
1363                        trctx.out->printf("%s%s %s,s0\n",(uniq?"uniq s0\n":""),opname,litstr(arg2));
1364                }
1365        else
1366                {
1367                trctx.out->printf("%s%s%s s0,s1\ninc m0\n",
1368                                  uniq?"uniq s1\n":"",
1369                                  negarg2?"neg s0\n":"",
1370                                  opname);
1371                trstack.adjust(+1);
1372                }
1373        }
1374}
1375
1376bool handleAssignOp(YYSTYPE& result,const YYSTYPE& var,const YYSTYPE& arg,const char* opname)
1377{
1378int loc; if (variableOk(result,var,loc))
1379        {
1380        loc-=trstack.currentPos();
1381        if (arg.constant)
1382                {
1383                trctx.out->printf("%s %s,s%d\npush s%d\n",opname,litstr(arg),loc,loc);
1384                trstack.adjust(-1);
1385                }
1386        else
1387                trctx.out->printf("%s s0,s%d\nmove s%d,s0\n",opname,loc,loc);
1388        return 1;
1389        }
1390return 0;
1391}
1392
1393bool handleAssignOp2(YYSTYPE& result,const char *var,const YYSTYPE& arg,const char* opname,int stackpos,bool push)
1394{
1395if (arg.constant)
1396        {
1397        trctx.out->printf("%s %s,%s\n",opname,litstr(arg),var);
1398        if (!push)
1399                trctx.out->printf("move %s,s%d\n",var,stackpos);
1400        else
1401                {
1402                trctx.out->printf("push %s\n",var);
1403                trstack.adjust(-1);
1404                }
1405        }
1406else
1407        trctx.out->printf("%s s0,%s\nmove %s,s%d\n",opname,var,var,stackpos);
1408return 1;
1409}
1410
1411bool handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,ExtValue::CmpOperator op,const char* opname)
1412{
1413trctx.emitLine();
1414result.ident=0;
1415if (arg1.constant && arg2.constant)
1416        {
1417        result.constant=1;
1418        ExtValue::CompareResult cmp=arg1.compare(arg2);
1419        ExtValue::CmpContext context;
1420        context.v1=&arg1;
1421        context.v2=&arg2;
1422        int ret=ExtValue::interpretCompare(op,cmp,&context);
1423        if (ret<0)
1424                result.setEmpty();//return false;
1425        else
1426                result.setInt(ret);
1427        return true;
1428        }
1429else
1430        {
1431        result.constant=0;
1432        result.assign=arg1.assign || arg2.assign;
1433        result.parens=0;
1434        result.setString(opname);
1435        if (arg1.constant)
1436                trctx.out->printf("setif %s,%s,s0,s0\n",litstr(arg1),opname);
1437        else if (arg2.constant)
1438                trctx.out->printf("setif s0,%s,%s,s0\n",opname,litstr(arg2));
1439        else
1440                {
1441                trctx.out->printf("setif s1,%s,s0,s1\ninc m0\n",opname);
1442                trstack.adjust(+1);
1443                }
1444        return true;
1445        }
1446}
1447
1448static bool resultIsRelaxedEqual(ExtValue::CompareResult res)
1449{
1450return (res==ExtValue::ResultEqual)||(res==ExtValue::ResultEqualUnordered)||(res==ExtValue::ResultUnequal_RelaxedEqual);
1451}
1452
1453bool variableOk(TokenValue &tok, const TokenValue& var,int &loc)
1454{
1455loc=trstack.getVariableLocation(var.getString());
1456if (loc != TranslatorStack::NOTFOUND)
1457        {tok.setInt(loc); tok.constant=0;
1458        return 1;}
1459return 0;
1460}
1461
1462bool globalOk(const TokenValue& var)
1463{
1464SymTabEntry* found=trstack.globals.find(var.getString());
1465if (found) return true;
1466return framscriptIsGlobalName(var.getString());
1467}
1468
1469void badVariable(TokenValue &tok, const TokenValue& var)
1470{
1471tok=var; tok.constant=1;
1472trctx.err->printf("undefined variable '%s'\n",str(var));
1473}
1474
1475bool doBreak(int level)
1476{
1477if (trstack.loops.size()<level)
1478        {trctx.err->printf("invalid 'break'\n"); return 0;}
1479LoopInfo* li=trstack.loops.getLoop(level-1);
1480if (li->location != trstack.currentPos())
1481        trctx.out->printf("add %d,m0\n",li->location-trstack.currentPos());
1482trctx.out->printf("jump :_loop_end_%d\n",li->id);
1483return 1;
1484}
1485
1486bool doContinue(int level)
1487{
1488if (trstack.loops.size()<level)
1489        {trctx.err->printf("invalid 'continue'\n"); return 0;}
1490LoopInfo* li=trstack.loops.getLoop(level-1);
1491if (li->location != trstack.currentPos())
1492        trctx.out->printf("add %d,m0\n",li->location-trstack.currentPos());
1493trctx.out->printf("jump :_loop_%d\n",li->id);
1494return 1;
1495}
1496
1497int lookupToken(char *s)
1498{
1499int len=strlen(s);
1500int i;
1501const char *t;
1502for (i = 0; i < YYNTOKENS; i++)
1503        {
1504        t=yytname[i];
1505        if (t && (t[0]=='"')
1506           && (!strncmp(t+1,s,len))
1507           && (t[len+1]=='"')
1508           && (t[len+2] == 0))
1509                return yytoknum[i];
1510        }
1511return -1;
1512}
1513
1514void warnTruthValue(const TokenValue& t)
1515{
1516if (t.assign && (!t.parens))
1517        FMprintf("FramScriptCompiler","translate",FMLV_WARN,"Assignment used as truth value, use ((double parens)) if you really mean it");
1518}
1519
1520void outFunName(const TokenValue& t)
1521{
1522if (trctx.functiontmplabel<0)
1523        {
1524        trctx.functiontmplabel=trctx.labelcounter++;
1525        trctx.out->printf("jump :_skipfun_%d\n",trctx.functiontmplabel);
1526        }
1527trctx.out->printf(":%s\n",str(t));
1528}
1529
1530bool evalVariable(TokenValue &tok,const TokenValue &var)
1531{
1532int loc;
1533if (variableOk(tok,var,loc))
1534        {
1535        trctx.out->printf("push s%d\n",loc-trstack.currentPos());
1536        trstack.adjust(-1);
1537        return true;
1538        }
1539else if (globalOk(var))
1540        {
1541        trctx.out->printf("push @%s\n",(const char*)var.getString());
1542        trstack.adjust(-1);
1543        return true;
1544        }
1545else
1546        {
1547        badVariable(tok,var); return false;
1548        }
1549}
Note: See TracBrowser for help on using the repository browser.