Browse Source

resolver: const evaluation: ranges, int+int

git-svn-id: trunk@36318 -
Mattias Gaertner 8 years ago
parent
commit
dd48453c57

+ 1 - 0
.gitattributes

@@ -2575,6 +2575,7 @@ packages/fcl-passrc/examples/parsepp.pp svneol=native#text/plain
 packages/fcl-passrc/examples/test_parser.pp svneol=native#text/plain
 packages/fcl-passrc/examples/test_parser.pp svneol=native#text/plain
 packages/fcl-passrc/examples/testunit1.pp svneol=native#text/plain
 packages/fcl-passrc/examples/testunit1.pp svneol=native#text/plain
 packages/fcl-passrc/fpmake.pp svneol=native#text/plain
 packages/fcl-passrc/fpmake.pp svneol=native#text/plain
+packages/fcl-passrc/src/pasresolveeval.pas svneol=native#text/plain
 packages/fcl-passrc/src/pasresolver.pp svneol=native#text/plain
 packages/fcl-passrc/src/pasresolver.pp svneol=native#text/plain
 packages/fcl-passrc/src/passrcutil.pp svneol=native#text/plain
 packages/fcl-passrc/src/passrcutil.pp svneol=native#text/plain
 packages/fcl-passrc/src/pastounittest.pp svneol=native#text/plain
 packages/fcl-passrc/src/pastounittest.pp svneol=native#text/plain

+ 1765 - 0
packages/fcl-passrc/src/pasresolveeval.pas

@@ -0,0 +1,1765 @@
+unit PasResolveEval;
+
+{$mode objfpc}{$H+}
+
+{$IFOPT Q+}{$DEFINE OverflowCheckOn}{$ENDIF}
+
+interface
+
+uses
+  PasTree, PScanner, sysutils;
+
+// message numbers
+const
+  nIdentifierNotFound = 3001;
+  nNotYetImplemented = 3002;
+  nIllegalQualifier = 3003;
+  nSyntaxErrorExpectedButFound = 3004;
+  nWrongNumberOfParametersForCallTo = 3005;
+  nIncompatibleTypeArgNo = 3006;
+  nIncompatibleTypeArgNoVarParamMustMatchExactly = 3007;
+  nVariableIdentifierExpected = 3008;
+  nDuplicateIdentifier = 3009;
+  nXExpectedButYFound = 3010;
+  nAncestorCycleDetected = 3011;
+  nCantUseForwardDeclarationAsAncestor = 3012;
+  nCantDetermineWhichOverloadedFunctionToCall = 3013;
+  nForwardTypeNotResolved = 3014;
+  nForwardProcNotResolved = 3015;
+  nInvalidXModifierY = 3016;
+  nAbstractMethodsMustNotHaveImplementation = 3017;
+  nCallingConventionMismatch = 3018;
+  nResultTypeMismatchExpectedButFound = 3019;
+  nFunctionHeaderMismatchForwardVarName = 3020;
+  nFunctionHidesIdentifier = 3021;
+  nNoMethodInAncestorToOverride = 3022;
+  nInheritedOnlyWorksInMethods = 3023;
+  nInheritedNeedsAncestor = 3024;
+  nNoPropertyFoundToOverride = 3025;
+  nExprTypeMustBeClassOrRecordTypeGot = 3026;
+  nPropertyNotWritable = 3027;
+  nIncompatibleTypesGotExpected = 3028;
+  nTypesAreNotRelated = 3029;
+  nAbstractMethodsCannotBeCalledDirectly = 3030;
+  nMissingParameterX = 3031;
+  nCannotAccessThisMemberFromAX = 3032;
+  nInOperatorExpectsSetElementButGot = 3033;
+  nWrongNumberOfParametersForTypeCast = 3034;
+  nIllegalTypeConversionTo = 3035;
+  nConstantExpressionExpected = 3036;
+  nLeftSideOfIsOperatorExpectsAClassButGot = 3037;
+  nNotReadable = 3038;
+  nClassPropertyAccessorMustBeStatic = 3039;
+  nClassPropertyAccessorMustNotBeStatic = 3040;
+  nOnlyOneDefaultPropertyIsAllowed = 3041;
+  nWrongNumberOfParametersForArray = 3042;
+  nCantAssignValuesToAnAddress = 3043;
+  nIllegalExpression = 3044;
+  nCantAccessPrivateMember = 3045;
+  nMustBeInsideALoop = 3046;
+  nExpectXArrayElementsButFoundY = 3047;
+  nCannotCreateADescendantOfTheSealedClass = 3048;
+  nAncestorIsNotExternal = 3049;
+  nVirtualMethodXHasLowerVisibility = 3050; // FPC 3250
+  nExternalClassInstanceCannotAccessStaticX = 3051;
+  nXModifierMismatchY = 3052;
+  nSymbolCannotBePublished = 3053;
+  nCannotTypecastAType = 3054;
+  nTypeIdentifierExpected = 3055;
+  nCannotNestAnonymousX = 3056;
+  nFoundCallCandidateX = 3057;
+  nSymbolXIsNotPortable = 3058;
+  nSymbolXIsExperimental = 3059;
+  nSymbolXIsNotImplemented = 3060;
+  nSymbolXBelongsToALibrary = 3061;
+  nSymbolXIsDeprecated = 3062;
+  nSymbolXIsDeprecatedY = 3063;
+  nRangeCheckError = 3064;
+  nHighRangeLimitLTLowRangeLimit = 3065;
+  nRangeCheckEvaluatingConstantsVMinMax = 3066;
+  nIllegalChar = 3067;
+  nOverflowInArithmeticOperation = 3068;
+
+// resourcestring patterns of messages
+resourcestring
+  sIdentifierNotFound = 'identifier not found "%s"';
+  sNotYetImplemented = 'not yet implemented: %s';
+  sIllegalQualifier = 'illegal qualifier "%s"';
+  sSyntaxErrorExpectedButFound = 'Syntax error, "%s" expected but "%s" found';
+  sWrongNumberOfParametersForCallTo = 'Wrong number of parameters specified for call to "%s"';
+  sIncompatibleTypeArgNo = 'Incompatible type arg no. %s: Got "%s", expected "%s"';
+  sIncompatibleTypeArgNoVarParamMustMatchExactly = 'Incompatible type arg no. %s: Got "%s", expected "%s". Var param must match exactly.';
+  sVariableIdentifierExpected = 'Variable identifier expected';
+  sDuplicateIdentifier = 'Duplicate identifier "%s" at %s';
+  sXExpectedButYFound = '%s expected, but %s found';
+  sAncestorCycleDetected = 'Ancestor cycle detected';
+  sCantUseForwardDeclarationAsAncestor = 'Can''t use forward declaration "%s" as ancestor';
+  sCantDetermineWhichOverloadedFunctionToCall = 'Can''t determine which overloaded function to call';
+  sForwardTypeNotResolved = 'Forward type not resolved "%s"';
+  sForwardProcNotResolved = 'Forward %s not resolved "%s"';
+  sInvalidXModifierY = 'Invalid %s modifier %s';
+  sAbstractMethodsMustNotHaveImplementation = 'Abstract method must not have an implementation.';
+  sCallingConventionMismatch = 'Calling convention mismatch';
+  sResultTypeMismatchExpectedButFound = 'Result type mismatch, expected %s, but found %s';
+  sFunctionHeaderMismatchForwardVarName = 'function header "%s" doesn''t match forward : var name changes %s => %s';
+  sFunctionHidesIdentifier = 'function hides identifier "%s" at "%s"';
+  sNoMethodInAncestorToOverride = 'There is no method in an ancestor class to be overridden "%s"';
+  sInheritedOnlyWorksInMethods = 'Inherited works only in methods';
+  sInheritedNeedsAncestor = 'inherited needs an ancestor';
+  sNoPropertyFoundToOverride = 'No property found to override';
+  sExprTypeMustBeClassOrRecordTypeGot = 'Expression type must be class or record type, got %s';
+  sPropertyNotWritable = 'No member is provided to access property';
+  sIncompatibleTypesGotExpected = 'Incompatible types: got "%s" expected "%s"';
+  sTypesAreNotRelated = 'Types are not related';
+  sAbstractMethodsCannotBeCalledDirectly = 'Abstract methods cannot be called directly';
+  sMissingParameterX = 'Missing parameter %s';
+  sCannotAccessThisMemberFromAX = 'Cannot access this member from a %s';
+  sInOperatorExpectsSetElementButGot = 'the in-operator expects a set element, but got %s';
+  sWrongNumberOfParametersForTypeCast = 'wrong number of parameters for type cast to %s';
+  sIllegalTypeConversionTo = 'Illegal type conversion: "%s" to "%s"';
+  sConstantExpressionExpected = 'Constant expression expected';
+  sLeftSideOfIsOperatorExpectsAClassButGot = 'left side of is-operator expects a class, but got %s';
+  sNotReadable = 'not readable';
+  sClassPropertyAccessorMustBeStatic = 'class property accessor must be static';
+  sClassPropertyAccessorMustNotBeStatic = 'class property accessor must not be static';
+  sOnlyOneDefaultPropertyIsAllowed = 'Only one default property is allowed';
+  sWrongNumberOfParametersForArray = 'Wrong number of parameters for array';
+  sCantAssignValuesToAnAddress = 'Can''t assign values to an address';
+  sIllegalExpression = 'Illegal expression';
+  sCantAccessPrivateMember = 'Can''t access %s member %s';
+  sMustBeInsideALoop = '%s must be inside a loop';
+  sExpectXArrayElementsButFoundY = 'Expect %s array elements, but found %s';
+  sCannotCreateADescendantOfTheSealedClass = 'Cannot create a descendant of the sealed class "%s"';
+  sAncestorIsNotExternal = 'Ancestor "%s" is not external';
+  sVirtualMethodXHasLowerVisibility = 'Virtual method "%s" has a lower visibility (%s) than parent class %s (%s)';
+  sExternalClassInstanceCannotAccessStaticX = 'External class instance cannot access static %s';
+  sXModifierMismatchY = '%s modifier "%s" mismatch';
+  sSymbolCannotBePublished = 'Symbol cannot be published';
+  sCannotTypecastAType = 'Cannot type cast a type';
+  sTypeIdentifierExpected = 'Type identifier expected';
+  sCannotNestAnonymousX = 'Cannot nest anonymous %s';
+  sFoundCallCandidateX = 'Found call candidate %s';
+  sSymbolXIsNotPortable = 'Symbol "%s" is not portable';
+  sSymbolXIsExperimental = 'Symbol "%s" is experimental';
+  sSymbolXIsNotImplemented = 'Symbol "%s" is implemented';
+  sSymbolXBelongsToALibrary = 'Symbol "%s" belongs to a library';
+  sSymbolXIsDeprecated = 'Symbol "%s" is deprecated';
+  sSymbolXIsDeprecatedY = 'Symbol "%s" is deprecated: %s';
+  sRangeCheckError = 'Range check error';
+  sHighRangeLimitLTLowRangeLimit = 'High range limit < low range limit';
+  sRangeCheckEvaluatingConstantsVMinMax = 'range check error while evaluating constants (%s must be between %s and %s)';
+  sIllegalChar = 'Illegal character';
+  sOverflowInArithmeticOperation = 'Overflow in arithmetic operation';
+
+type
+  { TResolveData - base class for data stored in TPasElement.CustomData }
+
+  TResolveData = Class(TPasElementBase)
+  private
+    FElement: TPasElement;
+    procedure SetElement(AValue: TPasElement);
+  public
+    Owner: TObject; // e.g. a TPasResolver
+    Next: TResolveData; // TPasResolver uses this for its memory chain
+    constructor Create; virtual;
+    destructor Destroy; override;
+    property Element: TPasElement read FElement write SetElement;// Element.CustomData=Self
+  end;
+  TResolveDataClass = class of TResolveData;
+
+type
+  { TResEvalValue }
+
+  TREVKind = (
+    revkNone,
+    revkCustom,
+    revkNil,  // TResEvalValue
+    revkBool, // TResEvalInt
+    revkInt,  // TResEvalInt
+    revkUInt, // TResEvalUInt
+    revkFloat, // TResEvalFloat
+    revkString, // TResEvalString
+    revkUnicodeString, // TResEvalUTF16
+    revkEnum,     // TResEvalEnum
+    revkRangeInt, // range of enum, int, char, widechar, e.g. 1..2
+    revkRangeUInt, // range of uint, e.g. 1..2
+    revkSetEmpty, // []
+    revkSetOfInt  // set of enum, int, char, widechar, e.g. [1,2..3]
+    );
+  TResEvalValue = class(TResolveData)
+  public
+    Kind: TREVKind;
+    IdentEl: TPasElement;
+    function Clone: TResEvalValue; virtual;
+    function AsDebugString: string; virtual;
+    function AsString: string; virtual;
+  end;
+  TResEvalValueClass = class of TResEvalValue;
+
+  { TResEvalInt }
+
+  TResEvalInt = class(TResEvalValue)
+  public
+    Int: NativeInt;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalUInt }
+
+  TResEvalUInt = class(TResEvalValue)
+  public
+    UInt: NativeUInt;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalFloat }
+
+  TResEvalFloat = class(TResEvalValue)
+  public
+    FloatValue: extended;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalString - Kind=revkString }
+
+  TResEvalString = class(TResEvalValue)
+  public
+    S: RawByteString;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalUTF16 - Kind=revkUnicodeString }
+
+  TResEvalUTF16 = class(TResEvalValue)
+  public
+    S: UnicodeString;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalEnum - Kind=revkEnum, Value.Int, IdentEl is TPasEnumValue }
+
+  TResEvalEnum = class(TResEvalValue)
+  public
+    Index: integer;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsDebugString: string; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalRangeInt - Kind=revkRangeInt }
+
+  TResEvalRangeInt = class(TResEvalValue)
+  public
+    type
+      TRgIntElKind = (
+        revrikBool,
+        revrikEnum, // IdentEl is TPasEnumType
+        revrikInt,
+        revrikChar
+        );
+  public
+    ElKind: TRgIntElKind;
+    RangeStart, RangeEnd: int64;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+    function ElementAsString(El: int64): string;
+  end;
+
+  { TResEvalRangeUInt }
+
+  TResEvalRangeUInt = class(TResEvalValue)
+  public
+    RangeStart, RangeEnd: qword;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalSetInt - Kind=revkASet }
+
+  TResEvalSetInt = class(TResEvalValue)
+  public
+    type
+      TSetElKind = (
+        revsikEnum, // IdentEl is TPasEnumType
+        revsikInt,
+        revsikChar,
+        revsikWChar
+        );
+      TItem = record
+        RangeStart, RangeEnd: int64;
+      end;
+      TItems = array of TItem;
+  public
+    ElKind: TSetElKind;
+    Ranges: TItems;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+    function ElementAsString(El: int64): string;
+  end;
+
+  TResEvalFlag = (
+    refConst, // computing a const, error if a value is not const
+    refAutoConst, // set refConst if in a const
+    refSet  // computing a set, allow ranges
+    );
+  TResEvalFlags = set of TResEvalFlag;
+
+  TResExprEvaluator = class;
+
+  TPasResEvalLogHandler = procedure(Sender: TResExprEvaluator; const id: int64;
+    MsgType: TMessageType; MsgNumber: integer;
+    const Fmt: String; Args: Array of const; PosEl: TPasElement) of object;
+  TPasResEvalIdentHandler = function(Sender: TResExprEvaluator;
+    Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue of object;
+
+  { TResExprEvaluator }
+
+  TResExprEvaluator = class
+  private
+    FOnEvalIdentifier: TPasResEvalIdentHandler;
+    FOnLog: TPasResEvalLogHandler;
+  protected
+    procedure LogMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
+      const Fmt: String; Args: Array of const; PosEl: TPasElement); overload;
+    procedure RaiseMsg(const Id: int64; MsgNumber: integer; const Fmt: String;
+      Args: Array of const; ErrorPosEl: TPasElement);
+    procedure RaiseNotYetImplemented(id: int64; El: TPasElement; Msg: string = ''); virtual;
+    procedure RaiseInternalError(id: int64; const Msg: string = '');
+    procedure RaiseConstantExprExp(id: int64; ErrorEl: TPasElement);
+    procedure RaiseRangeCheck(id: int64; ErrorEl: TPasElement);
+    procedure RaiseOverflowArithmetic(id: int64; ErrorEl: TPasElement);
+    function EvalUnaryExpr(Expr: TUnaryExpr; Flags: TResEvalFlags): TResEvalValue;
+    function EvalBinaryExpr(Expr: TBinaryExpr; Flags: TResEvalFlags): TResEvalValue;
+    function EvalArrayParams(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
+    function EvalFuncParams(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
+    function EvalSetParams(Expr: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
+    function ExprStringToOrd(Value: TResEvalValue; PosEl: TPasElement): longword; virtual;
+    function EvalPrimitiveExprString(Expr: TPrimitiveExpr): TResEvalValue; virtual;
+  public
+    function Eval(Expr: TPasExpr; Flags: TResEvalFlags): TResEvalValue;
+    function IsInRange(Expr, RangeExpr: TPasExpr; EmitHints: boolean): boolean;
+    function IsConst(Expr: TPasExpr): boolean;
+    function IsSimpleExpr(Expr: TPasExpr): boolean; // true = no need to store result
+    procedure EmitRangeCheckConst(id: int64; const aValue, MinVal, MaxVal: String;
+      PosEl: TPasElement); virtual;
+    procedure EmitRangeCheckConst(id: int64; const aValue: String;
+      MinVal, MaxVal: int64; PosEl: TPasElement);
+    property OnLog: TPasResEvalLogHandler read FOnLog write FOnLog;
+    property OnEvalIdentifier: TPasResEvalIdentHandler read FOnEvalIdentifier write FOnEvalIdentifier;
+  end;
+
+procedure ReleaseEvalValue(var Value: TResEvalValue);
+
+function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
+function UnicodeStrToCaption(const u: UnicodeString; MaxLength: integer): Unicodestring;
+function CanBeConvertedToUTF16(const s: String): integer;
+function CodePointToString(CodePoint: longword): String;
+function CodePointToUnicodeString(u: longword): UnicodeString;
+
+function GetObjName(o: TObject): string;
+function dbgs(const Flags: TResEvalFlags): string; overload;
+function dbgs(v: TResEvalValue): string; overload;
+
+implementation
+
+procedure ReleaseEvalValue(var Value: TResEvalValue);
+begin
+  if Value=nil then exit;
+  if Value.Element<>nil then exit;
+  Value.Free;
+  Value:=nil;
+end;
+
+function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
+var
+  s: RawByteString;
+  p: PAnsiChar;
+  InLit: boolean;
+  Len: integer;
+
+  procedure AddHash(o: integer);
+  var
+    h: String;
+  begin
+    if (Result<>'') and InLit then
+      begin
+      Result:=Result+'''';
+      inc(Len);
+      InLit:=false;
+      end;
+    h:='#'+IntToStr(o);
+    inc(Len,length(h));
+    if Len<=MaxLength then
+      Result:=Result+h;
+  end;
+
+  procedure AddLit(const Lit: string; CaptionLen: integer);
+  begin
+    if not InLit then
+      begin
+      Result:=Result+'''';
+      inc(Len);
+      InLit:=true;
+      end;
+    Result:=Result+Lit;
+    inc(Len,CaptionLen);
+  end;
+
+var
+  l: SizeInt;
+  CP: TSystemCodePage;
+  EndP: PAnsiChar;
+begin
+  Result:='';
+  s:=r;
+  CP:=StringCodePage(s);
+  if (CP<>CP_ACP) and (CP<>CP_UTF8) then
+    SetCodePage(s, CP_ACP, true);
+  p:=PAnsiChar(s);
+  EndP:=p+length(s);
+  Len:=0;
+  InLit:=false;
+  while Len<MaxLength do
+    case p^ of
+    #0:
+      begin
+      if p-PAnsiChar(s)=length(s) then
+        break;
+      AddHash(0);
+      inc(p);
+      end;
+    '''':
+      begin
+      AddLit('''''',2);
+      inc(p);
+      end;
+    #1..#31,#127..#192:
+      begin
+      AddHash(ord(p^));
+      inc(p);
+      end
+    else
+      begin
+      l:=Utf8CodePointLen(p,EndP-p,true);
+      if l<=0 then
+        begin
+        // invalid
+        AddHash(ord(p^));
+        inc(p);
+        end
+      else
+        begin
+        AddLit(copy(s,p-PAnsiChar(s)+1,l),1);
+        inc(p,l);
+        end;
+      end;
+    end;
+  if InLit then
+    Result:=Result+'''';
+end;
+
+function UnicodeStrToCaption(const u: UnicodeString; MaxLength: integer
+  ): Unicodestring;
+var
+  p: PWideChar;
+  InLit: boolean;
+  Len: integer;
+
+  procedure AddHash(o: integer);
+  var
+    h: UnicodeString;
+  begin
+    if (Result<>'') and InLit then
+      begin
+      Result:=Result+'''';
+      inc(Len);
+      InLit:=false;
+      end;
+    h:='#'+UnicodeString(IntToStr(o));
+    inc(Len,length(h));
+    if Len<=MaxLength then
+      Result:=Result+h;
+  end;
+
+  procedure AddLit(const Lit: Unicodestring; CaptionLen: integer);
+  begin
+    if not InLit then
+      begin
+      Result:=Result+'''';
+      inc(Len);
+      InLit:=true;
+      end;
+    Result:=Result+Lit;
+    inc(Len,CaptionLen);
+  end;
+
+begin
+  Result:='';
+  p:=PWideChar(u);
+  Len:=0;
+  InLit:=false;
+  while Len<MaxLength do
+    case p^ of
+    #0:
+      begin
+      if p-PWideChar(u)=length(u) then
+        break;
+      AddHash(0);
+      inc(p);
+      end;
+    '''':
+      begin
+      AddLit('''''',2);
+      inc(p);
+      end;
+    #1..#31,#127..#255,#$D800..#$ffff:
+      begin
+      AddHash(ord(p^));
+      inc(p);
+      end
+    else
+      begin
+      AddLit(p^,1);
+      inc(p);
+      end;
+    end;
+  if InLit then
+    Result:=Result+'''';
+end;
+
+function CanBeConvertedToUTF16(const s: String): integer;
+var
+  p, EndP: PAnsiChar;
+  cp: TSystemCodePage;
+  l: SizeInt;
+begin
+  if s='' then exit(0);
+  cp:=StringCodePage(s);
+  if (cp<>CP_UTF8) and ((cp<>CP_ACP) or (DefaultSystemCodePage<>CP_UTF8)) then
+    begin
+    // need conversion -> not yet supported
+    exit(1);
+    end;
+  p:=PChar(s);
+  EndP:=p+length(s);
+  while p<EndP do
+    begin
+    l:=Utf8CodePointLen(p,EndP-p,false);
+    if l<=0 then
+      exit(p-PAnsiChar(s)+1);
+    inc(p,l);
+    end;
+end;
+
+function CodePointToString(CodePoint: longword): String;
+begin
+  case CodePoint of
+    0..$7f:
+      begin
+        Result:=char(byte(CodePoint));
+      end;
+    $80..$7ff:
+      begin
+        Result:=char(byte($c0 or (CodePoint shr 6)))
+               +char(byte($80 or (CodePoint and $3f)));
+      end;
+    $800..$ffff:
+      begin
+        Result:=char(byte($e0 or (CodePoint shr 12)))
+               +char(byte((CodePoint shr 6) and $3f) or $80)
+               +char(byte(CodePoint and $3f) or $80);
+      end;
+    $10000..$10ffff:
+      begin
+        Result:=char(byte($f0 or (CodePoint shr 18)))
+               +char(byte((CodePoint shr 12) and $3f) or $80)
+               +char(byte((CodePoint shr 6) and $3f) or $80)
+               +char(byte(CodePoint and $3f) or $80);
+      end;
+  else
+    Result:='';
+  end;
+end;
+
+function CodePointToUnicodeString(u: longword): UnicodeString;
+begin
+  if u < $10000 then
+    // Note: codepoints $D800 - $DFFF are reserved
+    Result:=WideChar(u)
+  else
+    Result:=WideChar($D800+((u - $10000) shr 10))+WideChar($DC00+((u - $10000) and $3ff));
+end;
+
+function GetObjName(o: TObject): string;
+begin
+  if o=nil then
+    Result:='nil'
+  else if o is TPasElement then
+    Result:=TPasElement(o).Name+':'+o.ClassName
+  else
+    Result:=o.ClassName;
+end;
+
+function dbgs(const Flags: TResEvalFlags): string;
+var
+  s: string;
+  f: TResEvalFlag;
+begin
+  Result:='';
+  for f in Flags do
+    if f in Flags then
+      begin
+      if Result<>'' then Result:=Result+',';
+      str(f,s);
+      Result:=Result+s;
+      end;
+  Result:='['+Result+']';
+end;
+
+function dbgs(v: TResEvalValue): string;
+begin
+  if v=nil then
+    Result:='nil'
+  else
+    Result:=v.AsDebugString;
+end;
+
+{ TResEvalRangeUInt }
+
+constructor TResEvalRangeUInt.Create;
+begin
+  inherited Create;
+  Kind:=revkRangeInt;
+end;
+
+function TResEvalRangeUInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalRangeUInt(Result).RangeStart:=RangeStart;
+  TResEvalRangeUInt(Result).RangeEnd:=RangeEnd;
+end;
+
+function TResEvalRangeUInt.AsString: string;
+begin
+  Result:=IntToStr(RangeStart)+'..'+IntToStr(RangeEnd);
+end;
+
+{ TResExprEvaluator }
+
+procedure TResExprEvaluator.LogMsg(const id: int64; MsgType: TMessageType;
+  MsgNumber: integer; const Fmt: String; Args: array of const;
+  PosEl: TPasElement);
+begin
+  OnLog(Self,id,MsgType,MsgNumber,Fmt,Args,PosEl);
+end;
+
+procedure TResExprEvaluator.RaiseMsg(const Id: int64; MsgNumber: integer;
+  const Fmt: String; Args: array of const; ErrorPosEl: TPasElement);
+begin
+  LogMsg(id,mtError,MsgNumber,Fmt,Args,ErrorPosEl);
+  raise Exception.Create('['+IntToStr(id)+'] ('+IntToStr(MsgNumber)+') '+SafeFormat(Fmt,Args));
+end;
+
+procedure TResExprEvaluator.RaiseNotYetImplemented(id: int64; El: TPasElement;
+  Msg: string);
+var
+  s: String;
+begin
+  s:=sNotYetImplemented+' ['+IntToStr(id)+']';
+  if Msg<>'' then
+    s:=s+' '+Msg;
+  {$IFDEF VerbosePasResolver}
+  writeln('TResExprEvaluator.RaiseNotYetImplemented s="',s,'" El=',GetObjName(El));
+  {$ENDIF}
+  RaiseMsg(id,nNotYetImplemented,s,[GetObjName(El)],El);
+end;
+
+procedure TResExprEvaluator.RaiseInternalError(id: int64; const Msg: string);
+begin
+  raise Exception.Create('Internal error: ['+IntToStr(id)+'] '+Msg);
+end;
+
+procedure TResExprEvaluator.RaiseConstantExprExp(id: int64; ErrorEl: TPasElement
+  );
+begin
+  RaiseMsg(id,nConstantExpressionExpected,sConstantExpressionExpected,[],ErrorEl);
+end;
+
+procedure TResExprEvaluator.RaiseRangeCheck(id: int64; ErrorEl: TPasElement);
+begin
+  RaiseMsg(id,nRangeCheckError,sRangeCheckError,[],ErrorEl);
+end;
+
+procedure TResExprEvaluator.RaiseOverflowArithmetic(id: int64;
+  ErrorEl: TPasElement);
+begin
+  RaiseMsg(id,nOverflowInArithmeticOperation,sOverflowInArithmeticOperation,[],ErrorEl);
+end;
+
+function TResExprEvaluator.EvalUnaryExpr(Expr: TUnaryExpr; Flags: TResEvalFlags
+  ): TResEvalValue;
+begin
+  Result:=Eval(Expr.Operand,Flags);
+  if Result=nil then exit;
+  case Expr.OpCode of
+    eopAdd: ;
+    eopSubtract:
+      case Result.Kind of
+      revkInt:
+        begin
+        if TResEvalInt(Result).Int=0 then exit;
+        if Result.Element<>nil then
+          Result:=Result.Clone;
+        TResEvalInt(Result).Int:=-TResEvalInt(Result).Int;
+        end;
+      revkUInt:
+        begin
+        if TResEvalUInt(Result).UInt=0 then exit;
+        if Result.Element<>nil then
+          Result:=Result.Clone;
+        TResEvalUInt(Result).UInt:=-TResEvalUInt(Result).UInt;
+        end
+      else
+        begin
+        if Result.Element=nil then
+          Result.Free;
+        RaiseNotYetImplemented(20170518230738,Expr);
+        end;
+      end;
+    eopNot:
+      case Result.Kind of
+      revkBool:
+        begin
+        if Result.Element<>nil then
+          Result:=Result.Clone;
+        if TResEvalInt(Result).Int=0 then
+          TResEvalInt(Result).Int:=1
+        else
+          TResEvalInt(Result).Int:=0;
+        end
+      else
+        begin
+        if Result.Element=nil then
+          Result.Free;
+        RaiseNotYetImplemented(20170518232804,Expr);
+        end;
+      end;
+    eopAddress:
+      begin
+      if Result.Element=nil then
+        Result.Free;
+      // @ operator requires a compiler -> return nil
+      Result:=TResEvalValue.Create;
+      Result.Kind:=revkNil;
+      end
+    else
+      RaiseNotYetImplemented(20170518232823,Expr);
+    end;
+end;
+
+function TResExprEvaluator.EvalBinaryExpr(Expr: TBinaryExpr;
+  Flags: TResEvalFlags): TResEvalValue;
+var
+  LeftValue, RightValue: TResEvalValue;
+  LeftInt, RightInt: LongWord;
+  Int: NativeInt;
+  UInt: NativeUInt;
+begin
+  Result:=nil;
+  LeftValue:=nil;
+  RightValue:=nil;
+  try
+    LeftValue:=Eval(Expr.left,Flags);
+    if LeftValue=nil then exit;
+    RightValue:=Eval(Expr.right,Flags);
+    if RightValue=nil then exit;
+    case Expr.Kind of
+    pekRange:
+      // leftvalue..rightvalue
+      case LeftValue.Kind of
+      revkInt:
+        if RightValue.Kind=revkInt then
+          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;
+          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<=NativeUInt(High(NativeInt)) 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;
+            exit;
+            end
+          else if TResEvalInt(LeftValue).Int<0 then
+            RaiseRangeCheck(20170522151629,Expr.Right)
+          else if qword(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;
+          exit;
+          end
+        else
+          RaiseRangeCheck(20170518222812,Expr.Right);
+      revkUInt:
+        if RightValue.Kind=revkInt then
+          begin
+          // Note: when FPC compares int64 with qword it converts the qword to an int64
+          if TResEvalUInt(LeftValue).UInt>NativeUInt(High(NativeInt)) then
+            begin
+            if TResEvalInt(RightValue).Int<0 then
+              RaiseRangeCheck(20170522152608,Expr.Right)
+            else if TResEvalUInt(LeftValue).UInt>qword(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;
+            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;
+          exit;
+          end
+        else if RightValue.Kind=revkUInt then
+          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;
+          exit;
+          end
+        else
+          RaiseRangeCheck(20170522123106,Expr.Right);
+      revkEnum:
+        if (RightValue.Kind<>revkEnum) then
+          RaiseRangeCheck(20170522153003,Expr.Right)
+        else if (TResEvalEnum(LeftValue).IdentEl<>TResEvalEnum(RightValue).IdentEl) then
+          RaiseRangeCheck(20170522123241,Expr.Right)
+        else if TResEvalEnum(LeftValue).Index>TResEvalEnum(RightValue).Index then
+          RaiseMsg(20170522123320,nHighRangeLimitLTLowRangeLimit,
+            sHighRangeLimitLTLowRangeLimit,[],Expr.Right)
+        else
+          begin
+          Result:=TResEvalRangeInt.Create;
+          TResEvalRangeInt(Result).ElKind:=revrikEnum;
+          TResEvalRangeInt(Result).RangeStart:=TResEvalEnum(LeftValue).Index;
+          TResEvalRangeInt(Result).RangeEnd:=TResEvalEnum(RightValue).Index;
+          exit;
+          end;
+      revkString,revkUnicodeString:
+        begin
+        LeftInt:=ExprStringToOrd(LeftValue,Expr.left);
+        if RightValue.Kind in [revkString,revkUnicodeString] then
+          begin
+          RightInt:=ExprStringToOrd(RightValue,Expr.right);
+          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;
+          exit;
+          end
+        else
+          RaiseRangeCheck(20170522123106,Expr.Right);
+        end
+      else
+        {$IFDEF EnablePasResRangeCheck}
+        writeln('TPasResolver.Eval pekRange Left=',GetObjName(Expr.Left),' LeftValue.Kind=',LeftValue.Kind);
+        RaiseNotYetImplemented(20170518221103,Expr.Left);
+        {$ELSE}
+        exit(nil);
+        {$ENDIF}
+      end;
+    pekBinary:
+      case Expr.OpCode of
+      eopAdd:
+        case LeftValue.Kind of
+        revkInt:
+          if RightValue.Kind=revkInt then
+            // int+int
+            try
+              {$Q+}
+              Int:=TResEvalInt(LeftValue).Int+TResEvalInt(RightValue).Int;
+              {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+              Result:=TResEvalInt.Create;
+              TResEvalInt(Result).Int:=NativeInt(Int);
+            except
+              on E: EOverflow do
+                if (TResEvalInt(LeftValue).Int>0) and (TResEvalInt(RightValue).Int>0) then
+                  begin
+                  UInt:=NativeUInt(TResEvalInt(LeftValue).Int)+NativeUInt(TResEvalInt(RightValue).Int);
+                  Result:=TResEvalUInt.Create;
+                  TResEvalUInt(Result).UInt:=UInt;
+                  end
+                else
+                  RaiseOverflowArithmetic(20170525122256,Expr);
+            end
+          else
+            begin
+            {$IFDEF VerbosePasResolver}
+            writeln('TResExprEvaluator.EvalBinaryExpr add int+? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+            {$ENDIF}
+            RaiseNotYetImplemented(20170525115537,Expr);
+            end;
+        else
+          {$IFDEF VerbosePasResolver}
+          writeln('TResExprEvaluator.EvalBinaryExpr add ?+ Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+          {$ENDIF}
+          RaiseNotYetImplemented(20170525115548,Expr);
+        end;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryExpr Opcode=',OpcodeStrings[Expr.OpCode],' Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170518232823,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryExpr Kind=',Expr.Kind,' Opcode=',OpcodeStrings[Expr.OpCode]);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170518232823,Expr);
+    end;
+  finally
+    ReleaseEvalValue(LeftValue);
+    ReleaseEvalValue(RightValue);
+  end;
+end;
+
+function TResExprEvaluator.EvalArrayParams(Expr: TParamsExpr;
+  Flags: TResEvalFlags): TResEvalValue;
+begin
+  Result:=nil;
+  {$IFDEF VerbosePasResEval}
+  writeln('TResExprEvaluator.EvalArrayParams ');
+  {$ENDIF}
+  if refConst in Flags then
+    RaiseConstantExprExp(20170522173150,Expr);
+end;
+
+function TResExprEvaluator.EvalFuncParams(Expr: TParamsExpr;
+  Flags: TResEvalFlags): TResEvalValue;
+begin
+  Result:=nil;
+  {$IFDEF VerbosePasResEval}
+  writeln('TResExprEvaluator.EvalFuncParams ');
+  {$ENDIF}
+  if refConst in Flags then
+    RaiseConstantExprExp(20170522173150,Expr);
+end;
+
+function TResExprEvaluator.EvalSetParams(Expr: TParamsExpr; Flags: TResEvalFlags
+  ): TResEvalValue;
+begin
+  Result:=nil;
+  {$IFDEF VerbosePasResEval}
+  writeln('TResExprEvaluator.EvalSetParams ');
+  {$ENDIF}
+  if length(Expr.Params)=0 then
+    begin
+    Result:=TResEvalValue.Create;
+    Result.Kind:=revkSetEmpty;
+    exit;
+    end;
+  if refConst in Flags then
+    RaiseConstantExprExp(20170522173150,Expr);
+end;
+
+function TResExprEvaluator.ExprStringToOrd(Value: TResEvalValue;
+  PosEl: TPasElement): longword;
+var
+  l: SizeInt;
+  S: RawByteString;
+  U: UnicodeString;
+begin
+  if Value.Kind=revkString then
+    begin
+    S:=TResEvalString(Value).S;
+    l:=length(S);
+    if l=0 then
+      RaiseMsg(20170522221143,nXExpectedButYFound,sXExpectedButYFound,
+        ['char','string'],PosEl)
+    else if l=1 then
+      Result:=ord(S[1])
+    else if l<=4 then
+      begin
+      U:=UTF8Decode(S);
+      if length(U)<>1 then
+        RaiseMsg(20170523150826,nXExpectedButYFound,sXExpectedButYFound,
+          ['char','string'],PosEl);
+      Result:=ord(U[1]);
+      end;
+    end
+  else if Value.Kind=revkUnicodeString then
+    begin
+    if length(TResEvalUTF16(Value).S)<>1 then
+      RaiseMsg(20170522221358,nXExpectedButYFound,sXExpectedButYFound,
+        ['char','string'],PosEl)
+    else
+      Result:=ord(TResEvalUTF16(Value).S[1]);
+    end
+  else
+    RaiseNotYetImplemented(20170522220959,PosEl);
+end;
+
+function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
+  ): TResEvalValue;
+{ Extracts the value from a Pascal string literal
+
+  S is a Pascal string literal e.g. 'Line'#10
+    ''  empty string
+    '''' => "'"
+    #decimal
+    #$hex
+    ^l  l is a letter a-z
+}
+
+  procedure RangeError(id: int64);
+  begin
+    Result.Free;
+    RaiseRangeCheck(id,Expr);
+  end;
+
+  procedure Add(h: String);
+  begin
+    if Result.Kind=revkString then
+      TResEvalString(Result).S:=TResEvalString(Result).S+h
+    else
+      begin
+      if CanBeConvertedToUTF16(h)>0 then
+        begin
+        Result.Free;
+        RaiseMsg(20170523114733,nIllegalChar,sIllegalChar,[],Expr);
+        end;
+      TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+UnicodeString(h);
+      end;
+  end;
+
+  procedure AddHash(u: longword);
+  var
+    h: RawByteString;
+  begin
+    if (u>255) and (Result.Kind=revkString) then
+      begin
+      h:=TResEvalString(Result).S;
+      Result.Free;
+      if CanBeConvertedToUTF16(h)>0 then
+        RaiseMsg(20170523123140,nIllegalChar,sIllegalChar,[],Expr);
+      Result:=TResEvalUTF16.Create;
+      TResEvalUTF16(Result).S:=UnicodeString(h);
+      end;
+    if Result.Kind=revkString then
+      TResEvalString(Result).S:=TResEvalString(Result).S+Chr(u)
+    else
+      TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
+  end;
+
+var
+  p, StartP: PChar;
+  c: Char;
+  u: longword;
+  S: String;
+begin
+  Result:=nil;
+  S:=Expr.Value;
+  {$IFDEF VerbosePasResEval}
+  writeln('TResExprEvaluator.EvalPrimitiveExprString (',S,')');
+  {$ENDIF}
+  if S='' then
+    RaiseInternalError(20170523113809);
+  Result:=TResEvalString.Create;
+  p:=PChar(S);
+  repeat
+    case p^ of
+    #0: break;
+    '''':
+      begin
+      inc(p);
+      StartP:=p;
+      repeat
+        c:=p^;
+        case c of
+        #0:
+          RaiseInternalError(20170523113938);
+        '''':
+          begin
+          if p>StartP then
+            Add(copy(S,StartP-PChar(S)+1,p-StartP));
+          inc(p);
+          StartP:=p;
+          if p^<>'''' then
+            break;
+          Add('''');
+          inc(p);
+          StartP:=p;
+          end;
+        else
+          inc(p);
+        end;
+      until false;
+      if p>StartP then
+        Add(copy(S,StartP-PChar(S)+1,p-StartP));
+      end;
+    '#':
+      begin
+      inc(p);
+      if p^='$' then
+        begin
+        // #$hexnumber
+        inc(p);
+        StartP:=p;
+        u:=0;
+        repeat
+          c:=p^;
+          case c of
+          #0: break;
+          '0'..'9': u:=u*16+ord(c)-ord('0');
+          'a'..'f': u:=u*16+ord(c)-ord('a')+10;
+          'A'..'F': u:=u*16+ord(c)-ord('A')+10;
+          else break;
+          end;
+          if u>$ffff then
+            RangeError(20170523115712);
+          inc(p);
+        until false;
+        if p=StartP then
+          RaiseInternalError(20170207164956);
+        AddHash(u);
+        end
+      else
+        begin
+        // #decimalnumber
+        StartP:=p;
+        u:=0;
+        repeat
+          c:=p^;
+          case c of
+          #0: break;
+          '0'..'9': u:=u*10+ord(c)-ord('0');
+          else break;
+          end;
+          if u>$ffff then
+            RangeError(20170523123137);
+          inc(p);
+        until false;
+        if p=StartP then
+          RaiseInternalError(20170523123806);
+        AddHash(u);
+        end;
+      end;
+    '^':
+      begin
+      // ^A is #1
+      inc(p);
+      c:=p^;
+      case c of
+      'a'..'z': AddHash(ord(c)-ord('a')+1);
+      'A'..'Z': AddHash(ord(c)-ord('A')+1);
+      else RaiseInternalError(20170523123809);
+      end;
+      inc(p);
+      end;
+    else
+      RaiseNotYetImplemented(20170523123815,Expr,'ord='+IntToStr(ord(p^)));
+    end;
+  until false;
+  {$IFDEF VerbosePasResEval}
+  writeln('TResExprEvaluator.EvalPrimitiveExprString Result=',Result.AsString);
+  {$ENDIF}
+end;
+
+function TResExprEvaluator.Eval(Expr: TPasExpr; Flags: TResEvalFlags
+  ): TResEvalValue;
+var
+  C: TClass;
+  Code: integer;
+  Int: NativeInt;
+  UInt: NativeUInt;
+  Ext: Extended;
+begin
+  Result:=nil;
+  if Expr.CustomData is TResEvalValue then
+    begin
+    Result:=TResEvalValue(Expr.CustomData);
+    exit;
+    end;
+  {$IFDEF VerbosePasResEval}
+  writeln('TPasResolver.Eval Expr=',GetObjName(Expr),' Flags=',dbgs(Flags));
+  {$ENDIF}
+  if refAutoConst in Flags then
+    begin
+    Exclude(Flags,refAutoConst);
+    if IsConst(Expr) then
+      Include(Flags,refConst);
+    end;
+
+  C:=Expr.ClassType;
+  if C=TPrimitiveExpr then
+    begin
+    case TPrimitiveExpr(Expr).Kind of
+      pekIdent:
+        Result:=OnEvalIdentifier(Self,TPrimitiveExpr(Expr),Flags);
+      pekNumber:
+        begin
+        // try int64
+        val(TPrimitiveExpr(Expr).Value,Int,Code);
+        if Code=0 then
+          begin
+          Result:=TResEvalInt.Create;
+          TResEvalInt(Result).Int:=Int;
+          exit;
+          end;
+        // try qword
+        val(TPrimitiveExpr(Expr).Value,UInt,Code);
+        if Code=0 then
+          begin
+          Result:=TResEvalUInt.Create;
+          TResEvalUInt(Result).UInt:=UInt;
+          exit;
+          end;
+        // try float
+        val(TPrimitiveExpr(Expr).Value,Ext,Code);
+        if Code=0 then
+          begin
+          Result:=TResEvalFloat.Create;
+          TResEvalFloat(Result).FloatValue:=Ext;
+          exit;
+          end;
+        RaiseRangeCheck(20170518202252,Expr);
+        end;
+      pekString:
+        begin
+        Result:=EvalPrimitiveExprString(TPrimitiveExpr(Expr));
+        exit;
+        end;
+    else
+      RaiseNotYetImplemented(20170518200951,Expr);
+    end;
+    end
+  else if C=TNilExpr then
+    begin
+    Result:=TResEvalValue.Create;
+    Result.Kind:=revkNil;
+    end
+  else if C=TBoolConstExpr then
+    begin
+    Result:=TResEvalInt.Create;
+    Result.Kind:=revkBool;
+    if TBoolConstExpr(Expr).Value then
+      TResEvalInt(Result).Int:=1
+    else
+      TResEvalInt(Result).Int:=0;
+    end
+  else if C=TUnaryExpr then
+    Result:=EvalUnaryExpr(TUnaryExpr(Expr),Flags)
+  else if C=TBinaryExpr then
+    Result:=EvalBinaryExpr(TBinaryExpr(Expr),Flags)
+  else if C=TParamsExpr then
+    case TParamsExpr(Expr).Kind of
+    pekArrayParams: Result:=EvalArrayParams(TParamsExpr(Expr),Flags);
+    pekFuncParams: Result:=EvalFuncParams(TParamsExpr(Expr),Flags);
+    pekSet: Result:=EvalSetParams(TParamsExpr(Expr),Flags);
+    else
+      RaiseInternalError(20170522173013);
+    end
+  else if refConst in Flags then
+    RaiseConstantExprExp(20170518213800,Expr);
+end;
+
+function TResExprEvaluator.IsInRange(Expr, RangeExpr: TPasExpr;
+  EmitHints: boolean): boolean;
+var
+  ExprValue, RangeValue: TResEvalValue;
+  RgInt: TResEvalRangeInt;
+  RgUInt: TResEvalRangeUInt;
+  CharIndex: LongWord;
+begin
+  Result:=false;
+  ExprValue:=Eval(Expr,[refAutoConst]);
+  if ExprValue=nil then
+    exit(true); // a variable -> ok
+  RangeValue:=nil;
+  try
+    RangeValue:=Eval(RangeExpr,[]);
+    {$IFDEF VerbosePasResEval}
+    //writeln('TResExprEvaluator.IsInRange ExprValue=',dbgs(ExprValue),' RangeValue=',dbgs(RangeValue));
+    {$ENDIF}
+    if RangeValue=nil then
+      RaiseNotYetImplemented(20170522171226,RangeExpr);
+    case RangeValue.Kind of
+    revkSetEmpty:
+      begin
+      Result:=false;
+      exit;
+      end;
+    revkRangeInt:
+      begin
+      RgInt:=TResEvalRangeInt(RangeValue);
+      case RgInt.ElKind of
+        revrikBool:
+          if ExprValue.Kind=revkBool then
+            exit(true)
+          else
+            RaiseNotYetImplemented(20170522220104,Expr);
+        revrikEnum:
+          begin
+          if ExprValue.Kind<>revkEnum then
+            RaiseInternalError(20170522172754)
+          else if ExprValue.IdentEl<>RgInt.IdentEl then
+            RaiseInternalError(20170522174028)
+          else if (TResEvalEnum(ExprValue).Index<RgInt.RangeStart)
+              or (TResEvalEnum(ExprValue).Index>RgInt.RangeEnd) then
+            begin
+            if EmitHints then
+              EmitRangeCheckConst(20170522174406,ExprValue.AsString,
+                RgInt.ElementAsString(RgInt.RangeStart),
+                RgInt.ElementAsString(RgInt.RangeEnd),
+                Expr);
+            exit(false);
+            end
+          else
+            exit(true);
+          end;
+        revrikInt: // int..int
+          if ExprValue.Kind=revkInt then
+            begin
+            // int in int..int
+            if (TResEvalInt(ExprValue).Int<RgInt.RangeStart)
+                or (TResEvalInt(ExprValue).Int>RgInt.RangeEnd) then
+              begin
+              if EmitHints then
+                EmitRangeCheckConst(20170522174958,ExprValue.AsString,
+                  RgInt.ElementAsString(RgInt.RangeStart),
+                  RgInt.ElementAsString(RgInt.RangeEnd),
+                  Expr);
+              exit(false);
+              end
+            else
+              exit(true);
+            end
+          else if ExprValue.Kind=revkUInt then
+            begin
+            // uint in int..int
+            if (TResEvalUInt(ExprValue).UInt>NativeUInt(High(NativeInt)))
+                or (NativeInt(TResEvalUInt(ExprValue).UInt)<RgInt.RangeStart)
+                or (NativeInt(TResEvalUInt(ExprValue).UInt)>RgInt.RangeEnd) then
+              begin
+              if EmitHints then
+                EmitRangeCheckConst(20170522215852,ExprValue.AsString,
+                  RgInt.ElementAsString(RgInt.RangeStart),
+                  RgInt.ElementAsString(RgInt.RangeEnd),
+                  Expr);
+              exit(false);
+              end
+            else
+              exit(true);
+            end
+          else
+            RaiseNotYetImplemented(20170522215906,Expr);
+        revrikChar:
+          if ExprValue.Kind in [revkString,revkUnicodeString] then
+            begin
+            // string in char..char
+            CharIndex:=ExprStringToOrd(ExprValue,Expr);
+            if (CharIndex<RgInt.RangeStart) or (CharIndex>RgInt.RangeEnd) then
+              begin
+              if EmitHints then
+                EmitRangeCheckConst(20170522221709,ExprValue.AsString,
+                  RgInt.ElementAsString(RgInt.RangeStart),
+                  RgInt.ElementAsString(RgInt.RangeEnd),
+                  Expr);
+              exit(false);
+              end
+            else
+              exit(true);
+            end
+          else
+            RaiseNotYetImplemented(20170522220210,Expr);
+      else
+        RaiseInternalError(20170522172630);
+      end;
+      end;
+    revkRangeUInt:
+      if ExprValue.Kind=revkInt then
+        begin
+        // int in uint..uint
+        RgUInt:=TResEvalRangeUInt(RangeValue);
+        if (TResEvalInt(ExprValue).Int<0)
+            or (NativeUInt(TResEvalInt(ExprValue).Int)<RgUInt.RangeStart)
+            or (NativeUInt(TResEvalInt(ExprValue).Int)>RgUInt.RangeEnd) then
+          begin
+          if EmitHints then
+            EmitRangeCheckConst(20170522172250,ExprValue.AsString,
+              IntToStr(RgUInt.RangeStart),
+              IntToStr(RgUInt.RangeEnd),Expr);
+          exit(false);
+          end
+        else
+          exit(true);
+        end
+      else if ExprValue.Kind=revkUInt then
+        begin
+        // uint in uint..uint
+        RgUInt:=TResEvalRangeUInt(RangeValue);
+        if (TResEvalUInt(ExprValue).UInt<RgUInt.RangeStart)
+            or (TResEvalUInt(ExprValue).UInt>RgUInt.RangeEnd) then
+          begin
+          if EmitHints then
+            EmitRangeCheckConst(20170522172544,IntToStr(TResEvalUInt(ExprValue).UInt),
+              IntToStr(RgUInt.RangeStart),
+              IntToStr(RgUInt.RangeEnd),Expr);
+          exit(false);
+          end
+        else
+          exit(true);
+        end
+      else
+        RaiseNotYetImplemented(20170522171551,Expr);
+    else
+      RaiseNotYetImplemented(20170522171307,RangeExpr);
+    end;
+  finally
+    ReleaseEvalValue(ExprValue);
+    ReleaseEvalValue(RangeValue);
+  end;
+end;
+
+function TResExprEvaluator.IsConst(Expr: TPasExpr): boolean;
+var
+  El: TPasElement;
+  C: TClass;
+begin
+  El:=Expr;
+  while El<>nil do
+    begin
+    C:=El.ClassType;
+    if C.InheritsFrom(TPasProcedure) then exit(true);
+    if C.InheritsFrom(TPasImplBlock) then exit(false);
+    El:=El.Parent;
+    end;
+  Result:=true;
+end;
+
+function TResExprEvaluator.IsSimpleExpr(Expr: TPasExpr): boolean;
+var
+  C: TClass;
+begin
+  C:=Expr.ClassType;
+  Result:=(C=TNilExpr)
+       or (C=TBoolConstExpr)
+       or (C=TPrimitiveExpr);
+end;
+
+procedure TResExprEvaluator.EmitRangeCheckConst(id: int64; const aValue,
+  MinVal, MaxVal: String; PosEl: TPasElement);
+begin
+  LogMsg(id,mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
+    sRangeCheckEvaluatingConstantsVMinMax,[aValue,MinVal,MaxVal],PosEl);
+end;
+
+procedure TResExprEvaluator.EmitRangeCheckConst(id: int64;
+  const aValue: String; MinVal, MaxVal: int64; PosEl: TPasElement);
+begin
+  EmitRangeCheckConst(id,aValue,IntToStr(MinVal),IntToStr(MaxVal),PosEl);
+end;
+
+{ TResolveData }
+
+procedure TResolveData.SetElement(AValue: TPasElement);
+begin
+  if FElement=AValue then Exit;
+  if Element<>nil then
+    Element.Release;
+  FElement:=AValue;
+  if Element<>nil then
+    Element.AddRef;
+end;
+
+constructor TResolveData.Create;
+begin
+
+end;
+
+destructor TResolveData.Destroy;
+begin
+  {$IFDEF VerbosePasResolverMem}
+  writeln('TResolveData.Destroy START ',ClassName);
+  {$ENDIF}
+  Element:=nil;
+  Owner:=nil;
+  Next:=nil;
+  inherited Destroy;
+  {$IFDEF VerbosePasResolverMem}
+  writeln('TResolveData.Destroy END ',ClassName);
+  {$ENDIF}
+end;
+
+{ TResEvalValue }
+
+function TResEvalValue.Clone: TResEvalValue;
+begin
+  Result:=TResEvalValueClass(ClassType).Create;
+  Result.Kind:=Kind;
+  Result.IdentEl:=IdentEl;
+end;
+
+function TResEvalValue.AsDebugString: string;
+begin
+  str(Kind,Result);
+  Result:=Result+'='+AsString;
+end;
+
+function TResEvalValue.AsString: string;
+begin
+  case Kind of
+    revkNone: Result:='<None>';
+    revkNil: Result:='nil';
+    revkSetEmpty: Result:='[]';
+  else
+    str(Kind,Result);
+  end;
+end;
+
+{ TResEvalUInt }
+
+constructor TResEvalUInt.Create;
+begin
+  inherited Create;
+  Kind:=revkUInt;
+end;
+
+function TResEvalUInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalUInt(Result).UInt:=UInt;
+end;
+
+function TResEvalUInt.AsString: string;
+begin
+  Result:=IntToStr(UInt);
+end;
+
+{ TResEvalInt }
+
+constructor TResEvalInt.Create;
+begin
+  inherited Create;
+  Kind:=revkInt;
+end;
+
+function TResEvalInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalInt(Result).Int:=Int;
+end;
+
+function TResEvalInt.AsString: string;
+begin
+  case Kind of
+  revkBool: if Int=0 then Result:='false' else Result:='true';
+  revkInt: Result:=IntToStr(Int);
+  end;
+end;
+
+{ TResEvalFloat }
+
+constructor TResEvalFloat.Create;
+begin
+  inherited Create;
+  Kind:=revkFloat;
+end;
+
+function TResEvalFloat.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalFloat(Result).FloatValue:=FloatValue;
+end;
+
+function TResEvalFloat.AsString: string;
+begin
+  str(FloatValue,Result);
+end;
+
+{ TResEvalString }
+
+constructor TResEvalString.Create;
+begin
+  inherited Create;
+  Kind:=revkString;
+end;
+
+function TResEvalString.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalString(Result).S:=S;
+end;
+
+function TResEvalString.AsString: string;
+begin
+  Result:=RawStrToCaption(S,60);
+end;
+
+{ TResEvalUTF16 }
+
+constructor TResEvalUTF16.Create;
+begin
+  inherited Create;
+  Kind:=revkUnicodeString;
+end;
+
+function TResEvalUTF16.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalUTF16(Result).S:=S;
+end;
+
+function TResEvalUTF16.AsString: string;
+begin
+  Result:=String(UnicodeStrToCaption(S,60));
+end;
+
+{ TResEvalEnum }
+
+constructor TResEvalEnum.Create;
+begin
+  inherited Create;
+  Kind:=revkEnum;
+end;
+
+function TResEvalEnum.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalEnum(Result).Index:=Index;
+end;
+
+function TResEvalEnum.AsDebugString: string;
+begin
+  str(Kind,Result);
+  Result:=Result+'='+IdentEl.Name+'='+IntToStr(Index);
+end;
+
+function TResEvalEnum.AsString: string;
+begin
+  Result:=IdentEl.Name;
+end;
+
+{ TResEvalRangeInt }
+
+constructor TResEvalRangeInt.Create;
+begin
+  inherited Create;
+  Kind:=revkRangeInt;
+end;
+
+function TResEvalRangeInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalRangeInt(Result).ElKind:=ElKind;
+  TResEvalRangeInt(Result).RangeStart:=RangeStart;
+  TResEvalRangeInt(Result).RangeEnd:=RangeEnd;
+end;
+
+function TResEvalRangeInt.AsString: string;
+begin
+  Result:=ElementAsString(RangeStart)+'..'+ElementAsString(RangeEnd);
+end;
+
+function TResEvalRangeInt.ElementAsString(El: int64): string;
+begin
+  case ElKind of
+    revrikBool: if El=0 then Result:='false' else Result:='true';
+    revrikEnum: Result:=TPasEnumValue(TPasEnumType(IdentEl).Values[El]).Name;
+    revrikInt: Result:=IntToStr(El);
+    revrikChar:
+      if ((El>=32) and (El<=38)) or ((El>=40) and (El<=126)) then
+        Result:=''''+Chr(El)+''''
+      else
+        Result:='#'+IntToStr(El);
+  end;
+end;
+
+{ TResEvalSetInt }
+
+constructor TResEvalSetInt.Create;
+begin
+  inherited Create;
+  Kind:=revkSetOfInt;
+end;
+
+function TResEvalSetInt.Clone: TResEvalValue;
+var
+  RS: TResEvalSetInt;
+  i: Integer;
+begin
+  Result:=inherited Clone;
+  TResEvalSetInt(Result).ElKind:=ElKind;
+  RS:=TResEvalSetInt(Result);
+  SetLength(RS.Ranges,length(Ranges));
+  for i:=0 to length(Ranges)-1 do
+    RS.Ranges[i]:=Ranges[i];
+end;
+
+function TResEvalSetInt.AsString: string;
+var
+  i: Integer;
+begin
+  Result:='[';
+  for i:=0 to length(Ranges)-1 do
+    begin
+    if i>0 then Result:=Result+',';
+    Result:=Result+ElementAsString(Ranges[i].RangeStart);
+    if Ranges[i].RangeStart<>Ranges[i].RangeEnd then
+      Result:=Result+'..'+ElementAsString(Ranges[i].RangeEnd);
+    end;
+  Result:=Result+']';
+end;
+
+function TResEvalSetInt.ElementAsString(El: int64): string;
+begin
+  case ElKind of
+    revsikEnum: Result:=TPasEnumValue(TPasEnumType(IdentEl).Values[El]).Name;
+    revsikInt: Result:=IntToStr(El);
+    revsikChar: Result:=Chr(El);
+    revsikWChar: Result:=String(WideChar(El));
+  end;
+end;
+
+end.
+

+ 171 - 623
packages/fcl-passrc/src/pasresolver.pp

@@ -135,17 +135,22 @@ Works:
   - nil, assigned(), typecast, class, classref, dynarray, procvar
   - nil, assigned(), typecast, class, classref, dynarray, procvar
 - emit hints platform, deprecated, experimental, library, unimplemented
 - emit hints platform, deprecated, experimental, library, unimplemented
 - dotted unitnames
 - dotted unitnames
+- eval:
+  - nil, true, false
 
 
 ToDo:
 ToDo:
 - range checking:
 - range checking:
-  - nil,
-  - true, false
   - integer ranges
   - integer ranges
   - boolean ranges
   - boolean ranges
   - enum ranges
   - enum ranges
   - char ranges
   - char ranges
-  - +, -, *, div, mod, /, shl, shr, or, and, xor, not,
+  - +, -, *, div, mod, /, shl, shr, or, and, xor
   - ord(), low(), high(), pred(), succ(), length()
   - ord(), low(), high(), pred(), succ(), length()
+  - string[index]
+  - arr[index]
+  - call(param)
+  - indexedprop[param]
+  - a:=value
 - @@
 - @@
 - fail to write a loop var inside the loop
 - fail to write a loop var inside the loop
 - warn: create class with abstract methods
 - warn: create class with abstract methods
@@ -204,148 +209,12 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, Math, contnrs,
   Classes, SysUtils, Math, contnrs,
-  PasTree, PParser, PScanner;
+  PasTree, PScanner, PParser, PasResolveEval;
 
 
 const
 const
   ParserMaxEmbeddedColumn = 2048;
   ParserMaxEmbeddedColumn = 2048;
   ParserMaxEmbeddedRow = $7fffffff div ParserMaxEmbeddedColumn;
   ParserMaxEmbeddedRow = $7fffffff div ParserMaxEmbeddedColumn;
 
 
-// message numbers
-const
-  nIdentifierNotFound = 3001;
-  nNotYetImplemented = 3002;
-  nIllegalQualifier = 3003;
-  nSyntaxErrorExpectedButFound = 3004;
-  nWrongNumberOfParametersForCallTo = 3005;
-  nIncompatibleTypeArgNo = 3006;
-  nIncompatibleTypeArgNoVarParamMustMatchExactly = 3007;
-  nVariableIdentifierExpected = 3008;
-  nDuplicateIdentifier = 3009;
-  nXExpectedButYFound = 3010;
-  nAncestorCycleDetected = 3011;
-  nCantUseForwardDeclarationAsAncestor = 3012;
-  nCantDetermineWhichOverloadedFunctionToCall = 3013;
-  nForwardTypeNotResolved = 3014;
-  nForwardProcNotResolved = 3015;
-  nInvalidXModifierY = 3016;
-  nAbstractMethodsMustNotHaveImplementation = 3017;
-  nCallingConventionMismatch = 3018;
-  nResultTypeMismatchExpectedButFound = 3019;
-  nFunctionHeaderMismatchForwardVarName = 3020;
-  nFunctionHidesIdentifier = 3021;
-  nNoMethodInAncestorToOverride = 3022;
-  nInheritedOnlyWorksInMethods = 3023;
-  nInheritedNeedsAncestor = 3024;
-  nNoPropertyFoundToOverride = 3025;
-  nExprTypeMustBeClassOrRecordTypeGot = 3026;
-  nPropertyNotWritable = 3027;
-  nIncompatibleTypesGotExpected = 3028;
-  nTypesAreNotRelated = 3029;
-  nAbstractMethodsCannotBeCalledDirectly = 3030;
-  nMissingParameterX = 3031;
-  nCannotAccessThisMemberFromAX = 3032;
-  nInOperatorExpectsSetElementButGot = 3033;
-  nWrongNumberOfParametersForTypeCast = 3034;
-  nIllegalTypeConversionTo = 3035;
-  nConstantExpressionExpected = 3036;
-  nLeftSideOfIsOperatorExpectsAClassButGot = 3037;
-  nNotReadable = 3038;
-  nClassPropertyAccessorMustBeStatic = 3039;
-  nClassPropertyAccessorMustNotBeStatic = 3040;
-  nOnlyOneDefaultPropertyIsAllowed = 3041;
-  nWrongNumberOfParametersForArray = 3042;
-  nCantAssignValuesToAnAddress = 3043;
-  nIllegalExpression = 3044;
-  nCantAccessPrivateMember = 3045;
-  nMustBeInsideALoop = 3046;
-  nExpectXArrayElementsButFoundY = 3047;
-  nCannotCreateADescendantOfTheSealedClass = 3048;
-  nAncestorIsNotExternal = 3049;
-  nVirtualMethodXHasLowerVisibility = 3050; // FPC 3250
-  nExternalClassInstanceCannotAccessStaticX = 3051;
-  nXModifierMismatchY = 3052;
-  nSymbolCannotBePublished = 3053;
-  nCannotTypecastAType = 3054;
-  nTypeIdentifierExpected = 3055;
-  nCannotNestAnonymousX = 3056;
-  nFoundCallCandidateX = 3057;
-  nSymbolXIsNotPortable = 3058;
-  nSymbolXIsExperimental = 3059;
-  nSymbolXIsNotImplemented = 3060;
-  nSymbolXBelongsToALibrary = 3061;
-  nSymbolXIsDeprecated = 3062;
-  nSymbolXIsDeprecatedY = 3063;
-  nRangeCheckError = 3064;
-  nHighRangeLimitLTLowRangeLimit = 3065;
-
-// resourcestring patterns of messages
-resourcestring
-  sIdentifierNotFound = 'identifier not found "%s"';
-  sNotYetImplemented = 'not yet implemented: %s';
-  sIllegalQualifier = 'illegal qualifier "%s"';
-  sSyntaxErrorExpectedButFound = 'Syntax error, "%s" expected but "%s" found';
-  sWrongNumberOfParametersForCallTo = 'Wrong number of parameters specified for call to "%s"';
-  sIncompatibleTypeArgNo = 'Incompatible type arg no. %s: Got "%s", expected "%s"';
-  sIncompatibleTypeArgNoVarParamMustMatchExactly = 'Incompatible type arg no. %s: Got "%s", expected "%s". Var param must match exactly.';
-  sVariableIdentifierExpected = 'Variable identifier expected';
-  sDuplicateIdentifier = 'Duplicate identifier "%s" at %s';
-  sXExpectedButYFound = '%s expected, but %s found';
-  sAncestorCycleDetected = 'Ancestor cycle detected';
-  sCantUseForwardDeclarationAsAncestor = 'Can''t use forward declaration "%s" as ancestor';
-  sCantDetermineWhichOverloadedFunctionToCall = 'Can''t determine which overloaded function to call';
-  sForwardTypeNotResolved = 'Forward type not resolved "%s"';
-  sForwardProcNotResolved = 'Forward %s not resolved "%s"';
-  sInvalidXModifierY = 'Invalid %s modifier %s';
-  sAbstractMethodsMustNotHaveImplementation = 'Abstract method must not have an implementation.';
-  sCallingConventionMismatch = 'Calling convention mismatch';
-  sResultTypeMismatchExpectedButFound = 'Result type mismatch, expected %s, but found %s';
-  sFunctionHeaderMismatchForwardVarName = 'function header "%s" doesn''t match forward : var name changes %s => %s';
-  sFunctionHidesIdentifier = 'function hides identifier "%s" at "%s"';
-  sNoMethodInAncestorToOverride = 'There is no method in an ancestor class to be overridden "%s"';
-  sInheritedOnlyWorksInMethods = 'Inherited works only in methods';
-  sInheritedNeedsAncestor = 'inherited needs an ancestor';
-  sNoPropertyFoundToOverride = 'No property found to override';
-  sExprTypeMustBeClassOrRecordTypeGot = 'Expression type must be class or record type, got %s';
-  sPropertyNotWritable = 'No member is provided to access property';
-  sIncompatibleTypesGotExpected = 'Incompatible types: got "%s" expected "%s"';
-  sTypesAreNotRelated = 'Types are not related';
-  sAbstractMethodsCannotBeCalledDirectly = 'Abstract methods cannot be called directly';
-  sMissingParameterX = 'Missing parameter %s';
-  sCannotAccessThisMemberFromAX = 'Cannot access this member from a %s';
-  sInOperatorExpectsSetElementButGot = 'the in-operator expects a set element, but got %s';
-  sWrongNumberOfParametersForTypeCast = 'wrong number of parameters for type cast to %s';
-  sIllegalTypeConversionTo = 'Illegal type conversion: "%s" to "%s"';
-  sConstantExpressionExpected = 'Constant expression expected';
-  sLeftSideOfIsOperatorExpectsAClassButGot = 'left side of is-operator expects a class, but got %s';
-  sNotReadable = 'not readable';
-  sClassPropertyAccessorMustBeStatic = 'class property accessor must be static';
-  sClassPropertyAccessorMustNotBeStatic = 'class property accessor must not be static';
-  sOnlyOneDefaultPropertyIsAllowed = 'Only one default property is allowed';
-  sWrongNumberOfParametersForArray = 'Wrong number of parameters for array';
-  sCantAssignValuesToAnAddress = 'Can''t assign values to an address';
-  sIllegalExpression = 'Illegal expression';
-  sCantAccessPrivateMember = 'Can''t access %s member %s';
-  sMustBeInsideALoop = '%s must be inside a loop';
-  sExpectXArrayElementsButFoundY = 'Expect %s array elements, but found %s';
-  sCannotCreateADescendantOfTheSealedClass = 'Cannot create a descendant of the sealed class "%s"';
-  sAncestorIsNotExternal = 'Ancestor "%s" is not external';
-  sVirtualMethodXHasLowerVisibility = 'Virtual method "%s" has a lower visibility (%s) than parent class %s (%s)';
-  sExternalClassInstanceCannotAccessStaticX = 'External class instance cannot access static %s';
-  sXModifierMismatchY = '%s modifier "%s" mismatch';
-  sSymbolCannotBePublished = 'Symbol cannot be published';
-  sCannotTypecastAType = 'Cannot type cast a type';
-  sTypeIdentifierExpected = 'Type identifier expected';
-  sCannotNestAnonymousX = 'Cannot nest anonymous %s';
-  sFoundCallCandidateX = 'Found call candidate %s';
-  sSymbolXIsNotPortable = 'Symbol "%s" is not portable';
-  sSymbolXIsExperimental = 'Symbol "%s" is experimental';
-  sSymbolXIsNotImplemented = 'Symbol "%s" is implemented';
-  sSymbolXBelongsToALibrary = 'Symbol "%s" belongs to a library';
-  sSymbolXIsDeprecated = 'Symbol "%s" is deprecated';
-  sSymbolXIsDeprecatedY = 'Symbol "%s" is deprecated: %s';
-  sRangeCheckError = 'Range check error';
-  sHighRangeLimitLTLowRangeLimit = 'High range limit < low range limit';
-
 type
 type
   TResolverBaseType = (
   TResolverBaseType = (
     btNone,        // undefined
     btNone,        // undefined
@@ -578,20 +447,6 @@ type
   end;
   end;
 
 
 type
 type
-  { TResolveData - base class for data stored in TPasElement.CustomData }
-
-  TResolveData = Class(TPasElementBase)
-  private
-    FElement: TPasElement;
-    procedure SetElement(AValue: TPasElement);
-  public
-    Owner: TObject; // e.g. a TPasResolver
-    Next: TResolveData; // TPasResolver uses this for its memory chain
-    constructor Create; virtual;
-    destructor Destroy; override;
-    property Element: TPasElement read FElement write SetElement;// Element.CustomData=Self
-  end;
-  TResolveDataClass = class of TResolveData;
 
 
   { TUnresolvedPendingRef }
   { TUnresolvedPendingRef }
 
 
@@ -956,86 +811,6 @@ type
   end;
   end;
   PPasResolvedElement = ^TPasResolverResult;
   PPasResolvedElement = ^TPasResolverResult;
 
 
-  { TResEvalValue }
-
-  TREVKind = (
-    revkNone,
-    revkCustom,
-    revkNil,
-    revkBool,
-    revkInt,
-    revkUInt,
-    revkExtended,
-    revkString,
-    revkUnicodeString,
-    revkEnum,
-    revkSet
-    );
-  TResEvalSimpleValue = record
-    case TREVKind of
-    revkBool: (Bool: boolean);
-    revkInt: (Int: int64);
-    revkUInt: (UInt: qword);
-    revkExtended: (Ext: extended);
-  end;
-
-  TResEvalValue = class(TResolveData)
-  public
-    Kind: TREVKind;
-    Value: TResEvalSimpleValue;
-    IdentEl: TPasElement;
-    Expr: TPasExpr;
-    function Clone: TResEvalValue; virtual;
-    function AsString: string; virtual;
-  end;
-  TResEvalValueClass = class of TResEvalValue;
-
-  { TResEvalString - Kind=revkComplex }
-
-  TResEvalString = class(TResEvalValue)
-  public
-    S: String;
-    function Clone: TResEvalValue; override;
-    function AsString: string; override;
-  end;
-
-  { TResEvalUTF16 - Kind=revkComplex }
-
-  TResEvalUTF16 = class(TResEvalValue)
-  public
-    S: UnicodeString;
-    function Clone: TResEvalValue; override;
-    function AsString: string; override;
-  end;
-
-  { TResEvalEnum - Kind=revkComplex, Value.Int, IdentEl is TPasEnumValue }
-
-  TResEvalEnum = class(TResEvalValue)
-  public
-    function AsString: string; override;
-  end;
-
-  TResEvalSetItem = record
-    RangeStart, RangeEnd: int64;// ToDo: qword
-  end;
-  TResEvalSetItems = array of TResEvalSetItem;
-
-  { TResEvalSet - Kind=revkComplex, IdentEl is TPasEnumType }
-
-  TResEvalSet = class(TResEvalValue)
-  public
-    Ranges: TResEvalSetItems;
-    function Clone: TResEvalValue; override;
-    function AsString: string; override;
-  end;
-
-  TResEvalFlag = (
-    refStore, // store result in CustomData
-    refConst, // computing a const, error is a value is not const
-    refSet  // computing a set, allow ranges
-    );
-  TResEvalFlags = set of TResEvalFlag;
-
 type
 type
   TPasResolverComputeFlag = (
   TPasResolverComputeFlag = (
     rcSkipTypeAlias,
     rcSkipTypeAlias,
@@ -1125,6 +900,8 @@ type
     FBaseTypeString: TResolverBaseType;
     FBaseTypeString: TResolverBaseType;
     FDefaultNameSpace: String;
     FDefaultNameSpace: String;
     FDefaultScope: TPasDefaultScope;
     FDefaultScope: TPasDefaultScope;
+    FDynArrayMaxIndex: int64;
+    FDynArrayMinIndex: int64;
     FLastCreatedData: array[TResolveDataListKind] of TResolveData;
     FLastCreatedData: array[TResolveDataListKind] of TResolveData;
     FLastElement: TPasElement;
     FLastElement: TPasElement;
     FLastMsg: string;
     FLastMsg: string;
@@ -1303,7 +1080,13 @@ type
     function CheckRaiseTypeArgNo(id: int64; ArgNo: integer; Param: TPasExpr;
     function CheckRaiseTypeArgNo(id: int64; ArgNo: integer; Param: TPasExpr;
       const ParamResolved: TPasResolverResult; Expected: string; RaiseOnError: boolean): integer;
       const ParamResolved: TPasResolverResult; Expected: string; RaiseOnError: boolean): integer;
   protected
   protected
-    function Eval(Expr: TPasExpr; Flags: TResEvalFlags; ErrorEl: TPasElement = nil): TResEvalValue;
+    fExprEvaluator: TResExprEvaluator;
+    procedure OnExprEvalLog(Sender: TResExprEvaluator; const id: int64;
+      MsgType: TMessageType; MsgNumber: integer; const Fmt: String;
+      Args: array of const; PosEl: TPasElement);
+    function OnExprEvalIdentifier(Sender: TResExprEvaluator;
+      Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue;
+    function Eval(Expr: TPasExpr; Flags: TResEvalFlags; Store: boolean = true): TResEvalValue;
   protected
   protected
     // custom types (added by descendant resolvers)
     // custom types (added by descendant resolvers)
     function CheckAssignCompatibilityCustom(
     function CheckAssignCompatibilityCustom(
@@ -1485,7 +1268,7 @@ type
     function CheckCallPropertyCompatibility(PropEl: TPasProperty;
     function CheckCallPropertyCompatibility(PropEl: TPasProperty;
       Params: TParamsExpr; RaiseOnError: boolean): integer;
       Params: TParamsExpr; RaiseOnError: boolean): integer;
     function CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
     function CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
-      Params: TParamsExpr; RaiseOnError: boolean): integer;
+      Params: TParamsExpr; RaiseOnError: boolean; EmitHints: boolean = false): integer;
     function CheckParamCompatibility(Expr: TPasExpr; Param: TPasArgument;
     function CheckParamCompatibility(Expr: TPasExpr; Param: TPasArgument;
       ParamNo: integer; RaiseOnError: boolean; SetReferenceFlags: boolean = false): integer;
       ParamNo: integer; RaiseOnError: boolean; SetReferenceFlags: boolean = false): integer;
     function CheckAssignCompatibilityUserType(
     function CheckAssignCompatibilityUserType(
@@ -1585,6 +1368,8 @@ type
     property BaseTypeExtended: TResolverBaseType read FBaseTypeExtended write FBaseTypeExtended;
     property BaseTypeExtended: TResolverBaseType read FBaseTypeExtended write FBaseTypeExtended;
     property BaseTypeString: TResolverBaseType read FBaseTypeString write FBaseTypeString;
     property BaseTypeString: TResolverBaseType read FBaseTypeString write FBaseTypeString;
     property BaseTypeLength: TResolverBaseType read FBaseTypeLength write FBaseTypeLength;
     property BaseTypeLength: TResolverBaseType read FBaseTypeLength write FBaseTypeLength;
+    property DynArrayMinIndex: int64 read FDynArrayMinIndex write FDynArrayMinIndex;
+    property DynArrayMaxIndex: int64 read FDynArrayMaxIndex write FDynArrayMaxIndex;
     // parsed values
     // parsed values
     property DefaultNameSpace: String read FDefaultNameSpace;
     property DefaultNameSpace: String read FDefaultNameSpace;
     property RootElement: TPasModule read FRootElement;
     property RootElement: TPasModule read FRootElement;
@@ -1610,7 +1395,6 @@ type
     property LastSourcePos: TPasSourcePos read FLastSourcePos write FLastSourcePos;
     property LastSourcePos: TPasSourcePos read FLastSourcePos write FLastSourcePos;
   end;
   end;
 
 
-function GetObjName(o: TObject): string;
 function GetTreeDbg(El: TPasElement; Indent: integer = 0): string;
 function GetTreeDbg(El: TPasElement; Indent: integer = 0): string;
 function GetResolverResultDbg(const T: TPasResolverResult): string;
 function GetResolverResultDbg(const T: TPasResolverResult): string;
 function GetClassAncestorsDbg(El: TPasClassType): string;
 function GetClassAncestorsDbg(El: TPasClassType): string;
@@ -1626,8 +1410,6 @@ procedure SetResolverValueExpr(out ResolvedType: TPasResolverResult;
   BaseType: TResolverBaseType; TypeEl: TPasType; ExprEl: TPasExpr;
   BaseType: TResolverBaseType; TypeEl: TPasType; ExprEl: TPasExpr;
   Flags: TPasResolverResultFlags); overload;
   Flags: TPasResolverResultFlags); overload;
 
 
-procedure ReleaseEvalValue(var Value: TResEvalValue);
-
 function ProcNeedsImplProc(Proc: TPasProcedure): boolean;
 function ProcNeedsImplProc(Proc: TPasProcedure): boolean;
 function ChompDottedIdentifier(const Identifier: string): string;
 function ChompDottedIdentifier(const Identifier: string): string;
 function FirstDottedIdentifier(const Identifier: string): string;
 function FirstDottedIdentifier(const Identifier: string): string;
@@ -1639,20 +1421,9 @@ function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDot
 function dbgs(const Flags: TPasResolverComputeFlags): string; overload;
 function dbgs(const Flags: TPasResolverComputeFlags): string; overload;
 function dbgs(const a: TResolvedRefAccess): string;
 function dbgs(const a: TResolvedRefAccess): string;
 function dbgs(const Flags: TResolvedReferenceFlags): string; overload;
 function dbgs(const Flags: TResolvedReferenceFlags): string; overload;
-function dbgs(const Flags: TResEvalFlags): string; overload;
 
 
 implementation
 implementation
 
 
-function GetObjName(o: TObject): string;
-begin
-  if o=nil then
-    Result:='nil'
-  else if o is TPasElement then
-    Result:=TPasElement(o).Name+':'+o.ClassName
-  else
-    Result:=o.ClassName;
-end;
-
 function GetTreeDbg(El: TPasElement; Indent: integer): string;
 function GetTreeDbg(El: TPasElement; Indent: integer): string;
 
 
   procedure LineBreak(SubIndent: integer);
   procedure LineBreak(SubIndent: integer);
@@ -1893,14 +1664,6 @@ begin
   ResolvedType.Flags:=Flags;
   ResolvedType.Flags:=Flags;
 end;
 end;
 
 
-procedure ReleaseEvalValue(var Value: TResEvalValue);
-begin
-  if Value=nil then exit;
-  if Value.Element<>nil then exit;
-  Value.Free;
-  Value:=nil;
-end;
-
 function ProcNeedsImplProc(Proc: TPasProcedure): boolean;
 function ProcNeedsImplProc(Proc: TPasProcedure): boolean;
 begin
 begin
   Result:=true;
   Result:=true;
@@ -2027,106 +1790,6 @@ begin
   Result:='['+Result+']';
   Result:='['+Result+']';
 end;
 end;
 
 
-function dbgs(const Flags: TResEvalFlags): string;
-var
-  s: string;
-  f: TResEvalFlag;
-begin
-  Result:='';
-  for f in Flags do
-    if f in Flags then
-      begin
-      if Result<>'' then Result:=Result+',';
-      str(f,s);
-      Result:=Result+s;
-      end;
-  Result:='['+Result+']';
-end;
-
-{ TResEvalEnum }
-
-function TResEvalEnum.AsString: string;
-begin
-  Result:=inherited AsString+'='+IdentEl.Name+'='+IntToStr(Value.Int);
-end;
-
-{ TResEvalSet }
-
-function TResEvalSet.Clone: TResEvalValue;
-var
-  RS: TResEvalSet;
-  i: Integer;
-begin
-  Result:=inherited Clone;
-  RS:=TResEvalSet(Result);
-  SetLength(RS.Ranges,length(Ranges));
-  for i:=0 to length(Ranges)-1 do
-    RS.Ranges[i]:=Ranges[i];
-end;
-
-function TResEvalSet.AsString: string;
-var
-  i: Integer;
-begin
-  Result:=inherited AsString+'[';
-  for i:=0 to length(Ranges)-1 do
-    begin
-    if i>0 then Result:=Result+',';
-    Result:=Result+IntToStr(Ranges[i].RangeStart);
-    if Ranges[i].RangeStart<>Ranges[i].RangeEnd then
-      Result:=Result+'..'+IntToStr(Ranges[i].RangeEnd);
-    end;
-  Result:=Result+']';
-end;
-
-{ TResEvalUTF16 }
-
-function TResEvalUTF16.Clone: TResEvalValue;
-begin
-  Result:=inherited Clone;
-  TResEvalUTF16(Result).S:=S;
-end;
-
-function TResEvalUTF16.AsString: string;
-begin
-  Result:=inherited AsString+'='''+String(S)+'''';
-end;
-
-{ TResEvalString }
-
-function TResEvalString.Clone: TResEvalValue;
-begin
-  Result:=inherited Clone;
-  TResEvalString(Result).S:=S;
-end;
-
-function TResEvalString.AsString: string;
-begin
-  Result:=inherited AsString+'='''+S+'''';
-end;
-
-{ TResEvalValue }
-
-function TResEvalValue.Clone: TResEvalValue;
-begin
-  Result:=TResEvalValueClass(ClassType).Create;
-  Result.Kind:=Kind;
-  Result.Value:=Value;
-  Result.IdentEl:=IdentEl;
-  Result.Expr:=Expr;
-end;
-
-function TResEvalValue.AsString: string;
-begin
-  str(Kind,Result);
-  case Kind of
-    revkBool: Result:=Result+'='+BoolToStr(Value.Bool,true);
-    revkInt: Result:=Result+'='+IntToStr(Value.Int);
-    revkUInt: Result:=Result+'='+IntToStr(Value.UInt);
-    revkExtended: Result:=Result+'='+FloatToStr(Value.Ext);
-  end;
-end;
-
 { TPasPropertyScope }
 { TPasPropertyScope }
 
 
 destructor TPasPropertyScope.Destroy;
 destructor TPasPropertyScope.Destroy;
@@ -2562,37 +2225,6 @@ begin
   Result:=false;
   Result:=false;
 end;
 end;
 
 
-{ TResolveData }
-
-procedure TResolveData.SetElement(AValue: TPasElement);
-begin
-  if FElement=AValue then Exit;
-  if Element<>nil then
-    Element.Release;
-  FElement:=AValue;
-  if Element<>nil then
-    Element.AddRef;
-end;
-
-constructor TResolveData.Create;
-begin
-
-end;
-
-destructor TResolveData.Destroy;
-begin
-  {$IFDEF VerbosePasResolverMem}
-  writeln('TResolveData.Destroy START ',ClassName);
-  {$ENDIF}
-  Element:=nil;
-  Owner:=nil;
-  Next:=nil;
-  inherited Destroy;
-  {$IFDEF VerbosePasResolverMem}
-  writeln('TResolveData.Destroy END ',ClassName);
-  {$ENDIF}
-end;
-
 { TPasScope }
 { TPasScope }
 
 
 class function TPasScope.IsStoredInElement: boolean;
 class function TPasScope.IsStoredInElement: boolean;
@@ -3729,7 +3361,7 @@ procedure TPasResolver.FinishConstRangeExpr(Left, Right: TPasExpr; out LeftResol
   RightResolved: TPasResolverResult);
   RightResolved: TPasResolverResult);
 {$IFDEF EnablePasResRangeCheck}
 {$IFDEF EnablePasResRangeCheck}
 var
 var
-  LeftValue, RightValue: TResEvalValue;
+  RgValue: TResEvalValue;
 {$ENDIF}
 {$ENDIF}
 begin
 begin
   {$IFDEF VerbosePasResEval}
   {$IFDEF VerbosePasResEval}
@@ -3741,61 +3373,8 @@ begin
   CheckSetLitElCompatible(Left,Right,LeftResolved,RightResolved);
   CheckSetLitElCompatible(Left,Right,LeftResolved,RightResolved);
 
 
   {$IFDEF EnablePasResRangeCheck}
   {$IFDEF EnablePasResRangeCheck}
-  // check value
-  LeftValue:=nil;
-  RightValue:=nil;
-  try
-    LeftValue:=Eval(Left,[refStore,refConst]);
-    RightValue:=Eval(Right,[refStore,refConst]);
-    {$IFDEF VerbosePasResEval}
-    writeln('TPasResolver.FinishConstRangeExpr Left=',LeftValue.AsString,' Right=',RightValue.AsString);
-    {$ENDIF}
-    case LeftValue.Kind of
-    revkInt,revkUInt:
-      begin
-      if not (RightValue.Kind in [revkInt,revkUInt]) then
-        RaiseRangeCheck(20170518222812,Right);
-      if LeftValue.Kind=revkInt then
-        begin
-        if RightValue.Kind=revkInt then
-          begin
-          if LeftValue.Value.Int>RightValue.Value.Int then
-            RaiseMsg(20170518222939,nHighRangeLimitLTLowRangeLimit,
-              sHighRangeLimitLTLowRangeLimit,[],Right);
-          end
-        else
-          begin
-          if LeftValue.Value.Int>RightValue.Value.UInt then
-            RaiseMsg(20170519000235,nHighRangeLimitLTLowRangeLimit,
-              sHighRangeLimitLTLowRangeLimit,[],Right);
-          end;
-        end
-      else
-        begin
-        if RightValue.Kind=revkInt then
-          begin
-          if LeftValue.Value.UInt>RightValue.Value.Int then
-            RaiseMsg(20170519000238,nHighRangeLimitLTLowRangeLimit,
-              sHighRangeLimitLTLowRangeLimit,[],Right);
-          end
-        else
-          begin
-          if LeftValue.Value.UInt>RightValue.Value.UInt then
-            RaiseMsg(20170519000240,nHighRangeLimitLTLowRangeLimit,
-              sHighRangeLimitLTLowRangeLimit,[],Right);
-          end;
-        end;
-      end;
-    else
-      {$IFDEF EnablePasResRangeCheck}
-      writeln('TPasResolver.FinishConstRangeExpr Left=',GetObjName(Left),' LeftValue.Kind=',LeftValue.Kind);
-      RaiseNotYetImplemented(20170518221103,Left);
-      {$ENDIF}
-    end;
-  finally
-    ReleaseEvalValue(LeftValue);
-    ReleaseEvalValue(RightValue);
-  end;
+  RgValue:=Eval(Left.Parent as TBinaryExpr,[refConst]);
+  ReleaseEvalValue(RgValue);
   {$ENDIF}
   {$ENDIF}
 end;
 end;
 
 
@@ -6036,7 +5615,7 @@ begin
       begin
       begin
       if ResolvedValue.IdentEl is TPasType then
       if ResolvedValue.IdentEl is TPasType then
         RaiseMsg(20170216152215,nIllegalQualifier,sIllegalQualifier,['['],Params);
         RaiseMsg(20170216152215,nIllegalQualifier,sIllegalQualifier,['['],Params);
-      CheckCallArrayCompatibility(TPasArrayType(ResolvedValue.TypeEl),Params,true);
+      CheckCallArrayCompatibility(TPasArrayType(ResolvedValue.TypeEl),Params,true,true);
       for i:=0 to length(Params.Params)-1 do
       for i:=0 to length(Params.Params)-1 do
         AccessExpr(Params.Params[i],rraRead);
         AccessExpr(Params.Params[i],rraRead);
       exit;
       exit;
@@ -7705,196 +7284,135 @@ begin
   Result:=cIncompatible;
   Result:=cIncompatible;
 end;
 end;
 
 
-function TPasResolver.Eval(Expr: TPasExpr; Flags: TResEvalFlags;
-  ErrorEl: TPasElement): TResEvalValue;
-// Important: Caller must free result if (Result<>nil) and (Result.Element=nil)
+procedure TPasResolver.OnExprEvalLog(Sender: TResExprEvaluator;
+  const id: int64; MsgType: TMessageType; MsgNumber: integer;
+  const Fmt: String; Args: array of const; PosEl: TPasElement);
+begin
+  if MsgType<=mtError then
+    RaiseMsg(id,MsgNumber,Fmt,Args,PosEl)
+  else
+    LogMsg(id,MsgType,MsgNumber,Fmt,Args,PosEl);
+  if Sender=nil then ;
+end;
+
+function TPasResolver.OnExprEvalIdentifier(Sender: TResExprEvaluator;
+  Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue;
 var
 var
-  C: TClass;
-  Int: int64;
-  UInt: QWord;
-  Ext: Extended;
-  Code: integer;
   Ref: TResolvedReference;
   Ref: TResolvedReference;
   Decl: TPasElement;
   Decl: TPasElement;
+  C: TClass;
+  BaseTypeData: TResElDataBaseType;
 begin
 begin
   Result:=nil;
   Result:=nil;
-  if Expr.CustomData is TResEvalValue then
-    begin
-    Result:=TResEvalValue(Expr.CustomData);
-    exit;
-    end;
-  if ErrorEl=nil then
-    ErrorEl:=Expr;
-  if (refStore in Flags) and (Expr.CustomData=nil) then
+  if not (Expr.CustomData is TResolvedReference) then
+    RaiseNotYetImplemented(20170518203134,Expr);
+  Ref:=TResolvedReference(Expr.CustomData);
+  Decl:=Ref.Declaration;
+  C:=Decl.ClassType;
+  if C=TPasConst then
     begin
     begin
-    Result:=Eval(Expr,Flags-[refStore],ErrorEl);
-    if Result.Element<>nil then
-      exit; // already stored
-    AddResolveData(Expr,Result,lkModule);
-    exit;
-    end;
-
-  {$IFDEF VerbosePasResEval}
-  writeln('TPasResolver.Eval Expr=',GetObjName(Expr),' Flags=',dbgs(Flags));
-  {$ENDIF}
-  C:=Expr.ClassType;
-  if C=TPrimitiveExpr then
+    if (TPasConst(Decl).Expr<>nil)
+        and (TPasConst(Decl).IsConst or (TPasConst(Decl).VarType=nil)) then
+      begin
+      Result:=fExprEvaluator.Eval(TPasConst(Decl).Expr,Flags);
+      if Result<>nil then
+        begin
+        Result.IdentEl:=Decl;
+        exit;
+        end;
+      end;
+    if refConst in Flags then
+      RaiseConstantExprExp(20170518214928,Expr);
+    end
+  else if C.InheritsFrom(TPasType) then
     begin
     begin
-    case TPrimitiveExpr(Expr).Kind of
-      pekIdent:
+    Decl:=ResolveAliasType(TPasType(Decl));
+    C:=Decl.ClassType;
+    if C=TPasRangeType then
+      begin
+      Result:=fExprEvaluator.Eval(TPasRangeType(Decl).RangeExpr,Flags);
+      if Result<>nil then
         begin
         begin
-        if not (Expr.CustomData is TResolvedReference) then
-          RaiseNotYetImplemented(20170518203134,Expr);
-        Ref:=TResolvedReference(Expr.CustomData);
-        Decl:=Ref.Declaration;
-        C:=Decl.ClassType;
-        if C=TPasConst then
-          begin
-          if (TPasConst(Decl).Expr<>nil)
-              and (TPasConst(Decl).IsConst or (TPasConst(Decl).VarType=nil)) then
-            begin
-            Result:=Eval(TPasConst(Decl).Expr,Flags,ErrorEl);
-            Result.IdentEl:=Decl;
-            exit;
-            end;
-          if refConst in Flags then
-            RaiseConstantExprExp(20170518214928,ErrorEl);
-          end
-        else if Decl is TPasType then
-          begin
-          Decl:=ResolveAliasType(TPasType(Decl));
-          C:=Decl.ClassType;
-          if C=TPasRangeType then
-            begin
-            if refSet in Flags then
-              begin
-              Result:=Eval(TPasRangeType(Decl).RangeExpr,Flags,ErrorEl);
-              Result.IdentEl:=Ref.Declaration;
-              exit;
-              end;
-            end;
-          end;
-        if refConst in Flags then
-          RaiseConstantExprExp(20170518213616,ErrorEl);
+        Result.IdentEl:=Ref.Declaration;
+        exit;
         end;
         end;
-      pekNumber:
+      end
+    else if C=TPasUnresolvedSymbolRef then
+      begin
+      if (Decl.CustomData is TResElDataBaseType) then
         begin
         begin
-        // try int64
-        val(TPrimitiveExpr(Expr).Value,Int,Code);
-        if Code=0 then
+        BaseTypeData:=TResElDataBaseType(Decl.CustomData);
+        case BaseTypeData.BaseType of
+        btChar:
           begin
           begin
-          Result:=TResEvalValue.Create;
-          Result.Kind:=revkInt;
-          Result.Value.Int:=Int;
-          Result.Expr:=Expr;
-          exit;
+          Result:=TResEvalRangeInt.Create;
+          TResEvalRangeInt(Result).ElKind:=revrikChar;
+          TResEvalRangeInt(Result).RangeStart:=0;
+          if BaseTypeChar=btChar then
+            TResEvalRangeInt(Result).RangeEnd:=$ff
+          else
+            TResEvalRangeInt(Result).RangeEnd:=$ffff;
           end;
           end;
-        // try qword
-        val(TPrimitiveExpr(Expr).Value,UInt,Code);
-        if Code=0 then
+        btAnsiChar:
           begin
           begin
-          Result:=TResEvalValue.Create;
-          Result.Kind:=revkUInt;
-          Result.Value.UInt:=UInt;
-          Result.Expr:=Expr;
-          exit;
+          Result:=TResEvalRangeInt.Create;
+          TResEvalRangeInt(Result).ElKind:=revrikChar;
+          TResEvalRangeInt(Result).RangeStart:=0;
+          TResEvalRangeInt(Result).RangeEnd:=$ff
           end;
           end;
-        // try extended
-        val(TPrimitiveExpr(Expr).Value,Ext,Code);
-        if Code=0 then
+        btWideChar:
           begin
           begin
-          Result:=TResEvalValue.Create;
-          Result.Kind:=revkExtended;
-          Result.Value.Ext:=Ext;
-          Result.Expr:=Expr;
-          exit;
+          Result:=TResEvalRangeInt.Create;
+          TResEvalRangeInt(Result).ElKind:=revrikChar;
+          TResEvalRangeInt(Result).RangeStart:=0;
+          TResEvalRangeInt(Result).RangeEnd:=$ffff;
           end;
           end;
-        RaiseRangeCheck(20170518202252,Expr);
-        end;
-      pekString:
-        begin
-        Result:=TResEvalString.Create;
-        Result.Kind:=revkString;
-        Result.Expr:=Expr;
-        TResEvalString(Result).S:=TPrimitiveExpr(Expr).Value;
-        exit;
-        end;
-    else
-      RaiseNotYetImplemented(20170518200951,Expr);
-    end;
-    end
-  else if C=TNilExpr then
-    begin
-    Result:=TResEvalValue.Create;
-    Result.Kind:=revkNil;
-    Result.Expr:=Expr;
-    end
-  else if C=TBoolConstExpr then
-    begin
-    Result:=TResEvalValue.Create;
-    Result.Kind:=revkBool;
-    Result.Expr:=Expr;
-    Result.Value.Bool:=TBoolConstExpr(Expr).Value;
-    end
-  else if C=TUnaryExpr then
-    begin
-    Result:=Eval(TUnaryExpr(Expr).Operand,Flags,ErrorEl);
-    if Result=nil then exit;
-    case TUnaryExpr(Expr).OpCode of
-      eopAdd: ;
-      eopSubtract:
-        case Result.Kind of
-        revkInt:
+        btBoolean,btByteBool,btWordBool,btQWordBool:
           begin
           begin
-          if Result.Value.Int=0 then exit;
-          if Result.Element<>nil then
-            Result:=Result.Clone;
-          Result.Value.Int:=-Result.Value.Int;
+          Result:=TResEvalRangeInt.Create;
+          TResEvalRangeInt(Result).ElKind:=revrikBool;
+          TResEvalRangeInt(Result).RangeStart:=0;
+          TResEvalRangeInt(Result).RangeEnd:=1;
           end;
           end;
-        revkUInt:
+        btByte,
+        btShortInt,
+        btWord,
+        btSmallInt,
+        btLongWord,
+        btLongint,
+        btInt64,
+        btComp,
+        btIntSingle,
+        btUIntSingle,
+        btIntDouble,
+        btUIntDouble:
           begin
           begin
-          if Result.Value.UInt=0 then exit;
-          if Result.Element<>nil then
-            Result:=Result.Clone;
-          Result.Value.UInt:=-Result.Value.UInt;
-          end
-        else
-          begin
-          if Result.Element=nil then
-            Result.Free;
-          RaiseNotYetImplemented(20170518230738,Expr);
+          Result:=TResEvalRangeInt.Create;
+          TResEvalRangeInt(Result).ElKind:=revrikInt;
+          GetIntegerRange(BaseTypeData.BaseType,
+            TResEvalRangeInt(Result).RangeStart,TResEvalRangeInt(Result).RangeEnd);
           end;
           end;
         end;
         end;
-      eopNot:
-        case Result.Kind of
-        revkBool:
-          begin
-          if Result.Element<>nil then
-            Result:=Result.Clone;
-          Result.Value.Bool:=not Result.Value.Bool;
-          end
-        else
-          begin
-          if Result.Element=nil then
-            Result.Free;
-          RaiseNotYetImplemented(20170518232804,Expr);
-          end;
         end;
         end;
-      eopAddress:
-        begin
-        if Result.Element=nil then
-          Result.Free;
-        // @ operator requires a compiler -> return nil
-        Result:=TResEvalString.Create;
-        Result.Kind:=revkNil;
-        Result.Expr:=Expr;
-        end
-      else
-        RaiseNotYetImplemented(20170518232823,Expr);
       end;
       end;
-    end
-  else if refConst in Flags then
-    RaiseConstantExprExp(20170518213800,ErrorEl);
+    end;
+  if refConst in Flags then
+    RaiseConstantExprExp(20170518213616,Expr);
+end;
+
+function TPasResolver.Eval(Expr: TPasExpr; Flags: TResEvalFlags;
+  Store: boolean): TResEvalValue;
+// Important: Caller must free result if (Result<>nil) and (Result.Element=nil)
+//            use utility function ReleaseEvalValue(Result)
+begin
+  Result:=fExprEvaluator.Eval(Expr,Flags);
+  if Result=nil then exit;
+
+  if Store
+      and (Expr.CustomData=nil)
+      and (Result.Element=nil)
+      and (not fExprEvaluator.IsSimpleExpr(Expr)) then
+    AddResolveData(Expr,Result,lkModule);
 end;
 end;
 
 
 function TPasResolver.CheckAssignCompatibilityCustom(const LHS,
 function TPasResolver.CheckAssignCompatibilityCustom(const LHS,
@@ -8877,8 +8395,13 @@ begin
   FBaseTypeString:=btAnsiString;
   FBaseTypeString:=btAnsiString;
   FBaseTypeExtended:=btDouble;
   FBaseTypeExtended:=btDouble;
   FBaseTypeLength:=btInt64;
   FBaseTypeLength:=btInt64;
+  FDynArrayMinIndex:=0;
+  FDynArrayMaxIndex:=High(int64);
   FScopeClass_Class:=TPasClassScope;
   FScopeClass_Class:=TPasClassScope;
   FScopeClass_WithExpr:=TPasWithExprScope;
   FScopeClass_WithExpr:=TPasWithExprScope;
+  fExprEvaluator:=TResExprEvaluator.Create;
+  fExprEvaluator.OnLog:=@OnExprEvalLog;
+  fExprEvaluator.OnEvalIdentifier:=@OnExprEvalIdentifier;
   PushScope(FDefaultScope);
   PushScope(FDefaultScope);
 end;
 end;
 
 
@@ -9549,6 +9072,7 @@ begin
   writeln('TPasResolver.Destroy FPendingForwards...');
   writeln('TPasResolver.Destroy FPendingForwards...');
   {$ENDIF}
   {$ENDIF}
   FreeAndNil(FPendingForwards);
   FreeAndNil(FPendingForwards);
+  FreeAndNil(fExprEvaluator);
   inherited Destroy;
   inherited Destroy;
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasResolver.Destroy END ',ClassName);
   writeln('TPasResolver.Destroy END ',ClassName);
@@ -10304,7 +9828,7 @@ begin
 end;
 end;
 
 
 function TPasResolver.CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
 function TPasResolver.CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
-  Params: TParamsExpr; RaiseOnError: boolean): integer;
+  Params: TParamsExpr; RaiseOnError: boolean; EmitHints: boolean): integer;
 var
 var
   ArgNo: Integer;
   ArgNo: Integer;
   Param: TPasExpr;
   Param: TPasExpr;
@@ -10325,6 +9849,9 @@ var
   RangeResolved: TPasResolverResult;
   RangeResolved: TPasResolverResult;
   bt: TResolverBaseType;
   bt: TResolverBaseType;
   NextType: TPasType;
   NextType: TPasType;
+  ParamValue: TResEvalValue;
+  RangeExpr: TPasExpr;
+  TypeFits: Boolean;
 begin
 begin
   ArgNo:=0;
   ArgNo:=0;
   repeat
   repeat
@@ -10335,6 +9862,20 @@ begin
       if (not (rrfReadable in ParamResolved.Flags))
       if (not (rrfReadable in ParamResolved.Flags))
           or not (ParamResolved.BaseType in btAllInteger) then
           or not (ParamResolved.BaseType in btAllInteger) then
         exit(CheckRaiseTypeArgNo(20170216152417,ArgNo,Param,ParamResolved,'integer',RaiseOnError));
         exit(CheckRaiseTypeArgNo(20170216152417,ArgNo,Param,ParamResolved,'integer',RaiseOnError));
+      if EmitHints then
+        begin
+        ParamValue:=Eval(Param,[refAutoConst]);
+        if ParamValue<>nil then
+          try // has const value -> check range
+            if (ParamValue.Kind<>revkInt)
+                or (TResEvalInt(ParamValue).Int<DynArrayMinIndex)
+                or (TResEvalInt(ParamValue).Int>DynArrayMaxIndex) then
+              fExprEvaluator.EmitRangeCheckConst(20170520202212,ParamValue.AsString,
+                                  DynArrayMinIndex,DynArrayMaxIndex,Param);
+          finally
+            ReleaseEvalValue(ParamValue);
+          end;
+        end;
       end
       end
     else
     else
       begin
       begin
@@ -10342,7 +9883,8 @@ begin
       for DimNo:=0 to length(ArrayEl.Ranges)-1 do
       for DimNo:=0 to length(ArrayEl.Ranges)-1 do
         begin
         begin
         GetNextParam;
         GetNextParam;
-        ComputeElement(ArrayEl.Ranges[DimNo],RangeResolved,[]);
+        RangeExpr:=ArrayEl.Ranges[DimNo];
+        ComputeElement(RangeExpr,RangeResolved,[]);
         bt:=RangeResolved.BaseType;
         bt:=RangeResolved.BaseType;
         if bt=btRange then
         if bt=btRange then
           bt:=RangeResolved.SubType;
           bt:=RangeResolved.SubType;
@@ -10352,22 +9894,28 @@ begin
           RaiseIncompatibleTypeRes(20170216152421,nIncompatibleTypeArgNo,
           RaiseIncompatibleTypeRes(20170216152421,nIncompatibleTypeArgNo,
             [IntToStr(ArgNo)],ParamResolved,RangeResolved,Param);
             [IntToStr(ArgNo)],ParamResolved,RangeResolved,Param);
           end;
           end;
+        TypeFits:=false;
         if (bt in btAllBooleans) and (ParamResolved.BaseType in btAllBooleans) then
         if (bt in btAllBooleans) and (ParamResolved.BaseType in btAllBooleans) then
-          continue
+          TypeFits:=true
         else if (bt in btAllInteger) and (ParamResolved.BaseType in btAllInteger) then
         else if (bt in btAllInteger) and (ParamResolved.BaseType in btAllInteger) then
-          continue
+          TypeFits:=true
         else if (bt in btAllChars) and (ParamResolved.BaseType in btAllChars) then
         else if (bt in btAllChars) and (ParamResolved.BaseType in btAllChars) then
-          continue
+          TypeFits:=true
         else if (bt=btContext) and (ParamResolved.BaseType=btContext) then
         else if (bt=btContext) and (ParamResolved.BaseType=btContext) then
           begin
           begin
           if (RangeResolved.TypeEl.ClassType=TPasEnumType)
           if (RangeResolved.TypeEl.ClassType=TPasEnumType)
               and (RangeResolved.TypeEl=ParamResolved.TypeEl) then
               and (RangeResolved.TypeEl=ParamResolved.TypeEl) then
-            continue;
+            TypeFits:=true
+          end;
+        if not TypeFits then
+          begin
+          // incompatible
+          if not RaiseOnError then exit(cIncompatible);
+          RaiseIncompatibleTypeRes(20170216152422,nIncompatibleTypeArgNo,
+            [IntToStr(ArgNo)],ParamResolved,RangeResolved,Param);
           end;
           end;
-        // incompatible
-        if not RaiseOnError then exit(cIncompatible);
-        RaiseIncompatibleTypeRes(20170216152422,nIncompatibleTypeArgNo,
-          [IntToStr(ArgNo)],ParamResolved,RangeResolved,Param);
+        if EmitHints then
+          fExprEvaluator.IsInRange(Param,RangeExpr,true);
         end;
         end;
       end;
       end;
     if ArgNo=length(Params.Params) then exit(cExact);
     if ArgNo=length(Params.Params) then exit(cExact);

+ 5 - 1
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -49,7 +49,11 @@ unit PasUseAnalyzer;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, AVL_Tree, PasResolver, PasTree, PScanner;
+  Classes, SysUtils, AVL_Tree, PasTree, PScanner,
+  {$IFDEF VerbosePasAnalyzer}
+  PasResolveEval
+  {$ENDIF}
+  PasResolver;
 
 
 const
 const
   nPAUnitNotUsed = 5023;
   nPAUnitNotUsed = 5023;

+ 22 - 6
packages/fcl-passrc/src/pparser.pp

@@ -337,6 +337,7 @@ type
     function CurTokenText: String;
     function CurTokenText: String;
     Function CurComments : TStrings;
     Function CurComments : TStrings;
     function CurSourcePos: TPasSourcePos;
     function CurSourcePos: TPasSourcePos;
+    function HasToken: boolean;
     Function SavedComments : String;
     Function SavedComments : String;
     procedure NextToken; // read next non whitespace, non space
     procedure NextToken; // read next non whitespace, non space
     procedure ChangeToken(tk: TToken);
     procedure ChangeToken(tk: TToken);
@@ -866,10 +867,23 @@ end;
 
 
 function TPasParser.CurSourcePos: TPasSourcePos;
 function TPasParser.CurSourcePos: TPasSourcePos;
 begin
 begin
-  if FTokenRingStart=FTokenRingEnd then
-    Result:=Default(TPasSourcePos)
+  if HasToken then
+    Result:=FTokenRing[FTokenRingCur].SourcePos
   else
   else
-    Result:=FTokenRing[FTokenRingCur].SourcePos;
+    begin
+    if Scanner<>nil then
+      Result:=Scanner.CurSourcePos
+    else
+      Result:=Default(TPasSourcePos);
+    end;
+end;
+
+function TPasParser.HasToken: boolean;
+begin
+  if FTokenRingStart<FTokenRingEnd then
+    Result:=(FTokenRingCur>=FTokenRingStart) and (FTokenRingCur<FTokenRingEnd)
+  else
+    Result:=(FTokenRingCur>=FTokenRingStart) or (FTokenRingCur<FTokenRingEnd);
 end;
 end;
 
 
 function TPasParser.SavedComments: String;
 function TPasParser.SavedComments: String;
@@ -1001,7 +1015,7 @@ begin
   if not (CurToken in tk) then
   if not (CurToken in tk) then
     begin
     begin
     {$IFDEF VerbosePasParser}
     {$IFDEF VerbosePasParser}
-    writeln('TPasParser.ParseExcTokenError String="',CurTokenString,'" Text="',CurTokenText,'" CurToken=',CurToken,' tk=',tk);
+    writeln('TPasParser.ParseExcTokenError String="',CurTokenString,'" Text="',CurTokenText,'" CurToken=',CurToken);
     {$ENDIF}
     {$ENDIF}
     S:='';
     S:='';
     For T in TToken do
     For T in TToken do
@@ -1884,7 +1898,7 @@ end;
 
 
 function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
 function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
 
 
-  Function IsWriteOrstr(P : TPasExpr) : boolean;
+  Function IsWriteOrStr(P : TPasExpr) : boolean;
 
 
   Var
   Var
     N : String;
     N : String;
@@ -2030,6 +2044,7 @@ begin
       end;
       end;
     tkAt:
     tkAt:
       begin
       begin
+      // is this still needed?
       // P:=@function;
       // P:=@function;
       NextToken;
       NextToken;
       if (length(CurTokenText)=0) or not (CurTokenText[1] in ['A'..'_']) then
       if (length(CurTokenText)=0) or not (CurTokenText[1] in ['A'..'_']) then
@@ -2041,6 +2056,7 @@ begin
       end;
       end;
     tkCaret:
     tkCaret:
       begin
       begin
+      // is this still needed?
       // ^A..^_ characters. See #16341
       // ^A..^_ characters. See #16341
       NextToken;
       NextToken;
       if not (length(CurTokenText)=1) or not (CurTokenText[1] in ['A'..'_']) then
       if not (length(CurTokenText)=1) or not (CurTokenText[1] in ['A'..'_']) then
@@ -2086,7 +2102,7 @@ begin
       tkBraceOpen,tkSquaredBraceOpen:
       tkBraceOpen,tkSquaredBraceOpen:
         begin
         begin
         if CurToken=tkBraceOpen then
         if CurToken=tkBraceOpen then
-          prm:=ParseParams(AParent,pekFuncParams,isWriteOrStr(func))
+          prm:=ParseParams(AParent,pekFuncParams,IsWriteOrStr(func))
         else
         else
           prm:=ParseParams(AParent,pekArrayParams);
           prm:=ParseParams(AParent,pekArrayParams);
         if not Assigned(prm) then Exit;
         if not Assigned(prm) then Exit;

+ 160 - 92
packages/fcl-passrc/tests/tcresolver.pas

@@ -19,7 +19,7 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, contnrs, strutils, fpcunit, testregistry,
   Classes, SysUtils, contnrs, strutils, fpcunit, testregistry,
-  PasTree, PScanner, PParser, PasResolver,
+  PasTree, PScanner, PParser, PasResolver, PasResolveEval,
   tcbaseparser;
   tcbaseparser;
 
 
 type
 type
@@ -186,6 +186,7 @@ type
     Procedure TestVarNoSemicolonBeginFail;
     Procedure TestVarNoSemicolonBeginFail;
     Procedure TestIntegerRange;
     Procedure TestIntegerRange;
     Procedure TestIntegerRangeHighLowerLowFail;
     Procedure TestIntegerRangeHighLowerLowFail;
+    Procedure TestAssignIntRangeFail; // ToDo
 
 
     // strings
     // strings
     Procedure TestChar_Ord;
     Procedure TestChar_Ord;
@@ -527,6 +528,11 @@ type
     Procedure TestArray_ConstDynArrayWrite;
     Procedure TestArray_ConstDynArrayWrite;
     Procedure TestArray_ConstOpenArrayWriteFail;
     Procedure TestArray_ConstOpenArrayWriteFail;
 
 
+    // static arrays
+    Procedure TestArrayIntRange_OutOfRange;
+    Procedure TestArrayEnumRange_OutOfRange;
+    Procedure TestArrayCharRange_OutOfRange;
+
     // procedure types
     // procedure types
     Procedure TestProcTypesAssignObjFPC;
     Procedure TestProcTypesAssignObjFPC;
     Procedure TestMethodTypesAssignObjFPC;
     Procedure TestMethodTypesAssignObjFPC;
@@ -2027,7 +2033,7 @@ begin
   Add('var a: longint;');
   Add('var a: longint;');
   Add('var a: string;');
   Add('var a: string;');
   Add('begin');
   Add('begin');
-  CheckResolverException(sDuplicateIdentifier,PasResolver.nDuplicateIdentifier);
+  CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
 end;
 end;
 
 
 procedure TTestResolver.TestVarInitConst;
 procedure TTestResolver.TestVarInitConst;
@@ -2067,7 +2073,7 @@ begin
   Add('  a: string = 1;');
   Add('  a: string = 1;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestVarWrongExprFail;
 procedure TTestResolver.TestVarWrongExprFail;
@@ -2077,7 +2083,7 @@ begin
   Add('  a: string = 1;');
   Add('  a: string = 1;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestArgWrongExprFail;
 procedure TTestResolver.TestArgWrongExprFail;
@@ -2088,7 +2094,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestVarExternal;
 procedure TTestResolver.TestVarExternal;
@@ -2139,6 +2145,22 @@ begin
   {$ENDIF}
   {$ENDIF}
 end;
 end;
 
 
+procedure TTestResolver.TestAssignIntRangeFail;
+begin
+  // ToDo
+  StartProgram(false);
+  Add([
+  'type TMyInt = 1..2;',
+  'var i: TMyInt;',
+  'begin',
+  '  i:=3;']);
+  exit;
+  {$IFDEF EnablePasResRangeCheck}
+  CheckResolverException(sHighRangeLimitLTLowRangeLimit,
+    nHighRangeLimitLTLowRangeLimit);
+  {$ENDIF}
+end;
+
 procedure TTestResolver.TestChar_Ord;
 procedure TTestResolver.TestChar_Ord;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -2196,7 +2218,7 @@ begin
   Add('var s: string;');
   Add('var s: string;');
   Add('begin');
   Add('begin');
   Add('  if s[]=s then ;');
   Add('  if s[]=s then ;');
-  CheckResolverException('Missing parameter character index',PasResolver.nMissingParameterX);
+  CheckResolverException('Missing parameter character index',nMissingParameterX);
 end;
 end;
 
 
 procedure TTestResolver.TestStringElement_IndexNonIntFail;
 procedure TTestResolver.TestStringElement_IndexNonIntFail;
@@ -2206,7 +2228,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if s[true]=s then ;');
   Add('  if s[true]=s then ;');
   CheckResolverException('Incompatible types: got "Boolean" expected "integer"',
   CheckResolverException('Incompatible types: got "Boolean" expected "integer"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestStringElement_AsVarArgFail;
 procedure TTestResolver.TestStringElement_AsVarArgFail;
@@ -2219,7 +2241,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  DoIt(s[1]);');
   Add('  DoIt(s[1]);');
   CheckResolverException('Variable identifier expected',
   CheckResolverException('Variable identifier expected',
-    PasResolver.nVariableIdentifierExpected);
+    nVariableIdentifierExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestString_DoubleQuotesFail;
 procedure TTestResolver.TestString_DoubleQuotesFail;
@@ -2783,7 +2805,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  vstring:=2;');
   Add('  vstring:=2;');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestAssignStringToIntFail;
 procedure TTestResolver.TestAssignStringToIntFail;
@@ -2794,7 +2816,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  v:=''A'';');
   Add('  v:=''A'';');
   CheckResolverException('Incompatible types: got "Char" expected "Longint"',
   CheckResolverException('Incompatible types: got "Char" expected "Longint"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestIntegerOperators;
 procedure TTestResolver.TestIntegerOperators;
@@ -3013,7 +3035,7 @@ begin
   Add('  i: longint;');
   Add('  i: longint;');
   Add('begin');
   Add('begin');
   Add('  i:=longint(s);');
   Add('  i:=longint(s);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeCastStrToCharFail;
 procedure TTestResolver.TestTypeCastStrToCharFail;
@@ -3024,7 +3046,7 @@ begin
   Add('  c: char;');
   Add('  c: char;');
   Add('begin');
   Add('begin');
   Add('  c:=char(s);');
   Add('  c:=char(s);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeCastIntToStrFail;
 procedure TTestResolver.TestTypeCastIntToStrFail;
@@ -3035,7 +3057,7 @@ begin
   Add('  i: longint;');
   Add('  i: longint;');
   Add('begin');
   Add('begin');
   Add('  s:=string(i);');
   Add('  s:=string(i);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeCastDoubleToStrFail;
 procedure TTestResolver.TestTypeCastDoubleToStrFail;
@@ -3046,7 +3068,7 @@ begin
   Add('  d: double;');
   Add('  d: double;');
   Add('begin');
   Add('begin');
   Add('  s:=string(d);');
   Add('  s:=string(d);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeCastDoubleToIntFail;
 procedure TTestResolver.TestTypeCastDoubleToIntFail;
@@ -3057,7 +3079,7 @@ begin
   Add('  d: double;');
   Add('  d: double;');
   Add('begin');
   Add('begin');
   Add('  i:=longint(d);');
   Add('  i:=longint(d);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeCastDoubleToBoolFail;
 procedure TTestResolver.TestTypeCastDoubleToBoolFail;
@@ -3068,7 +3090,7 @@ begin
   Add('  d: double;');
   Add('  d: double;');
   Add('begin');
   Add('begin');
   Add('  b:=longint(d);');
   Add('  b:=longint(d);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeCastBooleanToDoubleFail;
 procedure TTestResolver.TestTypeCastBooleanToDoubleFail;
@@ -3079,7 +3101,7 @@ begin
   Add('  d: double;');
   Add('  d: double;');
   Add('begin');
   Add('begin');
   Add('  d:=double(b);');
   Add('  d:=double(b);');
-  CheckResolverException(sIllegalTypeConversionTo,PasResolver.nIllegalTypeConversionTo);
+  CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestAssign_Access;
 procedure TTestResolver.TestAssign_Access;
@@ -3210,7 +3232,7 @@ begin
   Add('  i: string;');
   Add('  i: string;');
   Add('begin');
   Add('begin');
   Add('  inc(i);');
   Add('  inc(i);');
-  CheckResolverException('Incompatible type arg no. 1: Got "String", expected "integer"',PasResolver.nIncompatibleTypeArgNo);
+  CheckResolverException('Incompatible type arg no. 1: Got "String", expected "integer"',nIncompatibleTypeArgNo);
 end;
 end;
 
 
 procedure TTestResolver.TestTypeInfo;
 procedure TTestResolver.TestTypeInfo;
@@ -3356,7 +3378,7 @@ begin
   Add('  except');
   Add('  except');
   Add('    on longint do ;');
   Add('    on longint do ;');
   Add('  end;');
   Add('  end;');
-  CheckResolverException('class expected, but Longint found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('class expected, but Longint found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestRaiseNonVarFail;
 procedure TTestResolver.TestRaiseNonVarFail;
@@ -3365,7 +3387,7 @@ begin
   Add('type TObject = class end;');
   Add('type TObject = class end;');
   Add('begin');
   Add('begin');
   Add('  raise TObject;');
   Add('  raise TObject;');
-  CheckResolverException('variable expected, but class found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('variable expected, but class found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestRaiseNonClassFail;
 procedure TTestResolver.TestRaiseNonClassFail;
@@ -3375,7 +3397,7 @@ begin
   Add('  E: longint;');
   Add('  E: longint;');
   Add('begin');
   Add('begin');
   Add('  raise E;');
   Add('  raise E;');
-  CheckResolverException('class expected, but Longint found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('class expected, but Longint found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestRaiseDescendant;
 procedure TTestResolver.TestRaiseDescendant;
@@ -3460,7 +3482,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  repeat');
   Add('  repeat');
   Add('  until 3;');
   Add('  until 3;');
-  CheckResolverException('Boolean expected, but Longint found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestWhileDoNonBoolFail;
 procedure TTestResolver.TestWhileDoNonBoolFail;
@@ -3468,7 +3490,7 @@ begin
   StartProgram(false);
   StartProgram(false);
   Add('begin');
   Add('begin');
   Add('  while 3 do ;');
   Add('  while 3 do ;');
-  CheckResolverException('Boolean expected, but Longint found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestIfThenNonBoolFail;
 procedure TTestResolver.TestIfThenNonBoolFail;
@@ -3476,7 +3498,7 @@ begin
   StartProgram(false);
   StartProgram(false);
   Add('begin');
   Add('begin');
   Add('  if 3 then ;');
   Add('  if 3 then ;');
-  CheckResolverException('Boolean expected, but Longint found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestForLoopVarNonVarFail;
 procedure TTestResolver.TestForLoopVarNonVarFail;
@@ -4286,7 +4308,7 @@ begin
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException(sDuplicateIdentifier,PasResolver.nDuplicateIdentifier);
+  CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
 end;
 end;
 
 
 procedure TTestResolver.TestNestedProc;
 procedure TTestResolver.TestNestedProc;
@@ -4335,7 +4357,7 @@ begin
   StartProgram(false);
   StartProgram(false);
   Add('procedure FuncA(i: longint); forward;');
   Add('procedure FuncA(i: longint); forward;');
   Add('begin');
   Add('begin');
-  CheckResolverException(sForwardProcNotResolved,PasResolver.nForwardProcNotResolved);
+  CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
 end;
 end;
 
 
 procedure TTestResolver.TestNestedForwardProc;
 procedure TTestResolver.TestNestedForwardProc;
@@ -4367,7 +4389,7 @@ begin
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException(sForwardProcNotResolved,PasResolver.nForwardProcNotResolved);
+  CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
 end;
 end;
 
 
 procedure TTestResolver.TestForwardProcFuncMismatch;
 procedure TTestResolver.TestForwardProcFuncMismatch;
@@ -4378,7 +4400,7 @@ begin
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('procedure expected, but function found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('procedure expected, but function found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestForwardFuncResultMismatch;
 procedure TTestResolver.TestForwardFuncResultMismatch;
@@ -4390,7 +4412,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Result type mismatch, expected Longint, but found String',
   CheckResolverException('Result type mismatch, expected Longint, but found String',
-    PasResolver.nResultTypeMismatchExpectedButFound);
+    nResultTypeMismatchExpectedButFound);
 end;
 end;
 
 
 procedure TTestResolver.TestUnitIntfProc;
 procedure TTestResolver.TestUnitIntfProc;
@@ -4415,7 +4437,7 @@ begin
   Add('procedure {#A_forward}FuncA(i: longint);');
   Add('procedure {#A_forward}FuncA(i: longint);');
   Add('implementation');
   Add('implementation');
   Add('initialization');
   Add('initialization');
-  CheckResolverException(sForwardProcNotResolved,PasResolver.nForwardProcNotResolved);
+  CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
 end;
 end;
 
 
 procedure TTestResolver.TestUnitIntfMismatchArgName;
 procedure TTestResolver.TestUnitIntfMismatchArgName;
@@ -4428,7 +4450,7 @@ begin
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
   CheckResolverException('function header "ProcA" doesn''t match forward : var name changes i => j',
   CheckResolverException('function header "ProcA" doesn''t match forward : var name changes i => j',
-    PasResolver.nFunctionHeaderMismatchForwardVarName);
+    nFunctionHeaderMismatchForwardVarName);
 end;
 end;
 
 
 procedure TTestResolver.TestProcOverloadIsNotFunc;
 procedure TTestResolver.TestProcOverloadIsNotFunc;
@@ -4441,7 +4463,7 @@ begin
   Add('procedure {#A_Impl}ProcA(i: longint);');
   Add('procedure {#A_Impl}ProcA(i: longint);');
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
-  CheckResolverException(sDuplicateIdentifier,PasResolver.nDuplicateIdentifier);
+  CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
 end;
 end;
 
 
 procedure TTestResolver.TestProcCallMissingParams;
 procedure TTestResolver.TestProcCallMissingParams;
@@ -4453,7 +4475,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  Proc1;');
   Add('  Proc1;');
   CheckResolverException('Wrong number of parameters specified for call to "Proc1"',
   CheckResolverException('Wrong number of parameters specified for call to "Proc1"',
-    PasResolver.nWrongNumberOfParametersForCallTo);
+    nWrongNumberOfParametersForCallTo);
 end;
 end;
 
 
 procedure TTestResolver.TestProcArgDefaultValue;
 procedure TTestResolver.TestProcArgDefaultValue;
@@ -4475,7 +4497,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestProcPassConstToVar;
 procedure TTestResolver.TestProcPassConstToVar;
@@ -4488,7 +4510,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Variable identifier expected',
   CheckResolverException('Variable identifier expected',
-    PasResolver.nVariableIdentifierExpected);
+    nVariableIdentifierExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestBuiltInProcCallMissingParams;
 procedure TTestResolver.TestBuiltInProcCallMissingParams;
@@ -4497,7 +4519,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  length;');
   Add('  length;');
   CheckResolverException('Wrong number of parameters specified for call to "function Length(const String or Array): sizeint"',
   CheckResolverException('Wrong number of parameters specified for call to "function Length(const String or Array): sizeint"',
-    PasResolver.nWrongNumberOfParametersForCallTo);
+    nWrongNumberOfParametersForCallTo);
 end;
 end;
 
 
 procedure TTestResolver.TestAssignFunctionResult;
 procedure TTestResolver.TestAssignFunctionResult;
@@ -4528,7 +4550,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  {@i}i:={@P}P();');
   Add('  {@i}i:={@P}P();');
   CheckResolverException('Incompatible types: got "Procedure/Function" expected "Longint"',
   CheckResolverException('Incompatible types: got "Procedure/Function" expected "Longint"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestFunctionResultInCondition;
 procedure TTestResolver.TestFunctionResultInCondition;
@@ -5081,7 +5103,7 @@ begin
   Add('    procedure ProcA;');
   Add('    procedure ProcA;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException(sForwardProcNotResolved,PasResolver.nForwardProcNotResolved);
+  CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_MethodUnresolvedUnit;
 procedure TTestResolver.TestClass_MethodUnresolvedUnit;
@@ -5095,7 +5117,7 @@ begin
   Add('    procedure ProcA;');
   Add('    procedure ProcA;');
   Add('  end;');
   Add('  end;');
   Add('implementation');
   Add('implementation');
-  CheckResolverException(sForwardProcNotResolved,PasResolver.nForwardProcNotResolved);
+  CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_MethodAbstract;
 procedure TTestResolver.TestClass_MethodAbstract;
@@ -5117,7 +5139,7 @@ begin
   Add('    procedure ProcA; abstract;');
   Add('    procedure ProcA; abstract;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('Invalid procedure modifier abstract without virtual',PasResolver.nInvalidXModifierY);
+  CheckResolverException('Invalid procedure modifier abstract without virtual',nInvalidXModifierY);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_MethodAbstractHasBodyFail;
 procedure TTestResolver.TestClass_MethodAbstractHasBodyFail;
@@ -5132,7 +5154,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException(sAbstractMethodsMustNotHaveImplementation,
   CheckResolverException(sAbstractMethodsMustNotHaveImplementation,
-    PasResolver.nAbstractMethodsMustNotHaveImplementation);
+    nAbstractMethodsMustNotHaveImplementation);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_MethodUnresolvedWithAncestor;
 procedure TTestResolver.TestClass_MethodUnresolvedWithAncestor;
@@ -5146,7 +5168,7 @@ begin
   Add('    procedure ProcA;');
   Add('    procedure ProcA;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException(sForwardProcNotResolved,PasResolver.nForwardProcNotResolved);
+  CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_ProcFuncMismatch;
 procedure TTestResolver.TestClass_ProcFuncMismatch;
@@ -5160,7 +5182,8 @@ begin
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('procedure expected, but function found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('procedure expected, but function found',
+    nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_MethodOverload;
 procedure TTestResolver.TestClass_MethodOverload;
@@ -5200,7 +5223,7 @@ begin
   Add('begin');
   Add('begin');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException(PasResolver.sDuplicateIdentifier,PasResolver.nDuplicateIdentifier);
+  CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_MethodOverride;
 procedure TTestResolver.TestClass_MethodOverride;
@@ -5519,7 +5542,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Abstract methods cannot be called directly',
   CheckResolverException('Abstract methods cannot be called directly',
-    PasResolver.nAbstractMethodsCannotBeCalledDirectly);
+    nAbstractMethodsCannotBeCalledDirectly);
 end;
 end;
 
 
 procedure TTestResolver.TestClassCallInheritedWithParamsAbstractFail;
 procedure TTestResolver.TestClassCallInheritedWithParamsAbstractFail;
@@ -5538,7 +5561,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Abstract methods cannot be called directly',
   CheckResolverException('Abstract methods cannot be called directly',
-    PasResolver.nAbstractMethodsCannotBeCalledDirectly);
+    nAbstractMethodsCannotBeCalledDirectly);
 end;
 end;
 
 
 procedure TTestResolver.TestClassCallInheritedConstructor;
 procedure TTestResolver.TestClassCallInheritedConstructor;
@@ -5706,7 +5729,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if {@o}o is {@v}v then;');
   Add('  if {@o}o is {@v}v then;');
   CheckResolverException('class type expected, but class found',
   CheckResolverException('class type expected, but class found',
-    PasResolver.nXExpectedButYFound);
+    nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_OperatorAsOnNonDescendantFail;
 procedure TTestResolver.TestClass_OperatorAsOnNonDescendantFail;
@@ -5722,7 +5745,7 @@ begin
   Add('  {#v}{=A}v: TClassA;');
   Add('  {#v}{=A}v: TClassA;');
   Add('begin');
   Add('begin');
   Add('  {@o}o:={@v}v as {@TObj}TObject;');
   Add('  {@o}o:={@v}v as {@TObj}TObject;');
-  CheckResolverException(sTypesAreNotRelated,PasResolver.nTypesAreNotRelated);
+  CheckResolverException(sTypesAreNotRelated,nTypesAreNotRelated);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_OperatorAsOnNonTypeFail;
 procedure TTestResolver.TestClass_OperatorAsOnNonTypeFail;
@@ -5739,7 +5762,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  {@o}o:={@v}v as {@o}o;');
   Add('  {@o}o:={@v}v as {@o}o;');
   CheckResolverException('class expected, but o found',
   CheckResolverException('class expected, but o found',
-    PasResolver.nXExpectedButYFound);
+    nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestClassAsFuncResult;
 procedure TTestResolver.TestClassAsFuncResult;
@@ -5833,7 +5856,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  {@vb}vb:=TClassB({@va}va);');
   Add('  {@vb}vb:=TClassB({@va}va);');
   CheckResolverException('Illegal type conversion: "TClassA" to "class TClassB"',
   CheckResolverException('Illegal type conversion: "TClassA" to "class TClassB"',
-    PasResolver.nIllegalTypeConversionTo);
+    nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_TypeCastSelf;
 procedure TTestResolver.TestClass_TypeCastSelf;
@@ -5874,7 +5897,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  o.i:=TObject(o,o).i;');
   Add('  o.i:=TObject(o,o).i;');
   CheckResolverException('wrong number of parameters for type cast to TObject',
   CheckResolverException('wrong number of parameters for type cast to TObject',
-    PasResolver.nWrongNumberOfParametersForTypeCast);
+    nWrongNumberOfParametersForTypeCast);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_TypeCastAssign;
 procedure TTestResolver.TestClass_TypeCastAssign;
@@ -5907,7 +5930,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if TObject.i=7 then ;');
   Add('  if TObject.i=7 then ;');
   CheckResolverException(sCannotAccessThisMemberFromAX,
   CheckResolverException(sCannotAccessThisMemberFromAX,
-    PasResolver.nCannotAccessThisMemberFromAX);
+    nCannotAccessThisMemberFromAX);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_FuncReturningObjectMember;
 procedure TTestResolver.TestClass_FuncReturningObjectMember;
@@ -5937,7 +5960,7 @@ begin
   Add('procedure TObject.ProcA; begin end;');
   Add('procedure TObject.ProcA; begin end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Invalid procedure modifier static',
   CheckResolverException('Invalid procedure modifier static',
-    PasResolver.nInvalidXModifierY);
+    nInvalidXModifierY);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_SelfInStaticFail;
 procedure TTestResolver.TestClass_SelfInStaticFail;
@@ -5952,7 +5975,7 @@ begin
   Add('  if Self=nil then ;');
   Add('  if Self=nil then ;');
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('identifier not found "Self"',PasResolver.nIdentifierNotFound);
+  CheckResolverException('identifier not found "Self"',nIdentifierNotFound);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_PrivateProtectedInSameUnit;
 procedure TTestResolver.TestClass_PrivateProtectedInSameUnit;
@@ -6009,7 +6032,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o.v=3 then ;');
   Add('  if o.v=3 then ;');
   CheckResolverException('Can''t access private member v',
   CheckResolverException('Can''t access private member v',
-    PasResolver.nCantAccessPrivateMember);
+    nCantAccessPrivateMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_PrivateInDescendantFail;
 procedure TTestResolver.TestClass_PrivateInDescendantFail;
@@ -6037,7 +6060,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Can''t access private member v',
   CheckResolverException('Can''t access private member v',
-    PasResolver.nCantAccessPrivateMember);
+    nCantAccessPrivateMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_ProtectedInDescendant;
 procedure TTestResolver.TestClass_ProtectedInDescendant;
@@ -6081,7 +6104,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o.v=3 then ;');
   Add('  if o.v=3 then ;');
   CheckResolverException('Can''t access strict private member v',
   CheckResolverException('Can''t access strict private member v',
-    PasResolver.nCantAccessPrivateMember);
+    nCantAccessPrivateMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_StrictProtectedInMainBeginFail;
 procedure TTestResolver.TestClass_StrictProtectedInMainBeginFail;
@@ -6096,7 +6119,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o.v=3 then ;');
   Add('  if o.v=3 then ;');
   CheckResolverException('Can''t access strict protected member v',
   CheckResolverException('Can''t access strict protected member v',
-    PasResolver.nCantAccessPrivateMember);
+    nCantAccessPrivateMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_Constructor_NewInstance;
 procedure TTestResolver.TestClass_Constructor_NewInstance;
@@ -6183,7 +6206,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  o:=o.Create; // normal call has no result -> fail');
   Add('  o:=o.Create; // normal call has no result -> fail');
   CheckResolverException('Incompatible types: got "Procedure/Function" expected "TObject"',
   CheckResolverException('Incompatible types: got "Procedure/Function" expected "TObject"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_Destructor_FreeInstance;
 procedure TTestResolver.TestClass_Destructor_FreeInstance;
@@ -6794,7 +6817,7 @@ begin
   Add('  TCars = class of longint;');
   Add('  TCars = class of longint;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "class"',
   CheckResolverException('Incompatible types: got "Longint" expected "class"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOfIsOperatorFail;
 procedure TTestResolver.TestClassOfIsOperatorFail;
@@ -6808,7 +6831,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if cars is TCars then ;');
   Add('  if cars is TCars then ;');
   CheckResolverException('left side of is-operator expects a class, but got "class of" type',
   CheckResolverException('left side of is-operator expects a class, but got "class of" type',
-    PasResolver.nLeftSideOfIsOperatorExpectsAClassButGot);
+    nLeftSideOfIsOperatorExpectsAClassButGot);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOfAsOperatorFail;
 procedure TTestResolver.TestClassOfAsOperatorFail;
@@ -6823,7 +6846,7 @@ begin
   Add('  cars: TCars;');
   Add('  cars: TCars;');
   Add('begin');
   Add('begin');
   Add('  cars:=cars as TCars;');
   Add('  cars:=cars as TCars;');
-  CheckResolverException('illegal qualifier "as"',PasResolver.nIllegalQualifier);
+  CheckResolverException('illegal qualifier "as"',nIllegalQualifier);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOfIsOperator;
 procedure TTestResolver.TestClassOfIsOperator;
@@ -6901,7 +6924,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  oc.Id:=3;');
   Add('  oc.Id:=3;');
   CheckResolverException(sCannotAccessThisMemberFromAX,
   CheckResolverException(sCannotAccessThisMemberFromAX,
-    PasResolver.nCannotAccessThisMemberFromAX);
+    nCannotAccessThisMemberFromAX);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOfDotClassProc;
 procedure TTestResolver.TestClassOfDotClassProc;
@@ -6961,7 +6984,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  oc.ProcA;');
   Add('  oc.ProcA;');
   CheckResolverException(sCannotAccessThisMemberFromAX,
   CheckResolverException(sCannotAccessThisMemberFromAX,
-    PasResolver.nCannotAccessThisMemberFromAX);
+    nCannotAccessThisMemberFromAX);
 end;
 end;
 
 
 procedure TTestResolver.TestClassOfDotClassProperty;
 procedure TTestResolver.TestClassOfDotClassProperty;
@@ -7008,7 +7031,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if oc.A=3 then ;');
   Add('  if oc.A=3 then ;');
   CheckResolverException(sCannotAccessThisMemberFromAX,
   CheckResolverException(sCannotAccessThisMemberFromAX,
-    PasResolver.nCannotAccessThisMemberFromAX);
+    nCannotAccessThisMemberFromAX);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_ClassProcSelf;
 procedure TTestResolver.TestClass_ClassProcSelf;
@@ -7048,7 +7071,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Illegal type conversion: "Self" to "class TObject"',
   CheckResolverException('Illegal type conversion: "Self" to "class TObject"',
-    PasResolver.nIllegalTypeConversionTo);
+    nIllegalTypeConversionTo);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_ClassMembers;
 procedure TTestResolver.TestClass_ClassMembers;
@@ -7285,7 +7308,7 @@ begin
   Add('    FB: longint;');
   Add('    FB: longint;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('identifier not found "FB"',PasResolver.nIdentifierNotFound);
+  CheckResolverException('identifier not found "FB"',nIdentifierNotFound);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyReadAccessorVarWrongType;
 procedure TTestResolver.TestPropertyReadAccessorVarWrongType;
@@ -7298,7 +7321,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyReadAccessorProcNotFunc;
 procedure TTestResolver.TestPropertyReadAccessorProcNotFunc;
@@ -7310,7 +7333,7 @@ begin
   Add('    property B: longint read GetB;');
   Add('    property B: longint read GetB;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('function expected, but procedure found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('function expected, but procedure found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyReadAccessorFuncWrongResult;
 procedure TTestResolver.TestPropertyReadAccessorFuncWrongResult;
@@ -7323,7 +7346,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('function result Longint expected, but String found',
   CheckResolverException('function result Longint expected, but String found',
-    PasResolver.nXExpectedButYFound);
+    nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyReadAccessorFuncWrongArgCount;
 procedure TTestResolver.TestPropertyReadAccessorFuncWrongArgCount;
@@ -7336,7 +7359,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
-    PasResolver.nWrongNumberOfParametersForCallTo);
+    nWrongNumberOfParametersForCallTo);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyReadAccessorFunc;
 procedure TTestResolver.TestPropertyReadAccessorFunc;
@@ -7367,7 +7390,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
   CheckResolverException('Incompatible types: got "Longint" expected "String"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyWriteAccessorFuncNotProc;
 procedure TTestResolver.TestPropertyWriteAccessorFuncNotProc;
@@ -7379,7 +7402,7 @@ begin
   Add('    property B: longint write SetB;');
   Add('    property B: longint write SetB;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('procedure expected, but function found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('procedure expected, but function found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArgCount;
 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArgCount;
@@ -7392,7 +7415,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Wrong number of parameters specified for call to "SetB"',
   CheckResolverException('Wrong number of parameters specified for call to "SetB"',
-    PasResolver.nWrongNumberOfParametersForCallTo);
+    nWrongNumberOfParametersForCallTo);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArg;
 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArg;
@@ -7405,7 +7428,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible type arg no. 1: Got "var", expected "const"',
   CheckResolverException('Incompatible type arg no. 1: Got "var", expected "const"',
-    PasResolver.nIncompatibleTypeArgNo);
+    nIncompatibleTypeArgNo);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArgType;
 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArgType;
@@ -7418,7 +7441,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible type arg no. 1: Got "String", expected "Longint"',
   CheckResolverException('Incompatible type arg no. 1: Got "String", expected "Longint"',
-    PasResolver.nIncompatibleTypeArgNo);
+    nIncompatibleTypeArgNo);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyWriteAccessorProc;
 procedure TTestResolver.TestPropertyWriteAccessorProc;
@@ -7468,8 +7491,8 @@ begin
   Add('    property B;');
   Add('    property B;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException(PasResolver.sNoPropertyFoundToOverride,
-    PasResolver.nNoPropertyFoundToOverride);
+  CheckResolverException(sNoPropertyFoundToOverride,
+    nNoPropertyFoundToOverride);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyStoredAccessor;
 procedure TTestResolver.TestPropertyStoredAccessor;
@@ -7498,7 +7521,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Incompatible types: got "Longint" expected "Boolean"',
   CheckResolverException('Incompatible types: got "Longint" expected "Boolean"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyStoredAccessorProcNotFunc;
 procedure TTestResolver.TestPropertyStoredAccessorProcNotFunc;
@@ -7511,7 +7534,7 @@ begin
   Add('    property B: longint read FB stored GetB;');
   Add('    property B: longint read FB stored GetB;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
-  CheckResolverException('function expected, but procedure found',PasResolver.nXExpectedButYFound);
+  CheckResolverException('function expected, but procedure found',nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyStoredAccessorFuncWrongResult;
 procedure TTestResolver.TestPropertyStoredAccessorFuncWrongResult;
@@ -7525,7 +7548,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('function: boolean expected, but function:String found',
   CheckResolverException('function: boolean expected, but function:String found',
-    PasResolver.nXExpectedButYFound);
+    nXExpectedButYFound);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyStoredAccessorFuncWrongArgCount;
 procedure TTestResolver.TestPropertyStoredAccessorFuncWrongArgCount;
@@ -7539,7 +7562,7 @@ begin
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
-    PasResolver.nWrongNumberOfParametersForCallTo);
+    nWrongNumberOfParametersForCallTo);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyArgs1;
 procedure TTestResolver.TestPropertyArgs1;
@@ -7654,7 +7677,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  obj.Items[3]:=4;');
   Add('  obj.Items[3]:=4;');
   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
-    PasResolver.nIncompatibleTypeArgNo);
+    nIncompatibleTypeArgNo);
 end;
 end;
 
 
 procedure TTestResolver.TestProperty_Option_ClassPropertyNonStatic;
 procedure TTestResolver.TestProperty_Option_ClassPropertyNonStatic;
@@ -7715,7 +7738,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o[5]=6 then;');
   Add('  if o[5]=6 then;');
   CheckResolverException('illegal qualifier "["',
   CheckResolverException('illegal qualifier "["',
-    PasResolver.nIllegalQualifier);
+    nIllegalQualifier);
 end;
 end;
 
 
 procedure TTestResolver.TestPropertyAssign;
 procedure TTestResolver.TestPropertyAssign;
@@ -7750,7 +7773,7 @@ begin
   Add('  o: TObject;');
   Add('  o: TObject;');
   Add('begin');
   Add('begin');
   Add('  o.B:=3;');
   Add('  o.B:=3;');
-  CheckResolverException('No member is provided to access property',PasResolver.nPropertyNotWritable);
+  CheckResolverException('No member is provided to access property',nPropertyNotWritable);
 end;
 end;
 
 
 procedure TTestResolver.TestProperty_PassAsParam;
 procedure TTestResolver.TestProperty_PassAsParam;
@@ -7793,7 +7816,7 @@ begin
   Add('  o: TObject;');
   Add('  o: TObject;');
   Add('begin');
   Add('begin');
   Add('  if o.B=3 then;');
   Add('  if o.B=3 then;');
-  CheckResolverException('not readable',PasResolver.nNotReadable);
+  CheckResolverException('not readable',nNotReadable);
 end;
 end;
 
 
 procedure TTestResolver.TestWithBlock1;
 procedure TTestResolver.TestWithBlock1;
@@ -8433,6 +8456,51 @@ begin
   CheckResolverException('Variable identifier expected',nVariableIdentifierExpected);
   CheckResolverException('Variable identifier expected',nVariableIdentifierExpected);
 end;
 end;
 
 
+procedure TTestResolver.TestArrayIntRange_OutOfRange;
+begin
+  StartProgram(false);
+  Add([
+  'type TArr = array[1..2] of longint;',
+  'var a: TArr;',
+  'begin',
+  '  a[0]:=3;',
+  '']);
+  ParseProgram;
+  CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
+    'range check error while evaluating constants (0 must be between 1 and 2)');
+  CheckResolverUnexpectedHints;
+end;
+
+procedure TTestResolver.TestArrayEnumRange_OutOfRange;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TEnum = (red,blue);',
+  '  TArr = array[TEnum] of longint;',
+  'var a: TArr;',
+  'begin',
+  '  a[red]:=3;',
+  '']);
+  ParseProgram;
+  CheckResolverUnexpectedHints;
+end;
+
+procedure TTestResolver.TestArrayCharRange_OutOfRange;
+begin
+  StartProgram(false);
+  Add([
+  'type TArr = array[''a''..''b''] of longint;',
+  'var a: TArr;',
+  'begin',
+  '  a[''0'']:=3;',
+  '']);
+  ParseProgram;
+  CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
+    'range check error while evaluating constants (''0'' must be between ''a'' and ''b'')');
+  CheckResolverUnexpectedHints;
+end;
+
 procedure TTestResolver.TestProcTypesAssignObjFPC;
 procedure TTestResolver.TestProcTypesAssignObjFPC;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -8749,7 +8817,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  n:=@ProcA;');
   Add('  n:=@ProcA;');
   CheckResolverException('procedure type modifier "of Object" mismatch',
   CheckResolverException('procedure type modifier "of Object" mismatch',
-    PasResolver.nXModifierMismatchY);
+    nXModifierMismatchY);
 end;
 end;
 
 
 procedure TTestResolver.TestAssignMethodToProcFail;
 procedure TTestResolver.TestAssignMethodToProcFail;
@@ -8768,7 +8836,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  n:[email protected];');
   Add('  n:[email protected];');
   CheckResolverException('procedure type modifier "of Object" mismatch',
   CheckResolverException('procedure type modifier "of Object" mismatch',
-    PasResolver.nXModifierMismatchY);
+    nXModifierMismatchY);
 end;
 end;
 
 
 procedure TTestResolver.TestAssignProcToFunctionFail;
 procedure TTestResolver.TestAssignProcToFunctionFail;
@@ -8783,7 +8851,7 @@ begin
   Add('  p:=@ProcA;');
   Add('  p:=@ProcA;');
   CheckResolverException(
   CheckResolverException(
     'Incompatible types: got "procedure type" expected "function type"',
     'Incompatible types: got "procedure type" expected "function type"',
-    PasResolver.nIncompatibleTypesGotExpected);
+    nIncompatibleTypesGotExpected);
 end;
 end;
 
 
 procedure TTestResolver.TestAssignProcWrongArgsFail;
 procedure TTestResolver.TestAssignProcWrongArgsFail;
@@ -8797,7 +8865,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  p:=@ProcA;');
   Add('  p:=@ProcA;');
   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
-    PasResolver.nIncompatibleTypeArgNo);
+    nIncompatibleTypeArgNo);
 end;
 end;
 
 
 procedure TTestResolver.TestAssignProcWrongArgAccessFail;
 procedure TTestResolver.TestAssignProcWrongArgAccessFail;
@@ -8811,7 +8879,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  p:=@ProcA;');
   Add('  p:=@ProcA;');
   CheckResolverException('Incompatible type arg no. 1: Got "access modifier const", expected "default"',
   CheckResolverException('Incompatible type arg no. 1: Got "access modifier const", expected "default"',
-    PasResolver.nIncompatibleTypeArgNo);
+    nIncompatibleTypeArgNo);
 end;
 end;
 
 
 procedure TTestResolver.TestProcType_AssignNestedProcFail;
 procedure TTestResolver.TestProcType_AssignNestedProcFail;
@@ -8829,7 +8897,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('procedure type modifier "is nested" mismatch',
   CheckResolverException('procedure type modifier "is nested" mismatch',
-    PasResolver.nXModifierMismatchY);
+    nXModifierMismatchY);
 end;
 end;
 
 
 procedure TTestResolver.TestArrayOfProc;
 procedure TTestResolver.TestArrayOfProc;

+ 2 - 3
packages/fcl-passrc/tests/tcuseanalyzer.pas

@@ -9,9 +9,8 @@ unit tcuseanalyzer;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, fpcunit,
-  PasTree, PScanner, PasResolver,
-  tcbaseparser, testregistry, strutils, tcresolver, PasUseAnalyzer;
+  Classes, SysUtils, fpcunit, PasTree, PScanner, PasResolver, tcbaseparser,
+  testregistry, strutils, tcresolver, PasUseAnalyzer, PasResolveEval;
 
 
 type
 type
 
 

+ 1 - 1
packages/fcl-passrc/tests/testpassrc.lpr

@@ -6,7 +6,7 @@ uses
   Classes, consoletestrunner, tcscanner, tctypeparser, tcstatements,
   Classes, consoletestrunner, tcscanner, tctypeparser, tcstatements,
   tcbaseparser, tcmoduleparser, tconstparser, tcvarparser, tcclasstype,
   tcbaseparser, tcmoduleparser, tconstparser, tcvarparser, tcclasstype,
   tcexprparser, tcprocfunc, tcpassrcutil, tcresolver, tcgenerics,
   tcexprparser, tcprocfunc, tcpassrcutil, tcresolver, tcgenerics,
-  tcuseanalyzer;
+  tcuseanalyzer, pasresolveeval;
 
 
 type
 type