Răsfoiți Sursa

--- Merging r36006 into '.':
U packages/fcl-passrc/src/pastree.pp
U packages/fcl-passrc/src/pasresolver.pp
U packages/fcl-passrc/src/passrcutil.pp
U packages/fcl-passrc/src/pasuseanalyzer.pas
U packages/fcl-passrc/src/pparser.pp
U packages/fcl-passrc/tests/tcmoduleparser.pas
U packages/fcl-passrc/tests/tcpassrcutil.pas
--- Recording mergeinfo for merge of r36006 into '.':
U .
--- Merging r36020 into '.':
U packages/fcl-passrc/src/paswrite.pp
--- Recording mergeinfo for merge of r36020 into '.':
G .
--- Merging r36069 into '.':
U packages/fcl-passrc/tests/tcbaseparser.pas
U packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36069 into '.':
G .
--- Merging r36084 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pasuseanalyzer.pas
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36084 into '.':
G .
--- Merging r36117 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36117 into '.':
G .
--- Merging r36121 into '.':
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36121 into '.':
G .
--- Merging r36125 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36125 into '.':
G .
--- Merging r36126 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36126 into '.':
G .
--- Merging r36127 into '.':
U packages/fcl-passrc/src/pscanner.pp
U packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/tests/tcresolver.pas
--- Recording mergeinfo for merge of r36127 into '.':
G .
--- Merging r36129 into '.':
G packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36129 into '.':
G .
--- Merging r36130 into '.':
U packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36130 into '.':
G .
--- Merging r36131 into '.':
U packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36131 into '.':
G .
--- Merging r36140 into '.':
G packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36140 into '.':
G .
--- Merging r36154 into '.':
U packages/pastojs/tests/tcmodules.pas
U packages/pastojs/src/fppas2js.pp
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36154 into '.':
G .
--- Merging r36155 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36155 into '.':
G .
--- Merging r36160 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36160 into '.':
G .
--- Merging r36161 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36161 into '.':
G .
--- Merging r36171 into '.':
G packages/fcl-passrc/src/pparser.pp
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36171 into '.':
G .
--- Merging r36177 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36177 into '.':
G .
--- Merging r36178 into '.':
G packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36178 into '.':
G .
--- Merging r36179 into '.':
U packages/fcl-passrc/tests/tcvarparser.pas
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36179 into '.':
G .
--- Merging r36181 into '.':
U packages/fcl-passrc/tests/tcstatements.pas
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36181 into '.':
G .
--- Merging r36182 into '.':
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36182 into '.':
G .
--- Merging r36183 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36183 into '.':
G .
--- Merging r36184 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36184 into '.':
G .
--- Merging r36185 into '.':
G packages/fcl-passrc/tests/tcstatements.pas
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36185 into '.':
G .
--- Merging r36186 into '.':
G packages/fcl-passrc/src/pparser.pp
U packages/fcl-passrc/tests/tcclasstype.pas
--- Recording mergeinfo for merge of r36186 into '.':
G .
--- Merging r36187 into '.':
U packages/fcl-passrc/tests/testpassrc.lpi
U packages/fcl-passrc/tests/tcexprparser.pas
--- Recording mergeinfo for merge of r36187 into '.':
G .
--- Merging r36188 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36188 into '.':
G .
--- Merging r36189 into '.':
G packages/fcl-passrc/tests/tcstatements.pas
G packages/fcl-passrc/tests/tcscanner.pas
G packages/fcl-passrc/src/pscanner.pp
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36189 into '.':
G .
--- Merging r36190 into '.':
G packages/fcl-passrc/tests/tcexprparser.pas
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36190 into '.':
G .
--- Merging r36192 into '.':
G packages/fcl-passrc/tests/tcscanner.pas
--- Recording mergeinfo for merge of r36192 into '.':
G .
--- Merging r36205 into '.':
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36205 into '.':
G .
--- Merging r36213 into '.':
G packages/fcl-passrc/src/pscanner.pp
G packages/fcl-passrc/src/pparser.pp
G packages/fcl-passrc/src/pastree.pp
--- Recording mergeinfo for merge of r36213 into '.':
G .
--- Merging r36216 into '.':
G packages/fcl-passrc/src/pparser.pp
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/tests/tcbaseparser.pas
G packages/fcl-passrc/tests/tcclasstype.pas
--- Recording mergeinfo for merge of r36216 into '.':
G .
--- Merging r36217 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36217 into '.':
G .
--- Merging r36218 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36218 into '.':
G .
--- Merging r36219 into '.':
G packages/fcl-passrc/src/pparser.pp
G packages/fcl-passrc/src/pastree.pp
--- Recording mergeinfo for merge of r36219 into '.':
G .
--- Merging r36220 into '.':
U packages/fcl-passrc/tests/tcgenerics.pp
--- Recording mergeinfo for merge of r36220 into '.':
G .
--- Merging r36221 into '.':
G packages/fcl-passrc/tests/tcgenerics.pp
--- Recording mergeinfo for merge of r36221 into '.':
G .
--- Merging r36222 into '.':
G packages/fcl-passrc/tests/tcgenerics.pp
G packages/fcl-passrc/src/pparser.pp
G packages/fcl-passrc/src/pscanner.pp
--- Recording mergeinfo for merge of r36222 into '.':
G .
--- Merging r36223 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36223 into '.':
G .
--- Merging r36224 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36224 into '.':
G .
--- Merging r36225 into '.':
G packages/fcl-passrc/tests/tcgenerics.pp
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pparser.pp
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36225 into '.':
G .
--- Merging r36226 into '.':
G packages/fcl-passrc/tests/tcstatements.pas
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36226 into '.':
G .
--- Merging r36228 into '.':
G packages/fcl-passrc/src/pparser.pp
U packages/fcl-passrc/tests/tctypeparser.pas
--- Recording mergeinfo for merge of r36228 into '.':
G .
--- Merging r36234 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36234 into '.':
G .
--- Merging r36237 into '.':
U packages/fcl-passrc/examples/parsepp.pp
--- Recording mergeinfo for merge of r36237 into '.':
G .
--- Merging r36238 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36238 into '.':
G .
--- Merging r36241 into '.':
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36241 into '.':
G .
--- Merging r36246 into '.':
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/tests/tcresolver.pas
--- Recording mergeinfo for merge of r36246 into '.':
G .
--- Merging r36248 into '.':
G packages/fcl-passrc/src/pparser.pp
--- Recording mergeinfo for merge of r36248 into '.':
G .
--- Merging r36318 into '.':
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/src/pasuseanalyzer.pas
G packages/fcl-passrc/src/pparser.pp
A packages/fcl-passrc/src/pasresolveeval.pas
G packages/fcl-passrc/tests/tcresolver.pas
U packages/fcl-passrc/tests/tcuseanalyzer.pas
U packages/fcl-passrc/tests/testpassrc.lpr
--- Recording mergeinfo for merge of r36318 into '.':
G .
--- Merging r36320 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/src/pasuseanalyzer.pas
--- Recording mergeinfo for merge of r36320 into '.':
G .
--- Merging r36321 into '.':
U packages/fcl-passrc/fpmake.pp
--- Recording mergeinfo for merge of r36321 into '.':
G .
--- Merging r36376 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
U packages/fcl-passrc/src/pasresolveeval.pas
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36376 into '.':
G .
--- Merging r36397 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pasresolveeval.pas
--- Recording mergeinfo for merge of r36397 into '.':
G .
--- Merging r36453 into '.':
G packages/fcl-passrc/src/pasresolveeval.pas
G packages/fcl-passrc/src/pastree.pp
G packages/fcl-passrc/src/pasresolver.pp
G packages/fcl-passrc/tests/tcresolver.pas
--- Recording mergeinfo for merge of r36453 into '.':
G .
--- Merging r36458 into '.':
G packages/fcl-passrc/tests/tcresolver.pas
G packages/fcl-passrc/src/pasresolver.pp
--- Recording mergeinfo for merge of r36458 into '.':
G .

# revisions: 36006,36020,36069,36084,36117,36121,36125,36126,36127,36129,36130,36131,36140,36154,36155,36160,36161,36171,36177,36178,36179,36181,36182,36183,36184,36185,36186,36187,36188,36189,36190,36192,36205,36213,36216,36217,36218,36219,36220,36221,36222,36223,36224,36225,36226,36228,36234,36237,36238,36241,36246,36248,36318,36320,36321,36376,36397,36453,36458

git-svn-id: branches/fixes_3_0@36534 -

marco 8 ani în urmă
părinte
comite
c7642a8c03

+ 1 - 0
.gitattributes

@@ -2530,6 +2530,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/testunit1.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/passrcutil.pp svneol=native#text/plain
 packages/fcl-passrc/src/pastounittest.pp svneol=native#text/plain

+ 4 - 1
packages/fcl-passrc/examples/parsepp.pp

@@ -62,6 +62,7 @@ begin
   For I:=1 to ParamCount do
     CmdLine:=CmdLine+' '+Paramstr(i);
   E := TSimpleEngine.Create;
+  M := nil;
   try
     M := ParseSource(E, cmdline, 'linux', 'i386');
  
@@ -84,6 +85,8 @@ begin
           (TObject(Decls[I]) as TPasElement).Name);
     end;
  
+  finally
     FreeAndNil(M);
-  finally FreeAndNil(E) end;
+    FreeAndNil(E)
+  end;
 end.

+ 8 - 1
packages/fcl-passrc/fpmake.pp

@@ -46,7 +46,6 @@ begin
           AddUnit('pscanner');
           AddUnit('pparser');
         end;
-    T.ResourceStrings := True;
     T:=P.Targets.AddUnit('pastounittest.pp');
       with T.Dependencies do
         begin
@@ -69,10 +68,18 @@ begin
         begin
           AddUnit('pastree');
         end;
+    T:=P.Targets.AddUnit('pasresolveeval.pas');
+      with T.Dependencies do
+        begin
+          AddUnit('pastree');
+          AddUnit('pscanner');
+        end;
+    T.ResourceStrings := True;
     T:=P.Targets.AddUnit('pasuseanalyzer.pas');
       with T.Dependencies do
         begin
           AddUnit('pastree');
+          AddUnit('pasresolver');
         end;
 
 {$ifndef ALLPACKAGES}

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

@@ -0,0 +1,2784 @@
+{
+    This file is part of the Free Component Library
+
+    Pascal source parser
+    Copyright (c) 2017 by Mattias Gaertner, [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************
+
+Abstract:
+  Evaluation of Pascal constants.
+
+Works:
+  - Emitting range check warnings
+  - Error on overflow
+  - bool: not, =, <>, and, or, xor, low(), high()
+  - int/uint
+    - unary +, -
+    - binary: +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not
+  - string: +
+  - float:
+  - enum/set
+
+ToDo:
+  - enable eval via option, default off
+  - bool:
+    - low(), high(), pred(), succ(), ord()
+  - int
+    - typecast
+    - low(), high(), pred(), succ()
+  - string:
+    - =, <>, <, >, <=, >=
+    - string encoding
+    - s[]
+    - length(string)
+    - chr(), ord(), low(), high(), pred(), succ()
+    - #65
+    - #$DC00
+  - float
+    - typecast float
+    - /
+    - +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not
+  - enum
+    - low(), high(), pred(), succ(), ord(), typecast
+  - sets
+    - [a,b,c..d]
+    - +, -, *, =, <>, <=, >=, in, ><
+  - arrays
+    - length(), low(), high()
+}
+unit PasResolveEval;
+
+{$mode objfpc}{$H+}
+
+{$IFOPT Q+}{$DEFINE OverflowCheckOn}{$ENDIF}
+{$IFOPT R+}{$DEFINE RangeCheckOn}{$ENDIF}
+
+interface
+
+uses
+  Sysutils, Math, PasTree, PScanner;
+
+// 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;
+  nDivByZero = 3069;
+
+// 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';
+  sDivByZero = 'Division by zero';
+
+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
+  MaxPrecInt = int64;
+  MaxPrecUInt = qword;
+  MaxPrecFloat = extended;
+const
+  // Note: when FPC compares int64 with qword it converts the qword to an int64,
+  //       possibly resulting in a range check error -> using a qword const instead
+  HighIntAsUInt = MaxPrecUInt(High(MaxPrecInt));
+
+type
+  { TResEvalValue }
+
+  TREVKind = (
+    revkNone,
+    revkCustom,
+    revkNil,  // TResEvalValue
+    revkBool, // TResEvalBool
+    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;
+    constructor CreateKind(const aKind: TREVKind);
+    function Clone: TResEvalValue; virtual;
+    function AsDebugString: string; virtual;
+    function AsString: string; virtual;
+  end;
+  TResEvalValueClass = class of TResEvalValue;
+
+  { TResEvalBool }
+
+  TResEvalBool = class(TResEvalValue)
+  public
+    B: boolean;
+    constructor Create; override;
+    constructor CreateValue(const aValue: boolean);
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalInt }
+
+  TResEvalInt = class(TResEvalValue)
+  public
+    Int: MaxPrecInt;
+    constructor Create; override;
+    constructor CreateValue(const aValue: MaxPrecInt);
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalUInt }
+
+  TResEvalUInt = class(TResEvalValue)
+  public
+    UInt: MaxPrecUInt;
+    constructor Create; override;
+    constructor CreateValue(const aValue: MaxPrecUInt);
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalFloat }
+
+  TResEvalFloat = class(TResEvalValue)
+  public
+    FloatValue: MaxPrecFloat;
+    constructor Create; override;
+    constructor CreateValue(const aValue: MaxPrecFloat);
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalString - Kind=revkString }
+
+  TResEvalString = class(TResEvalValue)
+  public
+    S: RawByteString;
+    constructor Create; override;
+    constructor CreateValue(const aValue: RawByteString);
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+  end;
+
+  { TResEvalUTF16 - Kind=revkUnicodeString }
+
+  TResEvalUTF16 = class(TResEvalValue)
+  public
+    S: UnicodeString;
+    constructor Create; override;
+    constructor CreateValue(const aValue: UnicodeString);
+    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;
+    constructor CreateValue(const aValue: integer; aIdentEl: TPasEnumValue);
+    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: MaxPrecInt;
+    constructor Create; override;
+    constructor CreateValue(const aElKind: TRgIntElKind;
+      const aRangeStart, aRangeEnd: MaxPrecInt);
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+    function ElementAsString(El: MaxPrecInt): string;
+  end;
+
+  { TResEvalRangeUInt }
+
+  TResEvalRangeUInt = class(TResEvalValue)
+  public
+    RangeStart, RangeEnd: MaxPrecUInt;
+    constructor Create; override;
+    constructor CreateValue(const aRangeStart, aRangeEnd: MaxPrecUInt);
+    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: MaxPrecInt;
+      end;
+      TItems = array of TItem;
+  public
+    ElKind: TSetElKind;
+    Ranges: TItems;
+    constructor Create; override;
+    function Clone: TResEvalValue; override;
+    function AsString: string; override;
+    function ElementAsString(El: MaxPrecInt): 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;
+  TPasResEvalParamsHandler = function(Sender: TResExprEvaluator;
+    Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue of object;
+
+  { TResExprEvaluator }
+
+  TResExprEvaluator = class
+  private
+    FOnEvalIdentifier: TPasResEvalIdentHandler;
+    FOnEvalParams: TPasResEvalParamsHandler;
+    FOnLog: TPasResEvalLogHandler;
+  protected
+    procedure LogMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
+      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);
+    procedure RaiseDivByZero(id: int64; ErrorEl: TPasElement);
+    function EvalUnaryExpr(Expr: TUnaryExpr; Flags: TResEvalFlags): TResEvalValue;
+    function EvalBinaryExpr(Expr: TBinaryExpr; Flags: TResEvalFlags): TResEvalValue;
+    function EvalBinaryRangeExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryAddExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinarySubExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryMulExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryDivExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryModExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryPowerExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryShiftExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryBoolOpExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryNEqualExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): TResEvalValue;
+    function EvalBinaryLessGreaterExpr(Expr: TBinaryExpr; LeftValue, RightValue: TResEvalValue): 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;
+    function CreateResEvalInt(UInt: MaxPrecUInt): 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: MaxPrecInt; PosEl: TPasElement);
+    property OnLog: TPasResEvalLogHandler read FOnLog write FOnLog;
+    property OnEvalIdentifier: TPasResEvalIdentHandler read FOnEvalIdentifier write FOnEvalIdentifier;
+    property OnEvalParams: TPasResEvalParamsHandler read FOnEvalParams write FOnEvalParams;
+  end;
+  TResExprEvaluatorClass = class of TResExprEvaluator;
+
+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;
+
+{ TResEvalBool }
+
+constructor TResEvalBool.Create;
+begin
+  inherited Create;
+  Kind:=revkBool;
+end;
+
+constructor TResEvalBool.CreateValue(const aValue: boolean);
+begin
+  Create;
+  B:=aValue;
+end;
+
+function TResEvalBool.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalBool(Result).B:=B;
+end;
+
+function TResEvalBool.AsString: string;
+begin
+  if B then Result:='false' else Result:='true';
+end;
+
+{ TResEvalRangeUInt }
+
+constructor TResEvalRangeUInt.Create;
+begin
+  inherited Create;
+  Kind:=revkRangeInt;
+end;
+
+constructor TResEvalRangeUInt.CreateValue(const aRangeStart,
+  aRangeEnd: MaxPrecUInt);
+begin
+  Create;
+  RangeStart:=aRangeStart;
+  RangeEnd:=aRangeEnd;
+end;
+
+function TResEvalRangeUInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  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;
+
+procedure TResExprEvaluator.RaiseDivByZero(id: int64; ErrorEl: TPasElement);
+begin
+  RaiseMsg(id,nDivByZero,sDivByZero,[],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;
+        TResEvalBool(Result).B:=not TResEvalBool(Result).B;
+        end;
+      revkInt:
+        begin
+        if Result.Element<>nil then
+          Result:=Result.Clone;
+        TResEvalInt(Result).Int:=not TResEvalInt(Result).Int;
+        end;
+      revkUInt:
+        begin
+        if Result.Element<>nil then
+          Result:=Result.Clone;
+        TResEvalUInt(Result).UInt:=not TResEvalUInt(Result).UInt;
+        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 (not just a resolver) -> return nil
+      Result:=TResEvalValue.CreateKind(revkNil);
+      end
+    else
+      RaiseNotYetImplemented(20170518232823,Expr,'operator='+OpcodeStrings[Expr.OpCode]);
+    end;
+end;
+
+function TResExprEvaluator.EvalBinaryExpr(Expr: TBinaryExpr;
+  Flags: TResEvalFlags): TResEvalValue;
+var
+  LeftValue, RightValue: TResEvalValue;
+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
+      Result:=EvalBinaryRangeExpr(Expr,LeftValue,RightValue);
+    pekBinary:
+      case Expr.OpCode of
+      eopAdd:
+        Result:=EvalBinaryAddExpr(Expr,LeftValue,RightValue);
+      eopSubtract:
+        Result:=EvalBinarySubExpr(Expr,LeftValue,RightValue);
+      eopMultiply:
+        Result:=EvalBinaryMulExpr(Expr,LeftValue,RightValue);
+      eopDiv:
+        Result:=EvalBinaryDivExpr(Expr,LeftValue,RightValue);
+      eopMod:
+        Result:=EvalBinaryModExpr(Expr,LeftValue,RightValue);
+      eopPower:
+        Result:=EvalBinaryPowerExpr(Expr,LeftValue,RightValue);
+      eopShl,eopShr:
+        Result:=EvalBinaryShiftExpr(Expr,LeftValue,RightValue);
+      eopAnd,eopOr,eopXor:
+        Result:=EvalBinaryBoolOpExpr(Expr,LeftValue,RightValue);
+      eopEqual,eopNotEqual:
+        Result:=EvalBinaryNEqualExpr(Expr,LeftValue,RightValue);
+      eopLessThan,eopGreaterThan, eopLessthanEqual,eopGreaterThanEqual:
+        Result:=EvalBinaryLessGreaterExpr(Expr,LeftValue,RightValue);
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryExpr Opcode=',OpcodeStrings[Expr.OpCode],' Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170530100823,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryExpr Kind=',Expr.Kind,' Opcode=',OpcodeStrings[Expr.OpCode]);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530100827,Expr);
+    end;
+    {$IFDEF VerbosePasResEval}
+    if Result<>nil then
+      writeln('TResExprEvaluator.EvalBinaryExpr Left=',LeftValue.AsDebugString,' Opcode=',OpcodeStrings[Expr.OpCode],' Right=',RightValue.AsDebugString,' Result=',Result.AsDebugString)
+    else
+      writeln('TResExprEvaluator.EvalBinaryExpr Left=',LeftValue.AsDebugString,' Opcode=',OpcodeStrings[Expr.OpCode],' Right=',RightValue.AsDebugString,' Result not set');
+    {$ENDIF}
+  finally
+    ReleaseEvalValue(LeftValue);
+    ReleaseEvalValue(RightValue);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryRangeExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+// LeftValue..RightValue
+var
+  LeftInt, RightInt: LongWord;
+begin
+  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.CreateValue(revrikInt,
+                        TResEvalInt(LeftValue).Int,TResEvalInt(RightValue).Int);
+      exit;
+      end
+    else if RightValue.Kind=revkUInt then
+      begin
+      // Note: when FPC compares int64 with qword it converts the qword to an int64
+      if TResEvalUInt(RightValue).UInt<=HighIntAsUInt then
+        begin
+        if TResEvalInt(LeftValue).Int>TResEvalUInt(RightValue).UInt then
+          RaiseMsg(20170519000235,nHighRangeLimitLTLowRangeLimit,
+            sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
+        Result:=TResEvalRangeInt.CreateValue(revrikInt,
+           TResEvalInt(LeftValue).Int,MaxPrecInt(TResEvalUInt(RightValue).UInt));
+        exit;
+        end
+      else if TResEvalInt(LeftValue).Int<0 then
+        RaiseRangeCheck(20170522151629,Expr.Right)
+      else if MaxPrecUInt(TResEvalInt(LeftValue).Int)>TResEvalUInt(RightValue).UInt then
+        RaiseMsg(20170522151708,nHighRangeLimitLTLowRangeLimit,
+          sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
+      Result:=TResEvalRangeUInt.CreateValue(MaxPrecUInt(TResEvalInt(LeftValue).Int),
+         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>HighIntAsUInt then
+        begin
+        if TResEvalInt(RightValue).Int<0 then
+          RaiseRangeCheck(20170522152608,Expr.Right)
+        else if TResEvalUInt(LeftValue).UInt>MaxPrecUInt(TResEvalInt(RightValue).Int) then
+          RaiseMsg(20170522152648,nHighRangeLimitLTLowRangeLimit,
+            sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
+        Result:=TResEvalRangeUInt.CreateValue(TResEvalUInt(LeftValue).UInt,
+          MaxPrecUInt(TResEvalInt(RightValue).Int));
+        exit;
+        end
+      else if TResEvalUInt(LeftValue).UInt>TResEvalInt(RightValue).Int then
+        RaiseMsg(20170522152804,nHighRangeLimitLTLowRangeLimit,
+          sHighRangeLimitLTLowRangeLimit,[],Expr.Right);
+      Result:=TResEvalRangeInt.CreateValue(revrikInt,
+        MaxPrecInt(TResEvalUInt(LeftValue).UInt),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.CreateValue(TResEvalUInt(LeftValue).UInt,
+        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.CreateValue(revrikEnum,
+        TResEvalEnum(LeftValue).Index,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.CreateValue(revrikChar,LeftInt,RightInt);
+      exit;
+      end
+    else
+      RaiseRangeCheck(20170522123106,Expr.Right);
+    end
+  else
+    {$IFDEF EnablePasResRangeCheck}
+    writeln('TResExprEvaluator.EvalBinaryRangeExpr Left=',GetObjName(Expr.Left),' LeftValue.Kind=',LeftValue.Kind);
+    RaiseNotYetImplemented(20170518221103,Expr.Left);
+    {$ELSE}
+    exit(nil);
+    {$ENDIF}
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryAddExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+
+  procedure IntAddUInt(const i: MaxPrecInt; const u: MaxPrecUInt);
+  var
+    Int: MaxPrecInt;
+    UInt: MaxPrecUInt;
+  begin
+    if (i>=0) then
+      begin
+      UInt:=MaxPrecUInt(i)+u;
+      Result:=CreateResEvalInt(UInt);
+      end
+    else if u<=HighIntAsUInt then
+      begin
+      Int:=i + MaxPrecInt(u);
+      Result:=TResEvalInt.CreateValue(Int);
+      end
+    else
+      RaiseRangeCheck(20170601140523,Expr);
+  end;
+
+var
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+  LeftCP, RightCP: TSystemCodePage;
+begin
+  Result:=nil;
+  try
+    {$Q+}
+    {$R+}
+    case LeftValue.Kind of
+    revkInt:
+      case RightValue.Kind of
+      revkInt:
+        // int+int
+        if (TResEvalInt(LeftValue).Int>0) and (TResEvalInt(RightValue).Int>0) then
+          begin
+          UInt:=MaxPrecUInt(TResEvalInt(LeftValue).Int)+MaxPrecUInt(TResEvalInt(RightValue).Int);
+          Result:=CreateResEvalInt(UInt);
+          end
+        else
+          begin
+          Int:=TResEvalInt(LeftValue).Int + TResEvalInt(RightValue).Int;
+          Result:=TResEvalInt.CreateValue(Int);
+          end;
+      revkUInt:
+        IntAddUInt(TResEvalInt(LeftValue).Int,TResEvalUInt(RightValue).UInt);
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryAddExpr int+? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170525115537,Expr);
+      end;
+    revkUInt:
+      case RightValue.Kind of
+      revkInt:
+        IntAddUInt(TResEvalUInt(LeftValue).UInt,TResEvalInt(RightValue).Int);
+      revkUInt:
+        begin
+        UInt:=TResEvalUInt(LeftValue).UInt+TResEvalUInt(RightValue).UInt;
+        Result:=TResEvalUInt.CreateValue(UInt);
+        end
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryAddExpr uint+? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170601141031,Expr);
+      end;
+    revkString:
+      case RightValue.Kind of
+      revkString:
+        begin
+        LeftCP:=StringCodePage(TResEvalString(LeftValue).S);
+        RightCP:=StringCodePage(TResEvalString(RightValue).S);
+        if (LeftCP=RightCP)
+            or ((LeftCP=CP_ACP) and (RightCP=DefaultSystemCodePage))
+            or ((RightCP=CP_ACP) and (LeftCP=DefaultSystemCodePage)) then
+          begin
+          Result:=TResEvalString.Create;
+          TResEvalString(Result).S:=TResEvalString(LeftValue).S+TResEvalString(RightValue).S;
+          end
+        else
+          begin
+          Result:=TResEvalUTF16.Create;
+          TResEvalUTF16(Result).S:=UnicodeString(TResEvalString(LeftValue).S)+UnicodeString(TResEvalString(RightValue).S);
+          end;
+        end;
+      revkUnicodeString:
+        begin
+        Result:=TResEvalUTF16.Create;
+        TResEvalUTF16(Result).S:=UnicodeString(TResEvalString(LeftValue).S)+TResEvalUTF16(RightValue).S;
+        end;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryAddExpr string+? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170601141834,Expr);
+      end;
+    revkUnicodeString:
+      case RightValue.Kind of
+      revkString:
+        begin
+        Result:=TResEvalUTF16.Create;
+        TResEvalUTF16(Result).S:=TResEvalUTF16(LeftValue).S+UnicodeString(TResEvalString(RightValue).S);
+        end;
+      revkUnicodeString:
+        begin
+        Result:=TResEvalUTF16.Create;
+        TResEvalUTF16(Result).S:=TResEvalUTF16(LeftValue).S+TResEvalUTF16(RightValue).S;
+        end;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryAddExpr utf16+? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        RaiseNotYetImplemented(20170601141811,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryAddExpr ?+ Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170525115548,Expr);
+    end;
+  except
+    on EOverflow do
+      RaiseOverflowArithmetic(20170601140130,Expr);
+    on ERangeError do
+      RaiseRangeCheck(20170601140132,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinarySubExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+begin
+  Result:=nil;
+  case LeftValue.Kind of
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      // int-int
+      try
+        {$Q+}
+        Int:=TResEvalInt(LeftValue).Int - TResEvalInt(RightValue).Int;
+        {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+        Result:=TResEvalInt.CreateValue(Int);
+      except
+        on E: EOverflow do
+          if (TResEvalInt(LeftValue).Int>0) and (TResEvalInt(RightValue).Int<0) then
+            begin
+            UInt:=MaxPrecUInt(TResEvalInt(LeftValue).Int)+MaxPrecUInt(-TResEvalInt(RightValue).Int);
+            Result:=CreateResEvalInt(UInt);
+            end
+          else
+            RaiseOverflowArithmetic(20170525230247,Expr);
+      end;
+    // ToDo: int-uint
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinarySubExpr sub int-? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170525230028,Expr);
+    end;
+  // ToDo: uint-int, uint-uint
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinarySubExpr sub ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170525225946,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryMulExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+begin
+  Result:=nil;
+  case LeftValue.Kind of
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      // int*int
+      try
+        {$Q+}
+        Int:=TResEvalInt(LeftValue).Int * TResEvalInt(RightValue).Int;
+        {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+        Result:=TResEvalInt.CreateValue(Int);
+      except
+        on E: EOverflow do
+          if (TResEvalInt(LeftValue).Int>0) and (TResEvalInt(RightValue).Int>0) then
+            try
+              // try uint*uint
+              {$Q+}
+              UInt:=MaxPrecUInt(TResEvalInt(LeftValue).Int) * MaxPrecUInt(TResEvalInt(RightValue).Int);
+              {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+              Result:=CreateResEvalInt(UInt);
+            except
+              on E: EOverflow do
+                RaiseOverflowArithmetic(20170530101616,Expr);
+            end
+          else
+            RaiseOverflowArithmetic(20170525230247,Expr);
+      end;
+    // ToDo: int*uint
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryMulExpr mul int*? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170525230028,Expr);
+    end;
+  // ToDo: uint*int, uint*uint
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinaryMulExpr mul ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170525225946,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryDivExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+begin
+  Result:=nil;
+  case LeftValue.Kind of
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      // int div int
+      if TResEvalInt(RightValue).Int=0 then
+        RaiseDivByZero(20170530102619,Expr)
+      else
+        begin
+        Int:=TResEvalInt(LeftValue).Int div TResEvalInt(RightValue).Int;
+        Result:=TResEvalInt.CreateValue(Int);
+        end;
+    revkUInt:
+      // int div uint
+      if TResEvalUInt(RightValue).UInt=0 then
+        RaiseDivByZero(20170530102745,Expr)
+      else
+        begin
+        if TResEvalUInt(RightValue).UInt>HighIntAsUInt then
+          Int:=0
+        else
+          Int:=TResEvalInt(LeftValue).Int div TResEvalUInt(RightValue).UInt;
+        Result:=TResEvalInt.CreateValue(Int);
+        end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryDivExpr int div ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530102403,Expr);
+    end;
+  revkUInt:
+    case RightValue.Kind of
+    revkInt:
+      // uint div int
+      if TResEvalInt(RightValue).Int=0 then
+        RaiseDivByZero(20170530103026,Expr)
+      else if TResEvalUInt(LeftValue).UInt<=HighIntAsUInt then
+        begin
+        Int:=MaxPrecInt(TResEvalUInt(LeftValue).UInt) div TResEvalInt(RightValue).Int;
+        Result:=TResEvalInt.CreateValue(Int);
+        end
+      else if TResEvalInt(RightValue).Int>0 then
+        begin
+        UInt:=TResEvalUInt(LeftValue).UInt div MaxPrecUInt(TResEvalInt(RightValue).Int);
+        Result:=CreateResEvalInt(UInt);
+        end
+      else
+        RaiseOverflowArithmetic(20170530104315,Expr);
+    revkUInt:
+      // uint div uint
+      if TResEvalInt(RightValue).Int=0 then
+        RaiseDivByZero(20170530103026,Expr)
+      else
+        begin
+        UInt:=TResEvalUInt(LeftValue).UInt div TResEvalUInt(RightValue).UInt;
+        Result:=CreateResEvalInt(UInt);
+        end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryDivExpr uint div ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530102403,Expr);
+    end;
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinaryDivExpr div ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170530102352,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryModExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+begin
+  Result:=nil;
+  case LeftValue.Kind of
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      // int mod int
+      if TResEvalInt(RightValue).Int=0 then
+        RaiseDivByZero(20170530104638,Expr)
+      else
+        begin
+        Int:=TResEvalInt(LeftValue).Int mod TResEvalInt(RightValue).Int;
+        Result:=TResEvalInt.CreateValue(Int);
+        end;
+    revkUInt:
+      // int mod uint
+      if TResEvalUInt(RightValue).UInt=0 then
+        RaiseDivByZero(20170530104758,Expr)
+      else
+        begin
+        if TResEvalInt(LeftValue).Int<0 then
+          UInt:=MaxPrecUInt(-TResEvalInt(LeftValue).Int) mod TResEvalUInt(RightValue).UInt
+        else
+          UInt:=MaxPrecUInt(TResEvalInt(LeftValue).Int) mod TResEvalUInt(RightValue).UInt;
+        Result:=CreateResEvalInt(UInt);
+        end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryModExpr int mod ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530110057,Expr);
+    end;
+  revkUInt:
+    case RightValue.Kind of
+    revkInt:
+      // uint mod int
+      if TResEvalInt(RightValue).Int=0 then
+        RaiseDivByZero(20170530110110,Expr)
+      else if TResEvalUInt(LeftValue).UInt<=HighIntAsUInt then
+        begin
+        Int:=MaxPrecInt(TResEvalUInt(LeftValue).UInt) mod TResEvalInt(RightValue).Int;
+        Result:=TResEvalInt.CreateValue(Int);
+        end
+      else if TResEvalInt(RightValue).Int>0 then
+        begin
+        UInt:=TResEvalUInt(LeftValue).UInt mod MaxPrecUInt(TResEvalInt(RightValue).Int);
+        Result:=CreateResEvalInt(UInt);
+        end
+      else
+        RaiseOverflowArithmetic(20170530110602,Expr);
+    revkUInt:
+      // uint div uint
+      if TResEvalInt(RightValue).Int=0 then
+        RaiseDivByZero(20170530110609,Expr)
+      else
+        begin
+        UInt:=TResEvalUInt(LeftValue).UInt mod TResEvalUInt(RightValue).UInt;
+        Result:=CreateResEvalInt(UInt);
+        end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryModExpr uint mod ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530110633,Expr);
+    end;
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinaryModExpr mod ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170530110644,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryShiftExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+  ShiftLeft: Boolean;
+begin
+  Result:=nil;
+  ShiftLeft:=Expr.OpCode=eopShl;
+  case LeftValue.Kind of
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      // int shl int
+      begin
+      if (TResEvalInt(RightValue).Int<0) or (TResEvalInt(RightValue).Int>63) then
+        EmitRangeCheckConst(20170530203840,IntToStr(TResEvalInt(RightValue).Int),0,63,Expr);
+      if ShiftLeft then
+        Int:=TResEvalInt(LeftValue).Int shl byte(TResEvalInt(RightValue).Int)
+      else
+        Int:=TResEvalInt(LeftValue).Int shr byte(TResEvalInt(RightValue).Int);
+      Result:=TResEvalInt.CreateValue(Int);
+      end;
+    revkUInt:
+      // int shl uint
+      begin
+      if (TResEvalUInt(RightValue).UInt>63) then
+        EmitRangeCheckConst(20170530203840,IntToStr(TResEvalUInt(RightValue).UInt),0,63,Expr);
+      if ShiftLeft then
+        Int:=TResEvalInt(LeftValue).Int shl byte(TResEvalUInt(RightValue).UInt)
+      else
+        Int:=TResEvalInt(LeftValue).Int shr byte(TResEvalUInt(RightValue).UInt);
+      Result:=TResEvalInt.CreateValue(Int);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryModExpr int shl/shr ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530205332,Expr);
+    end;
+  revkUInt:
+    case RightValue.Kind of
+    revkInt:
+      // uint shl int
+      begin
+      if (TResEvalInt(RightValue).Int<0) or (TResEvalInt(RightValue).Int>63) then
+        EmitRangeCheckConst(20170530205414,IntToStr(TResEvalInt(RightValue).Int),0,63,Expr);
+      if ShiftLeft then
+        UInt:=TResEvalUInt(LeftValue).UInt shl byte(TResEvalInt(RightValue).Int)
+      else
+        UInt:=TResEvalUInt(LeftValue).UInt shr byte(TResEvalInt(RightValue).Int);
+      Result:=CreateResEvalInt(UInt);
+      end;
+    revkUInt:
+      // uint shl uint
+      begin
+      if (TResEvalUInt(RightValue).UInt>63) then
+        EmitRangeCheckConst(20170530205601,IntToStr(TResEvalUInt(RightValue).UInt),0,63,Expr);
+      if ShiftLeft then
+        UInt:=TResEvalUInt(LeftValue).UInt shl byte(TResEvalUInt(RightValue).UInt)
+      else
+        UInt:=TResEvalUInt(LeftValue).UInt shr byte(TResEvalUInt(RightValue).UInt);
+      Result:=CreateResEvalInt(UInt);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryShiftExpr uint shl/shr ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530205640,Expr);
+    end;
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinaryShiftExpr shl/shr ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170530205646,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryBoolOpExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+// AND, OR, XOR
+begin
+  Result:=nil;
+  case LeftValue.Kind of
+  revkBool:
+    case RightValue.Kind of
+    revkBool:
+      begin
+      // logical and/or/xor
+      Result:=TResEvalBool.Create;
+      case Expr.OpCode of
+      eopAnd: TResEvalBool(Result).B:=TResEvalBool(LeftValue).B and TResEvalBool(RightValue).B;
+      eopOr: TResEvalBool(Result).B:=TResEvalBool(LeftValue).B or TResEvalBool(RightValue).B;
+      eopXor: TResEvalBool(Result).B:=TResEvalBool(LeftValue).B xor TResEvalBool(RightValue).B;
+      end;
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryBoolOpExpr bool ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170531011502,Expr);
+    end;
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      begin
+      // bitwise and/or/xor
+      Result:=TResEvalInt.Create;
+      case Expr.OpCode of
+      eopAnd: TResEvalInt(Result).Int:=TResEvalInt(LeftValue).Int and TResEvalInt(RightValue).Int;
+      eopOr: TResEvalInt(Result).Int:=TResEvalInt(LeftValue).Int or TResEvalInt(RightValue).Int;
+      eopXor: TResEvalInt(Result).Int:=TResEvalInt(LeftValue).Int xor TResEvalInt(RightValue).Int;
+      end;
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryBoolOpExpr int ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530211140,Expr);
+    end;
+  revkUInt:
+    case RightValue.Kind of
+    revkUInt:
+      begin
+      // bitwise and/or/xor
+      Result:=TResEvalUInt.Create;
+      case Expr.OpCode of
+      eopAnd: TResEvalUInt(Result).UInt:=TResEvalUInt(LeftValue).UInt and TResEvalUInt(RightValue).UInt;
+      eopOr: TResEvalUInt(Result).UInt:=TResEvalUInt(LeftValue).UInt or TResEvalUInt(RightValue).UInt;
+      eopXor: TResEvalUInt(Result).UInt:=TResEvalUInt(LeftValue).UInt xor TResEvalUInt(RightValue).UInt;
+      end;
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryBoolOpExpr int ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530211140,Expr);
+    end;
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinaryBoolOpExpr ',Expr.OpCode,' ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170530205938,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryNEqualExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  UInt: MaxPrecUInt;
+begin
+  Result:=TResEvalBool.Create;
+  try
+    {$Q+}
+    {$R+}
+    case LeftValue.Kind of
+    revkBool:
+      case RightValue.Kind of
+      revkBool:
+        TResEvalBool(Result).B:=TResEvalBool(LeftValue).B=TResEvalBool(RightValue).B;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryNEqualExpr bool ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170531011937,Expr);
+      end;
+    revkInt:
+      case RightValue.Kind of
+      revkInt:
+        TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int=TResEvalInt(RightValue).Int;
+      revkUInt:
+        TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int=TResEvalUInt(RightValue).UInt;
+      revkFloat:
+        TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int=TResEvalFloat(RightValue).FloatValue;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryNEqualExpr int ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170531012412,Expr);
+      end;
+    revkUInt:
+      begin
+      UInt:=TResEvalUInt(LeftValue).UInt;
+      case RightValue.Kind of
+      revkInt:
+        TResEvalBool(Result).B:=(UInt<=HighIntAsUInt)
+                               and (MaxPrecInt(UInt)=TResEvalInt(RightValue).Int);
+      revkUInt:
+        TResEvalBool(Result).B:=UInt=TResEvalUInt(RightValue).UInt;
+      revkFloat:
+        TResEvalBool(Result).B:=UInt=TResEvalFloat(RightValue).FloatValue;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryNEqualExpr uint ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170601122803,Expr);
+      end;
+      end;
+    revkFloat:
+      case RightValue.Kind of
+      revkInt:
+        TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue=TResEvalInt(RightValue).Int;
+      revkUInt:
+        TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue=TResEvalUInt(RightValue).UInt;
+      revkFloat:
+        TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue=TResEvalFloat(RightValue).FloatValue;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryNEqualExpr float ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170601122806,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryNEqualExpr ',Expr.OpCode,' ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      Result.Free;
+      RaiseNotYetImplemented(20170531011931,Expr);
+    end;
+    {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+    {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
+  except
+    on EOverflow do
+      RaiseOverflowArithmetic(20170601132729,Expr);
+    on ERangeError do
+      RaiseRangeCheck(20170601132740,Expr);
+  end;
+  if Expr.OpCode=eopNotEqual then
+    TResEvalBool(Result).B:=not TResEvalBool(Result).B;
+end;
+
+function TResExprEvaluator.EvalBinaryLessGreaterExpr(Expr: TBinaryExpr;
+  LeftValue, RightValue: TResEvalValue): TResEvalValue;
+begin
+  Result:=TResEvalBool.Create;
+  try
+    {$Q+}
+    {$R+}
+    case LeftValue.Kind of
+    revkInt:
+      case RightValue.Kind of
+      revkInt:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int < TResEvalInt(RightValue).Int;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int > TResEvalInt(RightValue).Int;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int <= TResEvalInt(RightValue).Int;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int >= TResEvalInt(RightValue).Int;
+        end;
+      revkUInt:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int < TResEvalUInt(RightValue).UInt;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int > TResEvalUInt(RightValue).UInt;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int <= TResEvalUInt(RightValue).UInt;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int >= TResEvalUInt(RightValue).UInt;
+        end;
+      revkFloat:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int < TResEvalFloat(RightValue).FloatValue;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int > TResEvalFloat(RightValue).FloatValue;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int <= TResEvalFloat(RightValue).FloatValue;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalInt(LeftValue).Int >= TResEvalFloat(RightValue).FloatValue;
+        end;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryLowerGreaterExpr int ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170601122512,Expr);
+      end;
+    revkUInt:
+      case RightValue.Kind of
+      revkInt:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt < TResEvalInt(RightValue).Int;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt > TResEvalInt(RightValue).Int;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt <= TResEvalInt(RightValue).Int;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt >= TResEvalInt(RightValue).Int;
+        end;
+      revkUInt:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt < TResEvalUInt(RightValue).UInt;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt > TResEvalUInt(RightValue).UInt;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt <= TResEvalUInt(RightValue).UInt;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt >= TResEvalUInt(RightValue).UInt;
+        end;
+      revkFloat:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt < TResEvalFloat(RightValue).FloatValue;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt > TResEvalFloat(RightValue).FloatValue;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt <= TResEvalFloat(RightValue).FloatValue;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalUInt(LeftValue).UInt >= TResEvalFloat(RightValue).FloatValue;
+        end;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryLowerGreaterExpr uint ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170601133222,Expr);
+      end;
+    revkFloat:
+      case RightValue.Kind of
+      revkInt:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue < TResEvalInt(RightValue).Int;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue > TResEvalInt(RightValue).Int;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue <= TResEvalInt(RightValue).Int;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue >= TResEvalInt(RightValue).Int;
+        end;
+      revkUInt:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue < TResEvalUInt(RightValue).UInt;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue > TResEvalUInt(RightValue).UInt;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue <= TResEvalUInt(RightValue).UInt;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue >= TResEvalUInt(RightValue).UInt;
+        end;
+      revkFloat:
+        case Expr.OpCode of
+        eopLessThan:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue < TResEvalFloat(RightValue).FloatValue;
+        eopGreaterThan:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue > TResEvalFloat(RightValue).FloatValue;
+        eopLessthanEqual:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue <= TResEvalFloat(RightValue).FloatValue;
+        eopGreaterThanEqual:
+          TResEvalBool(Result).B:=TResEvalFloat(LeftValue).FloatValue >= TResEvalFloat(RightValue).FloatValue;
+        end;
+      else
+        {$IFDEF VerbosePasResolver}
+        writeln('TResExprEvaluator.EvalBinaryLowerGreaterExpr float ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+        {$ENDIF}
+        Result.Free;
+        RaiseNotYetImplemented(20170601133421,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryLowerGreaterExpr ? ',Expr.OpCode,' ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      Result.Free;
+      RaiseNotYetImplemented(20170601122529,Expr);
+    end;
+  except
+    on EOverflow do
+      RaiseOverflowArithmetic(20170601132956,Expr);
+    on ERangeError do
+      RaiseRangeCheck(20170601132958,Expr);
+  end;
+end;
+
+function TResExprEvaluator.EvalBinaryPowerExpr(Expr: TBinaryExpr; LeftValue,
+  RightValue: TResEvalValue): TResEvalValue;
+var
+  Int: MaxPrecInt;
+begin
+  Result:=nil;
+  case LeftValue.Kind of
+  revkInt:
+    case RightValue.Kind of
+    revkInt:
+      // int^^int
+      try
+        {$Q+}{$R+}
+        Int:=trunc(Math.power(TResEvalInt(LeftValue).Int,TResEvalInt(RightValue).Int));
+        {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+        {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
+        Result:=TResEvalInt.CreateValue(Int);
+      except
+        RaiseOverflowArithmetic(20170530210533,Expr);
+      end;
+    revkUInt:
+      // int^^uint
+      try
+        {$Q+}{$R+}
+        Int:=trunc(Math.power(TResEvalInt(LeftValue).Int,TResEvalUInt(RightValue).UInt));
+        {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+        {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
+        Result:=TResEvalInt.CreateValue(Int);
+      except
+        RaiseOverflowArithmetic(20170530211028,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryPowerExpr int ^^ ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530205640,Expr);
+    end;
+  revkUInt:
+    case RightValue.Kind of
+    revkInt:
+      // uint^^int
+      try
+        {$Q+}{$R+}
+        Int:=trunc(Math.power(TResEvalUInt(LeftValue).UInt,TResEvalInt(RightValue).Int));
+        {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+        {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
+        Result:=TResEvalInt.CreateValue(Int);
+      except
+        RaiseOverflowArithmetic(20170530211102,Expr);
+      end;
+    revkUInt:
+      // uint^^uint
+      try
+        {$Q+}{$R+}
+        Int:=trunc(Math.power(TResEvalUInt(LeftValue).UInt,TResEvalUInt(RightValue).UInt));
+        {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
+        {$IFNDEF RangeCheckOn}{$R-}{$ENDIF}
+        Result:=TResEvalInt.CreateValue(Int);
+      except
+        RaiseOverflowArithmetic(20170530211121,Expr);
+      end;
+    else
+      {$IFDEF VerbosePasResolver}
+      writeln('TResExprEvaluator.EvalBinaryPowerExpr uint ^^ ? Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+      {$ENDIF}
+      RaiseNotYetImplemented(20170530211140,Expr);
+    end;
+  else
+    {$IFDEF VerbosePasResolver}
+    writeln('TResExprEvaluator.EvalBinaryPowerExpr ^^ ?- Left=',LeftValue.AsDebugString,' Right=',RightValue.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20170530205938,Expr);
+  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}
+  Result:=OnEvalParams(Self,Expr,Flags);
+  if (refConst in Flags) and (Result=nil) 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.CreateKind(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.CreateResEvalInt(UInt: MaxPrecUInt): TResEvalValue;
+begin
+  if UInt<=HighIntAsUInt then
+    Result:=TResEvalInt.CreateValue(MaxPrecInt(UInt))
+  else
+    Result:=TResEvalUInt.CreateValue(UInt);
+end;
+
+function TResExprEvaluator.Eval(Expr: TPasExpr; Flags: TResEvalFlags
+  ): TResEvalValue;
+var
+  C: TClass;
+  Code: integer;
+  Int: MaxPrecInt;
+  UInt: MaxPrecUInt;
+  Flo: MaxPrecFloat;
+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 MaxPrecInt
+        val(TPrimitiveExpr(Expr).Value,Int,Code);
+        if Code=0 then
+          begin
+          Result:=TResEvalInt.CreateValue(Int);
+          exit;
+          end;
+        // try MaxPrecUInt
+        val(TPrimitiveExpr(Expr).Value,UInt,Code);
+        if Code=0 then
+          begin
+          Result:=TResEvalUInt.CreateValue(UInt);
+          exit;
+          end;
+        // try float
+        val(TPrimitiveExpr(Expr).Value,Flo,Code);
+        if Code=0 then
+          begin
+          Result:=TResEvalFloat.CreateValue(Flo);
+          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
+    Result:=TResEvalValue.CreateKind(revkNil)
+  else if C=TBoolConstExpr then
+    Result:=TResEvalBool.CreateValue(TBoolConstExpr(Expr).Value)
+  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>HighIntAsUInt)
+                or (MaxPrecInt(TResEvalUInt(ExprValue).UInt)<RgInt.RangeStart)
+                or (MaxPrecInt(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 (MaxPrecUInt(TResEvalInt(ExprValue).Int)<RgUInt.RangeStart)
+            or (MaxPrecUInt(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: MaxPrecInt; 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 }
+
+constructor TResEvalValue.CreateKind(const aKind: TREVKind);
+begin
+  Create;
+  Kind:=aKind;
+end;
+
+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;
+
+constructor TResEvalUInt.CreateValue(const aValue: MaxPrecUInt);
+begin
+  Create;
+  UInt:=aValue;
+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;
+
+constructor TResEvalInt.CreateValue(const aValue: MaxPrecInt);
+begin
+  Create;
+  Int:=aValue;
+end;
+
+function TResEvalInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  TResEvalInt(Result).Int:=Int;
+end;
+
+function TResEvalInt.AsString: string;
+begin
+  Result:=IntToStr(Int);
+end;
+
+{ TResEvalFloat }
+
+constructor TResEvalFloat.Create;
+begin
+  inherited Create;
+  Kind:=revkFloat;
+end;
+
+constructor TResEvalFloat.CreateValue(const aValue: MaxPrecFloat);
+begin
+  Create;
+  FloatValue:=aValue;
+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;
+
+constructor TResEvalString.CreateValue(const aValue: RawByteString);
+begin
+  Create;
+  S:=aValue;
+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;
+
+constructor TResEvalUTF16.CreateValue(const aValue: UnicodeString);
+begin
+  Create;
+  S:=aValue;
+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;
+
+constructor TResEvalEnum.CreateValue(const aValue: integer;
+  aIdentEl: TPasEnumValue);
+begin
+  Create;
+  Index:=aValue;
+  IdentEl:=aIdentEl;
+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;
+
+constructor TResEvalRangeInt.CreateValue(const aElKind: TRgIntElKind;
+  const aRangeStart, aRangeEnd: MaxPrecInt);
+begin
+  Create;
+  ElKind:=aElKind;
+  RangeStart:=aRangeStart;
+  RangeEnd:=aRangeEnd;
+end;
+
+function TResEvalRangeInt.Clone: TResEvalValue;
+begin
+  Result:=inherited Clone;
+  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: MaxPrecInt): 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: MaxPrecInt): 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.
+

Fișier diff suprimat deoarece este prea mare
+ 364 - 247
packages/fcl-passrc/src/pasresolver.pp


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

@@ -195,7 +195,7 @@ begin
   If not Assigned(ASection) then exit;
   if ASection.UsesList.Count=length(ASection.UsesClause) then
     For I:=0 to length(ASection.UsesClause)-1 do
-      List.Add(ASection.UsesClause[i].Identifier)
+      List.Add(ASection.UsesClause[i].Name)
   else
     For I:=0 to ASection.UsesList.Count-1 do
       List.Add(TPasElement(ASection.UsesList[i]).Name);

+ 176 - 29
packages/fcl-passrc/src/pastree.pp

@@ -164,8 +164,9 @@ type
     Property DocComment : String Read FDocComment Write FDocComment;
   end;
 
-  TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst, pekRange,
-     pekUnary, pekBinary, pekFuncParams, pekArrayParams, pekListOfExp, pekInherited, pekSelf);
+  TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst,
+     pekRange, pekUnary, pekBinary, pekFuncParams, pekArrayParams, pekListOfExp,
+     pekInherited, pekSelf);
 
   TExprOpCode = (eopNone,
                  eopAdd,eopSubtract,eopMultiply,eopDivide, eopDiv,eopMod, eopPower,// arithmetic
@@ -256,7 +257,7 @@ type
   TParamsExpr = class(TPasExpr)
     Value     : TPasExpr;
     Params    : TPasExprArray;
-    {pekArrayParams, pekFuncParams, pekSet}
+    // Kind: pekArrayParams, pekFuncParams, pekSet
     constructor Create(AParent : TPasElement; AKind: TPasExprKind); overload;
     function GetDeclaration(full : Boolean) : string; override;
     destructor Destroy; override;
@@ -310,7 +311,7 @@ type
     Functions, Variables, Properties, ExportSymbols: TFPList;
   end;
 
-  { TPasUsesUnit }
+  { TPasUsesUnit - Parent is TPasSection }
 
   TPasUsesUnit = class(TPasElement)
   public
@@ -319,10 +320,9 @@ type
     procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
       const Arg: Pointer); override;
   public
-    Expr: TPasExpr;
-    Identifier: string; // e.g. 'name.space.unitname'
+    Expr: TPasExpr; // name expression
     InFilename: TPrimitiveExpr; // Kind=pekString, can be nil
-    Module: TPasElement; // TPasUnresolvedTypeRef or TPasModule
+    Module: TPasElement; // TPasUnresolvedUnitRef or TPasModule
   end;
   TPasUsesClause = array of TPasUsesUnit;
 
@@ -332,12 +332,14 @@ type
   public
     constructor Create(const AName: string; AParent: TPasElement); override;
     destructor Destroy; override;
-    procedure AddUnitToUsesList(const AUnitName: string);
+    function AddUnitToUsesList(const AUnitName: string; aName: TPasExpr = nil;
+      InFilename: TPrimitiveExpr = nil; aModule: TPasElement = nil;
+      UsesUnit: TPasUsesUnit = nil): TPasUsesUnit;
     function ElementTypeName: string; override;
     procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
       const Arg: Pointer); override;
   public
-    UsesList: TFPList;   // kept for compatibility, see UsesClause Module
+    UsesList: TFPList; // kept for compatibility, see TPasUsesUnit.Module
     UsesClause: TPasUsesClause;
   end;
 
@@ -456,9 +458,9 @@ type
     function ElementTypeName: string; override;
   end;
 
-  { TPasPointerType }
+  { TPasAliasType }
 
-  TPasPointerType = class(TPasType)
+  TPasAliasType = class(TPasType)
   public
     destructor Destroy; override;
     function ElementTypeName: string; override;
@@ -467,11 +469,12 @@ type
       const Arg: Pointer); override;
   public
     DestType: TPasType;
+    Expr: TPasExpr;
   end;
 
-  { TPasAliasType }
+  { TPasPointerType - todo: change it TPasAliasType }
 
-  TPasAliasType = class(TPasType)
+  TPasPointerType = class(TPasType)
   public
     destructor Destroy; override;
     function ElementTypeName: string; override;
@@ -497,6 +500,36 @@ type
     function GetDeclaration(full: boolean) : string; override;
   end;
 
+  { TPasSpecializeType }
+
+  TPasSpecializeType = class(TPasAliasType)
+  public
+    constructor Create(const AName: string; AParent: TPasElement); override;
+    destructor Destroy; override;
+    function ElementTypeName: string; override;
+    function GetDeclaration(full: boolean) : string; override;
+    procedure AddParam(El: TPasElement);
+  public
+    Params: TFPList; // list of TPasType or TPasExpr
+  end;
+
+  { TInlineTypeExpr }
+
+  TInlineTypeExpr = class(TPasExpr)
+  public
+    destructor Destroy; override;
+    function ElementTypeName: string; override;
+    function GetDeclaration(full : Boolean): string; override;
+    procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
+      const Arg: Pointer); override;
+  public
+    DestType: TPasType;
+  end;
+
+  { TInlineSpecializeExpr }
+
+  TInlineSpecializeExpr = class(TInlineTypeExpr)
+  end;
 
   { TPasRangeType }
 
@@ -570,7 +603,7 @@ type
     procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
       const Arg: Pointer); override;
   public
-    Values: TFPList;      // List of TPasEnumValue objects
+    Values: TFPList;      // List of TPasEnumValue
   end;
 
   { TPasSetType }
@@ -620,9 +653,11 @@ type
     Members: TFPList;     // array of TPasVariable elements
     VariantEl: TPasElement; // TPasVariable or TPasType
     Variants: TFPList;	// array of TPasVariant elements, may be nil!
+    GenericTemplateTypes: TFPList; // list of TPasGenericTemplateType
     Function IsPacked: Boolean;
     Function IsBitPacked : Boolean;
     Function IsAdvancedRecord : Boolean;
+    Procedure SetGenericTemplates(AList : TFPList);
   end;
 
   TPasGenericTemplateType = Class(TPasType);
@@ -813,6 +848,7 @@ type
 
   TPasConst = class(TPasVariable)
   public
+    IsConst: boolean; // e.g. $WritableConst off
     function ElementTypeName: string; override;
   end;
 
@@ -1484,6 +1520,77 @@ begin
   El:=nil;
 end;
 
+{ TInlineTypeExpr }
+
+destructor TInlineTypeExpr.Destroy;
+begin
+  ReleaseAndNil(TPasElement(DestType));
+  inherited Destroy;
+end;
+
+function TInlineTypeExpr.ElementTypeName: string;
+begin
+  Result := DestType.ElementTypeName;
+end;
+
+function TInlineTypeExpr.GetDeclaration(full: Boolean): string;
+begin
+  Result:=DestType.GetDeclaration(full);
+end;
+
+procedure TInlineTypeExpr.ForEachCall(
+  const aMethodCall: TOnForEachPasElement; const Arg: Pointer);
+begin
+  DestType.ForEachChildCall(aMethodCall,Arg,DestType,true);
+end;
+
+{ TPasSpecializeType }
+
+constructor TPasSpecializeType.Create(const AName: string; AParent: TPasElement
+  );
+begin
+  inherited Create(AName, AParent);
+  Params:=TFPList.Create;
+end;
+
+destructor TPasSpecializeType.Destroy;
+var
+  i: Integer;
+begin
+  for i:=0 to Params.Count-1 do
+    TPasElement(Params[i]).Release;
+  FreeAndNil(Params);
+  inherited Destroy;
+end;
+
+function TPasSpecializeType.ElementTypeName: string;
+begin
+  Result:=SPasTreeSpecializedType;
+end;
+
+function TPasSpecializeType.GetDeclaration(full: boolean): string;
+var
+  i: Integer;
+begin
+  Result:='specialize '+DestType.Name+'<';
+  for i:=0 to Params.Count-1 do
+    begin
+    if i>0 then
+      Result:=Result+',';
+    Result:=Result+TPasElement(Params[i]).GetDeclaration(false);
+    end;
+  If Full then
+    begin
+    Result:=Name+' = '+Result;
+    ProcessHints(False,Result);
+    end;
+end;
+
+procedure TPasSpecializeType.AddParam(El: TPasElement);
+begin
+  Params.Add(El);
+end;
+
 { TInterfaceSection }
 
 function TInterfaceSection.ElementTypeName: string;
@@ -1794,16 +1901,16 @@ begin
     ForEachChildCall(aMethodCall,Arg,TPasModule(Modules[i]),true);
 end;
 
-function TPasResString.ElementTypeName: string; begin Result := SPasTreeResString end;
-function TPasType.ElementTypeName: string; begin Result := SPasTreeType end;
-function TPasPointerType.ElementTypeName: string; begin Result := SPasTreePointerType end;
-function TPasAliasType.ElementTypeName: string; begin Result := SPasTreeAliasType end;
-function TPasTypeAliasType.ElementTypeName: string; begin Result := SPasTreeTypeAliasType end;
-function TPasClassOfType.ElementTypeName: string; begin Result := SPasTreeClassOfType end;
-function TPasRangeType.ElementTypeName: string; begin Result := SPasTreeRangeType end;
-function TPasArrayType.ElementTypeName: string; begin Result := SPasTreeArrayType end;
-function TPasFileType.ElementTypeName: string; begin Result := SPasTreeFileType end;
-function TPasEnumValue.ElementTypeName: string; begin Result := SPasTreeEnumValue end;
+function TPasResString.ElementTypeName: string; begin Result := SPasTreeResString; end;
+function TPasType.ElementTypeName: string; begin Result := SPasTreeType; end;
+function TPasPointerType.ElementTypeName: string; begin Result := SPasTreePointerType; end;
+function TPasAliasType.ElementTypeName: string; begin Result := SPasTreeAliasType; end;
+function TPasTypeAliasType.ElementTypeName: string; begin Result := SPasTreeTypeAliasType; end;
+function TPasClassOfType.ElementTypeName: string; begin Result := SPasTreeClassOfType; end;
+function TPasRangeType.ElementTypeName: string; begin Result := SPasTreeRangeType; end;
+function TPasArrayType.ElementTypeName: string; begin Result := SPasTreeArrayType; end;
+function TPasFileType.ElementTypeName: string; begin Result := SPasTreeFileType; end;
+function TPasEnumValue.ElementTypeName: string; begin Result := SPasTreeEnumValue; end;
 
 procedure TPasEnumValue.ForEachCall(const aMethodCall: TOnForEachPasElement;
   const Arg: Pointer);
@@ -1988,6 +2095,7 @@ begin
     {$if defined(debugrefcount) or defined(VerbosePasTreeMem)}writeln('TPasElement.Destroy ',Name,':',ClassName);{$ENDIF}
     raise Exception.Create('');
     end;
+  FParent:=nil;
   inherited Destroy;
 end;
 
@@ -2226,8 +2334,8 @@ end;
 
 destructor TPasAliasType.Destroy;
 begin
-  if Assigned(DestType) then
-    DestType.Release;
+  ReleaseAndNil(TPasElement(DestType));
+  ReleaseAndNil(TPasElement(Expr));
   inherited Destroy;
 end;
 
@@ -2354,12 +2462,17 @@ constructor TPasRecordType.Create(const AName: string; AParent: TPasElement);
 begin
   inherited Create(AName, AParent);
   Members := TFPList.Create;
+  GenericTemplateTypes:=TFPList.Create;
 end;
 
 destructor TPasRecordType.Destroy;
 var
   i: Integer;
 begin
+  for i := 0 to GenericTemplateTypes.Count - 1 do
+    TPasElement(GenericTemplateTypes[i]).Release;
+  FreeAndNil(GenericTemplateTypes);
+
   for i := 0 to Members.Count - 1 do
     TPasVariable(Members[i]).Release;
   FreeAndNil(Members);
@@ -3485,6 +3598,8 @@ begin
   if Variants<>nil then
     for i:=0 to Variants.Count-1 do
       ForEachChildCall(aMethodCall,Arg,TPasElement(Variants[i]),false);
+  for i:=0 to GenericTemplateTypes.Count-1 do
+    ForEachChildCall(aMethodCall,Arg,TPasElement(GenericTemplateTypes[i]),false);
 end;
 
 function TPasRecordType.IsPacked: Boolean;
@@ -3513,6 +3628,17 @@ begin
     end;
 end;
 
+procedure TPasRecordType.SetGenericTemplates(AList: TFPList);
+var
+  I: Integer;
+begin
+  For I:=0 to AList.Count-1 do
+    begin
+    TPasElement(AList[i]).Parent:=Self;
+    GenericTemplateTypes.Add(AList[i]);
+    end;
+end;
+
 procedure TPasProcedureType.GetArguments(List : TStrings);
 
 Var
@@ -4028,14 +4154,35 @@ begin
   {$IFDEF VerbosePasTreeMem}writeln('TPasSection.Destroy END');{$ENDIF}
 end;
 
-procedure TPasSection.AddUnitToUsesList(const AUnitName: string);
+function TPasSection.AddUnitToUsesList(const AUnitName: string;
+  aName: TPasExpr; InFilename: TPrimitiveExpr; aModule: TPasElement;
+  UsesUnit: TPasUsesUnit): TPasUsesUnit;
 var
   l: Integer;
 begin
-  UsesList.Add(TPasUnresolvedTypeRef.Create(AUnitName, Self));
+  if (InFilename<>nil) and (InFilename.Kind<>pekString) then
+    raise Exception.Create('');
+  if aModule=nil then
+    aModule:=TPasUnresolvedUnitRef.Create(AUnitName, Self);
   l:=length(UsesClause);
   SetLength(UsesClause,l+1);
-  UsesClause[l]:=TPasUsesUnit.Create(AUnitName,Self);
+  if UsesUnit=nil then
+    begin
+    UsesUnit:=TPasUsesUnit.Create(AUnitName,Self);
+    if aName<>nil then
+      begin
+      Result.SourceFilename:=aName.SourceFilename;
+      Result.SourceLinenumber:=aName.SourceLinenumber;
+      end;
+    end;
+  UsesClause[l]:=UsesUnit;
+  UsesUnit.Expr:=aName;
+  UsesUnit.InFilename:=InFilename;
+  UsesUnit.Module:=aModule;
+  Result:=UsesUnit;
+
+  UsesList.Add(aModule);
+  aModule.AddRef;
 end;
 
 function TPasSection.ElementTypeName: string;

+ 16 - 12
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -49,7 +49,11 @@ unit PasUseAnalyzer;
 interface
 
 uses
-  Classes, SysUtils, AVL_Tree, PasResolver, PasTree, PScanner;
+  Classes, SysUtils, AVL_Tree, PasTree, PScanner,
+  {$IFDEF VerbosePasAnalyzer}
+  PasResolveEval,
+  {$ENDIF}
+  PasResolver;
 
 const
   nPAUnitNotUsed = 5023;
@@ -616,7 +620,7 @@ begin
       El:=El.Parent;
     until not (El is TPasType);
     end
-  else if C.InheritsFrom(TPasModule) then
+  else if (C.InheritsFrom(TPasModule)) or (C=TPasUsesUnit) then
     // e.g. unitname.identifier -> the module is used by the identifier
   else
     RaiseNotSupported(20170307090947,El);
@@ -740,11 +744,11 @@ end;
 procedure TPasAnalyzer.UseSection(Section: TPasSection; Mode: TPAUseMode);
 // called by UseModule
 var
-  UsesList: TFPList;
   i: Integer;
   UsedModule: TPasModule;
   Decl: TPasElement;
   OnlyExports: Boolean;
+  UsesClause: TPasUsesClause;
 begin
   // Section is TProgramSection, TLibrarySection, TInterfaceSection, TImplementationSection
   if Mode=paumElement then
@@ -760,12 +764,12 @@ begin
   {$ENDIF}
 
   // used units
-  UsesList:=Section.UsesList;
-  for i:=0 to UsesList.Count-1 do
+  UsesClause:=Section.UsesClause;
+  for i:=0 to length(UsesClause)-1 do
     begin
-    if TObject(UsesList[i]) is TPasModule then
+    if UsesClause[i].Module is TPasModule then
       begin
-      UsedModule:=TPasModule(UsesList[i]);
+      UsedModule:=TPasModule(UsesClause[i].Module);
       if ScopeModule=nil then
         // whole program analysis
         UseModule(UsedModule,paumAllExports)
@@ -1563,21 +1567,21 @@ end;
 
 procedure TPasAnalyzer.EmitSectionHints(Section: TPasSection);
 var
-  UsesList: TFPList;
   i: Integer;
   UsedModule, aModule: TPasModule;
+  UsesClause: TPasUsesClause;
 begin
   {$IFDEF VerbosePasAnalyzer}
   writeln('TPasAnalyzer.EmitSectionHints ',GetElModName(Section));
   {$ENDIF}
   // initialization, program or library sections
   aModule:=Section.GetModule;
-  UsesList:=Section.UsesList;
-  for i:=0 to UsesList.Count-1 do
+  UsesClause:=Section.UsesClause;
+  for i:=0 to length(UsesClause)-1 do
     begin
-    if TObject(UsesList[i]) is TPasModule then
+    if UsesClause[i].Module is TPasModule then
       begin
-      UsedModule:=TPasModule(UsesList[i]);
+      UsedModule:=TPasModule(UsesClause[i].Module);
       if CompareText(UsedModule.Name,'system')=0 then continue;
       if FindNode(UsedModule)=nil then
         EmitMessage(20170311191725,mtHint,nPAUnitNotUsed,sPAUnitNotUsed,

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

@@ -190,7 +190,7 @@ begin
         begin
         if i > 0 then
           wrt(', ');
-        wrt(ASection.UsesClause[i].Identifier);
+        wrt(ASection.UsesClause[i].Name);
         if ASection.UsesClause[i].InFilename is TPrimitiveExpr then
           wrt(' in '''+TPrimitiveExpr(ASection.UsesClause[i].InFilename).Value+'''');
         end

Fișier diff suprimat deoarece este prea mare
+ 463 - 190
packages/fcl-passrc/src/pparser.pp


Fișier diff suprimat deoarece este prea mare
+ 930 - 24
packages/fcl-passrc/src/pscanner.pp


+ 12 - 5
packages/fcl-passrc/tests/tcbaseparser.pas

@@ -8,7 +8,7 @@ uses
   Classes, SysUtils, fpcunit, pastree, pscanner, pparser, testregistry;
 
 const
-  MainFilename = 'afile.pp';
+  DefaultMainFilename = 'afile.pp';
 Type
   { TTestEngine }
 
@@ -32,6 +32,7 @@ Type
     FDeclarations: TPasDeclarations;
     FDefinition: TPasElement;
     FEngine : TPasTreeContainer;
+    FMainFilename: string;
     FModule: TPasModule;
     FParseResult: TPasElement;
     FScanner : TPascalScanner;
@@ -98,6 +99,7 @@ Type
     // If set, Will be freed in teardown
     Property ParseResult : TPasElement Read FParseResult Write FParseResult;
     Property UseImplementation : Boolean Read FUseImplementation Write FUseImplementation;
+    Property MainFilename: string read FMainFilename write FMainFilename;
   end;
 
 function ExtractFileUnitName(aFilename: string): string;
@@ -402,6 +404,7 @@ function TTestEngine.CreateElement(AClass: TPTreeElement; const AName: String;
   AParent: TPasElement; AVisibility: TPasMemberVisibility;
   const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
 begin
+  //writeln('TTestEngine.CreateElement ',AName,' ',AClass.ClassName);
   Result := AClass.Create(AName, AParent);
   Result.Visibility := AVisibility;
   Result.SourceFilename := ASourceFilename;
@@ -411,9 +414,12 @@ begin
 //    Writeln('Saving comment : ',CurrentParser.SavedComments);
     Result.DocComment:=CurrentParser.SavedComments;
     end;
-  If not Assigned(FList) then
-    FList:=TFPList.Create;
-  FList.Add(Result);
+  if AName<>'' then
+    begin
+    If not Assigned(FList) then
+      FList:=TFPList.Create;
+    FList.Add(Result);
+    end;
 end;
 
 function TTestEngine.FindElement(const AName: String): TPasElement;
@@ -429,7 +435,7 @@ begin
     While (Result=Nil) and (I>=0) do
       begin
       if CompareText(TPasElement(FList[I]).Name,AName)=0 then
-        Result:=TPasElement(Flist[i]);
+        Result:=TPasElement(FList[i]);
       Dec(i);
       end;
     end;
@@ -517,6 +523,7 @@ end;
 
 procedure TTestParser.SetUp;
 begin
+  FMainFilename:=DefaultMainFilename;
   Inherited;
   SetupParser;
 end;

+ 49 - 13
packages/fcl-passrc/tests/tcclasstype.pas

@@ -19,7 +19,8 @@ type
     FParent : String;
     FEnded,
     FStarted: Boolean;
-    procedure AssertSpecializedClass(C: TPasClassType);
+    procedure AssertGenericClass(C: TPasClassType);
+    procedure AssertSpecializedClass(C: TPasSpecializeType);
     function GetC(AIndex: Integer): TPasConst;
     function GetF1: TPasVariable;
     function GetM(AIndex : Integer): TPasElement;
@@ -29,7 +30,7 @@ type
     function GetP2: TPasProperty;
     function GetT(AIndex : Integer) : TPasType;
   protected
-    Procedure StartClass (AParent : String = 'TObject'; InterfaceList : String = '');
+    Procedure StartClass (AncestorName : String = 'TObject'; InterfaceList : String = '');
     Procedure StartExternalClass (AParent : String; AExternalName,AExternalNameSpace : String );
     Procedure StartClassHelper (ForType : String = 'TOriginal'; AParent : String = 'TObject');
     Procedure StartInterface (AParent : String = 'IInterface'; UUID : String = ''; Disp : Boolean = False);
@@ -85,6 +86,7 @@ type
     Procedure TestTwoVarFieldsB;
     procedure TestNoVarFields;
     procedure TestVarClassFunction;
+    procedure TestClassVarClassFunction;
     Procedure TestTwoFieldsVisibility;
     Procedure TestConstProtectedEnd;
     Procedure TestTypeProtectedEnd;
@@ -246,22 +248,22 @@ begin
   Result:=TPasConst(Members[AIndex]);
 end;
 
-procedure TTestClassType.StartClass(AParent: String; InterfaceList: String);
+procedure TTestClassType.StartClass(AncestorName: String; InterfaceList: String);
 
 Var
   S : String;
 begin
   FStarted:=True;
   S:='TMyClass = Class';
-  if (AParent<>'') then
+  if (AncestorName<>'') then
     begin
-    S:=S+'('+AParent;
+    S:=S+'('+AncestorName;
     if (InterfaceList<>'') then
       S:=S+','+InterfaceList;
     S:=S+')';
     end;
   FDecl.Add(S);
-  FParent:=AParent;
+  FParent:=AncestorName;
 end;
 
 procedure TTestClassType.StartExternalClass(AParent: String; AExternalName,
@@ -377,13 +379,15 @@ begin
 end;
 
 procedure TTestClassType.DoParseClass(FromSpecial: Boolean);
+var
+  AncestorType: TPasType;
 begin
   EndClass;
   Add('Type');
   if AddComment then
     begin
     Add('// A comment');
-    engine.NeedComments:=True;
+    Engine.NeedComments:=True;
     end;
   Add('  '+TrimRight(FDecl.Text)+';');
   ParseDeclarations;
@@ -396,7 +400,14 @@ begin
      AssertNotNull('Have parent class',TheClass.AncestorType);
      if FromSpecial then
        begin
-       AssertEquals('Parent class',TPasClassType,TheClass.AncestorType.ClassType);
+       AncestorType:=TheClass.AncestorType;
+       if AncestorType is TPasSpecializeType then
+         begin
+         AncestorType:=TPasSpecializeType(AncestorType).DestType;
+         AssertEquals('Parent class',TPasUnresolvedTypeRef,AncestorType.ClassType);
+         end
+       else
+         AssertEquals('Parent class',TPasClassType,AncestorType.ClassType);
        end
      else
        begin
@@ -524,7 +535,7 @@ begin
   AssertEquals('Interface name','ISomethingElse',TPasUnresolvedTypeRef(TheClass.Interfaces[1]).Name);
 end;
 
-procedure TTestClassType.AssertSpecializedClass(C : TPasClassType);
+procedure TTestClassType.AssertGenericClass(C : TPasClassType);
 
 begin
   AssertEquals('Parent class name is empty','',C.Name);
@@ -536,26 +547,38 @@ begin
   AssertEquals('Have generic template types','Integer',TPasElement(C.GenericTemplateTypes[0]).Name);
 end;
 
+procedure TTestClassType.AssertSpecializedClass(C: TPasSpecializeType);
+begin
+  AssertEquals('Parent class name is empty','',C.Name);
+  AssertNotNull('Have dest type',C.DestType);
+  AssertEquals('Have dest type name','TMyList',C.DestType.Name);
+  AssertNotNull('Have param types',C.Params);
+  AssertEquals('Have one param type',1,C.Params.Count);
+  AssertNotNull('First Param ',C.Params[0]);
+  AssertEquals('First Param expr',TPrimitiveExpr,TObject(C.Params[0]).ClassType);
+  AssertEquals('Has specialize param integer','Integer',TPrimitiveExpr(C.Params[0]).Value);
+end;
+
 procedure TTestClassType.TestOneSpecializedClass;
 
 Var
-  C : TPasClassType;
+  C : TPasSpecializeType;
 
 begin
   StartClass('Specialize TMyList<Integer>','');
   DoParseClass(True);
-  C:=TPasClassType(TheClass.AncestorType);
+  C:=TPasSpecializeType(TheClass.AncestorType);
   AssertSpecializedClass(C);
 end;
 
 procedure TTestClassType.TestOneSpecializedClassInterface;
 Var
-  C : TPasClassType;
+  C : TPasSpecializeType;
 
 begin
   StartClass('Specialize TMyList<Integer>','ISomething');
   DoParseClass(True);
-  C:=TPasClassType(TheClass.AncestorType);
+  C:=TPasSpecializeType(TheClass.AncestorType);
   AssertSpecializedClass(C);
   AssertEquals('Have 1 interface',1,TheClass.Interfaces.Count);
   AssertNotNull('Correct class',TheClass.Interfaces[0]);
@@ -717,6 +740,19 @@ begin
   AssertVisibility(visPublic,Members[0]);
 end;
 
+procedure TTestClassType.TestClassVarClassFunction;
+begin
+  StartVisibility(visPublic);
+  FDecl.Add('class var');
+  AddMember('class Function b : integer');
+  ParseClass;
+  AssertEquals('member count',1,TheClass.members.Count);
+  AssertNotNull('Have function',Members[0]);
+  AssertMemberName('b',Members[0]);
+  AssertMemberType(TPasClassFunction,Members[0]);
+  AssertVisibility(visPublic,Members[0]);
+end;
+
 procedure TTestClassType.TestTwoFieldsVisibility;
 begin
   StartVisibility(visPublic);

+ 39 - 0
packages/fcl-passrc/tests/tcexprparser.pas

@@ -136,8 +136,11 @@ type
     procedure TestTypeCast2;
     Procedure TestCreate;
     procedure TestChainedPointers;
+    procedure TestChainedPointers2;
+    procedure TestChainedPointers3;
     Procedure TestNilCaret;
     Procedure TestExpCaret;
+    Procedure TestArrayAccess;
   end;
 
 implementation
@@ -607,6 +610,34 @@ begin
   ParseModule;
 end;
 
+procedure TTestExpressions.TestChainedPointers2;
+begin
+  Source.Add('program afile;');
+  Source.Add('procedure test;');
+  Source.Add('begin');
+  Source.Add('ResourcePool.Shared^.Register(TypeOf(tTexture), @LoadTexture)^.Tag(GLResourceTag)');
+  Source.Add(' ^.Register(TypeOf(tShader), @LoadShader)^.Tag(GLResourceTag)//space - works');
+  Source.Add('^.Register(TypeOf(ShaderProgram), @LoadShaderProgram)^.Tag(GLResourceTag);//without space - does not work');
+  Source.Add('end;');
+  Source.Add('begin');
+  Source.Add('end.');
+  ParseModule;
+end;
+
+procedure TTestExpressions.TestChainedPointers3;
+begin
+  Source.Add('program afile;');
+  Source.Add('procedure test;');
+  Source.Add('begin');
+  Source.Add('ResourcePool.Shared^.Register(TypeOf(tTexture), @LoadTexture)^.Tag(GLResourceTag)');
+  Source.Add(' ^.Register(TypeOf(tShader), @LoadShader)^.Tag(GLResourceTag)//space - works');
+  Source.Add(#9'^.Register(TypeOf(ShaderProgram), @LoadShaderProgram)^.Tag(GLResourceTag);// tab - does not work');
+  Source.Add('end;');
+  Source.Add('begin');
+  Source.Add('end.');
+  ParseModule;
+end;
+
 procedure TTestExpressions.TestNilCaret;
 begin
   Source.Add('{$mode objfpc}');
@@ -625,6 +656,14 @@ begin
   ParseModule;
 end;
 
+procedure TTestExpressions.TestArrayAccess;
+begin
+  Source.Add('begin');
+  Source.Add('DoSomething((pb + 10)[4]);');
+  Source.Add('end.');
+  ParseModule;
+end;
+
 
 procedure TTestExpressions.TestUnaryMinus;
 begin

+ 54 - 9
packages/fcl-passrc/tests/tcgenerics.pp

@@ -5,7 +5,7 @@ unit tcgenerics;
 interface
 
 uses
-  Classes, SysUtils, fpcunit, pastree, testregistry, pscanner, pparser, tctypeparser;
+  Classes, SysUtils, fpcunit, pastree, testregistry, pscanner, tctypeparser;
 
 Type
 
@@ -14,27 +14,53 @@ Type
   TTestGenerics = Class(TBaseTestTypeParser)
   Published
     Procedure TestObjectGenerics;
+    Procedure TestRecordGenerics;
+    Procedure TestArrayGenerics;
     Procedure TestSpecializationDelphi;
     Procedure TestDeclarationDelphi;
     Procedure TestDeclarationDelphiSpecialize;
     Procedure TestMethodImplementation;
-    Procedure TestInlineSpecializationInProcedure;
+    Procedure TestInlineSpecializationInArgument;
+    Procedure TestSpecializeNested;
+    Procedure TestInlineSpecializeInStatement;
   end;
 
 implementation
 
 procedure TTestGenerics.TestObjectGenerics;
 begin
-  Source.Add('Type');
-  Source.Add('Generic TSomeClass<T> = Object');
-  Source.Add('  b : T;');
-  Source.Add('end;');
+  Add([
+    'Type',
+    'Generic TSomeClass<T> = Object',
+    '  b : T;',
+    'end;',
+    '']);
+  ParseDeclarations;
+end;
+
+procedure TTestGenerics.TestRecordGenerics;
+begin
+  Add([
+    'Type',
+    '  Generic TSome<T> = Record',
+    '    b : T;',
+    '  end;',
+    '']);
+  ParseDeclarations;
+end;
+
+procedure TTestGenerics.TestArrayGenerics;
+begin
+  Add([
+    'Type',
+    '  Generic TSome<T> = array of T;',
+    '']);
   ParseDeclarations;
 end;
 
 procedure TTestGenerics.TestSpecializationDelphi;
 begin
-  ParseType('TFPGList<integer>',TPasClassType,'');
+  ParseType('TFPGList<integer>',TPasSpecializeType,'');
 end;
 
 procedure TTestGenerics.TestDeclarationDelphi;
@@ -78,7 +104,6 @@ begin
   AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
   AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
-
 end;
 
 procedure TTestGenerics.TestMethodImplementation;
@@ -100,7 +125,7 @@ begin
   ParseModule;
 end;
 
-procedure TTestGenerics.TestInlineSpecializationInProcedure;
+procedure TTestGenerics.TestInlineSpecializationInArgument;
 begin
   With source do
     begin
@@ -116,6 +141,26 @@ begin
   ParseModule;
 end;
 
+procedure TTestGenerics.TestSpecializeNested;
+begin
+  Add([
+    'Type',
+    '  generic TSomeClass<A,B> = class(specialize TOther<A,specialize TAnother<B>>) end;',
+    '']);
+  ParseDeclarations;
+end;
+
+procedure TTestGenerics.TestInlineSpecializeInStatement;
+begin
+  Add([
+  'begin',
+  '  vec:=TVector<double>.create;',
+  '  b:=a<b;',
+  '  t:=a<b.c<d,e.f>>;',
+  '']);
+  ParseModule;
+end;
+
 initialization
   RegisterTest(TTestGenerics);
 end.

+ 54 - 26
packages/fcl-passrc/tests/tcmoduleparser.pas

@@ -15,7 +15,7 @@ Type
   private
     function GetIf: TInterfaceSection;
     function GetIm: TImplementationSection;
-    function CheckUnit(AIndex: Integer; const AName: String; AList: TFPList): TPasUnresolvedUnitRef;
+    function CheckUnit(AIndex: Integer; const AName: String; Section: TPasSection): TPasUnresolvedUnitRef;
   Protected
     Procedure ParseUnit;
     Procedure ParseProgram;
@@ -98,18 +98,32 @@ begin
 end;
 
 function TTestModuleParser.CheckUnit(AIndex: Integer; const AName: String;
-  AList: TFPList) : TPasUnresolvedUnitRef;
+  Section: TPasSection): TPasUnresolvedUnitRef;
 
 Var
   C : string;
+  AList: TFPList;
+  Clause: TPasUsesClause;
 
 begin
+  Result:=nil;
   C:='Unit '+IntTostr(AIndex)+' ';
+
+  AList:=Section.UsesList;
+  AssertNotNull('Have useslist',AList);
   if (AIndex>=AList.Count) then
     Fail(Format('Index %d larger than unit list count %d',[AIndex,AList.Count ]));
   AssertNotNull('Have pascal element',AList[AIndex]);
   AssertEquals(C+'Correct class',TPasUnresolvedUnitRef,TObject(AList[AIndex]).CLassType);
-  Result:=TPasUnresolvedUnitRef(AList[AIndex]);
+
+  Clause:=Section.UsesClause;
+  if AIndex>=length(Clause) then
+    Fail(Format('Index %d larger than unit list count %d',[AIndex,length(Clause) ]));
+  AssertNotNull('Have pascal element',Clause[AIndex]);
+  AssertEquals(C+'Correct class',TPasUsesUnit,Clause[AIndex].ClassType);
+  AssertNotNull(C+'Has Module',Clause[AIndex].Module);
+  AssertEquals(C+'Correct module class',TPasUnresolvedUnitRef,Clause[AIndex].Module.ClassType);
+  Result:=TPasUnresolvedUnitRef(Clause[AIndex].Module);
   AssertEquals(C+'Unit name correct',AName,Result.Name);
 end;
 
@@ -119,8 +133,10 @@ begin
   StartImplementation;
   ParseUnit;
   AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
-  CheckUnit(0,'System',IntfSection.UsesList);
+  AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
+  CheckUnit(0,'System',IntfSection);
   AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
+  AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
 end;
 
 procedure TTestModuleParser.TestUnitOneUses;
@@ -130,9 +146,11 @@ begin
   StartImplementation;
   ParseUnit;
   AssertEquals('Two interface units',2,IntfSection.UsesList.Count);
-  CheckUnit(0,'System',IntfSection.UsesList);
-  CheckUnit(1,'a',IntfSection.UsesList);
+  AssertEquals('Two interface units',2,length(IntfSection.UsesClause));
+  CheckUnit(0,'System',IntfSection);
+  CheckUnit(1,'a',IntfSection);
   AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
+  AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
 end;
 
 procedure TTestModuleParser.TestUnitTwoUses;
@@ -141,11 +159,13 @@ begin
   UsesClause(['a','b']);
   StartImplementation;
   ParseUnit;
-  AssertEquals('Two interface units',3,IntfSection.UsesList.Count);
-  CheckUnit(0,'System',IntfSection.UsesList);
-  CheckUnit(1,'a',IntfSection.UsesList);
-  CheckUnit(2,'b',IntfSection.UsesList);
+  AssertEquals('Three interface units',3,IntfSection.UsesList.Count);
+  AssertEquals('Three interface units',3,length(IntfSection.UsesClause));
+  CheckUnit(0,'System',IntfSection);
+  CheckUnit(1,'a',IntfSection);
+  CheckUnit(2,'b',IntfSection);
   AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
+  AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
 end;
 
 procedure TTestModuleParser.TestUnitOneImplUses;
@@ -155,9 +175,11 @@ begin
   UsesClause(['a']);
   ParseUnit;
   AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
-  CheckUnit(0,'a',ImplSection.UsesList);
+  AssertEquals('One implementation units',1,length(ImplSection.UsesClause));
+  CheckUnit(0,'a',ImplSection);
   AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
-  CheckUnit(0,'System',IntfSection.UsesList);
+  AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
+  CheckUnit(0,'System',IntfSection);
 end;
 
 procedure TTestModuleParser.TestUnitTwoImplUses;
@@ -167,10 +189,12 @@ begin
   UsesClause(['a','b']);
   ParseUnit;
   AssertEquals('One interface unit',1,IntfSection.UsesList.Count);
-  CheckUnit(0,'System',IntfSection.UsesList);
+  AssertEquals('One interface unit',1,length(IntfSection.UsesClause));
+  CheckUnit(0,'System',IntfSection);
   AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
-  CheckUnit(0,'a',ImplSection.UsesList);
-  CheckUnit(1,'b',ImplSection.UsesList);
+  AssertEquals('Two implementation units',2,length(ImplSection.UsesClause));
+  CheckUnit(0,'a',ImplSection);
+  CheckUnit(1,'b',ImplSection);
 end;
 
 procedure TTestModuleParser.TestEmptyUnitInitialization;
@@ -260,8 +284,9 @@ begin
   Add('begin');
   ParseProgram;
   AssertEquals('Two interface units',2, PasProgram.ProgramSection.UsesList.Count);
-  CheckUnit(0,'System',PasProgram.ProgramSection.UsesList);
-  CheckUnit(1,'a',PasProgram.ProgramSection.UsesList);
+  AssertEquals('Two interface units',2, length(PasProgram.ProgramSection.UsesClause));
+  CheckUnit(0,'System',PasProgram.ProgramSection);
+  CheckUnit(1,'a',PasProgram.ProgramSection);
 end;
 
 procedure TTestModuleParser.TestEmptyProgramUsesTwoUnits;
@@ -270,9 +295,10 @@ begin
   Add('begin');
   ParseProgram;
   AssertEquals('Three interface units',3, PasProgram.ProgramSection.UsesList.Count);
-  CheckUnit(0,'System',PasProgram.ProgramSection.UsesList);
-  CheckUnit(1,'a',PasProgram.ProgramSection.UsesList);
-  CheckUnit(2,'b',PasProgram.ProgramSection.UsesList);
+  AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
+  CheckUnit(0,'System',PasProgram.ProgramSection);
+  CheckUnit(1,'a',PasProgram.ProgramSection);
+  CheckUnit(2,'b',PasProgram.ProgramSection);
 end;
 
 procedure TTestModuleParser.TestEmptyProgramUsesUnitIn;
@@ -284,11 +310,12 @@ begin
   UsesClause(['a in ''../a.pas''','b']);
   Add('begin');
   ParseProgram;
-  AssertEquals('One interface unit',3, PasProgram.ProgramSection.UsesList.Count);
-  CheckUnit(0,'System',PasProgram.ProgramSection.UsesList);
-  U:=CheckUnit(1,'a',PasProgram.ProgramSection.UsesList);
+  AssertEquals('Three interface unit',3, PasProgram.ProgramSection.UsesList.Count);
+  AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
+  CheckUnit(0,'System',PasProgram.ProgramSection);
+  U:=CheckUnit(1,'a',PasProgram.ProgramSection);
   AssertEquals('Filename','''../a.pas''',U.FileName);
-  CheckUnit(2,'b',PasProgram.ProgramSection.UsesList);
+  CheckUnit(2,'b',PasProgram.ProgramSection);
 end;
 
 procedure TTestModuleParser.TestEmptyLibrary;
@@ -305,8 +332,9 @@ begin
   ParseLibrary;
   AssertEquals('Correct class',TPasLibrary,Module.ClassType);
   AssertEquals('Two interface units',2, PasLibrary.LibrarySection.UsesList.Count);
-  CheckUnit(0,'System',PasLibrary.LibrarySection.UsesList);
-  CheckUnit(1,'a',PasLibrary.LibrarySection.UsesList);
+  AssertEquals('Two interface units',2, length(PasLibrary.LibrarySection.UsesClause));
+  CheckUnit(0,'System',PasLibrary.LibrarySection);
+  CheckUnit(1,'a',PasLibrary.LibrarySection);
 end;
 
 procedure TTestModuleParser.TestEmptyLibraryExports;

+ 1 - 1
packages/fcl-passrc/tests/tcpassrcutil.pas

@@ -16,7 +16,7 @@ type
     FAnalyser : TPasSrcAnalysis;
     FSrc : TStrings;
     FList : TStrings;
-    FStream: TmemoryStream;
+    FStream: TMemoryStream;
   protected
     procedure SetUp; override;
     procedure TearDown; override;

Fișier diff suprimat deoarece este prea mare
+ 568 - 92
packages/fcl-passrc/tests/tcresolver.pas


+ 170 - 5
packages/fcl-passrc/tests/tcscanner.pas

@@ -224,6 +224,22 @@ type
     procedure TestMacro2;
     procedure TestMacro3;
     procedure TestMacroHandling;
+    procedure TestIFDefined;
+    procedure TestIFUnDefined;
+    procedure TestIFAnd;
+    procedure TestIFAndShortEval;
+    procedure TestIFOr;
+    procedure TestIFOrShortEval;
+    procedure TestIFXor;
+    procedure TestIFAndOr;
+    procedure TestIFEqual;
+    procedure TestIFNotEqual;
+    procedure TestIFGreaterThan;
+    procedure TestIFGreaterEqualThan;
+    procedure TestIFLesserThan;
+    procedure TestIFLesserEqualThan;
+    procedure TestIFDefinedElseIf;
+    procedure TestIfError;
     Procedure TestModeSwitch;
   end;
 
@@ -1095,7 +1111,7 @@ end;
 procedure TTestScanner.TestOn;
 
 begin
-  TestToken(tkon,'on');
+  TestToken(tkIdentifier,'on');
 end;
 
 
@@ -1511,21 +1527,21 @@ procedure TTestScanner.TestMacro1;
 begin
   FScanner.SkipWhiteSpace:=True;
   FScanner.SkipComments:=True;
-  TestTokens([tkbegin,tkend,tkDot],'{$DEFINE MM:=begin end.}'#13#10'MM',True,False);
+  TestTokens([tkbegin,tkend,tkDot],'{$MACRO on}{$DEFINE MM:=begin end.}'#13#10'MM',True,False);
 end;
 
 procedure TTestScanner.TestMacro2;
 begin
   FScanner.SkipWhiteSpace:=True;
   FScanner.SkipComments:=True;
-  TestTokens([tkbegin,tkend,tkDot],'{$DEFINE MM:=begin end}'#13#10'MM .',True,False);
+  TestTokens([tkbegin,tkend,tkDot],'{$MACRO on}{$DEFINE MM:=begin end}'#13#10'MM .',True,False);
 end;
 
 procedure TTestScanner.TestMacro3;
 begin
   FScanner.SkipComments:=True;
   FScanner.SkipWhiteSpace:=True;
-  TestTokens([tkof],'{$DEFINE MM:=begin end}'#13#10'{$IFDEF MM} of {$ELSE} in {$ENDIF}');
+  TestTokens([tkof],'{$MACRO on}{$DEFINE MM:=begin end}'#13#10'{$IFDEF MM} of {$ELSE} in {$ENDIF}');
 end;
 
 procedure TTestScanner.TestMacroHandling;
@@ -1533,10 +1549,159 @@ begin
   TTestingPascalScanner(FScanner).DoSpecial:=True;
   FScanner.SkipComments:=True;
   FScanner.SkipWhiteSpace:=True;
-  TestTokens([tkIdentifier],'{$DEFINE MM:=begin end}'#13#10'MM');
+  TestTokens([tkIdentifier],'{$MACRO on}{$DEFINE MM:=begin end}'#13#10'MM');
   AssertEQuals('Correct identifier', 'somethingweird',LastIdentifier);
 end;
 
+procedure TTestScanner.TestIFDefined;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],'{$DEFINE A}{$IF defined(A)}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFUnDefined;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],'{$IF undefined(A)}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFAnd;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$DEFINE A}{$IF defined(A) and undefined(B)}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFAndShortEval;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$UNDEFINE A}{$IF defined(A) and undefined(B)}wrong{$ELSE}begin{$ENDIF}end.',
+    True,False);
+end;
+
+procedure TTestScanner.TestIFOr;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$DEFINE B}{$IF defined(A) or defined(B)}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFOrShortEval;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$DEFINE A}{$IF defined(A) or defined(B)}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFXor;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$DEFINE B}{$IF defined(A) xor defined(B)}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFAndOr;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkbegin,tkend,tkDot],
+     '{$IF   defined(A) and   defined(B) or   defined(C)}wrong1{$ENDIF}'+LineEnding
+    +'{$IF   defined(A) and   defined(B) or undefined(C)}{$ELSE}wrong2{$ENDIF}'+LineEnding
+    +'{$IF   defined(A) and undefined(B) or   defined(C)}wrong3{$ENDIF}'+LineEnding
+    +'{$IF   defined(A) and undefined(B) or undefined(C)}{$ELSE}wrong4{$ENDIF}'+LineEnding
+    +'{$IF undefined(A) and   defined(B) or   defined(C)}wrong5{$ENDIF}'+LineEnding
+    +'{$IF undefined(A) and   defined(B) or undefined(C)}{$ELSE}wrong6{$ENDIF}'+LineEnding
+    +'{$IF undefined(A) and undefined(B) or   defined(C)}{$ELSE}wrong7{$ENDIF}'+LineEnding
+    +'{$IF undefined(A) and undefined(B) or undefined(C)}begin{$ENDIF}end.',
+    True,False);
+end;
+
+procedure TTestScanner.TestIFEqual;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddMacro('Version','30101');
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$IF Version=30101}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFNotEqual;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddMacro('Version','30101');
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$IF Version<>30000}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFGreaterThan;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddMacro('Version','30101');
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$IF Version>30000}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFGreaterEqualThan;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddMacro('Version','30101');
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$IF Version>=30000}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFLesserThan;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddMacro('Version','30101');
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$IF Version<40000}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFLesserEqualThan;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddMacro('Version','30101');
+  TestTokens([tkbegin,tkend,tkDot],
+    '{$IF Version<=30101}begin{$ENDIF}end.',True,False);
+end;
+
+procedure TTestScanner.TestIFDefinedElseIf;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  FScanner.AddDefine('cpu32');
+  TestTokens([tkconst,tkIdentifier,tkEqual,tkString,tkSemicolon,tkbegin,tkend,tkDot],
+    'const platform = '+LineEnding
+    +'{$if defined(cpu32)} ''x86'''+LineEnding
+    +'{$elseif defined(cpu64)} ''x64'''+LineEnding
+    +'{$else} {$error unknown platform} {$endif};'+LineEnding
+    +'begin end.',True,False);
+end;
+
+procedure TTestScanner.TestIfError;
+begin
+  FScanner.SkipWhiteSpace:=True;
+  FScanner.SkipComments:=True;
+  TestTokens([tkprogram,tkIdentifier,tkSemicolon,tkbegin,tkend,tkDot],
+    'program Project1;'+LineEnding
+    +'begin'+LineEnding
+    +'{$if sizeof(integer) <> 4} {$error wrong sizeof(integer)} {$endif}'+LineEnding
+    +'end.',True,False);
+end;
+
 procedure TTestScanner.TestModeSwitch;
 
 Const

+ 38 - 2
packages/fcl-passrc/tests/tcstatements.pas

@@ -118,6 +118,10 @@ Type
     Procedure TestGotoInIfThen;
     procedure AssignToAddress;
     procedure FinalizationNoSemicolon;
+    procedure MacroComment;
+    Procedure PLatformIdentifier;
+    Procedure PLatformIdentifier2;
+    Procedure Onidentifier;
   end;
 
 
@@ -1718,6 +1722,39 @@ begin
   ParseModule;
 end;
 
+procedure TTestStatementParser.MacroComment;
+begin
+  AddStatements(['{$MACRO ON}',
+  '{$DEFINE func := //}',
+  '  calltest;',
+  '  func (''1'',''2'',''3'');',
+  'CallTest2;'
+  ]);
+  ParseModule;
+end;
+
+procedure TTestStatementParser.PLatformIdentifier;
+begin
+  AddStatements(['write(platform);']);
+  ParseModule;
+end;
+
+procedure TTestStatementParser.PLatformIdentifier2;
+begin
+  AddStatements(['write(libs+platform);']);
+  ParseModule;
+end;
+
+procedure TTestStatementParser.Onidentifier;
+begin
+  Source.Add('function TryOn(const on: boolean): boolean;');
+  Source.Add('  begin');
+  Source.Add('  end;');
+  Source.Add('  begin');
+  Source.Add('  end.');
+  ParseModule;
+end;
+
 Procedure TTestStatementParser.TestGotoInIfThen;
 
 begin
@@ -1728,8 +1765,7 @@ begin
   '  else',
   '    dosomething;',
   '  try_qword:',
-  '  dosomething;',
-  'end.']);
+  '  dosomething;']);
   ParseModule;
 end;
 

+ 28 - 0
packages/fcl-passrc/tests/tctypeparser.pas

@@ -113,8 +113,12 @@ type
     procedure TestStaticArrayPlatform;
     Procedure TestStaticArrayPacked;
     Procedure TestStaticArrayTypedIndex;
+    Procedure TestStaticArrayOfMethod;
+    procedure TestStaticArrayOfProcedure;
     Procedure TestDynamicArray;
     Procedure TestDynamicArrayComment;
+    procedure TestDynamicArrayOfMethod;
+    procedure TestDynamicArrayOfProcedure;
     Procedure TestGenericArray;
     Procedure TestSimpleEnumerated;
     Procedure TestSimpleEnumeratedComment;
@@ -2916,6 +2920,30 @@ begin
   AssertEquals('Array type','Boolean',TPasArrayType(TheType).IndexRange);
 end;
 
+procedure TTestTypeParser.TestStaticArrayOfMethod;
+begin
+  DoParseArray('array[0..127] of procedure of object','',TPasProcedureType);
+  AssertEquals('Array element type',TPasProcedureType,TPasArrayType(TheType).ElType.ClassType);
+end;
+
+procedure TTestTypeParser.TestStaticArrayOfProcedure;
+begin
+  DoParseArray('array[0..127] of procedure','',TPasProcedureType);
+  AssertEquals('Array element type',TPasProcedureType,TPasArrayType(TheType).ElType.ClassType);
+end;
+
+procedure TTestTypeParser.TestDynamicArrayOfMethod;
+begin
+  DoParseArray('array of procedure of object','',TPasProcedureType);
+  AssertEquals('Array element type',TPasProcedureType,TPasArrayType(TheType).ElType.ClassType);
+end;
+
+procedure TTestTypeParser.TestDynamicArrayOfProcedure;
+begin
+  DoParseArray('array of procedure ','',TPasProcedureType);
+  AssertEquals('Array element type',TPasProcedureType,TPasArrayType(TheType).ElType.ClassType);
+end;
+
 procedure TTestTypeParser.TestDynamicArray;
 begin
   DoParseArray('array of integer','',Nil);

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

@@ -9,9 +9,8 @@ unit tcuseanalyzer;
 interface
 
 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
 

+ 24 - 0
packages/fcl-passrc/tests/tcvarparser.pas

@@ -33,6 +33,9 @@ Type
     Procedure TestSimpleVarInitialized;
     procedure TestSimpleVarInitializedDeprecated;
     procedure TestSimpleVarInitializedPlatform;
+    Procedure TestSimpleVarAbsolute;
+    Procedure TestSimpleVarAbsoluteDot;
+    Procedure TestSimpleVarAbsolute2Dots;
     Procedure TestVarProcedure;
     Procedure TestVarFunctionINitialized;
     Procedure TestVarProcedureDeprecated;
@@ -182,6 +185,27 @@ begin
   AssertExpression('Variable value',TheVar.expr,pekNumber,'123');
 end;
 
+procedure TTestVarParser.TestSimpleVarAbsolute;
+begin
+  ParseVar('q absolute v','');
+  AssertVariableType('q');
+  AssertEquals('correct absolute location','v',TheVar.AbsoluteLocation);
+end;
+
+procedure TTestVarParser.TestSimpleVarAbsoluteDot;
+begin
+  ParseVar('q absolute v.w','');
+  AssertVariableType('q');
+  AssertEquals('correct absolute location','v.w',TheVar.AbsoluteLocation);
+end;
+
+procedure TTestVarParser.TestSimpleVarAbsolute2Dots;
+begin
+  ParseVar('q absolute v.w.x','');
+  AssertVariableType('q');
+  AssertEquals('correct absolute location','v.w.x',TheVar.AbsoluteLocation);
+end;
+
 procedure TTestVarParser.TestVarProcedure;
 begin
   ParseVar('procedure','');

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

@@ -27,7 +27,7 @@
     <RunParams>
       <local>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="--suite=TTestGenerics.TestInlineSpecializationInProcedure"/>
+        <CommandLineParams Value="--suite=TTestExpressions.TestArrayAccess"/>
       </local>
     </RunParams>
     <RequiredPackages Count="1">

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

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

+ 26 - 5
packages/pastojs/src/fppas2js.pp

@@ -246,6 +246,11 @@ Works:
   - use 0o for octal literals
 
 ToDos:
+- $modeswitch -> define/undefine <modeswitch>
+- scanner: bark on unknown modeswitch
+- scanner: bark on disabling fixed modeswitch
+- $ifopt, $if option
+
 - constant evaluation
 - integer ranges
 - static arrays
@@ -260,9 +265,6 @@ ToDos:
 - local var absolute
 - make -Jirtl.js default for -Jc and -Tnodejs, needs #IFDEF in cfg
 - FuncName:= (instead of Result:=)
-- $modeswitch -> define <modeswitch>
-- scanner: define list of allowed modeswitches
-- $modeswitch- -> turn off
 - check memleaks
 - @@ compare method in delphi mode
 - make records more lightweight
@@ -779,8 +781,27 @@ type
 //------------------------------------------------------------------------------
 // TPas2JSResolver
 const
-  msAllPas2jsModeSwitches = [msDelphi,msFpc,msObjfpc,
-    msExternalClass,msHintDirective,msNestedComment];
+  msAllPas2jsModeSwitchesReadOnly = [
+    msClass,
+    msResult,
+    msRepeatForward,
+    // ToDo: msPointer2Procedure,
+    // ToDo: msAutoDeref,
+    msInitFinal,
+    msOut,
+    msDefaultPara,
+    // ToDo: msDuplicateNames
+    msProperty,
+    // ToDo: msDefaultInline
+    msExcept,
+    // ToDo: msAdvancedRecords
+    msDefaultUnicodestring,
+    msCBlocks
+    ];
+  msAllPas2jsModeSwitches = msAllPas2jsModeSwitchesReadOnly+[
+    msDelphi,msObjfpc,
+    msHintDirective,msNestedComment,
+    msExternalClass];
 
   btAllJSBaseTypes = [
     btChar,

+ 2 - 0
packages/pastojs/tests/tcmodules.pas

@@ -653,6 +653,8 @@ begin
   FFileResolver.OwnsStreams:=True;
   FScanner:=TPascalScanner.Create(FFileResolver);
   FScanner.AllowedModeSwitches:=msAllPas2jsModeSwitches;
+  FScanner.ReadOnlyModeSwitches:=msAllPas2jsModeSwitchesReadOnly;
+  FScanner.CurrentModeSwitches:=OBJFPCModeSwitches*msAllPas2jsModeSwitches+msAllPas2jsModeSwitchesReadOnly;
   FEngine:=AddModule(Filename);
   FParser:=TTestPasParser.Create(FScanner,FFileResolver,FEngine);
   Parser.Options:=Parser.Options+po_pas2js;

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff