Explorar o código

fcl-passrc: const eval: low(range), high(range)

git-svn-id: trunk@36453 -
Mattias Gaertner %!s(int64=8) %!d(string=hai) anos
pai
achega
e1d5e52227

+ 178 - 106
packages/fcl-passrc/src/pasresolveeval.pas

@@ -19,8 +19,40 @@ Abstract:
 Works:
   - Emitting range check warnings
   - Error on overflow
-  - int/uint unary +, -
-  - int/uint binary: +, -
+  - bool: not, =, <>, and, or, xor, low(), high()
+  - int/uint
+    - unary +, -
+    - binary: +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not
+  - string: +
+  - float:
+  - enum/set
+
+ToDo:
+  - enable eval via option, default off
+  - bool:
+    - low(), high(), pred(), succ(), ord()
+  - int
+    - typecast
+    - low(), high(), pred(), succ()
+  - string:
+    - =, <>, <, >, <=, >=
+    - string encoding
+    - s[]
+    - length(string)
+    - chr(), ord(), low(), high(), pred(), succ()
+    - #65
+    - #$DC00
+  - float
+    - typecast float
+    - /
+    - +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not
+  - enum
+    - low(), high(), pred(), succ(), ord(), typecast
+  - sets
+    - [a,b,c..d]
+    - +, -, *, =, <>, <=, >=, in, ><
+  - arrays
+    - length(), low(), high()
 }
 unit PasResolveEval;
 
@@ -198,6 +230,10 @@ type
   MaxPrecInt = int64;
   MaxPrecUInt = qword;
   MaxPrecFloat = extended;
+const
+  // Note: when FPC compares int64 with qword it converts the qword to an int64,
+  //       possibly resulting in a range check error -> using a qword const instead
+  HighIntAsUInt = MaxPrecUInt(High(MaxPrecInt));
 
 type
   { TResEvalValue }
@@ -222,6 +258,7 @@ type
   public
     Kind: TREVKind;
     IdentEl: TPasElement;
+    constructor CreateKind(const aKind: TREVKind);
     function Clone: TResEvalValue; virtual;
     function AsDebugString: string; virtual;
     function AsString: string; virtual;
@@ -234,6 +271,7 @@ type
   public
     B: boolean;
     constructor Create; override;
+    constructor CreateValue(const aValue: boolean);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -244,6 +282,7 @@ type
   public
     Int: MaxPrecInt;
     constructor Create; override;
+    constructor CreateValue(const aValue: MaxPrecInt);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -254,6 +293,7 @@ type
   public
     UInt: MaxPrecUInt;
     constructor Create; override;
+    constructor CreateValue(const aValue: MaxPrecUInt);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -264,6 +304,7 @@ type
   public
     FloatValue: MaxPrecFloat;
     constructor Create; override;
+    constructor CreateValue(const aValue: MaxPrecFloat);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -274,6 +315,7 @@ type
   public
     S: RawByteString;
     constructor Create; override;
+    constructor CreateValue(const aValue: RawByteString);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -284,6 +326,7 @@ type
   public
     S: UnicodeString;
     constructor Create; override;
+    constructor CreateValue(const aValue: UnicodeString);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -294,6 +337,7 @@ type
   public
     Index: integer;
     constructor Create; override;
+    constructor CreateValue(const aValue: integer; aIdentEl: TPasEnumValue);
     function Clone: TResEvalValue; override;
     function AsDebugString: string; override;
     function AsString: string; override;
@@ -312,11 +356,13 @@ type
         );
   public
     ElKind: TRgIntElKind;
-    RangeStart, RangeEnd: int64;
+    RangeStart, RangeEnd: MaxPrecInt;
     constructor Create; override;
+    constructor CreateValue(const aElKind: TRgIntElKind;
+      const aRangeStart, aRangeEnd: MaxPrecInt);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
-    function ElementAsString(El: int64): string;
+    function ElementAsString(El: MaxPrecInt): string;
   end;
 
   { TResEvalRangeUInt }
@@ -325,6 +371,7 @@ type
   public
     RangeStart, RangeEnd: MaxPrecUInt;
     constructor Create; override;
+    constructor CreateValue(const aRangeStart, aRangeEnd: MaxPrecUInt);
     function Clone: TResEvalValue; override;
     function AsString: string; override;
   end;
@@ -341,7 +388,7 @@ type
         revsikWChar
         );
       TItem = record
-        RangeStart, RangeEnd: int64;
+        RangeStart, RangeEnd: MaxPrecInt;
       end;
       TItems = array of TItem;
   public
@@ -350,7 +397,7 @@ type
     constructor Create; override;
     function Clone: TResEvalValue; override;
     function AsString: string; override;
-    function ElementAsString(El: int64): string;
+    function ElementAsString(El: MaxPrecInt): string;
   end;
 
   TResEvalFlag = (
@@ -367,12 +414,15 @@ type
     const Fmt: String; Args: Array of const; PosEl: TPasElement) of object;
   TPasResEvalIdentHandler = function(Sender: TResExprEvaluator;
     Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue of object;
+  TPasResEvalParamsHandler = function(Sender: TResExprEvaluator;
+    Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue of object;
 
   { TResExprEvaluator }
 
   TResExprEvaluator = class
   private
     FOnEvalIdentifier: TPasResEvalIdentHandler;
+    FOnEvalParams: TPasResEvalParamsHandler;
     FOnLog: TPasResEvalLogHandler;
   protected
     procedure LogMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
@@ -415,6 +465,7 @@ type
       MinVal, MaxVal: MaxPrecInt; PosEl: TPasElement);
     property OnLog: TPasResEvalLogHandler read FOnLog write FOnLog;
     property OnEvalIdentifier: TPasResEvalIdentHandler read FOnEvalIdentifier write FOnEvalIdentifier;
+    property OnEvalParams: TPasResEvalParamsHandler read FOnEvalParams write FOnEvalParams;
   end;
   TResExprEvaluatorClass = class of TResExprEvaluator;
 
@@ -702,6 +753,12 @@ begin
   Kind:=revkBool;
 end;
 
+constructor TResEvalBool.CreateValue(const aValue: boolean);
+begin
+  Create;
+  B:=aValue;
+end;
+
 function TResEvalBool.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -721,6 +778,14 @@ begin
   Kind:=revkRangeInt;
 end;
 
+constructor TResEvalRangeUInt.CreateValue(const aRangeStart,
+  aRangeEnd: MaxPrecUInt);
+begin
+  Create;
+  RangeStart:=aRangeStart;
+  RangeEnd:=aRangeEnd;
+end;
+
 function TResEvalRangeUInt.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -852,8 +917,7 @@ begin
       if Result.Element=nil then
         Result.Free;
       // @ operator requires a compiler (not just a resolver) -> return nil
-      Result:=TResEvalValue.Create;
-      Result.Kind:=revkNil;
+      Result:=TResEvalValue.CreateKind(revkNil);
       end
     else
       RaiseNotYetImplemented(20170518232823,Expr,'operator='+OpcodeStrings[Expr.OpCode]);
@@ -936,24 +1000,20 @@ begin
       if TResEvalInt(LeftValue).Int>TResEvalInt(RightValue).Int then
         RaiseMsg(20170518222939,nHighRangeLimitLTLowRangeLimit,
           sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-      Result:=TResEvalRangeInt.Create;
-      TResEvalRangeInt(Result).ElKind:=revrikInt;
-      TResEvalRangeInt(Result).RangeStart:=TResEvalInt(LeftValue).Int;
-      TResEvalRangeInt(Result).RangeEnd:=TResEvalInt(RightValue).Int;
+      Result:=TResEvalRangeInt.CreateValue(revrikInt,
+                        TResEvalInt(LeftValue).Int,TResEvalInt(RightValue).Int);
       exit;
       end
     else if RightValue.Kind=revkUInt then
       begin
       // Note: when FPC compares int64 with qword it converts the qword to an int64
-      if TResEvalUInt(RightValue).UInt<=MaxPrecUInt(High(MaxPrecInt)) then
+      if TResEvalUInt(RightValue).UInt<=HighIntAsUInt then
         begin
         if TResEvalInt(LeftValue).Int>TResEvalUInt(RightValue).UInt then
           RaiseMsg(20170519000235,nHighRangeLimitLTLowRangeLimit,
             sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-        Result:=TResEvalRangeInt.Create;
-        TResEvalRangeInt(Result).ElKind:=revrikInt;
-        TResEvalRangeInt(Result).RangeStart:=TResEvalInt(LeftValue).Int;
-        TResEvalRangeInt(Result).RangeEnd:=TResEvalUInt(RightValue).UInt;
+        Result:=TResEvalRangeInt.CreateValue(revrikInt,
+           TResEvalInt(LeftValue).Int,MaxPrecInt(TResEvalUInt(RightValue).UInt));
         exit;
         end
       else if TResEvalInt(LeftValue).Int<0 then
@@ -961,9 +1021,8 @@ begin
       else if MaxPrecUInt(TResEvalInt(LeftValue).Int)>TResEvalUInt(RightValue).UInt then
         RaiseMsg(20170522151708,nHighRangeLimitLTLowRangeLimit,
           sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-      Result:=TResEvalRangeUInt.Create;
-      TResEvalRangeUInt(Result).RangeStart:=TResEvalInt(LeftValue).Int;
-      TResEvalRangeUInt(Result).RangeEnd:=TResEvalUInt(RightValue).UInt;
+      Result:=TResEvalRangeUInt.CreateValue(MaxPrecUInt(TResEvalInt(LeftValue).Int),
+         TResEvalUInt(RightValue).UInt);
       exit;
       end
     else
@@ -972,25 +1031,22 @@ begin
     if RightValue.Kind=revkInt then
       begin
       // Note: when FPC compares int64 with qword it converts the qword to an int64
-      if TResEvalUInt(LeftValue).UInt>MaxPrecUInt(High(MaxPrecInt)) then
+      if TResEvalUInt(LeftValue).UInt>HighIntAsUInt then
         begin
         if TResEvalInt(RightValue).Int<0 then
           RaiseRangeCheck(20170522152608,Expr.Right)
         else if TResEvalUInt(LeftValue).UInt>MaxPrecUInt(TResEvalInt(RightValue).Int) then
           RaiseMsg(20170522152648,nHighRangeLimitLTLowRangeLimit,
             sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-        Result:=TResEvalRangeUInt.Create;
-        TResEvalRangeUInt(Result).RangeStart:=TResEvalUInt(LeftValue).UInt;
-        TResEvalRangeUInt(Result).RangeEnd:=TResEvalInt(RightValue).Int;
+        Result:=TResEvalRangeUInt.CreateValue(TResEvalUInt(LeftValue).UInt,
+          MaxPrecUInt(TResEvalInt(RightValue).Int));
         exit;
         end
       else if TResEvalUInt(LeftValue).UInt>TResEvalInt(RightValue).Int then
         RaiseMsg(20170522152804,nHighRangeLimitLTLowRangeLimit,
           sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-      Result:=TResEvalRangeInt.Create;
-      TResEvalRangeInt(Result).ElKind:=revrikInt;
-      TResEvalRangeInt(Result).RangeStart:=TResEvalUInt(LeftValue).UInt;
-      TResEvalRangeInt(Result).RangeEnd:=TResEvalInt(RightValue).Int;
+      Result:=TResEvalRangeInt.CreateValue(revrikInt,
+        MaxPrecInt(TResEvalUInt(LeftValue).UInt),TResEvalInt(RightValue).Int);
       exit;
       end
     else if RightValue.Kind=revkUInt then
@@ -998,9 +1054,8 @@ begin
       if TResEvalUInt(LeftValue).UInt>TResEvalUInt(RightValue).UInt then
         RaiseMsg(20170519000240,nHighRangeLimitLTLowRangeLimit,
           sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-      Result:=TResEvalRangeUInt.Create;
-      TResEvalRangeUInt(Result).RangeStart:=TResEvalUInt(LeftValue).UInt;
-      TResEvalRangeUInt(Result).RangeEnd:=TResEvalUInt(RightValue).UInt;
+      Result:=TResEvalRangeUInt.CreateValue(TResEvalUInt(LeftValue).UInt,
+        TResEvalUInt(RightValue).UInt);
       exit;
       end
     else
@@ -1015,10 +1070,8 @@ begin
         sHighRangeLimitLTLowRangeLimit,[],Expr.Right)
     else
       begin
-      Result:=TResEvalRangeInt.Create;
-      TResEvalRangeInt(Result).ElKind:=revrikEnum;
-      TResEvalRangeInt(Result).RangeStart:=TResEvalEnum(LeftValue).Index;
-      TResEvalRangeInt(Result).RangeEnd:=TResEvalEnum(RightValue).Index;
+      Result:=TResEvalRangeInt.CreateValue(revrikEnum,
+        TResEvalEnum(LeftValue).Index,TResEvalEnum(RightValue).Index);
       exit;
       end;
   revkString,revkUnicodeString:
@@ -1030,10 +1083,7 @@ begin
       if LeftInt>RightInt then
         RaiseMsg(20170523151508,nHighRangeLimitLTLowRangeLimit,
           sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
-      Result:=TResEvalRangeInt.Create;
-      TResEvalRangeInt(Result).ElKind:=revrikChar;
-      TResEvalRangeInt(Result).RangeStart:=LeftInt;
-      TResEvalRangeInt(Result).RangeEnd:=RightInt;
+      Result:=TResEvalRangeInt.CreateValue(revrikChar,LeftInt,RightInt);
       exit;
       end
     else
@@ -1052,7 +1102,7 @@ end;
 function TResExprEvaluator.EvalBinaryAddExpr(Expr: TBinaryExpr; LeftValue,
   RightValue: TResEvalValue): TResEvalValue;
 
-  procedure IntAddUInt(i: MaxPrecInt; u: MaxPrecUInt);
+  procedure IntAddUInt(const i: MaxPrecInt; const u: MaxPrecUInt);
   var
     Int: MaxPrecInt;
     UInt: MaxPrecUInt;
@@ -1062,11 +1112,10 @@ function TResExprEvaluator.EvalBinaryAddExpr(Expr: TBinaryExpr; LeftValue,
       UInt:=MaxPrecUInt(i)+u;
       Result:=CreateResEvalInt(UInt);
       end
-    else if u<=High(MaxPrecInt) then
+    else if u<=HighIntAsUInt then
       begin
       Int:=i + MaxPrecInt(u);
-      Result:=TResEvalInt.Create;
-      TResEvalInt(Result).Int:=Int;
+      Result:=TResEvalInt.CreateValue(Int);
       end
     else
       RaiseRangeCheck(20170601140523,Expr);
@@ -1094,8 +1143,7 @@ begin
         else
           begin
           Int:=TResEvalInt(LeftValue).Int + TResEvalInt(RightValue).Int;
-          Result:=TResEvalInt.Create;
-          TResEvalInt(Result).Int:=Int;
+          Result:=TResEvalInt.CreateValue(Int);
           end;
       revkUInt:
         IntAddUInt(TResEvalInt(LeftValue).Int,TResEvalUInt(RightValue).UInt);
@@ -1112,8 +1160,7 @@ begin
       revkUInt:
         begin
         UInt:=TResEvalUInt(LeftValue).UInt+TResEvalUInt(RightValue).UInt;
-        Result:=TResEvalUInt.Create;
-        TResEvalUInt(Result).UInt:=UInt;
+        Result:=TResEvalUInt.CreateValue(UInt);
         end
       else
         {$IFDEF VerbosePasResolver}
@@ -1199,8 +1246,7 @@ begin
         {$Q+}
         Int:=TResEvalInt(LeftValue).Int - TResEvalInt(RightValue).Int;
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
       except
         on E: EOverflow do
           if (TResEvalInt(LeftValue).Int>0) and (TResEvalInt(RightValue).Int<0) then
@@ -1243,8 +1289,7 @@ begin
         {$Q+}
         Int:=TResEvalInt(LeftValue).Int * TResEvalInt(RightValue).Int;
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
       except
         on E: EOverflow do
           if (TResEvalInt(LeftValue).Int>0) and (TResEvalInt(RightValue).Int>0) then
@@ -1294,8 +1339,7 @@ begin
       else
         begin
         Int:=TResEvalInt(LeftValue).Int div TResEvalInt(RightValue).Int;
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
         end;
     revkUInt:
       // int div uint
@@ -1303,12 +1347,11 @@ begin
         RaiseDivByZero(20170530102745,Expr)
       else
         begin
-        if TResEvalUInt(RightValue).UInt>High(MaxPrecInt) then
+        if TResEvalUInt(RightValue).UInt>HighIntAsUInt then
           Int:=0
         else
           Int:=TResEvalInt(LeftValue).Int div TResEvalUInt(RightValue).UInt;
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
         end;
     else
       {$IFDEF VerbosePasResolver}
@@ -1322,11 +1365,10 @@ begin
       // uint div int
       if TResEvalInt(RightValue).Int=0 then
         RaiseDivByZero(20170530103026,Expr)
-      else if TResEvalUInt(LeftValue).UInt<=High(MaxPrecInt) then
+      else if TResEvalUInt(LeftValue).UInt<=HighIntAsUInt then
         begin
         Int:=MaxPrecInt(TResEvalUInt(LeftValue).UInt) div TResEvalInt(RightValue).Int;
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
         end
       else if TResEvalInt(RightValue).Int>0 then
         begin
@@ -1375,8 +1417,7 @@ begin
       else
         begin
         Int:=TResEvalInt(LeftValue).Int mod TResEvalInt(RightValue).Int;
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
         end;
     revkUInt:
       // int mod uint
@@ -1402,11 +1443,10 @@ begin
       // uint mod int
       if TResEvalInt(RightValue).Int=0 then
         RaiseDivByZero(20170530110110,Expr)
-      else if TResEvalUInt(LeftValue).UInt<=High(MaxPrecInt) then
+      else if TResEvalUInt(LeftValue).UInt<=HighIntAsUInt then
         begin
         Int:=MaxPrecInt(TResEvalUInt(LeftValue).UInt) mod TResEvalInt(RightValue).Int;
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
         end
       else if TResEvalInt(RightValue).Int>0 then
         begin
@@ -1459,8 +1499,7 @@ begin
         Int:=TResEvalInt(LeftValue).Int shl byte(TResEvalInt(RightValue).Int)
       else
         Int:=TResEvalInt(LeftValue).Int shr byte(TResEvalInt(RightValue).Int);
-      Result:=TResEvalInt.Create;
-      TResEvalInt(Result).Int:=Int;
+      Result:=TResEvalInt.CreateValue(Int);
       end;
     revkUInt:
       // int shl uint
@@ -1471,8 +1510,7 @@ begin
         Int:=TResEvalInt(LeftValue).Int shl byte(TResEvalUInt(RightValue).UInt)
       else
         Int:=TResEvalInt(LeftValue).Int shr byte(TResEvalUInt(RightValue).UInt);
-      Result:=TResEvalInt.Create;
-      TResEvalInt(Result).Int:=Int;
+      Result:=TResEvalInt.CreateValue(Int);
       end;
     else
       {$IFDEF VerbosePasResolver}
@@ -1627,7 +1665,7 @@ begin
       UInt:=TResEvalUInt(LeftValue).UInt;
       case RightValue.Kind of
       revkInt:
-        TResEvalBool(Result).B:=(UInt<=High(MaxPrecInt))
+        TResEvalBool(Result).B:=(UInt<=HighIntAsUInt)
                                and (MaxPrecInt(UInt)=TResEvalInt(RightValue).Int);
       revkUInt:
         TResEvalBool(Result).B:=UInt=TResEvalUInt(RightValue).UInt;
@@ -1840,8 +1878,7 @@ begin
         Int:=trunc(Math.power(TResEvalInt(LeftValue).Int,TResEvalInt(RightValue).Int));
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
         {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
       except
         RaiseOverflowArithmetic(20170530210533,Expr);
       end;
@@ -1852,8 +1889,7 @@ begin
         Int:=trunc(Math.power(TResEvalInt(LeftValue).Int,TResEvalUInt(RightValue).UInt));
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
         {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
       except
         RaiseOverflowArithmetic(20170530211028,Expr);
       end;
@@ -1872,8 +1908,7 @@ begin
         Int:=trunc(Math.power(TResEvalUInt(LeftValue).UInt,TResEvalInt(RightValue).Int));
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
         {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
       except
         RaiseOverflowArithmetic(20170530211102,Expr);
       end;
@@ -1884,8 +1919,7 @@ begin
         Int:=trunc(Math.power(TResEvalUInt(LeftValue).UInt,TResEvalUInt(RightValue).UInt));
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
         {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
-        Result:=TResEvalInt.Create;
-        TResEvalInt(Result).Int:=Int;
+        Result:=TResEvalInt.CreateValue(Int);
       except
         RaiseOverflowArithmetic(20170530211121,Expr);
       end;
@@ -1921,7 +1955,8 @@ begin
   {$IFDEF VerbosePasResEval}
   writeln('TResExprEvaluator.EvalFuncParams ');
   {$ENDIF}
-  if refConst in Flags then
+  Result:=OnEvalParams(Self,Expr,Flags);
+  if (refConst in Flags) and (Result=nil) then
     RaiseConstantExprExp(20170522173150,Expr);
 end;
 
@@ -1934,8 +1969,7 @@ begin
   {$ENDIF}
   if length(Expr.Params)=0 then
     begin
-    Result:=TResEvalValue.Create;
-    Result.Kind:=revkSetEmpty;
+    Result:=TResEvalValue.CreateKind(revkSetEmpty);
     exit;
     end;
   if refConst in Flags then
@@ -2147,16 +2181,10 @@ end;
 
 function TResExprEvaluator.CreateResEvalInt(UInt: MaxPrecUInt): TResEvalValue;
 begin
-  if UInt<=high(MaxPrecInt) then
-    begin
-    Result:=TResEvalInt.Create;
-    TResEvalInt(Result).Int:=MaxPrecInt(UInt);
-    end
+  if UInt<=HighIntAsUInt then
+    Result:=TResEvalInt.CreateValue(MaxPrecInt(UInt))
   else
-    begin
-    Result:=TResEvalUInt.Create;
-    TResEvalUInt(Result).UInt:=UInt;
-    end;
+    Result:=TResEvalUInt.CreateValue(UInt);
 end;
 
 function TResExprEvaluator.Eval(Expr: TPasExpr; Flags: TResEvalFlags
@@ -2196,24 +2224,21 @@ begin
         val(TPrimitiveExpr(Expr).Value,Int,Code);
         if Code=0 then
           begin
-          Result:=TResEvalInt.Create;
-          TResEvalInt(Result).Int:=Int;
+          Result:=TResEvalInt.CreateValue(Int);
           exit;
           end;
         // try MaxPrecUInt
         val(TPrimitiveExpr(Expr).Value,UInt,Code);
         if Code=0 then
           begin
-          Result:=TResEvalUInt.Create;
-          TResEvalUInt(Result).UInt:=UInt;
+          Result:=TResEvalUInt.CreateValue(UInt);
           exit;
           end;
         // try float
         val(TPrimitiveExpr(Expr).Value,Flo,Code);
         if Code=0 then
           begin
-          Result:=TResEvalFloat.Create;
-          TResEvalFloat(Result).FloatValue:=Flo;
+          Result:=TResEvalFloat.CreateValue(Flo);
           exit;
           end;
         RaiseRangeCheck(20170518202252,Expr);
@@ -2228,15 +2253,9 @@ begin
     end;
     end
   else if C=TNilExpr then
-    begin
-    Result:=TResEvalValue.Create;
-    Result.Kind:=revkNil;
-    end
+    Result:=TResEvalValue.CreateKind(revkNil)
   else if C=TBoolConstExpr then
-    begin
-    Result:=TResEvalBool.Create;
-    TResEvalBool(Result).B:=TBoolConstExpr(Expr).Value;
-    end
+    Result:=TResEvalBool.CreateValue(TBoolConstExpr(Expr).Value)
   else if C=TUnaryExpr then
     Result:=EvalUnaryExpr(TUnaryExpr(Expr),Flags)
   else if C=TBinaryExpr then
@@ -2327,7 +2346,7 @@ begin
           else if ExprValue.Kind=revkUInt then
             begin
             // uint in int..int
-            if (TResEvalUInt(ExprValue).UInt>MaxPrecUInt(High(MaxPrecInt)))
+            if (TResEvalUInt(ExprValue).UInt>HighIntAsUInt)
                 or (MaxPrecInt(TResEvalUInt(ExprValue).UInt)<RgInt.RangeStart)
                 or (MaxPrecInt(TResEvalUInt(ExprValue).UInt)>RgInt.RangeEnd) then
               begin
@@ -2483,6 +2502,12 @@ end;
 
 { TResEvalValue }
 
+constructor TResEvalValue.CreateKind(const aKind: TREVKind);
+begin
+  Create;
+  Kind:=aKind;
+end;
+
 function TResEvalValue.Clone: TResEvalValue;
 begin
   Result:=TResEvalValueClass(ClassType).Create;
@@ -2515,6 +2540,12 @@ begin
   Kind:=revkUInt;
 end;
 
+constructor TResEvalUInt.CreateValue(const aValue: MaxPrecUInt);
+begin
+  Create;
+  UInt:=aValue;
+end;
+
 function TResEvalUInt.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2534,6 +2565,12 @@ begin
   Kind:=revkInt;
 end;
 
+constructor TResEvalInt.CreateValue(const aValue: MaxPrecInt);
+begin
+  Create;
+  Int:=aValue;
+end;
+
 function TResEvalInt.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2553,6 +2590,12 @@ begin
   Kind:=revkFloat;
 end;
 
+constructor TResEvalFloat.CreateValue(const aValue: MaxPrecFloat);
+begin
+  Create;
+  FloatValue:=aValue;
+end;
+
 function TResEvalFloat.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2572,6 +2615,12 @@ begin
   Kind:=revkString;
 end;
 
+constructor TResEvalString.CreateValue(const aValue: RawByteString);
+begin
+  Create;
+  S:=aValue;
+end;
+
 function TResEvalString.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2591,6 +2640,12 @@ begin
   Kind:=revkUnicodeString;
 end;
 
+constructor TResEvalUTF16.CreateValue(const aValue: UnicodeString);
+begin
+  Create;
+  S:=aValue;
+end;
+
 function TResEvalUTF16.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2610,6 +2665,14 @@ begin
   Kind:=revkEnum;
 end;
 
+constructor TResEvalEnum.CreateValue(const aValue: integer;
+  aIdentEl: TPasEnumValue);
+begin
+  Create;
+  Index:=aValue;
+  IdentEl:=aIdentEl;
+end;
+
 function TResEvalEnum.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2635,6 +2698,15 @@ begin
   Kind:=revkRangeInt;
 end;
 
+constructor TResEvalRangeInt.CreateValue(const aElKind: TRgIntElKind;
+  const aRangeStart, aRangeEnd: MaxPrecInt);
+begin
+  Create;
+  ElKind:=aElKind;
+  RangeStart:=aRangeStart;
+  RangeEnd:=aRangeEnd;
+end;
+
 function TResEvalRangeInt.Clone: TResEvalValue;
 begin
   Result:=inherited Clone;
@@ -2648,7 +2720,7 @@ begin
   Result:=ElementAsString(RangeStart)+'..'+ElementAsString(RangeEnd);
 end;
 
-function TResEvalRangeInt.ElementAsString(El: int64): string;
+function TResEvalRangeInt.ElementAsString(El: MaxPrecInt): string;
 begin
   case ElKind of
     revrikBool: if El=0 then Result:='false' else Result:='true';
@@ -2698,7 +2770,7 @@ begin
   Result:=Result+']';
 end;
 
-function TResEvalSetInt.ElementAsString(El: int64): string;
+function TResEvalSetInt.ElementAsString(El: MaxPrecInt): string;
 begin
   case ElKind of
     revsikEnum: Result:=TPasEnumValue(TPasEnumType(IdentEl).Values[El]).Name;

+ 272 - 22
packages/fcl-passrc/src/pasresolver.pp

@@ -1088,9 +1088,11 @@ type
     fExprEvaluator: TResExprEvaluator;
     procedure OnExprEvalLog(Sender: TResExprEvaluator; const id: int64;
       MsgType: TMessageType; MsgNumber: integer; const Fmt: String;
-      Args: array of const; PosEl: TPasElement);
+      Args: array of const; PosEl: TPasElement); virtual;
     function OnExprEvalIdentifier(Sender: TResExprEvaluator;
-      Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue;
+      Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
+    function OnExprEvalParams(Sender: TResExprEvaluator;
+      Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
     function Eval(Expr: TPasExpr; Flags: TResEvalFlags; Store: boolean = true): TResEvalValue;
   protected
     // custom types (added by descendant resolvers)
@@ -1142,10 +1144,14 @@ type
       Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
     procedure BI_LowHigh_OnGetCallResult(Proc: TResElDataBuiltInProc;
       {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
+    procedure BI_LowHigh_OnEval(Proc: TResElDataBuiltInProc;
+      Params: TParamsExpr; out Evaluated: TResEvalValue); virtual;
     function BI_PredSucc_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
       Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
     procedure BI_PredSucc_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
       {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
+    procedure BI_PredSucc_OnEval(Proc: TResElDataBuiltInProc;
+      Params: TParamsExpr; out Evaluated: TResEvalValue); virtual;
     function BI_Str_CheckParam(IsFunc: boolean; Param: TPasExpr;
       const ParamResolved: TPasResolverResult; ArgNo: integer;
       RaiseOnError: boolean): integer;
@@ -7377,26 +7383,11 @@ begin
             TResEvalRangeInt(Result).RangeEnd:=$ffff;
           end;
         btAnsiChar:
-          begin
-          Result:=TResEvalRangeInt.Create;
-          TResEvalRangeInt(Result).ElKind:=revrikChar;
-          TResEvalRangeInt(Result).RangeStart:=0;
-          TResEvalRangeInt(Result).RangeEnd:=$ff
-          end;
+          Result:=TResEvalRangeInt.CreateValue(revrikChar,0,$ff);
         btWideChar:
-          begin
-          Result:=TResEvalRangeInt.Create;
-          TResEvalRangeInt(Result).ElKind:=revrikChar;
-          TResEvalRangeInt(Result).RangeStart:=0;
-          TResEvalRangeInt(Result).RangeEnd:=$ffff;
-          end;
+          Result:=TResEvalRangeInt.CreateValue(revrikChar,0,$ffff);
         btBoolean,btByteBool,btWordBool,btQWordBool:
-          begin
-          Result:=TResEvalRangeInt.Create;
-          TResEvalRangeInt(Result).ElKind:=revrikBool;
-          TResEvalRangeInt(Result).RangeStart:=0;
-          TResEvalRangeInt(Result).RangeEnd:=1;
-          end;
+          Result:=TResEvalRangeInt.CreateValue(revrikBool,0,1);
         btByte,
         btShortInt,
         btWord,
@@ -7423,6 +7414,41 @@ begin
     RaiseConstantExprExp(20170518213616,Expr);
 end;
 
+function TPasResolver.OnExprEvalParams(Sender: TResExprEvaluator;
+  Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
+var
+  Ref: TResolvedReference;
+  Decl: TPasElement;
+  C: TClass;
+  BuiltInProc: TResElDataBuiltInProc;
+begin
+  Result:=nil;
+  if Params.Value.CustomData is TResolvedReference then
+    begin
+    Ref:=TResolvedReference(Params.Value.CustomData);
+    Decl:=Ref.Declaration;
+    if Decl is TPasType then
+      Decl:=ResolveAliasType(TPasType(Decl));
+    C:=Decl.ClassType;
+
+    if C=TPasUnresolvedSymbolRef then
+      begin
+      if Decl.CustomData is TResElDataBuiltInProc then
+        begin
+        BuiltInProc:=TResElDataBuiltInProc(Decl.CustomData);
+        {$IFDEF VerbosePas2JS}
+        writeln('TPasResolver.OnExprEvalParams BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
+        {$ENDIF}
+        case BuiltInProc.BuiltIn of
+          bfLength: BI_Length_OnEval(BuiltInProc,Params,Result);
+          bfLow,bfHigh: BI_LowHigh_OnEval(BuiltInProc,Params,Result);
+        end;
+        end;
+      end;
+    end;
+  if Flags=[] then ;
+end;
+
 function TPasResolver.Eval(Expr: TPasExpr; Flags: TResEvalFlags;
   Store: boolean): TResEvalValue;
 // Important: Caller must free result if (Result<>nil) and (Result.Element=nil)
@@ -7983,6 +8009,223 @@ begin
   ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable]+[rrfReadable];
 end;
 
+procedure TPasResolver.BI_LowHigh_OnEval(Proc: TResElDataBuiltInProc;
+  Params: TParamsExpr; out Evaluated: TResEvalValue);
+var
+  Param: TPasExpr;
+  ResolvedEl: TPasResolverResult;
+
+  procedure EvalRange(RangeExpr: TPasExpr);
+  var
+    Range: TResEvalValue;
+    EnumType: TPasEnumType;
+  begin
+    Range:=Eval(RangeExpr,[refConst]);
+    if Range=nil then
+      RaiseNotYetImplemented(20170601191258,RangeExpr);
+    case Range.Kind of
+    revkRangeInt:
+      case TResEvalRangeInt(Range).ElKind of
+        revrikBool:
+          if Proc.BuiltIn=bfLow then
+            Evaluated:=TResEvalBool.CreateValue(low(Boolean))
+          else
+            Evaluated:=TResEvalBool.CreateValue(high(Boolean));
+        revrikEnum:
+          begin
+          EnumType:=TResEvalRangeInt(Range).IdentEl as TPasEnumType;
+          if Proc.BuiltIn=bfLow then
+            Evaluated:=TResEvalEnum.CreateValue(
+              TResEvalRangeInt(Range).RangeStart,TPasEnumValue(EnumType.Values[0]))
+          else
+            Evaluated:=TResEvalEnum.CreateValue(
+              TResEvalRangeInt(Range).RangeEnd,
+              TPasEnumValue(EnumType.Values[EnumType.Values.Count-1]));
+          end;
+        revrikInt:
+          if Proc.BuiltIn=bfLow then
+            Evaluated:=TResEvalInt.CreateValue(TResEvalRangeInt(Range).RangeStart)
+          else
+            Evaluated:=TResEvalInt.CreateValue(TResEvalRangeInt(Range).RangeEnd);
+        revrikChar:
+          if Proc.BuiltIn=bfLow then
+            Evaluated:=TResEvalString.CreateValue(chr(TResEvalRangeInt(Range).RangeStart))
+          else if TResEvalRangeInt(Range).RangeEnd<256 then
+            Evaluated:=TResEvalString.CreateValue(chr(TResEvalRangeInt(Range).RangeEnd))
+          else
+            Evaluated:=TResEvalUTF16.CreateValue(widechar(TResEvalRangeInt(Range).RangeEnd));
+      else
+        RaiseNotYetImplemented(20170601195240,Param);
+      end;
+    revkRangeUInt:
+      if Proc.BuiltIn=bfLow then
+        Evaluated:=TResEvalUInt.CreateValue(TResEvalRangeUInt(Range).RangeStart)
+      else
+        Evaluated:=TResEvalUInt.CreateValue(TResEvalRangeUInt(Range).RangeEnd);
+    else
+      RaiseNotYetImplemented(20170601195336,Params);
+    end;
+  end;
+
+var
+  TypeEl: TPasType;
+  ArrayEl: TPasArrayType;
+  Value: TResEvalValue;
+  EnumType: TPasEnumType;
+  aSet: TResEvalSetInt;
+  Int: MaxPrecInt;
+  bt: TResolverBaseType;
+  MinInt, MaxInt: int64;
+begin
+  Evaluated:=nil;
+  Param:=Params.Params[0];
+  ComputeElement(Param,ResolvedEl,[]);
+  TypeEl:=ResolvedEl.TypeEl;
+  if ResolvedEl.BaseType=btContext then
+    begin
+    if TypeEl.ClassType=TPasArrayType then
+      begin
+      // array: result is first dimension
+      ArrayEl:=TPasArrayType(TypeEl);
+      if length(ArrayEl.Ranges)=0 then
+        begin
+        // dyn or open array
+        if Proc.BuiltIn=bfLow then
+          Evaluated:=TResEvalInt.CreateValue(0)
+        else if (ResolvedEl.IdentEl is TPasVariable)
+            and (TPasVariable(ResolvedEl.IdentEl).Expr is TPasExpr) then
+          begin
+          RaiseNotYetImplemented(20170601191003,Params);
+          end
+        else
+          exit;
+        end
+      else
+        begin
+        // static array
+        EvalRange(ArrayEl.Ranges[0]);
+        end;
+      end
+    else if TypeEl.ClassType=TPasSetType then
+      begin
+      TypeEl:=TPasSetType(TypeEl).EnumType;
+      if TypeEl.ClassType=TPasEnumType then
+        begin
+        EnumType:=TPasEnumType(TPasSetType(TypeEl).EnumType);
+        if Proc.BuiltIn=bfLow then
+          Evaluated:=TResEvalEnum.CreateValue(0,TPasEnumValue(EnumType.Values[0]))
+        else
+          Evaluated:=TResEvalEnum.CreateValue(EnumType.Values.Count-1,
+            TPasEnumValue(EnumType.Values[EnumType.Values.Count-1]));
+        end
+      else
+        begin
+        {$IFDEF VerbosePasResolver}
+        writeln('TPasResolver.BI_LowHigh_OnEval ',GetResolverResultDbg(ResolvedEl),' TypeEl=',TypeEl.ClassName);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170601203026,Params);
+        end;
+      end;
+    end
+  else if ResolvedEl.BaseType=btSet then
+    begin
+    Value:=Eval(Param,[refAutoConst]);
+    if Value=nil then exit;
+    case Value.Kind of
+    revkSetOfInt:
+      begin
+      aSet:=TResEvalSetInt(Value);
+      if length(aSet.Ranges)=0 then
+        RaiseXExpectedButYFound(20170601201637,'ordinal value',Value.AsString,Param);
+      if Proc.BuiltIn=bfLow then
+        Int:=aSet.Ranges[0].RangeStart
+      else
+        Int:=aSet.Ranges[length(aSet.Ranges)-1].RangeEnd;
+      case aSet.ElKind of
+        revsikEnum:
+          begin
+          EnumType:=aSet.IdentEl as TPasEnumType;
+          Evaluated:=TResEvalEnum.CreateValue(Int,TPasEnumValue(EnumType.Values[Int]));
+          end;
+        revsikInt:
+          Evaluated:=TResEvalInt.CreateValue(Int);
+        revsikChar:
+          if Int<256 then
+            Evaluated:=TResEvalString.CreateValue(chr(Int))
+          else
+            Evaluated:=TResEvalUTF16.CreateValue(widechar(Int));
+        revsikWChar:
+          Evaluated:=TResEvalUTF16.CreateValue(widechar(Int));
+      end;
+      end;
+    else
+      RaiseXExpectedButYFound(20170601201237,'ordinal value',Value.AsString,Param);
+    end;
+    end
+  else if (TypeEl is TPasUnresolvedSymbolRef)
+      and (TypeEl.CustomData is TResElDataBaseType) then
+    begin
+    // low,high(base type)
+    bt:=TResElDataBaseType(TypeEl.CustomData).BaseType;
+    bt:=GetActualBaseType(bt);
+    if bt in btAllBooleans then
+      Evaluated:=TResEvalBool.CreateValue(Proc.BuiltIn=bfHigh)
+    else if bt=btQWord then
+      begin
+      if Proc.BuiltIn=bfLow then
+        Evaluated:=TResEvalInt.CreateValue(0)
+      else
+        Evaluated:=TResEvalUInt.CreateValue(High(QWord));
+      end
+    else if (bt in (btAllInteger-[btQWord])) and GetIntegerRange(bt,MinInt,MaxInt) then
+      begin
+      if Proc.BuiltIn=bfLow then
+        Evaluated:=TResEvalInt.CreateValue(MinInt)
+      else
+        Evaluated:=TResEvalInt.CreateValue(MaxInt);
+      end
+    else if bt in [btChar,btAnsiChar] then
+      begin
+      if Proc.BuiltIn=bfLow then
+        Evaluated:=TResEvalString.CreateValue(#0)
+      else
+        Evaluated:=TResEvalString.CreateValue(#255);
+      end
+    else if bt=btWideChar then
+      begin
+      if Proc.BuiltIn=bfLow then
+        Evaluated:=TResEvalUTF16.CreateValue(#0)
+      else
+        Evaluated:=TResEvalUTF16.CreateValue(#$ffff);
+      end
+    else
+      begin
+      {$IFDEF VerbosePasResolver}
+      writeln('TPasResolver.BI_LowHigh_OnEval ',GetResolverResultDbg(ResolvedEl));
+      {$ENDIF}
+      RaiseNotYetImplemented(20170602070738,Params);
+      end;
+    end
+  else if ResolvedEl.TypeEl is TPasRangeType then
+    begin
+    // e.g. type t = 2..10;
+    EvalRange(TPasRangeType(TypeEl).RangeExpr);
+    end
+  else
+    begin
+    {$IFDEF VerbosePasResolver}
+    writeln('TPasResolver.BI_LowHigh_OnEval ',GetResolverResultDbg(ResolvedEl));
+    {$ENDIF}
+    RaiseNotYetImplemented(20170601202353,Params);
+    end;
+  {$IFDEF VerbosePasResEval}
+  if Evaluated=nil then
+    writeln('TPasResolver.BI_LowHigh_OnEval ResolvedEl=',GetResolverResultDbg(ResolvedEl),' Evaluated NO SET')
+  else
+    writeln('TPasResolver.BI_LowHigh_OnEval ResolvedEl=',GetResolverResultDbg(ResolvedEl),' Evaluated=',Evaluated.AsDebugString);
+  {$ENDIF}
+end;
+
 function TPasResolver.BI_PredSucc_OnGetCallCompatibility(
   Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
 // check params of built in proc 'Pred' or 'Succ'
@@ -8014,6 +8257,12 @@ begin
   ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable];
 end;
 
+procedure TPasResolver.BI_PredSucc_OnEval(Proc: TResElDataBuiltInProc;
+  Params: TParamsExpr; out Evaluated: TResEvalValue);
+begin
+
+end;
+
 function TPasResolver.BI_Str_CheckParam(IsFunc: boolean; Param: TPasExpr;
   const ParamResolved: TPasResolverResult; ArgNo: integer; RaiseOnError: boolean
   ): integer;
@@ -8450,6 +8699,7 @@ begin
   fExprEvaluator:=TResExprEvaluator.Create;
   fExprEvaluator.OnLog:=@OnExprEvalLog;
   fExprEvaluator.OnEvalIdentifier:=@OnExprEvalIdentifier;
+  fExprEvaluator.OnEvalParams:=@OnExprEvalParams;
   PushScope(FDefaultScope);
 end;
 
@@ -9199,11 +9449,11 @@ begin
   if bfLow in TheBaseProcs then
     AddBuiltInProc('Low','function Low(const array or ordinal): ordinal or integer',
         @BI_LowHigh_OnGetCallCompatibility,@BI_LowHigh_OnGetCallResult,
-        nil,nil,bfLow);
+        @BI_LowHigh_OnEval,nil,bfLow);
   if bfHigh in TheBaseProcs then
     AddBuiltInProc('High','function High(const array or ordinal): ordinal or integer',
         @BI_LowHigh_OnGetCallCompatibility,@BI_LowHigh_OnGetCallResult,
-        nil,nil,bfHigh);
+        @BI_LowHigh_OnEval,nil,bfHigh);
   if bfPred in TheBaseProcs then
     AddBuiltInProc('Pred','function Pred(const ordinal): ordinal',
         @BI_PredSucc_OnGetCallCompatibility,@BI_PredSucc_OnGetCallResult,

+ 1 - 1
packages/fcl-passrc/src/pastree.pp

@@ -603,7 +603,7 @@ type
     procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
       const Arg: Pointer); override;
   public
-    Values: TFPList;      // List of TPasEnumValue objects
+    Values: TFPList;      // List of TPasEnumValue
   end;
 
   { TPasSetType }

+ 37 - 5
packages/fcl-passrc/tests/tcresolver.pas

@@ -186,6 +186,7 @@ type
     Procedure TestVarNoSemicolonBeginFail;
     Procedure TestIntegerRange;
     Procedure TestIntegerRangeHighLowerLowFail;
+    Procedure TestIntegerRangeLowHigh;
     Procedure TestAssignIntRangeFail;
     Procedure TestByteRangeFail;
     Procedure TestCustomIntRangeFail;
@@ -2034,6 +2035,7 @@ begin
   Add('  c1 = 3');
   Add('  c2: longint=c1;'); // defined in system.pp
   Add('begin');
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestDuplicateVar;
@@ -2052,6 +2054,7 @@ begin
   Add('var a: longint = {@c}c;');
   Add('begin');
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestVarOfVarFail;
@@ -2154,6 +2157,21 @@ begin
   {$ENDIF}
 end;
 
+procedure TTestResolver.TestIntegerRangeLowHigh;
+begin
+  StartProgram(false);
+  Add([
+  'const',
+  '  MinInt = -1;',
+  '  MaxInt = +10;',
+  'type',
+  '  {#TMyInt}TMyInt = MinInt..MaxInt;',
+  'const a = low(TMyInt)+High(TMyInt);',
+  'begin']);
+  ParseProgram;
+  CheckResolverUnexpectedHints;
+end;
+
 procedure TTestResolver.TestAssignIntRangeFail;
 begin
   StartProgram(false);
@@ -2202,6 +2220,8 @@ procedure TTestResolver.TestConstIntOperators;
 begin
   StartProgram(false);
   Add([
+  'type',
+  '  integer = longint;',
   'const',
   '  a:byte=1+2;',
   '  b:shortint=1-2;',
@@ -2219,9 +2239,12 @@ begin
   '  n:longword=5 and 2;',
   '  o:longword=5 or 2;',
   '  p:longword=5 xor 2;',
-  '  q:longword=5 or not 2;',
+  '  q:longword=not (5 or not 2);',
+  '  r=low(word)+high(int64);',
+  '  s=low(longint)+high(integer);',
   'begin']);
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestConstBoolOperators;
@@ -2235,8 +2258,11 @@ begin
   '  d=not b;',
   '  e=a=b;',
   '  f=a<>b;',
+  '  g=low(boolean) or high(boolean);',
+  '  h=succ(false) or pred(true);',
   'begin']);
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestChar_Ord;
@@ -2352,6 +2378,7 @@ begin
   '  a=''o''+''x'';',
   'begin']);
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestEnums;
@@ -2665,6 +2692,7 @@ begin
   '  s:=teAny+teRedBlue+[e];',
   '']);
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestSet_AnonymousEnumtype;
@@ -2720,17 +2748,18 @@ end;
 
 procedure TTestResolver.TestSet_Const;
 begin
-  exit; // ToDo
-
   StartProgram(false);
   Add([
   'type',
   '  TFlag = (a,b,c,d,e,f);',
   'const',
-  '  all = b..d;',
-  '  all = low(TFlag)..high(TFlag);',
+  '  ab = [a..b];',
+  //'  notc = [a..b,d..e,f];',
+  //'  all = [low(TFlag)..high(TFlag)];',
+  //'  notaf = [succ(low(TFlag))..pred(high(TFlag))];',
   'begin']);
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestPrgAssignment;
@@ -6799,6 +6828,7 @@ begin
   Add('  with TObject do if ci=25 then;');
   Add('  with Cla do if ci=26 then;');
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestClass_PublishedClassVarFail;
@@ -8356,6 +8386,7 @@ begin
   'begin',
   '']);
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestArray_AssignNilToStaticArrayFail1;
@@ -8567,6 +8598,7 @@ begin
   Add('end;');
   Add('begin');
   ParseProgram;
+  CheckResolverUnexpectedHints;
 end;
 
 procedure TTestResolver.TestArray_ConstOpenArrayWriteFail;