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

Last change on this file since 295 was 286, checked in by Maciej Komosinski, 10 years ago

Updated headers

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