Index: cpp/frams/vm/framscript.l
===================================================================
--- cpp/frams/vm/framscript.l	(revision 330)
+++ cpp/frams/vm/framscript.l	(revision 332)
@@ -33,6 +33,6 @@
 \"\"\"             {trctx.tmp=""; trctx.multilimit='\"'; BEGIN multiline;}
 "'''"              {trctx.tmp=""; trctx.multilimit='\''; BEGIN multiline;}
-"@line "[0-9]+\n   {trctx.line=atol(yytext+6);}
-"@file "[^\n\t\r]+\n {trctx.srcname=SString(yytext+6,yyleng-7);}
+"@line "[0-9]+\n   {trctx.line=atol(yytext+6);trctx.linechanged=true;}
+"@file "[^\n\t\r]+\n {trctx.srcname=SString(yytext+6,yyleng-7);trctx.namechanged=true;}
 
 [a-zA-Z_][a-zA-Z0-9_]* { int t=lookupToken(yytext);
@@ -65,9 +65,9 @@
 ">>"                return RSHIFT;
 
-<INITIAL,asmcode,asmcode2>\/\/.*\n         {trctx.line++;} // komentarz jednoliniowy
+<INITIAL,asmcode,asmcode2>\/\/.*\n         {trctx.line++;trctx.linechanged=true;} // komentarz jednoliniowy
 <INITIAL,asmcode,asmcode2>\/\/[^\n]*       ;               // komentarz ale nie ma potem \n
 
 <INITIAL>\/\*       BEGIN comment;
-<comment>\n         {trctx.line++;}
+<comment>\n         {trctx.line++;trctx.linechanged=true;}
 <comment>\*\/       BEGIN 0;
 <comment>.          ;
@@ -85,7 +85,7 @@
                        trctx.tmp+=SString(yytext,yyleng);
                     }
-<multiline>\n       {trctx.line++; trctx.tmp+="\n";}
+<multiline>\n       {trctx.line++; trctx.linechanged=true; trctx.tmp+="\n";}
 [ \t\r\f]           ;
-\n                  {trctx.line++;}
+\n                  {trctx.line++; trctx.linechanged=true;}
 .                   return yytext[0];
 
@@ -94,9 +94,10 @@
                     char *t=yytext;
                     while(t=strchr(t+1,'\n')) trctx.line++;
+                    trctx.linechanged=true;
                     return ASM;
                     }
 <asmcode>.*\n {
               char *t=yytext;
-              trctx.line++;
+              trctx.line++; trctx.linechanged=true;
               while ((*t==' ')||(*t=='\t')) t++;
               if (*t=='}') {yyless((t-yytext)+1); BEGIN 0; return '}';}
Index: cpp/frams/vm/framscript.y
===================================================================
--- cpp/frams/vm/framscript.y	(revision 330)
+++ cpp/frams/vm/framscript.y	(revision 332)
@@ -15,7 +15,7 @@
 static void yyprint (FILE *file,int type,YYSTYPE value);
 void handleTwoArg(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
-		  int optoken,const char* opname, bool logic, bool negarg2, bool uniq);
-void handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
-		   int optoken,const char* opname);
+		  int optoken,const char* opname, bool negarg2, bool uniq);
+bool handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
+		   ExtValue::CmpOperator,const char* opname);
 bool handleAssignOp(YYSTYPE& result,const YYSTYPE& var,const YYSTYPE& arg,const char* opname);
 bool handleAssignOp2(YYSTYPE& result,const char *var,const YYSTYPE& arg,const char* opname,int stackpos,bool push);
@@ -46,4 +46,7 @@
 %left NEG     /* negation--unary minus */
 %left TYPEOF
+%left INT
+%left FLOAT
+%left STRING
 
 %token IDENT
@@ -65,4 +68,7 @@
 
 %token TYPEOF    "typeof"
+%token INT       "int"
+%token FLOAT     "float"
+%token STRING    "string"
 
 %token ASM     
@@ -111,5 +117,5 @@
       | GLOBAL globaldeflist ';'
       | IDENT ':'     {trctx.out->printf(":%s\n",str($1));}
-      | expr ';'      {if (!$1.constant) { trctx.out->printf("inc m0\n"); trstack.adjust(+1); } }
+      | expr ';'      {if (!$1.constant) { trctx.out->printf("inc m0\n"); trstack.adjust(+1); } trctx.emitLine(); }
       | functiondef
       | blok
@@ -138,5 +144,5 @@
  {
 #ifdef FRAMSCRIPT_GOTO
-trctx.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);
+trctx.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); trctx.emitLine();
 #else
 trctx.err->printf("goto is not supported\n");return 1;
@@ -183,4 +189,5 @@
 else
 	offset=trctx.functionstackpos-trstack.currentPos();
+trctx.emitLine();
 if (!offset)
 	trctx.out->printf("move invalid,s0\nreturn\n");
@@ -194,6 +201,6 @@
 ;
 
-vardef: IDENT               {trstack.addVariable($1.getString()); trctx.out->printf("push invalid\n");}
-      | IDENT '=' stackexpr {trstack.adjust(1); trstack.addVariable($1.getString());}
+vardef: IDENT               { trctx.emitLine(); trstack.addVariable($1.getString()); trctx.out->printf("push invalid\n");}
+      | IDENT '=' stackexpr { trctx.emitLine(); trstack.adjust(1); trstack.addVariable($1.getString());}
 ;
 
@@ -220,4 +227,5 @@
 functiondef:                FUNCTION funnamelist
 {
+trctx.emitLine();
 int pos=trstack.currentPos();
 $$.setInt(pos);
@@ -236,4 +244,5 @@
 trctx.out->printf(":_skipfun_%d\n",trctx.functiontmplabel);
 trctx.functiontmplabel=-1;
+trctx.emitLine();
 };
 
@@ -241,4 +250,5 @@
                | BREAK expr ';'
 {
+trctx.emitLine();
 if (!$2.constant)
 	{trctx.err->printf("break level must be a constant expression\n");return 1;}
@@ -247,4 +257,5 @@
 	{trctx.err->printf("break level must be a positive integer\n");return 1;}
 if (!doBreak(level)) return 1;
+trctx.emitLine();
 };
 
@@ -258,8 +269,10 @@
 	{trctx.err->printf("continue level must be a positive integer\n");return 1;}
 if (!doContinue(level)) return 1;
+trctx.emitLine();
 };
 
 while_statement: WHILE '('
-{ int c=trctx.labelcounter++; $$.setInt(c);
+{
+int c=trctx.labelcounter++; $$.setInt(c);
 $$.stack=trstack.currentPos();
 trstack.loops.addLoop(c,$$.stack);
@@ -273,10 +286,11 @@
 else
 	{
-	trctx.out->printf("if m[m0++],==,0,:_loop_end_%d\n",c,c);
+	trctx.out->printf("if ~=,m[m0++],:_loop_end_%d\n",c,c);
 	trstack.adjust(+1);
 	}
 }
                  pseudoblok_statement
-{trctx.out->printf("jump :_loop_%d\n:_loop_end_%d\n",$3.getInt(),$3.getInt());
+{
+trctx.out->printf("jump :_loop_%d\n:_loop_end_%d\n",$3.getInt(),$3.getInt());
 trstack.adjust($3.stack-trstack.currentPos());
 trstack.loops.drop();
@@ -285,5 +299,7 @@
 
 dowhile_statement: DO
-{ int c=trctx.labelcounter++; $$.setInt(c);
+{
+trctx.emitLine();
+int c=trctx.labelcounter++; $$.setInt(c);
 $$.stack=trstack.currentPos();
 trstack.loops.addLoop(c,$$.stack);
@@ -299,5 +315,5 @@
 else
 	{
-	trctx.out->printf("if !=,m[m0++],:_loop_%d\n",c);
+	trctx.out->printf("if !~,m[m0++],:_loop_%d\n",c);
 	trstack.adjust(+1);
 	}
@@ -305,15 +321,26 @@
 trstack.adjust($2.stack-trstack.currentPos());
 trstack.loops.drop();
+trctx.emitLine();
 }
 ;
 
 switch_statement: SWITCH '('
-{int c=trctx.labelcounter++; $1.setInt(c);
+{
+int c=trctx.labelcounter++; $1.setInt(c);
 trstack.loops.addLoop(c,trstack.currentPos());}
        stackexpr ')'
-{trctx.out->printf("dec m0\n");trstack.adjust(-1);}
+{trctx.emitLine(); trctx.out->printf("dec m0\n"); trstack.adjust(-1);}
  '{' inside_switch '}'
-{int c=$1.getInt(); trctx.out->printf("add 2,m0\n:_loop_end_%d\n",c); trstack.adjust(+2);
-trstack.loops.drop();}
+{
+trctx.emitLine(); 
+LoopInfo *li=trstack.loops.getLoop(0);
+trctx.out->printf(":_case_after_%d_%d\n"
+		  "add 2,m0\n"
+		  ":_loop_end_%d\n",
+		  li->id,li->casecounter,
+		  li->id);
+trstack.adjust(+2);
+trstack.loops.drop();
+}
 ;
 
@@ -324,17 +351,43 @@
 
 case_label: CASE expr ':'
-{if (!$2.constant) {trctx.err->printf("case label must be a constant expression\n");return 1;}
-int c=trctx.labelcounter++; $1.setInt(c);
-trctx.out->printf("if s1,!=,%s,:_skip_%d\n",litstr($2),c);
+{
+LoopInfo *li=trstack.loops.getLoop(0);
+if ($2.constant)
+	trctx.out->printf("if s1,!=,%s,:_case_before_%d_%d\n",
+			  litstr($2),
+			  li->id,li->casecounter+1);
+else
+	{
+	trctx.out->printf("if s2,!=,m[m0++],:_case_before_%d_%d\n",
+			  li->id,li->casecounter+1);
+	trstack.adjust(+1);
+	}
+trctx.out->printf(":_case_after_%d_%d\n",
+		  li->id,li->casecounter);
 int pos=trstack.currentPos(); $$.setInt(pos);
 }
  recurcode
 {
+trctx.emitLine();
+LoopInfo *li=trstack.loops.getLoop(0);
 int pos=$4.getInt();
 if (pos!=trstack.currentPos()) trctx.out->printf("add %d,m0\n",pos-trstack.currentPos());
 trstack.dropToPos(pos);
-trctx.out->printf(":_skip_%d\n",$1.getInt());
-}
-      |  DEFAULT ':' recurcode
+li->casecounter++;
+trctx.out->printf("jump :_case_after_%d_%d\n"
+		  ":_case_before_%d_%d\n",
+		  li->id,li->casecounter,
+		  li->id,li->casecounter);
+}
+      |  DEFAULT ':'
+  {
+  LoopInfo *li=trstack.loops.getLoop(0);
+  trctx.out->printf(":_case_after_%d_%d\n",li->id,li->casecounter);
+  }
+  recurcode
+  {
+  LoopInfo *li=trstack.loops.getLoop(0);
+  li->casecounter++;
+  }
 ;
 
@@ -409,4 +462,5 @@
            expr_or_objname ')'
 	   {//6
+	   trctx.emitLine();
 	   if ($4.constant) 
 		   {trctx.err->printf("%s can't be iterated\n",str($4)); return 1;}
@@ -439,4 +493,5 @@
            for_statement_begin ';'
            { //3
+	   trctx.emitLine();
 	   //trctx.out->printf("# for_statement_begin pos=%d ident=%d var=%d\n",trstack.currentPos(),$1.ident,$1.var);
 	   if ((!$1.var) && ($1.ident))
@@ -460,4 +515,5 @@
            expr_or_empty ';'
 	   { //6
+	   trctx.emitLine();
 	   int c=$1.counter;
 	   warnTruthValue($4);
@@ -475,4 +531,5 @@
            expr_or_empty ')'
 	   { //9
+	   trctx.emitLine();
 	   if (!$7.constant) { trctx.out->printf("inc m0\n"); trstack.adjust(+1); }
 	   trctx.restoreOut();
@@ -498,6 +555,5 @@
 
 pseudoblok_statement:
-{int pos=trstack.currentPos(); $$.setInt(pos);
-}
+{trctx.emitLine(); int pos=trstack.currentPos(); $$.setInt(pos);}
   statement
 {
@@ -505,4 +561,5 @@
 if (pos!=trstack.currentPos()) trctx.out->printf("add %d,m0\n",pos-trstack.currentPos());
 trstack.dropToPos(pos);
+trctx.emitLine();
 };
 
@@ -535,8 +592,9 @@
 
 if_condition: IF
-{$$.stack=trstack.currentPos();}
+{$$.stack=trstack.currentPos();trctx.emitLine();}
 
  '(' expr ')'
 {
+trctx.emitLine();
 int c=trctx.labelcounter++;
 $$.setInt(c);
@@ -548,5 +606,5 @@
 else
 	{
-	trctx.out->printf("if m[m0++],==,0,:_if_else_%d\n",c);
+	trctx.out->printf("if ~=,m[m0++],:_if_else_%d\n",c);
 	trstack.adjust(+1);
 	}
@@ -585,4 +643,5 @@
   else
 	  {$$=$1; $$.ident=false;}
+  trctx.emitLine();
   }
 ;
@@ -606,4 +665,5 @@
        | plusminus IDENT
 {
+trctx.emitLine();
 $$.ident=0;
 int loc; if (variableOk($$,$2,loc))
@@ -619,4 +679,5 @@
        | IDENT plusminus
 {
+trctx.emitLine();
 $$.ident=0;
 int loc; if (variableOk($$,$1,loc))
@@ -630,5 +691,5 @@
 }
 
-       | IDENT assign_op expr { $$.ident=0;
+       | IDENT assign_op expr { trctx.emitLine(); $$.ident=0;
                                 if (!handleAssignOp($$,$1,$3,assign_op_names[$2.getInt()]))
 	                        if (globalOk($1)) {SString t="@"; t+=$1.getString();
@@ -637,39 +698,167 @@
                               }
 
-       | TYPEOF expr { $$.ident=0;
-                       if ($2.constant)
-                             {$$.constant=1; $$=$2.getExtType();}
+       | TYPEOF '(' expr ')' { trctx.emitLine(); $$.ident=0;
+                       if ($3.constant)
+                             {$$.constant=1; $$=$3.getExtType();}
                        else
                              {trctx.out->printf("type s0,s0\n");}
                      }
-
-       | expr '+' expr { handleTwoArg($$,$1,$3,'+',"add",0,0,1); }
-       | expr '-' expr { handleTwoArg($$,$1,$3,'-',"sub",0,0,0); }
-       | expr '*' expr { handleTwoArg($$,$1,$3,'*',"mul",0,0,1); }
-       | expr '/' expr { handleTwoArg($$,$1,$3,'/',"div",0,0,0); }
-       | expr '&' expr { handleTwoArg($$,$1,$3,'&',"and",0,0,0); }
-       | expr '|' expr { handleTwoArg($$,$1,$3,'|',"or",0,0,0); }
-       | expr '%' expr { handleTwoArg($$,$1,$3,'%',"mod",0,0,0); }
-       | expr LOGIC_AND expr { handleTwoArg($$,$1,$3,LOGIC_AND,"and",1,0,0); }
-       | expr LOGIC_OR expr { handleTwoArg($$,$1,$3,LOGIC_OR,"or",1,0,0); }
-       | expr LSHIFT expr { handleTwoArg($$,$1,$3,LSHIFT,"shift",0,0,0); }
-       | expr RSHIFT expr { handleTwoArg($$,$1,$3,RSHIFT,"shift",0,1,0); }
-       | expr EQUAL expr     { handleCompare($$,$1,$3,EQUAL,"=="); }
-       | expr NOT_EQUAL expr { handleCompare($$,$1,$3,NOT_EQUAL,"!="); }
-       | expr GEQUAL expr    { handleCompare($$,$1,$3,GEQUAL,">="); }
-       | expr LEQUAL expr    { handleCompare($$,$1,$3,LEQUAL,"<="); }
-       | expr '>' expr       { handleCompare($$,$1,$3,'>',">"); }
-       | expr '<' expr       { handleCompare($$,$1,$3,'<',"<"); }
+       | INT '(' expr ')' { trctx.emitLine(); $$.ident=0;
+                       if ($3.constant)
+			     {$$.constant=1; $$=ExtValue($3.getInt());}
+                       else
+                             {trctx.out->printf("conv 1,s0\n");}
+                     }
+       | FLOAT '(' expr ')' { trctx.emitLine(); $$.ident=0;
+                       if ($3.constant)
+			     {$$.constant=1; $$=ExtValue($3.getDouble());}
+                       else
+                             {trctx.out->printf("conv 2,s0\n");}
+                     }
+       | STRING '(' expr ')' { trctx.emitLine(); $$.ident=0;
+                       if ($3.constant)
+			     {$$.constant=1; $$=ExtValue($3.getString());}
+                       else
+                             {trctx.out->printf("conv 3,s0\n");}
+                     }
+
+       | expr '+' expr { handleTwoArg($$,$1,$3,'+',"add",0,1); }
+       | expr '-' expr { handleTwoArg($$,$1,$3,'-',"sub",0,0); }
+       | expr '*' expr { handleTwoArg($$,$1,$3,'*',"mul",0,1); }
+       | expr '/' expr { handleTwoArg($$,$1,$3,'/',"div",0,0); }
+       | expr '&' expr { handleTwoArg($$,$1,$3,'&',"and",0,0); }
+       | expr '|' expr { handleTwoArg($$,$1,$3,'|',"or",0,0); }
+       | expr '%' expr { handleTwoArg($$,$1,$3,'%',"mod",0,0); }
+
+       | expr LOGIC_AND
+ {
+ // a && b:
+ //   push a
+ //   if (a)
+ //     pop; goto and_b
+ //   else
+ //     pop; push 0; goto and_end
+ // and_b:
+ //   push b
+ // and_end:
+ trctx.emitLine();
+// trctx.out->printf("\n####### logic AND\n");
+ int c=trctx.labelcounter++;
+ $$.setInt(c);
+ if ($1.constant)
+	 {
+	 int cond=$1.compare(ExtValue::zero());
+	 if ((cond==0)||(cond==2))
+		 {
+		 $1.counter=0;
+		 // no stack adjust - next tokens are processed in a different context
+		 trctx.out->printf("push 0\njump :_and_end_%d\n",c);
+		 }
+	 else
+		 $1.counter=1;
+	 }
+ else
+	 {
+	 trstack.adjust(+1); // stack as if (a==true), b expr is processed
+	 trctx.out->printf("if !~,m[m0++],:_and_b_%d\n"
+			   "push 0\n"
+			   "jump :_and_end_%d\n"
+			   ":_and_b_%d\n"
+			   ,c,c,c);
+	 }
+ }
+         expr
+ {
+ $$.ident=false;
+ $$.constant=0;
+ if ($4.constant)
+	 {
+	 if (!($1.constant && $1.counter==0))
+		 {
+		 int cond=$4.compare(ExtValue::zero());
+		 bool value=!((cond==0)||(cond==2));
+		 trstack.adjust(-1);
+		 trctx.out->printf("push %d\n",value);
+		 }
+	 }
+ trctx.out->printf(":_and_end_%d\n",$3.getInt());
+// trctx.out->printf("#################\n\n");
+ }
+
+       | expr LOGIC_OR
+ {
+ // a || b:
+ //   push a
+ //   if (!a)
+ //     pop; goto and_b
+ //   else
+ //     pop; push 1; goto and_end
+ // and_b:
+ //   push b
+ // and_end:
+ trctx.emitLine();
+// trctx.out->printf("\n####### logic AND\n");
+ int c=trctx.labelcounter++;
+ $$.setInt(c);
+ if ($1.constant)
+	 {
+	 int cond=$1.compare(ExtValue::zero());
+	 if (!((cond==0)||(cond==2)))
+		 {
+		 $1.counter=1;
+		 // no stack adjust - next tokens are processed in a different context
+		 trctx.out->printf("push 1\njump :_or_end_%d\n",c);
+		 }
+	 else
+		 $1.counter=0;
+	 }
+ else
+	 {
+	 trstack.adjust(+1); // stack for (a==false)
+	 trctx.out->printf("if ~=,m[m0++],:_or_b_%d\n"
+			   "push 1\n"
+			   "jump :_or_end_%d\n"
+			   ":_or_b_%d\n"
+			   ,c,c,c);
+	 }
+ }
+         expr
+ {
+ $$.ident=false;
+ $$.constant=0;
+ if ($4.constant)
+	 {
+	 if (!($1.constant && $1.counter==1))
+		 {
+		 int cond=$4.compare(ExtValue::zero());
+		 bool value=!((cond==0)||(cond==2));
+		 trstack.adjust(-1);
+		 trctx.out->printf("push %d\n",value);
+		 }
+	 }
+ trctx.out->printf(":_or_end_%d\n",$3.getInt());
+// trctx.out->printf("#################\n\n");
+ }
+
+
+       | expr LSHIFT expr { handleTwoArg($$,$1,$3,LSHIFT,"shift",0,0); }
+       | expr RSHIFT expr { handleTwoArg($$,$1,$3,RSHIFT,"shift",1,0); }
+       | expr EQUAL expr     { if (!handleCompare($$,$1,$3,ExtValue::CmpEQ,"==")) return 1; }
+       | expr NOT_EQUAL expr { if (!handleCompare($$,$1,$3,ExtValue::CmpNE,"!=")) return 1; }
+       | expr GEQUAL expr    { if (!handleCompare($$,$1,$3,ExtValue::CmpGE,">=")) return 1; }
+       | expr LEQUAL expr    { if (!handleCompare($$,$1,$3,ExtValue::CmpLE,"<=")) return 1; }
+       | expr '>' expr       { if (!handleCompare($$,$1,$3,ExtValue::CmpGT,">")) return 1; }
+       | expr '<' expr       { if (!handleCompare($$,$1,$3,ExtValue::CmpLT,"<")) return 1; }
 
        | '!' expr        {
-                         $$.assign=$2.assign; $$.parens=0; $$.ident=0;
+                         trctx.emitLine(); $$.assign=$2.assign; $$.parens=0; $$.ident=0;
                          if ($2.constant)
-                                {$$.constant=1; $$.setInt(!$2.getInt());}
+				 {$$.constant=1; int res=$2.compare(ExtValue((paInt)0)); $$.setInt((res==0)||(res==2));}
                          else
-				{trctx.out->printf("setif ==,s0,s0\n");}
+				{trctx.out->printf("setif ~=,s0,s0\n");}
                          }
 
      | '-' expr %prec NEG { 
-                          $$.assign=$2.assign; $$.parens=0; $$.ident=0;
+                          trctx.emitLine(); $$.assign=$2.assign; $$.parens=0; $$.ident=0;
                           if ($2.constant)
 	                          { $$.constant=$2.constant;
@@ -685,8 +874,8 @@
                           }
 
-     | '(' expr ')'    { $$ = $2; $$.assign=$2.assign?(!$2.parens):0; $$.parens=1; $$.ident=0; }
+     | '(' expr ')'    { trctx.emitLine(); $$ = $2; $$.assign=$2.assign?(!$2.parens):0; $$.parens=1; $$.ident=0; }
 
      | OBJNAME '.' member {
-                        $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 			if ($3.constant)
 				{
@@ -700,5 +889,5 @@
 
      | OBJNAME '.' member assign_op expr
-                  { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+                  { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 		  if ($3.constant)
 			  {
@@ -716,5 +905,5 @@
 
      | plusminus OBJNAME '.' member {
-                        $$.constant=0; $$.ident=0; SString t=$2.getString(); t+="."; t+=$4.getString(); $$.setString(t);
+                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$2.getString(); t+="."; t+=$4.getString(); $$.setString(t);
 			if ($4.constant)
 				{
@@ -731,5 +920,5 @@
 
      | OBJNAME '.' member plusminus {
-                        $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 			if ($3.constant)
 				{
@@ -746,5 +935,5 @@
 
      | OBJNAME '.' '*'    {
-                        $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".*"; $$.setString(t);
+                        trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".*"; $$.setString(t);
 			trctx.out->printf("push %s.*\n",str($1)); trstack.adjust(-1);
                         }
@@ -752,5 +941,5 @@
 
      | OBJNAME '.' member '=' expr {
-			$$=$5; $$.assign=1; $$.parens=0; $$.ident=0;
+			trctx.emitLine(); $$=$5; $$.assign=1; $$.parens=0; $$.ident=0;
 			if ($3.constant)
 				{
@@ -779,5 +968,5 @@
      | OBJNAME '.' member '(' arguments ')' 
                         {
-                        $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+			trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 			int adj=0,adj2=0;
 			if ($5.getInt()==0)
@@ -799,5 +988,5 @@
 
      | CALL expr '(' arguments ')'
-             { $$.constant=0; $$.ident=0; $$.setString($2.getString());
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; $$.setString($2.getString());
 	     short adj=0;
 	     if ($4.getInt()==0)
@@ -815,5 +1004,5 @@
 
      | FUNCTION IDENT
-             { $$.constant=0; $$.ident=0; SString t=":"; t+=$1.getString(); $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=":"; t+=$1.getString(); $$.setString(t);
 	     trctx.out->printf("push :%s\n",(const char*)$2.getString());
 	     trstack.adjust(-1);
@@ -821,5 +1010,5 @@
 
      | expr '.' member
-             { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 	     if ($3.constant)
 		     trctx.out->printf("move s0,m1\nmove [m1].%s,s0\n",str($3));
@@ -830,5 +1019,5 @@
 
      | plusminus expr '.' member
-             { $$.constant=0; $$.ident=0; SString t=$2.getString(); t+="."; t+=$4.getString(); $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$2.getString(); t+="."; t+=$4.getString(); $$.setString(t);
 	     if ($4.constant)
 		     trctx.out->printf("move s0,m1\n%s [m1].%s\nmove [m1].%s,s0\n",
@@ -841,5 +1030,5 @@
 
      | expr '.' member plusminus
-             { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 	     if ($3.constant)
 		     trctx.out->printf("move s0,m1\nmove [m1].%s,s0\n%s [m1].%s\n",
@@ -852,5 +1041,5 @@
 
      | expr '.' member assign_op expr
-             { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 	     if ($3.constant)
 		     {
@@ -880,5 +1069,5 @@
 
      | expr '.' member '=' stackexpr
-	     { $$=$5; $$.assign=1; $$.parens=0; $$.ident=0;
+	     { trctx.emitLine(); $$=$5; $$.assign=1; $$.parens=0; $$.ident=0;
 	     if ($3.constant)
 		     {
@@ -894,5 +1083,5 @@
 
      | expr '.' member '(' arguments ')'
-             { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+="."; t+=$3.getString(); $$.setString(t);
 	     int adj=0;
 	     if ($5.getInt()==0)
@@ -917,5 +1106,5 @@
 
       | expr '[' expr ']' '=' expr    // shortcut: expr.set(expr,expr)
-	     { $$=$6; $$.assign=1; $$.parens=0; $$.ident=0;
+	     { trctx.emitLine(); $$=$6; $$.assign=1; $$.parens=0; $$.ident=0;
 	     if ($3.constant)
 		     {
@@ -935,5 +1124,5 @@
 
       | expr '[' expr ']'    /* shortcut: expr.get(expr) */
-             { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".get"; $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".get"; $$.setString(t);
 	     if ($3.constant)
 		     {
@@ -947,5 +1136,5 @@
 	     }
 
-     | IDENT '=' expr { $$=$3; $$.assign=1; $$.ident=0;
+     | IDENT '=' expr { trctx.emitLine(); $$=$3; $$.assign=1; $$.ident=0;
                         int loc=trstack.getVariableLocation($1.getString());
 			if (loc!=TranslatorStack::NOTFOUND)
@@ -963,5 +1152,5 @@
 
       | OBJNAME '[' expr ']'    /* shortcut: OBJNAME.get(expr) */
-             { $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".get"; $$.setString(t);
+             { trctx.emitLine(); $$.constant=0; $$.ident=0; SString t=$1.getString(); t+=".get"; $$.setString(t);
 	     if ($3.constant)
 		     {
@@ -977,5 +1166,5 @@
       | IDENT '(' arguments ')'
 {
-$$.constant=0; $$.ident=0; $$.setString("function call");
+trctx.emitLine(); $$.constant=0; $$.ident=0; $$.setString("function call");
 if ($3.getInt()==0)
 	{trctx.out->printf("dec m0\n");trstack.adjust(-1);}
@@ -988,9 +1177,9 @@
 }
 
-| '[' {$$.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)
+| '[' {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)
         v_elements ']'
         {$$.constant=0; trctx.out->printf("inc m0\n");trstack.adjust(1);}
 
-| '{' {$$.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)
+| '{' {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)
         d_elements '}'
         {$$.constant=0; trctx.out->printf("inc m0\n"); trstack.adjust(1);}
@@ -999,5 +1188,5 @@
 
       | '&' IDENT {
-        $$.ident=0;
+        trctx.emitLine(); $$.ident=0;
 	int loc=trstack.getVariableLocation($2.getString());
 	if (loc!=TranslatorStack::NOTFOUND)
@@ -1014,5 +1203,5 @@
 
       | '&' OBJNAME '.' member {
-      $$.ident=0;
+      trctx.emitLine(); $$.ident=0;
       if ($4.constant)
 	      {
@@ -1027,5 +1216,5 @@
 
       | '&' '(' stackexpr ')' '.' member {
-      $$.ident=0;
+      trctx.emitLine(); $$.ident=0;
       if ($6.constant)
 	      {
@@ -1040,5 +1229,5 @@
 
       | '(' stackexpr ',' stackexpr ',' stackexpr ')' {
-      $$.ident=0;
+      trctx.emitLine(); $$.ident=0;
       trctx.out->printf("call XYZ.new\nadd 2,m0\nmove s-2,s0\n");trstack.adjust(2);}
 ;
@@ -1133,6 +1322,7 @@
 
 void handleTwoArg(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,
-		  int optoken,const char* opname,bool logic,bool negarg2,bool uniq)
-{
+		  int optoken,const char* opname,bool negarg2,bool uniq)
+{
+trctx.emitLine();
 result.ident=false;
 if (arg1.constant && arg2.constant)
@@ -1150,6 +1340,4 @@
 		case LSHIFT: result.setInt(arg1.getInt() << arg2.getInt()); break;
 		case RSHIFT: result.setInt(arg1.getInt() >> arg2.getInt()); break;
-		case LOGIC_AND: result.setInt(arg1.getInt() && arg2.getInt()); break;
-		case LOGIC_OR: result.setInt(arg1.getInt() || arg2.getInt()); break;
 		}
 	}
@@ -1164,25 +1352,18 @@
 	result.setString(opname);
 	if (arg1.constant)
-		trctx.out->printf("move %s,m1\n%s%s%s s0,m1\nmove m1,s0\n",litstr(arg1),
-				  (logic?"setif !=,m1,m1\nsetif !=,s0,s0\n":""),
+		trctx.out->printf("move %s,m1\n%s%s s0,m1\nmove m1,s0\n",litstr(arg1),
 				  negarg2?"neg s0\n":"",
 				  opname);
 	else if (arg2.constant)
 		{
-		if (logic)
-			trctx.out->printf("move %s,m1\nsetif !=,m1,m1\nsetif !=,s0,s0\n%s m1,s0\n",
-					  litstr(arg2),opname);
+		if (negarg2)
+			trctx.out->printf("%s %d,s0\n",opname,-arg2.getInt());
 		else
-			{
-			if (negarg2)
-				trctx.out->printf("%s %d,s0\n",opname,-arg2.getInt());
-			else
-				trctx.out->printf("%s%s %s,s0\n",(uniq?"uniq s0\n":""),opname,litstr(arg2));
-			}
+			trctx.out->printf("%s%s %s,s0\n",(uniq?"uniq s0\n":""),opname,litstr(arg2));
 		}
 	else 
 		{
 		trctx.out->printf("%s%s%s s0,s1\ninc m0\n",
-				  (logic?"setif !=,s0,s0\nsetif !=,s1,s1\n":(uniq?"uniq s1\n":"")),
+				  uniq?"uniq s1\n":"",
 				  negarg2?"neg s0\n":"",
 				  opname);
@@ -1227,19 +1408,34 @@
 }
 
-void handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,int optoken,const char* opname)
-{
+class FramscriptCmpMessageHandler: public ExtValue::CmpMessageHandler
+{
+  public:
+void cmpMessage(SString& msg)
+  {
+  FMprintf("FramScriptCompiler","translate",FMLV_WARN,"%s (%s line %d)",(const char*)msg,(const char*)trctx.srcname,trctx.line);
+  //trctx.err->printf("%s",(const char*)msg);
+  }
+};
+
+static FramscriptCmpMessageHandler framscript_cmp_messages;
+
+bool handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,ExtValue::CmpOperator op,const char* opname)
+{
+trctx.emitLine();
 result.ident=0;
 if (arg1.constant && arg2.constant)
 	{
 	result.constant=1;
-	switch(optoken)
-		{
-		case '>': result.setInt(arg1.compare(arg2) > 0); break;
-		case '<': result.setInt(arg1.compare(arg2) < 0); break;
-		case EQUAL: result.setInt(arg1.compare(arg2) == 0); break;
-		case NOT_EQUAL: result.setInt(arg1.compare(arg2) != 0); break;
-		case GEQUAL: result.setInt(arg1.compare(arg2) >= 0); break;
-		case LEQUAL: result.setInt(arg1.compare(arg2) <= 0); break;
-		}
+	int cmp=arg1.compare(arg2);
+	ExtValue::CmpContext context;
+	context.v1=&arg1;
+	context.v2=&arg2;
+	context.handler=&framscript_cmp_messages;
+	int ret=ExtValue::interpretCompare(op,cmp,&context);
+	if (ret<0)
+		result.setEmpty();//return false;
+	else
+		result.setInt(ret);
+	return true;
 	}
 else
@@ -1258,4 +1454,5 @@
 		trstack.adjust(+1);
 		}
+	return true;
 	}
 }
