2
0
Эх сурвалжийг харах

compiler: further improve preprocessor evaluator:
* support TRUE,FALSE for all modes
* refactor texprvalue.evaluate to support arithmetic expressions and implement them here
* simplify read_expr and read_factor code

git-svn-id: trunk@25463 -

paul 12 жил өмнө
parent
commit
7ecaaf0ef8
1 өөрчлөгдсөн 125 нэмэгдсэн , 86 устгасан
  1. 125 86
      compiler/scanner.pas

+ 125 - 86
compiler/scanner.pas

@@ -814,6 +814,7 @@ type
     def: tdef;
     def: tdef;
     constructor create_const(c:tconstsym);
     constructor create_const(c:tconstsym);
     constructor create_error;
     constructor create_error;
+    constructor create_ord(v: Tconstexprint);
     constructor create_int(v: int64);
     constructor create_int(v: int64);
     constructor create_uint(v: qword);
     constructor create_uint(v: qword);
     constructor create_bool(b: boolean);
     constructor create_bool(b: boolean);
@@ -822,7 +823,7 @@ type
     constructor create_real(r: bestreal);
     constructor create_real(r: bestreal);
     class function try_parse_number(s:string):texprvalue; static;
     class function try_parse_number(s:string):texprvalue; static;
     class function try_parse_real(s:string):texprvalue; static;
     class function try_parse_real(s:string):texprvalue; static;
-    function evaluate(v:texprvalue;op:ttoken): boolean;
+    function evaluate(v:texprvalue;op:ttoken):texprvalue;
     procedure error(expecteddef, place: string);
     procedure error(expecteddef, place: string);
     function asBool: Boolean;
     function asBool: Boolean;
     function asInt: Integer;
     function asInt: Integer;
@@ -894,6 +895,17 @@ type
       def:=generrordef;
       def:=generrordef;
     end;
     end;
 
 
+  constructor texprvalue.create_ord(v: Tconstexprint);
+    begin
+      fillchar(value,sizeof(value),#0);
+      consttyp:=constord;
+      value.valueord:=v;
+      if v.signed then
+        def:=sintdef
+      else
+        def:=uintdef;
+    end;
+
   constructor texprvalue.create_int(v: int64);
   constructor texprvalue.create_int(v: int64);
     begin
     begin
       fillchar(value,sizeof(value),#0);
       fillchar(value,sizeof(value),#0);
@@ -984,7 +996,7 @@ type
         result:=nil;
         result:=nil;
     end;
     end;
 
 
-  function texprvalue.evaluate(v:texprvalue;op:ttoken): boolean;
+  function texprvalue.evaluate(v:texprvalue;op:ttoken):texprvalue;
 
 
     function check_compatbile: boolean;
     function check_compatbile: boolean;
       begin
       begin
@@ -994,103 +1006,138 @@ type
                 ) or
                 ) or
                 (is_string(v.def) and is_string(def));
                 (is_string(v.def) and is_string(def));
         if not result then
         if not result then
-          incompatibletypes(def,v.def);
+          Message2(type_e_incompatible_types,def.typename,v.def.typename);
       end;
       end;
     var
     var
       lv,rv: tconstexprint;
       lv,rv: tconstexprint;
       lvd,rvd: bestreal;
       lvd,rvd: bestreal;
       lvs,rvs: string;
       lvs,rvs: string;
     begin
     begin
-      if op = _IN then
+      case op of
+        _IN:
         begin
         begin
           if not is_set(v.def) then
           if not is_set(v.def) then
             begin
             begin
-              v.error('set', 'IN');
-              result:=false;
+              v.error('Set', 'IN');
+              result:=texprvalue.create_error;
             end
             end
           else
           else
           if not is_ordinal(def) then
           if not is_ordinal(def) then
             begin
             begin
-              error('ordinal', 'IN');
-              result:=false;
+              error('Ordinal', 'IN');
+              result:=texprvalue.create_error;
             end
             end
           else
           else
           if value.valueord.signed then
           if value.valueord.signed then
-            result:=value.valueord.svalue in pnormalset(v.value.valueptr)^
+            result:=texprvalue.create_bool(value.valueord.svalue in pnormalset(v.value.valueptr)^)
           else
           else
-           result:=value.valueord.uvalue in pnormalset(v.value.valueptr)^;
-        end
-      else
-      if check_compatbile then
+            result:=texprvalue.create_bool(value.valueord.uvalue in pnormalset(v.value.valueptr)^);
+        end;
+        _OP_NOT:
         begin
         begin
-          if (is_ordinal(def) and is_ordinal(v.def)) then
-            begin
-              lv:=value.valueord;
-              rv:=v.value.valueord;
-              case op of
-                _EQ:
-                  result:=lv=rv;
-                _NE:
-                  result:=lv<>rv;
-                _LT:
-                  result:=lv<rv;
-                _GT:
-                  result:=lv>rv;
-                _GTE:
-                  result:=lv>=rv;
-                _LTE:
-                  result:=lv<=rv;
-              end;
-            end
+          if is_boolean(def) then
+            result:=texprvalue.create_bool(not asBool)
           else
           else
-          if (is_fpu(def) or is_ordinal(def)) and
-             (is_fpu(v.def) or is_ordinal(v.def)) then
             begin
             begin
-              if is_fpu(def) then
-                lvd:=pbestreal(value.valueptr)^
-              else
-                lvd:=value.valueord;
-              if is_fpu(v.def) then
-                rvd:=pbestreal(v.value.valueptr)^
-              else
-                rvd:=v.value.valueord;
+              error('Boolean', 'NOT');
+              result:=texprvalue.create_error;
+            end;
+        end;
+        _EQ,_NE,_LT,_GT,_GTE,_LTE,_PLUS,_MINUS,_STAR,_SLASH:
+        if check_compatbile then
+          begin
+            if (is_ordinal(def) and is_ordinal(v.def)) then
+              begin
+                lv:=value.valueord;
+                rv:=v.value.valueord;
+                case op of
+                  _EQ:
+                    result:=texprvalue.create_bool(lv=rv);
+                  _NE:
+                    result:=texprvalue.create_bool(lv<>rv);
+                  _LT:
+                    result:=texprvalue.create_bool(lv<rv);
+                  _GT:
+                    result:=texprvalue.create_bool(lv>rv);
+                  _GTE:
+                    result:=texprvalue.create_bool(lv>=rv);
+                  _LTE:
+                    result:=texprvalue.create_bool(lv<=rv);
+                  _PLUS:
+                    result:=texprvalue.create_ord(lv+rv);
+                  _MINUS:
+                    result:=texprvalue.create_ord(lv-rv);
+                  _STAR:
+                    result:=texprvalue.create_ord(lv*rv);
+                  _SLASH:
+                    result:=texprvalue.create_real(lv/rv);
+                end;
+              end
+            else
+            if (is_fpu(def) or is_ordinal(def)) and
+               (is_fpu(v.def) or is_ordinal(v.def)) then
+              begin
+                if is_fpu(def) then
+                  lvd:=pbestreal(value.valueptr)^
+                else
+                  lvd:=value.valueord;
+                if is_fpu(v.def) then
+                  rvd:=pbestreal(v.value.valueptr)^
+                else
+                  rvd:=v.value.valueord;
+                case op of
+                  _EQ:
+                    result:=texprvalue.create_bool(lvd=rvd);
+                  _NE:
+                    result:=texprvalue.create_bool(lvd<>rvd);
+                  _LT:
+                    result:=texprvalue.create_bool(lvd<rvd);
+                  _GT:
+                    result:=texprvalue.create_bool(lvd>rvd);
+                  _GTE:
+                    result:=texprvalue.create_bool(lvd>=rvd);
+                  _LTE:
+                    result:=texprvalue.create_bool(lvd<=rvd);
+                  _PLUS:
+                    result:=texprvalue.create_real(lvd+rvd);
+                  _MINUS:
+                    result:=texprvalue.create_real(lvd-rvd);
+                  _STAR:
+                    result:=texprvalue.create_real(lvd*rvd);
+                  _SLASH:
+                    result:=texprvalue.create_real(lvd/rvd);
+                end;
+              end
+            else
+            begin
+              lvs:=asStr;
+              rvs:=v.asStr;
               case op of
               case op of
                 _EQ:
                 _EQ:
-                  result:=lvd=rvd;
+                  result:=texprvalue.create_bool(lvs=rvs);
                 _NE:
                 _NE:
-                  result:=lvd<>rvd;
+                  result:=texprvalue.create_bool(lvs<>rvs);
                 _LT:
                 _LT:
-                  result:=lvd<rvd;
+                  result:=texprvalue.create_bool(lvs<rvs);
                 _GT:
                 _GT:
-                  result:=lvd>rvd;
+                  result:=texprvalue.create_bool(lvs>rvs);
                 _GTE:
                 _GTE:
-                  result:=lvd>=rvd;
+                  result:=texprvalue.create_bool(lvs>=rvs);
                 _LTE:
                 _LTE:
-                  result:=lvd<=rvd;
+                  result:=texprvalue.create_bool(lvs<=rvs);
+                _PLUS:
+                  result:=texprvalue.create_str(lvs+rvs);
+                _MINUS, _STAR, _SLASH:
+                  begin
+                    Message(parser_e_illegal_expression);
+                    result:=texprvalue.create_error;
+                  end;
               end;
               end;
-            end
-          else
-          begin
-            lvs:=asStr;
-            rvs:=v.asStr;
-            case op of
-              _EQ:
-                result:=lvs=rvs;
-              _NE:
-                result:=lvs<>rvs;
-              _LT:
-                result:=lvs<rvs;
-              _GT:
-                result:=lvs>rvs;
-              _GTE:
-                result:=lvs>=rvs;
-              _LTE:
-                result:=lvs<=rvs;
             end;
             end;
-          end;
-        end
-      else
-        result:=false;
+          end
+        else
+          result:=texprvalue.create_error;
+      end;
     end;
     end;
 
 
   procedure texprvalue.error(expecteddef, place: string);
   procedure texprvalue.error(expecteddef, place: string);
@@ -1375,9 +1422,9 @@ type
           result:=texprvalue.try_parse_number(pp);
           result:=texprvalue.try_parse_number(pp);
           if not assigned(result) then
           if not assigned(result) then
             begin
             begin
-              if assigned(mac) and (m_mac in current_settings.modeswitches) and (pp='FALSE') then
+              if assigned(mac) and (pp='FALSE') then
                 result:=texprvalue.create_bool(false)
                 result:=texprvalue.create_bool(false)
-              else if assigned(mac) and (m_mac in current_settings.modeswitches) and (pp='TRUE') then
+              else if assigned(mac) and (pp='TRUE') then
                 result:=texprvalue.create_bool(true)
                 result:=texprvalue.create_bool(true)
               else if (m_mac in current_settings.modeswitches) and
               else if (m_mac in current_settings.modeswitches) and
                       (not assigned(mac) or not mac.defined) and
                       (not assigned(mac) or not mac.defined) and
@@ -1691,24 +1738,19 @@ type
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     exprvalue:=read_factor(eval);
                     exprvalue:=read_factor(eval);
                     if eval then
                     if eval then
-                      begin
-                        if is_boolean(exprvalue.def) then
-                          result:=texprvalue.create_bool(not exprvalue.asBool)
-                        else
-                         exprvalue.error('Boolean', 'NOT');
-                      end
+                      result:=exprvalue.evaluate(nil,_OP_NOT)
                     else
                     else
                       result:=texprvalue.create_bool(false); {Just to have something}
                       result:=texprvalue.create_bool(false); {Just to have something}
                     exprvalue.free;
                     exprvalue.free;
                   end
                   end
                 else
                 else
-                if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='TRUE') then
+                if (current_scanner.preproc_pattern='TRUE') then
                   begin
                   begin
                     result:=texprvalue.create_bool(true);
                     result:=texprvalue.create_bool(true);
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                   end
                   end
                 else
                 else
-                if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='FALSE') then
+                if (current_scanner.preproc_pattern='FALSE') then
                   begin
                   begin
                     result:=texprvalue.create_bool(false);
                     result:=texprvalue.create_bool(false);
                     preproc_consume(_ID);
                     preproc_consume(_ID);
@@ -1871,8 +1913,7 @@ type
         function read_expr(eval:Boolean): texprvalue;
         function read_expr(eval:Boolean): texprvalue;
         var
         var
            hs1,hs2: texprvalue;
            hs1,hs2: texprvalue;
-           b : boolean;
-           op : ttoken;
+           op: ttoken;
         begin
         begin
            hs1:=read_simple_expr(eval);
            hs1:=read_simple_expr(eval);
            op:=current_scanner.preproc_token;
            op:=current_scanner.preproc_token;
@@ -1891,14 +1932,12 @@ type
            hs2:=read_simple_expr(eval);
            hs2:=read_simple_expr(eval);
 
 
            if eval then
            if eval then
-             b:=hs1.evaluate(hs2,op)
+             result:=hs1.evaluate(hs2,op)
            else
            else
-             b:= false; {Just to have something}
+             result:=texprvalue.create_bool(false); {Just to have something}
 
 
            hs1.free;
            hs1.free;
            hs2.free;
            hs2.free;
-
-           result:=texprvalue.create_bool(b);
         end;
         end;
 
 
      begin
      begin