Browse Source

pastojs: write expression

git-svn-id: trunk@38182 -
Mattias Gaertner 7 years ago
parent
commit
99e99e17f0
2 changed files with 960 additions and 86 deletions
  1. 532 58
      packages/pastojs/src/pas2jsfiler.pp
  2. 428 28
      packages/pastojs/tests/tcfiler.pas

+ 532 - 58
packages/pastojs/src/pas2jsfiler.pp

@@ -45,6 +45,11 @@ const
 
 
   PJUDefaultParserOptions: TPOptions = po_Pas2js;
   PJUDefaultParserOptions: TPOptions = po_Pas2js;
 
 
+  PJUBoolStr: array[boolean] of string = (
+    'False',
+    'True'
+    );
+
   PJUParserOptionNames: array[TPOption] of string = (
   PJUParserOptionNames: array[TPOption] of string = (
     'delphi',
     'delphi',
     'KeepScannerError',
     'KeepScannerError',
@@ -278,6 +283,84 @@ const
     'SubId'
     'SubId'
     );
     );
 
 
+  PJUPackModeNames: array[TPackMode] of string = (
+    'None',
+    'Packed',
+    'BitPacked'
+    );
+
+  PJUObjKindNames: array[TPasObjKind] of string = (
+    'Object',
+    'Class',
+    'Interface',
+    'Generic',
+    'Specialize',
+    'ClassHelper',
+    'RecordHelper',
+    'TypeHelper',
+    'DispInterface'
+    );
+
+  PJUArgumentAccessNames: array[TArgumentAccess] of string = (
+    'Default',
+    'Const',
+    'Var',
+    'Out',
+    'ConstRef'
+    );
+
+  PJUCallingConventionNames: array[TCallingConvention] of string = (
+    'Default',
+    'Register',
+    'Pascal',
+    'CDecl',
+    'StdCall',
+    'OldFPCCall',
+    'SafeCall',
+    'SysCall'
+    );
+
+  PJUProcedureMessageTypeNames: array[TProcedureMessageType] of string = (
+    'None',
+    'Integer',
+    'String'
+    );
+
+  PJUOperatorTypeNames: array[TOperatorType] of string = (
+    'Unknown',
+    'Implicit',
+    'Explicit',
+    'Mul',
+    'Plus',
+    'Minus',
+    'Division',
+    'LessThan',
+    'Equal',
+    'GreaterThan',
+    'Assign',
+    'NotEqual',
+    'LessEqualThan',
+    'GreaterEqualThan',
+    'Power',
+    'SymmetricalDifference',
+    'Inc',
+    'Dec',
+    'Mod',
+    'Negative',
+    'Positive',
+    'BitWiseOr',
+    'Div',
+    'LeftShift',
+    'LogicalOr',
+    'BitwiseAnd',
+    'bitwiseXor',
+    'LogicalAnd',
+    'LogicalNot',
+    'LogicalXor',
+    'RightShift',
+    'Enumerator'
+    );
+
 type
 type
   { TPJUInitialFlags }
   { TPJUInitialFlags }
 
 
@@ -445,15 +528,42 @@ type
     procedure WriteSection(ParentJSON: TJSONObject; Section: TPasSection;
     procedure WriteSection(ParentJSON: TJSONObject; Section: TPasSection;
       const PropName: string; aContext: TPJUWriterContext); virtual;
       const PropName: string; aContext: TPJUWriterContext); virtual;
     procedure WriteDeclarations(ParentJSON: TJSONObject; Decls: TPasDeclarations; aContext: TPJUWriterContext); virtual;
     procedure WriteDeclarations(ParentJSON: TJSONObject; Decls: TPasDeclarations; aContext: TPJUWriterContext); virtual;
-    procedure WriteDeclaration(Obj: TJSONObject; Decl: TPasElement; aContext: TPJUWriterContext); virtual;
-    procedure WriteElType(Obj: TJSONObject; const PropName: string; El: TPasElement; aType: TPasType; aContext: TPJUWriterContext); virtual;
+    procedure WriteElementProperty(Obj: TJSONObject; Parent: TPasElement;
+      const PropName: string; El: TPasElement; aContext: TPJUWriterContext); virtual;
+    procedure WriteElementList(Obj: TJSONObject; Parent: TPasElement;
+      const PropName: string; ListOfElements: TFPList; aContext: TPJUWriterContext); virtual;
+    procedure WriteElement(Obj: TJSONObject; El: TPasElement; aContext: TPJUWriterContext); virtual;
+    procedure WriteElType(Obj: TJSONObject; El: TPasElement; const PropName: string; aType: TPasType; aContext: TPJUWriterContext); virtual;
     procedure WriteVarModifiers(Obj: TJSONObject; const Value, DefaultValue: TVariableModifiers); virtual;
     procedure WriteVarModifiers(Obj: TJSONObject; const Value, DefaultValue: TVariableModifiers); virtual;
-    procedure WriteVariable(Obj: TJSONObject; Decl: TPasVariable; aContext: TPJUWriterContext); virtual;
-    procedure WriteConst(Obj: TJSONObject; Decl: TPasConst; aContext: TPJUWriterContext); virtual;
-    procedure WriteExpr(Obj: TJSONObject; const PropName: string; Expr: TPasExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteExpr(Obj: TJSONObject; Parent: TPasElement;
+      const PropName: string; Expr: TPasExpr; aContext: TPJUWriterContext); virtual;
     procedure WritePasExpr(Obj: TJSONObject; Expr: TPasExpr;
     procedure WritePasExpr(Obj: TJSONObject; Expr: TPasExpr;
       WriteKind: boolean; DefaultOpCode: TExprOpCode; aContext: TPJUWriterContext); virtual;
       WriteKind: boolean; DefaultOpCode: TExprOpCode; aContext: TPJUWriterContext); virtual;
-    procedure WritePrimitiveExpr(Obj: TJSONObject; const PropName: string; Expr: TPrimitiveExpr; aContext: TPJUWriterContext); virtual;
+    procedure WritePasExprArray(Obj: TJSONObject; Parent: TPasElement;
+      const PropName: string; const ExprArr: TPasExprArray; aContext: TPJUWriterContext); virtual;
+    procedure WriteUnaryExpr(Obj: TJSONObject; Expr: TUnaryExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteBinaryExpr(Obj: TJSONObject; Expr: TBinaryExpr; aContext: TPJUWriterContext); virtual;
+    procedure WritePrimitiveExpr(Obj: TJSONObject; Expr: TPrimitiveExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteBoolConstExpr(Obj: TJSONObject; Expr: TBoolConstExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteParamsExpr(Obj: TJSONObject; Expr: TParamsExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteRecordValues(Obj: TJSONObject; Expr: TRecordValues; aContext: TPJUWriterContext); virtual;
+    procedure WriteArrayValues(Obj: TJSONObject; Expr: TArrayValues; aContext: TPJUWriterContext); virtual;
+    procedure WriteResString(Obj: TJSONObject; El: TPasResString; aContext: TPJUWriterContext); virtual;
+    procedure WriteAliasType(Obj: TJSONObject; El: TPasAliasType; aContext: TPJUWriterContext); virtual;
+    procedure WritePointerType(Obj: TJSONObject; El: TPasPointerType; aContext: TPJUWriterContext); virtual;
+    procedure WriteSpecializeType(Obj: TJSONObject; El: TPasSpecializeType; aContext: TPJUWriterContext); virtual;
+    procedure WriteInlineTypeExpr(Obj: TJSONObject; Expr: TInlineTypeExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteInlineSpecializeExpr(Obj: TJSONObject; Expr: TInlineSpecializeExpr; aContext: TPJUWriterContext); virtual;
+    procedure WriteArrayType(Obj: TJSONObject; El: TPasArrayType; aContext: TPJUWriterContext); virtual;
+    procedure WriteFileType(Obj: TJSONObject; El: TPasFileType; aContext: TPJUWriterContext); virtual;
+    procedure WriteEnumValue(Obj: TJSONObject; El: TPasEnumValue; aContext: TPJUWriterContext); virtual;
+    procedure WriteEnumType(Obj: TJSONObject; El: TPasEnumType; aContext: TPJUWriterContext); virtual;
+    procedure WriteSetType(Obj: TJSONObject; El: TPasSetType; aContext: TPJUWriterContext); virtual;
+    procedure WriteRecordVariant(Obj: TJSONObject; El: TPasVariant; aContext: TPJUWriterContext); virtual;
+    procedure WriteRecordType(Obj: TJSONObject; El: TPasRecordType; aContext: TPJUWriterContext); virtual;
+    procedure WriteClassType(Obj: TJSONObject; El: TPasClassType; aContext: TPJUWriterContext); virtual;
+    procedure WriteVariable(Obj: TJSONObject; El: TPasVariable; aContext: TPJUWriterContext); virtual;
+    procedure WriteConst(Obj: TJSONObject; El: TPasConst; aContext: TPJUWriterContext); virtual;
     procedure WriteExternalReferences(ParentJSON: TJSONObject); virtual;
     procedure WriteExternalReferences(ParentJSON: TJSONObject); virtual;
   public
   public
     constructor Create; override;
     constructor Create; override;
@@ -1431,6 +1541,7 @@ var
   Ordered: TPasIdentifierArray;
   Ordered: TPasIdentifierArray;
 begin
 begin
   Arr:=nil;
   Arr:=nil;
+  if aContext=nil then ;
   Locals:=Scope.GetLocalIdentifiers;
   Locals:=Scope.GetLocalIdentifiers;
   try
   try
     p:=0;
     p:=0;
@@ -1519,6 +1630,8 @@ begin
   for i:=0 to Decls.Declarations.Count-1 do
   for i:=0 to Decls.Declarations.Count-1 do
     begin
     begin
     Decl:=TPasElement(Decls.Declarations[i]);
     Decl:=TPasElement(Decls.Declarations[i]);
+    if Decl.Parent<>Decls then
+      RaiseMsg(20180208221915,Decl,'['+IntToStr(i)+']='+GetObjName(Decl)+': '+GetObjName(Decls)+'<>'+GetObjName(Decl.Parent));
     if Arr=nil then
     if Arr=nil then
       begin
       begin
       Arr:=TJSONArray.Create;
       Arr:=TJSONArray.Create;
@@ -1526,41 +1639,209 @@ begin
       end;
       end;
     DeclObj:=TJSONObject.Create;
     DeclObj:=TJSONObject.Create;
     Arr.Add(DeclObj);
     Arr.Add(DeclObj);
-    WriteDeclaration(DeclObj,Decl,aContext);
+    WriteElement(DeclObj,Decl,aContext);
+    end;
+end;
+
+procedure TPJUWriter.WriteElementProperty(Obj: TJSONObject;
+  Parent: TPasElement; const PropName: string; El: TPasElement;
+  aContext: TPJUWriterContext);
+var
+  SubObj: TJSONObject;
+begin
+  if El=nil then exit;
+  if Parent<>El.Parent then
+    RaiseMsg(20180208221751,El,GetObjName(Parent)+'<>'+GetObjName(El.Parent));
+  SubObj:=TJSONObject.Create;
+  Obj.Add(PropName,SubObj);
+  WriteElement(SubObj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteElementList(Obj: TJSONObject; Parent: TPasElement;
+  const PropName: string; ListOfElements: TFPList; aContext: TPJUWriterContext);
+var
+  Arr: TJSONArray;
+  i: Integer;
+  SubObj: TJSONObject;
+  Item: TPasElement;
+begin
+  if (ListOfElements=nil) or (ListOfElements.Count=0) then exit;
+  Arr:=TJSONArray.Create;
+  Obj.Add(PropName,Arr);
+  for i:=0 to ListOfElements.Count-1 do
+    begin
+    Item:=TPasElement(ListOfElements[i]);
+    if Item.Parent<>Parent then
+      RaiseMsg(20180209191444,Item,GetObjName(Parent)+'<>'+GetObjName(Item.Parent));
+    SubObj:=TJSONObject.Create;
+    Arr.Add(SubObj);
+    WriteElement(SubObj,Item,aContext);
     end;
     end;
 end;
 end;
 
 
-procedure TPJUWriter.WriteDeclaration(Obj: TJSONObject;
-  Decl: TPasElement; aContext: TPJUWriterContext);
+procedure TPJUWriter.WriteElement(Obj: TJSONObject;
+  El: TPasElement; aContext: TPJUWriterContext);
 var
 var
   C: TClass;
   C: TClass;
 begin
 begin
-  C:=Decl.ClassType;
-  if C=TPasConst then
-  begin
-    Obj.Add('Type','Const');
-    WriteConst(Obj,TPasConst(Decl),aContext);
-  end else if C=TPasVariable then
-  begin
+  C:=El.ClassType;
+  if C=TUnaryExpr then
+    begin
+    Obj.Add('Type','Unary');
+    WriteUnaryExpr(Obj,TUnaryExpr(El),aContext);
+    end
+  else if C=TBinaryExpr then
+    begin
+    Obj.Add('Type','Binary');
+    WriteBinaryExpr(Obj,TBinaryExpr(El),aContext);
+    end
+  else if C.InheritsFrom(TPasExpr) then
+    begin
+    Obj.Add('Type',PJUExprKindNames[TPrimitiveExpr(El).Kind]);
+    WritePrimitiveExpr(Obj,TPrimitiveExpr(El),aContext);
+    end
+  else if C=TBoolConstExpr then
+    begin
+    if El.CustomData=nil then
+      Obj.Add('Type',PJUBoolStr[TBoolConstExpr(El).Value])
+    else
+      WriteBoolConstExpr(Obj,TBoolConstExpr(El),aContext);
+    end
+  else if C=TNilExpr then
+    Obj.Add('Type','nil')
+  else if C=TInheritedExpr then
+    begin
+    Obj.Add('Type','inherited');
+    WritePasExpr(Obj,TInheritedExpr(El),false,eopNone,aContext);
+    end
+  else if C=TSelfExpr then
+    begin
+    Obj.Add('Type','Self');
+    WritePasExpr(Obj,TSelfExpr(El),false,eopNone,aContext);
+    end
+  else if C=TParamsExpr then
+    begin
+    case TParamsExpr(El).Kind of
+    pekArrayParams: Obj.Add('Type','A[]');
+    pekFuncParams: Obj.Add('Type','F()');
+    pekSet: Obj.Add('Type','[]');
+    end;
+    WriteParamsExpr(Obj,TParamsExpr(El),aContext);
+    end
+  else if C=TRecordValues then
+    begin
+    Obj.Add('Type','RecValues');
+    WriteRecordValues(Obj,TRecordValues(El),aContext);
+    end
+  else if C=TArrayValues then
+    begin
+    Obj.Add('Type','ArrValues');
+    WriteArrayValues(Obj,TArrayValues(El),aContext);
+    end
+  else if C=TPasResString then
+    begin
+    Obj.Add('Type','ResString');
+    WriteResString(Obj,TPasResString(El),aContext);
+    end
+  else if C=TPasAliasType then
+    begin
+    Obj.Add('Type','Alias');
+    WriteAliasType(Obj,TPasAliasType(El),aContext);
+    end
+  else if C=TPasPointerType then
+    begin
+    Obj.Add('Type','Pointer');
+    WritePointerType(Obj,TPasPointerType(El),aContext);
+    end
+  else if C=TPasTypeAliasType then
+    begin
+    Obj.Add('Type','TypeAlias');
+    WriteAliasType(Obj,TPasTypeAliasType(El),aContext);
+    end
+  else if C=TPasClassOfType then
+    begin
+    Obj.Add('Type','ClassOf');
+    WriteAliasType(Obj,TPasClassOfType(El),aContext);
+    end
+  else if C=TPasSpecializeType then
+    begin
+    Obj.Add('Type','Specialize');
+    WriteSpecializeType(Obj,TPasSpecializeType(El),aContext);
+    end
+  else if C=TInlineSpecializeExpr then
+    begin
+    Obj.Add('Type','InlineSpecialize');
+    WriteInlineSpecializeExpr(Obj,TInlineSpecializeExpr(El),aContext);
+    end
+  else if C=TPasArrayType then
+    begin
+    Obj.Add('Type','ArrType');
+    WriteArrayType(Obj,TPasArrayType(El),aContext);
+    end
+  else if C=TPasFileType then
+    begin
+    Obj.Add('Type','File');
+    WriteFileType(Obj,TPasFileType(El),aContext);
+    end
+  else if C=TPasEnumValue then
+    begin
+    Obj.Add('Type','EnumV');
+    WriteEnumValue(Obj,TPasEnumValue(El),aContext);
+    end
+  else if C=TPasEnumType then
+    begin
+    Obj.Add('Type','EnumType');
+    WriteEnumType(Obj,TPasEnumType(El),aContext);
+    end
+  else if C=TPasSetType then
+    begin
+    Obj.Add('Type','SetType');
+    WriteSetType(Obj,TPasSetType(El),aContext);
+    end
+  else if C=TPasVariant then
+    begin
+    Obj.Add('Type','RecVariant');
+    WriteRecordVariant(Obj,TPasVariant(El),aContext);
+    end
+  else if C=TPasRecordType then
+    begin
+    Obj.Add('Type','Record');
+    WriteRecordType(Obj,TPasRecordType(El),aContext);
+    end
+  else if C=TPasClassType then
+    begin
+    Obj.Add('Type','Class');// ToDo
+    WriteClassType(Obj,TPasClassType(El),aContext);
+    end
+
+  else if C=TPasVariable then
+    begin
     Obj.Add('Type','Var');
     Obj.Add('Type','Var');
-    WriteVariable(Obj,TPasVariable(Decl),aContext)
-  end else
-    RaiseMsg(20180205154041,Decl);
+    WriteVariable(Obj,TPasVariable(El),aContext);
+    end
+  else if C=TPasConst then
+    begin
+      Obj.Add('Type','Const');
+      WriteConst(Obj,TPasConst(El),aContext);
+    end
+  else
+    RaiseMsg(20180205154041,El);
 end;
 end;
 
 
-procedure TPJUWriter.WriteElType(Obj: TJSONObject; const PropName: string;
-  El: TPasElement; aType: TPasType; aContext: TPJUWriterContext);
+procedure TPJUWriter.WriteElType(Obj: TJSONObject; El: TPasElement;
+  const PropName: string; aType: TPasType; aContext: TPJUWriterContext);
 begin
 begin
   if aType=nil then exit;
   if aType=nil then exit;
   if (aType.Name='') or (aType.Parent=El) then
   if (aType.Name='') or (aType.Parent=El) then
-  begin
+    begin
     // anonymous type
     // anonymous type
-
-  end
-  else begin
+    WriteElementProperty(Obj,El,PropName,aType,aContext);
+    end
+  else
+    begin
     // reference
     // reference
-
-  end;
+    AddReferenceToObj(Obj,PropName,aType);
+    end;
   RaiseMsg(20180206183542,El);
   RaiseMsg(20180206183542,El);
 end;
 end;
 
 
@@ -1576,38 +1857,54 @@ begin
       AddArrayFlag(Obj,Arr,'VarMod',PJUVarModifierNames[f],f in Value);
       AddArrayFlag(Obj,Arr,'VarMod',PJUVarModifierNames[f],f in Value);
 end;
 end;
 
 
-procedure TPJUWriter.WriteVariable(Obj: TJSONObject; Decl: TPasVariable;
+procedure TPJUWriter.WriteUnaryExpr(Obj: TJSONObject; Expr: TUnaryExpr;
   aContext: TPJUWriterContext);
   aContext: TPJUWriterContext);
 begin
 begin
-  WriteElType(Obj,'VarType',Decl,Decl.VarType,aContext);
-  WriteVarModifiers(Obj,Decl.VarModifiers,[]);
-  WriteExpr(Obj,'Library',Decl.LibraryName,aContext);
-  WriteExpr(Obj,'Export',Decl.ExportName,aContext);
-  WriteExpr(Obj,'Absolute',Decl.AbsoluteExpr,aContext);
-  WriteExpr(Obj,'Expr',Decl.Expr,aContext);
+  WriteExpr(Obj,Expr,'Operand',Expr.Operand,aContext);
+  WritePasExpr(Obj,Expr,false,eopAdd,aContext);
+end;
+
+procedure TPJUWriter.WriteBinaryExpr(Obj: TJSONObject; Expr: TBinaryExpr;
+  aContext: TPJUWriterContext);
+begin
+  WriteExpr(Obj,Expr,'left',Expr.left,aContext);
+  WriteExpr(Obj,Expr,'right',Expr.right,aContext);
+  WritePasExpr(Obj,Expr,false,eopAdd,aContext);
+end;
+
+procedure TPJUWriter.WriteVariable(Obj: TJSONObject; El: TPasVariable;
+  aContext: TPJUWriterContext);
+begin
+  WriteElType(Obj,El,'VarType',El.VarType,aContext);
+  WriteVarModifiers(Obj,El.VarModifiers,[]);
+  WriteExpr(Obj,El,'Library',El.LibraryName,aContext);
+  WriteExpr(Obj,El,'Export',El.ExportName,aContext);
+  WriteExpr(Obj,El,'Absolute',El.AbsoluteExpr,aContext);
+  WriteExpr(Obj,El,'Expr',El.Expr,aContext);
 
 
-  WritePasElement(Obj,Decl,aContext);
+  WritePasElement(Obj,El,aContext);
 end;
 end;
 
 
-procedure TPJUWriter.WriteConst(Obj: TJSONObject; Decl: TPasConst;
+procedure TPJUWriter.WriteConst(Obj: TJSONObject; El: TPasConst;
   aContext: TPJUWriterContext);
   aContext: TPJUWriterContext);
 begin
 begin
-  if Decl.IsConst<>(Decl.VarType=nil) then
-    Obj.Add('IsConst',Decl.IsConst);
-  WriteVariable(Obj,Decl,aContext);
+  if El.IsConst<>(El.VarType=nil) then
+    Obj.Add('IsConst',El.IsConst);
+  WriteVariable(Obj,El,aContext);
 end;
 end;
 
 
-procedure TPJUWriter.WriteExpr(Obj: TJSONObject; const PropName: string;
-  Expr: TPasExpr; aContext: TPJUWriterContext);
+procedure TPJUWriter.WriteExpr(Obj: TJSONObject; Parent: TPasElement;
+  const PropName: string; Expr: TPasExpr; aContext: TPJUWriterContext);
 var
 var
-  C: TClass;
+  SubObj: TJSONObject;
 begin
 begin
   if Expr=nil then exit;
   if Expr=nil then exit;
-  C:=Expr.ClassType;
-  if C=TPrimitiveExpr then
-    WritePrimitiveExpr(Obj,PropName,TPrimitiveExpr(Expr),aContext)
-  else
-    RaiseMsg(20180206185146,Expr);
+  if Parent<>Expr.Parent then
+    RaiseMsg(20180208221051,Expr,GetObjName(Parent)+'<>'+GetObjName(Expr.Parent));
+  // ToDo: write simple expressions in a compact format
+  SubObj:=TJSONObject.Create;
+  Obj.Add(PropName,SubObj);
+  WriteElement(SubObj,Expr,aContext);
 end;
 end;
 
 
 procedure TPJUWriter.WritePasExpr(Obj: TJSONObject; Expr: TPasExpr;
 procedure TPJUWriter.WritePasExpr(Obj: TJSONObject; Expr: TPasExpr;
@@ -1617,22 +1914,200 @@ begin
     Obj.Add('Kind',PJUExprKindNames[Expr.Kind]);
     Obj.Add('Kind',PJUExprKindNames[Expr.Kind]);
   if (Expr.OpCode<>DefaultOpCode) then
   if (Expr.OpCode<>DefaultOpCode) then
     Obj.Add('Op',PJUExprOpCodeNames[Expr.OpCode]);
     Obj.Add('Op',PJUExprOpCodeNames[Expr.OpCode]);
-  WriteExpr(Obj,'Format1',Expr.format1,aContext);
-  WriteExpr(Obj,'Format2',Expr.format2,aContext);
+  WriteExpr(Obj,Expr,'Format1',Expr.format1,aContext);
+  WriteExpr(Obj,Expr,'Format2',Expr.format2,aContext);
   WritePasElement(Obj,Expr,aContext);
   WritePasElement(Obj,Expr,aContext);
 end;
 end;
 
 
-procedure TPJUWriter.WritePrimitiveExpr(Obj: TJSONObject;
-  const PropName: string; Expr: TPrimitiveExpr; aContext: TPJUWriterContext);
+procedure TPJUWriter.WritePasExprArray(Obj: TJSONObject; Parent: TPasElement;
+  const PropName: string; const ExprArr: TPasExprArray;
+  aContext: TPJUWriterContext);
 var
 var
+  Arr: TJSONArray;
+  i: Integer;
+  Expr: TPasExpr;
   SubObj: TJSONObject;
   SubObj: TJSONObject;
 begin
 begin
-  SubObj:=TJSONObject.Create;
-  Obj.Add(PropName,SubObj);
-  SubObj.Add('Type',PJUExprKindNames[Expr.Kind]);
+  if length(ExprArr)=0 then exit;
+  Arr:=TJSONArray.Create;
+  Obj.Add(PropName,Arr);
+  for i:=0 to length(ExprArr)-1 do
+    begin
+    Expr:=ExprArr[i];
+    if Expr.Parent<>Parent then
+      RaiseMsg(20180209191444,Expr,GetObjName(Parent)+'<>'+GetObjName(Expr.Parent));
+    SubObj:=TJSONObject.Create;
+    Arr.Add(SubObj);
+    WriteElement(SubObj,Expr,aContext);
+    end;
+end;
+
+procedure TPJUWriter.WritePrimitiveExpr(Obj: TJSONObject; Expr: TPrimitiveExpr;
+  aContext: TPJUWriterContext);
+begin
   if Expr.Value<>'' then
   if Expr.Value<>'' then
-    SubObj.Add('Value',Expr.Value);
-  WritePasExpr(SubObj,Expr,false,eopNone,aContext);
+    Obj.Add('Value',Expr.Value);
+  WritePasExpr(Obj,Expr,false,eopNone,aContext);
+end;
+
+procedure TPJUWriter.WriteBoolConstExpr(Obj: TJSONObject; Expr: TBoolConstExpr;
+  aContext: TPJUWriterContext);
+begin
+  if Expr.Value then
+    Obj.Add('Value',true);
+  WritePasExpr(Obj,Expr,false,eopNone,aContext);
+end;
+
+procedure TPJUWriter.WriteParamsExpr(Obj: TJSONObject; Expr: TParamsExpr;
+  aContext: TPJUWriterContext);
+begin
+  WriteExpr(Obj,Expr,'Value',Expr.Value,aContext);
+  WritePasExprArray(Obj,Expr,'Params',Expr.Params,aContext);
+  WritePasExpr(Obj,Expr,false,eopNone,aContext);
+end;
+
+procedure TPJUWriter.WriteRecordValues(Obj: TJSONObject; Expr: TRecordValues;
+  aContext: TPJUWriterContext);
+var
+  Arr: TJSONArray;
+  i: Integer;
+  SubObj: TJSONObject;
+  RecValue: TRecordValuesItem;
+begin
+  if length(Expr.Fields)>0 then
+    begin
+    Arr:=TJSONArray.Create;
+    Obj.Add('Fields',Arr);
+    for i:=0 to length(Expr.Fields)-1 do
+      begin
+      RecValue:=Expr.Fields[i];
+      SubObj:=TJSONObject.Create;
+      Arr.Add(SubObj);
+      SubObj.Add('Name',RecValue.Name);
+      if (RecValue.ValueExp<>nil) and (RecValue.ValueExp.Name<>'') then
+        RaiseMsg(20180209192240,RecValue.ValueExp);
+      WriteElement(SubObj,RecValue.ValueExp,aContext);
+      end;
+    end;
+  WritePasExpr(Obj,Expr,false,eopNone,aContext);
+end;
+
+procedure TPJUWriter.WriteArrayValues(Obj: TJSONObject; Expr: TArrayValues;
+  aContext: TPJUWriterContext);
+begin
+  WritePasExprArray(Obj,Expr,'Values',Expr.Values,aContext);
+  WritePasExpr(Obj,Expr,false,eopNone,aContext);
+end;
+
+procedure TPJUWriter.WriteResString(Obj: TJSONObject; El: TPasResString;
+  aContext: TPJUWriterContext);
+begin
+  WriteExpr(Obj,El,'Expr',El.Expr,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteAliasType(Obj: TJSONObject; El: TPasAliasType;
+  aContext: TPJUWriterContext);
+begin
+  WriteElType(Obj,El,'Dest',El.DestType,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WritePointerType(Obj: TJSONObject; El: TPasPointerType;
+  aContext: TPJUWriterContext);
+begin
+  WriteElType(Obj,El,'Dest',El.DestType,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteSpecializeType(Obj: TJSONObject;
+  El: TPasSpecializeType; aContext: TPJUWriterContext);
+begin
+  WriteElementList(Obj,El,'Params',El.Params,aContext);
+  WriteAliasType(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteInlineTypeExpr(Obj: TJSONObject; Expr: TInlineTypeExpr;
+  aContext: TPJUWriterContext);
+begin
+  WriteElType(Obj,Expr,'Dest',Expr.DestType,aContext);
+  WritePasExpr(Obj,Expr,false,eopNone,aContext);
+end;
+
+procedure TPJUWriter.WriteInlineSpecializeExpr(Obj: TJSONObject;
+  Expr: TInlineSpecializeExpr; aContext: TPJUWriterContext);
+begin
+  WriteInlineTypeExpr(Obj,Expr,aContext);
+end;
+
+procedure TPJUWriter.WriteArrayType(Obj: TJSONObject; El: TPasArrayType;
+  aContext: TPJUWriterContext);
+begin
+  WritePasExprArray(Obj,El,'Ranges',El.Ranges,aContext);
+  if El.PackMode<>pmNone then
+    Obj.Add('Packed',PJUPackModeNames[El.PackMode]);
+  WriteElType(Obj,El,'ElType',El.ElType,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteFileType(Obj: TJSONObject; El: TPasFileType;
+  aContext: TPJUWriterContext);
+begin
+  WriteElType(Obj,El,'ElType',El.ElType,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteEnumValue(Obj: TJSONObject; El: TPasEnumValue;
+  aContext: TPJUWriterContext);
+begin
+  WriteExpr(Obj,El,'Value',El.Value,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteEnumType(Obj: TJSONObject; El: TPasEnumType;
+  aContext: TPJUWriterContext);
+begin
+  WriteElementList(Obj,El,'Values',El.Values,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteSetType(Obj: TJSONObject; El: TPasSetType;
+  aContext: TPJUWriterContext);
+begin
+  WriteElType(Obj,El,'EnumType',El.EnumType,aContext);
+  if El.IsPacked then
+    Obj.Add('Packed',true);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteRecordVariant(Obj: TJSONObject; El: TPasVariant;
+  aContext: TPJUWriterContext);
+begin
+  WriteElementList(Obj,El,'Values',El.Values,aContext);
+  WriteElType(Obj,El,'Members',El.Members,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteRecordType(Obj: TJSONObject; El: TPasRecordType;
+  aContext: TPJUWriterContext);
+begin
+  if El.PackMode<>pmNone then
+    Obj.Add('Packed',PJUPackModeNames[El.PackMode]);
+  WriteElementList(Obj,El,'Members',El.Members,aContext);
+  // VariantEl: TPasElement can be TPasVariable or TPasType
+  if El.VariantEl is TPasType then
+    WriteElType(Obj,El,'VariantEl',TPasType(El.VariantEl),aContext)
+  else
+    WriteElementProperty(Obj,El,'VariantEl',El.VariantEl,aContext);
+  WriteElementList(Obj,El,'Variants',El.Variants,aContext);
+  WriteElementList(Obj,El,'Templates',El.GenericTemplateTypes,aContext);
+  WritePasElement(Obj,El,aContext);
+end;
+
+procedure TPJUWriter.WriteClassType(Obj: TJSONObject; El: TPasClassType;
+  aContext: TPJUWriterContext);
+begin
+  // ToDo
 end;
 end;
 
 
 procedure TPJUWriter.WriteExternalReferences(ParentJSON: TJSONObject);
 procedure TPJUWriter.WriteExternalReferences(ParentJSON: TJSONObject);
@@ -1668,11 +2143,9 @@ begin
       SystemArr.Add(Obj);
       SystemArr.Add(Obj);
       Obj.Add('Name',El.Name);
       Obj.Add('Name',El.Name);
       if Data is TResElDataBuiltInProc then
       if Data is TResElDataBuiltInProc then
-        begin
         case TResElDataBuiltInProc(Data).BuiltIn of
         case TResElDataBuiltInProc(Data).BuiltIn of
         bfStrFunc: Obj.Add('Type','Func');
         bfStrFunc: Obj.Add('Type','Func');
         end;
         end;
-        end;
       Ref.Obj:=Obj;
       Ref.Obj:=Obj;
       ResolvePendingElRefs(Ref);
       ResolvePendingElRefs(Ref);
       continue;
       continue;
@@ -2465,6 +2938,7 @@ var
   Data: TJSONData;
   Data: TJSONData;
   Id: Integer;
   Id: Integer;
 begin
 begin
+  if aContext=nil then ;
   Data:=Obj.Find(PropName);
   Data:=Obj.Find(PropName);
   if Data=nil then exit;
   if Data=nil then exit;
   if Data is TJSONIntegerNumber then
   if Data is TJSONIntegerNumber then

+ 428 - 28
packages/pastojs/tests/tcfiler.pas

@@ -53,10 +53,41 @@ type
     procedure CheckRestoredSectionScope(const Path: string; Orig, Rest: TPasSectionScope); virtual;
     procedure CheckRestoredSectionScope(const Path: string; Orig, Rest: TPasSectionScope); virtual;
     procedure CheckRestoredCustomData(const Path: string; El: TPasElement; Orig, Rest: TObject); virtual;
     procedure CheckRestoredCustomData(const Path: string; El: TPasElement; Orig, Rest: TObject); virtual;
     procedure CheckRestoredElement(const Path: string; Orig, Rest: TPasElement); virtual;
     procedure CheckRestoredElement(const Path: string; Orig, Rest: TPasElement); virtual;
-    procedure CheckRestoredConst(const Path: string; Orig, Rest: TPasConst); virtual;
-    procedure CheckRestoredVariable(const Path: string; Orig, Rest: TPasVariable); virtual;
+    procedure CheckRestoredElementList(const Path: string; Orig, Rest: TFPList); virtual;
+    procedure CheckRestoredPasExpr(const Path: string; Orig, Rest: TPasExpr); virtual;
+    procedure CheckRestoredUnaryExpr(const Path: string; Orig, Rest: TUnaryExpr); virtual;
+    procedure CheckRestoredBinaryExpr(const Path: string; Orig, Rest: TBinaryExpr); virtual;
     procedure CheckRestoredPrimitiveExpr(const Path: string; Orig, Rest: TPrimitiveExpr); virtual;
     procedure CheckRestoredPrimitiveExpr(const Path: string; Orig, Rest: TPrimitiveExpr); virtual;
-    procedure CheckRestoredExpr(const Path: string; Orig, Rest: TPasExpr); virtual;
+    procedure CheckRestoredBoolConstExpr(const Path: string; Orig, Rest: TBoolConstExpr); virtual;
+    procedure CheckRestoredParamsExpr(const Path: string; Orig, Rest: TParamsExpr); virtual;
+    procedure CheckRestoredRecordValues(const Path: string; Orig, Rest: TRecordValues); virtual;
+    procedure CheckRestoredPasExprArray(const Path: string; Orig, Rest: TPasExprArray); virtual;
+    procedure CheckRestoredArrayValues(const Path: string; Orig, Rest: TArrayValues); virtual;
+    procedure CheckRestoredResString(const Path: string; Orig, Rest: TPasResString); virtual;
+    procedure CheckRestoredAliasType(const Path: string; Orig, Rest: TPasAliasType); virtual;
+    procedure CheckRestoredPointerType(const Path: string; Orig, Rest: TPasPointerType); virtual;
+    procedure CheckRestoredSpecializedType(const Path: string; Orig, Rest: TPasSpecializeType); virtual;
+    procedure CheckRestoredInlineSpecializedExpr(const Path: string; Orig, Rest: TInlineSpecializeExpr); virtual;
+    procedure CheckRestoredRangeType(const Path: string; Orig, Rest: TPasRangeType); virtual;
+    procedure CheckRestoredArrayType(const Path: string; Orig, Rest: TPasArrayType); virtual;
+    procedure CheckRestoredFileType(const Path: string; Orig, Rest: TPasFileType); virtual;
+    procedure CheckRestoredEnumValue(const Path: string; Orig, Rest: TPasEnumValue); virtual;
+    procedure CheckRestoredEnumType(const Path: string; Orig, Rest: TPasEnumType); virtual;
+    procedure CheckRestoredSetType(const Path: string; Orig, Rest: TPasSetType); virtual;
+    procedure CheckRestoredVariant(const Path: string; Orig, Rest: TPasVariant); virtual;
+    procedure CheckRestoredRecordType(const Path: string; Orig, Rest: TPasRecordType); virtual;
+    procedure CheckRestoredClassType(const Path: string; Orig, Rest: TPasClassType); virtual;
+    procedure CheckRestoredArgument(const Path: string; Orig, Rest: TPasArgument); virtual;
+    procedure CheckRestoredProcedureType(const Path: string; Orig, Rest: TPasProcedureType); virtual;
+    procedure CheckRestoredResultElement(const Path: string; Orig, Rest: TPasResultElement); virtual;
+    procedure CheckRestoredFunctionType(const Path: string; Orig, Rest: TPasFunctionType); virtual;
+    procedure CheckRestoredStringType(const Path: string; Orig, Rest: TPasStringType); virtual;
+    procedure CheckRestoredVariable(const Path: string; Orig, Rest: TPasVariable); virtual;
+    procedure CheckRestoredExportSymbol(const Path: string; Orig, Rest: TPasExportSymbol); virtual;
+    procedure CheckRestoredConst(const Path: string; Orig, Rest: TPasConst); virtual;
+    procedure CheckRestoredProperty(const Path: string; Orig, Rest: TPasProperty); virtual;
+    procedure CheckRestoredProcedure(const Path: string; Orig, Rest: TPasProcedure); virtual;
+    procedure CheckRestoredOperator(const Path: string; Orig, Rest: TPasOperator); virtual;
     procedure CheckRestoredReference(const Path: string; Orig, Rest: TPasElement); virtual;
     procedure CheckRestoredReference(const Path: string; Orig, Rest: TPasElement); virtual;
   public
   public
     property PJUWriter: TPJUWriter read FPJUWriter write FPJUWriter;
     property PJUWriter: TPJUWriter read FPJUWriter write FPJUWriter;
@@ -392,27 +423,356 @@ begin
   CheckRestoredCustomData(Path+'.CustomData',Rest,Orig.CustomData,Rest.CustomData);
   CheckRestoredCustomData(Path+'.CustomData',Rest,Orig.CustomData,Rest.CustomData);
 
 
   C:=Orig.ClassType;
   C:=Orig.ClassType;
-  if (C=TPasModule)
-      or (C=TPasProgram)
-      or (C=TPasLibrary) then
+  if C=TUnaryExpr then
+    CheckRestoredUnaryExpr(Path,TUnaryExpr(Orig),TUnaryExpr(Rest))
+  else if C=TBinaryExpr then
+    CheckRestoredBinaryExpr(Path,TBinaryExpr(Orig),TBinaryExpr(Rest))
+  else if C=TPrimitiveExpr then
+    CheckRestoredPrimitiveExpr(Path,TPrimitiveExpr(Orig),TPrimitiveExpr(Rest))
+  else if C=TBoolConstExpr then
+    CheckRestoredBoolConstExpr(Path,TBoolConstExpr(Orig),TBoolConstExpr(Rest))
+  else if (C=TNilExpr)
+      or (C=TInheritedExpr)
+      or (C=TSelfExpr) then
+    CheckRestoredPasExpr(Path,TPasExpr(Orig),TPasExpr(Rest))
+  else if C=TParamsExpr then
+    CheckRestoredParamsExpr(Path,TParamsExpr(Orig),TParamsExpr(Rest))
+  else if C=TRecordValues then
+    CheckRestoredRecordValues(Path,TRecordValues(Orig),TRecordValues(Rest))
+  else if C=TArrayValues then
+    CheckRestoredArrayValues(Path,TArrayValues(Orig),TArrayValues(Rest))
+  // TPasDeclarations is a base class
+  // TPasUsesUnit is checked in usesclause
+  // TPasSection is a base class
+  else if C=TPasResString then
+    CheckRestoredResString(Path,TPasResString(Orig),TPasResString(Rest))
+  // TPasType is a base clas
+  else if (C=TPasAliasType)
+      or (C=TPasTypeAliasType)
+      or (C=TPasClassOfType) then
+    CheckRestoredAliasType(Path,TPasAliasType(Orig),TPasAliasType(Rest))
+  else if C=TPasPointerType then
+    CheckRestoredPointerType(Path,TPasPointerType(Orig),TPasPointerType(Rest))
+  else if C=TPasSpecializeType then
+    CheckRestoredSpecializedType(Path,TPasSpecializeType(Orig),TPasSpecializeType(Rest))
+  else if C=TInlineSpecializeExpr then
+    CheckRestoredInlineSpecializedExpr(Path,TInlineSpecializeExpr(Orig),TInlineSpecializeExpr(Rest))
+  else if C=TPasRangeType then
+    CheckRestoredRangeType(Path,TPasRangeType(Orig),TPasRangeType(Rest))
+  else if C=TPasArrayType then
+    CheckRestoredArrayType(Path,TPasArrayType(Orig),TPasArrayType(Rest))
+  else if C=TPasFileType then
+    CheckRestoredFileType(Path,TPasFileType(Orig),TPasFileType(Rest))
+  else if C=TPasEnumValue then
+    CheckRestoredEnumValue(Path,TPasEnumValue(Orig),TPasEnumValue(Rest))
+  else if C=TPasEnumType then
+    CheckRestoredEnumType(Path,TPasEnumType(Orig),TPasEnumType(Rest))
+  else if C=TPasSetType then
+    CheckRestoredSetType(Path,TPasSetType(Orig),TPasSetType(Rest))
+  else if C=TPasVariant then
+    CheckRestoredVariant(Path,TPasVariant(Orig),TPasVariant(Rest))
+  else if C=TPasRecordType then
+    CheckRestoredRecordType(Path,TPasRecordType(Orig),TPasRecordType(Rest))
+  else if C=TPasClassType then
+    CheckRestoredClassType(Path,TPasClassType(Orig),TPasClassType(Rest))
+  else if C=TPasArgument then
+    CheckRestoredArgument(Path,TPasArgument(Orig),TPasArgument(Rest))
+  else if C=TPasProcedureType then
+    CheckRestoredProcedureType(Path,TPasProcedureType(Orig),TPasProcedureType(Rest))
+  else if C=TPasResultElement then
+    CheckRestoredResultElement(Path,TPasResultElement(Orig),TPasResultElement(Rest))
+  else if C=TPasFunctionType then
+    CheckRestoredFunctionType(Path,TPasFunctionType(Orig),TPasFunctionType(Rest))
+  else if C=TPasStringType then
+    CheckRestoredStringType(Path,TPasStringType(Orig),TPasStringType(Rest))
+  else if C=TPasVariable then
+    CheckRestoredVariable(Path,TPasVariable(Orig),TPasVariable(Rest))
+  else if C=TPasExportSymbol then
+    CheckRestoredExportSymbol(Path,TPasExportSymbol(Orig),TPasExportSymbol(Rest))
+  else if C=TPasConst then
+    CheckRestoredConst(Path,TPasConst(Orig),TPasConst(Rest))
+  else if C=TPasProperty then
+    CheckRestoredProperty(Path,TPasProperty(Orig),TPasProperty(Rest))
+  else if (C=TPasProcedure)
+      or (C=TPasFunction)
+      or (C=TPasConstructor)
+      or (C=TPasClassConstructor)
+      or (C=TPasDestructor)
+      or (C=TPasClassDestructor)
+      or (C=TPasClassProcedure)
+      or (C=TPasClassFunction)
+      then
+    CheckRestoredProcedure(Path,TPasProcedure(Orig),TPasProcedure(Rest))
+  else if (C=TPasOperator)
+      or (C=TPasClassOperator) then
+    CheckRestoredOperator(Path,TPasOperator(Orig),TPasOperator(Rest))
+  else if (C=TPasModule)
+        or (C=TPasProgram)
+        or (C=TPasLibrary) then
     CheckRestoredModule(Path,TPasModule(Orig),TPasModule(Rest))
     CheckRestoredModule(Path,TPasModule(Orig),TPasModule(Rest))
   else if C.InheritsFrom(TPasSection) then
   else if C.InheritsFrom(TPasSection) then
     CheckRestoredSection(Path,TPasSection(Orig),TPasSection(Rest))
     CheckRestoredSection(Path,TPasSection(Orig),TPasSection(Rest))
-  else if C=TPasConst then
-    CheckRestoredConst(Path,TPasConst(Orig),TPasConst(Rest))
-  else if C=TPasVariable then
-    CheckRestoredVariable(Path,TPasVariable(Orig),TPasVariable(Rest))
-  else if C=TPrimitiveExpr then
-    CheckRestoredPrimitiveExpr(Path,TPrimitiveExpr(Orig),TPrimitiveExpr(Rest))
   else
   else
     Fail(Path+': unknown class '+C.ClassName);
     Fail(Path+': unknown class '+C.ClassName);
 end;
 end;
 
 
-procedure TCustomTestPrecompile.CheckRestoredConst(const Path: string; Orig,
-  Rest: TPasConst);
+procedure TCustomTestPrecompile.CheckRestoredElementList(const Path: string;
+  Orig, Rest: TFPList);
+var
+  OrigItem, RestItem: TObject;
+  i: Integer;
+  SubPath: String;
 begin
 begin
-  AssertEquals(Path+': IsConst',Orig.IsConst,Rest.IsConst);
-  CheckRestoredVariable(Path,Orig,Rest);
+  if Orig=nil then
+    begin
+    if Rest=nil then
+      exit;
+    Fail(Path+' Orig=nil Rest='+GetObjName(Rest));
+    end
+  else if Rest=nil then
+    Fail(Path+' Orig='+GetObjName(Orig)+' Rest=nil')
+  else if Orig.ClassType<>Rest.ClassType then
+    Fail(Path+' Orig='+GetObjName(Orig)+' Rest='+GetObjName(Rest));
+  AssertEquals(Path+'.Count',Orig.Count,Rest.Count);
+  for i:=0 to Orig.Count-1 do
+    begin
+    SubPath:=Path+'['+IntToStr(i)+']';
+    OrigItem:=TObject(Orig[i]);
+    if not (OrigItem is TPasElement) then
+      Fail(SubPath+' Orig='+GetObjName(OrigItem));
+    RestItem:=TObject(Rest[i]);
+    if not (RestItem is TPasElement) then
+      Fail(SubPath+' Rest='+GetObjName(RestItem));
+    CheckRestoredElement(SubPath,TPasElement(OrigItem),TPasElement(RestItem));
+    end;
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredPasExpr(const Path: string; Orig,
+  Rest: TPasExpr);
+begin
+  if Orig.Kind<>Rest.Kind then
+    Fail(Path+'.Kind');
+  if Orig.OpCode<>Rest.OpCode then
+    Fail(Path+'.OpCode');
+  CheckRestoredElement(Path+'.Format1',Orig.format1,Rest.format1);
+  CheckRestoredElement(Path+'.Format2',Orig.format2,Rest.format2);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredUnaryExpr(const Path: string;
+  Orig, Rest: TUnaryExpr);
+begin
+  CheckRestoredElement(Path+'.Operand',Orig.Operand,Rest.Operand);
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredBinaryExpr(const Path: string;
+  Orig, Rest: TBinaryExpr);
+begin
+  CheckRestoredElement(Path+'.left',Orig.left,Rest.left);
+  CheckRestoredElement(Path+'.right',Orig.right,Rest.right);
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredPrimitiveExpr(const Path: string;
+  Orig, Rest: TPrimitiveExpr);
+begin
+  AssertEquals(Path+'.Value',Orig.Value,Rest.Value);
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredBoolConstExpr(const Path: string;
+  Orig, Rest: TBoolConstExpr);
+begin
+  AssertEquals(Path+'.Value',Orig.Value,Rest.Value);
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredParamsExpr(const Path: string;
+  Orig, Rest: TParamsExpr);
+begin
+  CheckRestoredElement(Path+'.Value',Orig.Value,Rest.Value);
+  CheckRestoredPasExprArray(Path+'.Params',Orig.Params,Rest.Params);
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredRecordValues(const Path: string;
+  Orig, Rest: TRecordValues);
+var
+  i: Integer;
+begin
+  AssertEquals(Path+'.Fields.length',length(Orig.Fields),length(Rest.Fields));
+  for i:=0 to length(Orig.Fields)-1 do
+    begin
+    AssertEquals(Path+'.Field['+IntToStr(i)+'].Name',Orig.Fields[i].Name,Rest.Fields[i].Name);
+    CheckRestoredElement(Path+'.Field['+IntToStr(i)+'].ValueExp',Orig.Fields[i].ValueExp,Rest.Fields[i].ValueExp);
+    end;
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredPasExprArray(const Path: string;
+  Orig, Rest: TPasExprArray);
+var
+  i: Integer;
+begin
+  AssertEquals(Path+'.length',length(Orig),length(Rest));
+  for i:=0 to length(Orig)-1 do
+    CheckRestoredElement(Path+'['+IntToStr(i)+']',Orig[i],Rest[i]);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredArrayValues(const Path: string;
+  Orig, Rest: TArrayValues);
+begin
+  CheckRestoredPasExprArray(Path+'.Values',Orig.Values,Rest.Values);
+  CheckRestoredPasExpr(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredResString(const Path: string;
+  Orig, Rest: TPasResString);
+begin
+  CheckRestoredElement(Path+'.Expr',Orig.Expr,Rest.Expr);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredAliasType(const Path: string;
+  Orig, Rest: TPasAliasType);
+begin
+  CheckRestoredElement(Path+'.DestType',Orig.DestType,Rest.DestType);
+  CheckRestoredElement(Path+'.Expr',Orig.Expr,Rest.Expr);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredPointerType(const Path: string;
+  Orig, Rest: TPasPointerType);
+begin
+  CheckRestoredElement(Path+'.DestType',Orig.DestType,Rest.DestType);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredSpecializedType(
+  const Path: string; Orig, Rest: TPasSpecializeType);
+begin
+  CheckRestoredElementList(Path+'.Params',Orig.Params,Rest.Params);
+  CheckRestoredElement(Path+'.DestType',Orig.DestType,Rest.DestType);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredInlineSpecializedExpr(
+  const Path: string; Orig, Rest: TInlineSpecializeExpr);
+begin
+  CheckRestoredElement(Path+'.DestType',Orig.DestType,Rest.DestType);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredRangeType(const Path: string;
+  Orig, Rest: TPasRangeType);
+begin
+  CheckRestoredElement(Path+'.RangeExpr',Orig.RangeExpr,Rest.RangeExpr);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredArrayType(const Path: string;
+  Orig, Rest: TPasArrayType);
+begin
+  CheckRestoredPasExprArray(Path+'.Ranges',Orig.Ranges,Rest.Ranges);
+  if Orig.PackMode<>Rest.PackMode then
+    Fail(Path+'.PackMode Orig='+PJUPackModeNames[Orig.PackMode]+' Rest='+PJUPackModeNames[Rest.PackMode]);
+  CheckRestoredElement(Path+'.ElType',Orig.ElType,Rest.ElType);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredFileType(const Path: string; Orig,
+  Rest: TPasFileType);
+begin
+  CheckRestoredElement(Path+'.ElType',Orig.ElType,Rest.ElType);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredEnumValue(const Path: string;
+  Orig, Rest: TPasEnumValue);
+begin
+  CheckRestoredElement(Path+'.Value',Orig.Value,Rest.Value);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredEnumType(const Path: string; Orig,
+  Rest: TPasEnumType);
+begin
+  CheckRestoredElementList(Path+'.Values',Orig.Values,Rest.Values);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredSetType(const Path: string; Orig,
+  Rest: TPasSetType);
+begin
+  CheckRestoredElement(Path+'.EnumType',Orig.EnumType,Rest.EnumType);
+  AssertEquals(Path+'.IsPacked',Orig.IsPacked,Rest.IsPacked);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredVariant(const Path: string; Orig,
+  Rest: TPasVariant);
+begin
+  CheckRestoredElementList(Path+'.Values',Orig.Values,Rest.Values);
+  CheckRestoredElement(Path+'.Members',Orig.Members,Rest.Members);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredRecordType(const Path: string;
+  Orig, Rest: TPasRecordType);
+begin
+  if Orig.PackMode<>Rest.PackMode then
+    Fail(Path+'.PackMode Orig='+PJUPackModeNames[Orig.PackMode]+' Rest='+PJUPackModeNames[Rest.PackMode]);
+  CheckRestoredElementList(Path+'.Members',Orig.Members,Rest.Members);
+  CheckRestoredElement(Path+'.VariantEl',Orig.VariantEl,Rest.VariantEl);
+  CheckRestoredElementList(Path+'.Variants',Orig.Variants,Rest.Variants);
+  CheckRestoredElementList(Path+'.GenericTemplateTypes',Orig.GenericTemplateTypes,Rest.GenericTemplateTypes);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredClassType(const Path: string;
+  Orig, Rest: TPasClassType);
+begin
+  if Orig.PackMode<>Rest.PackMode then
+    Fail(Path+'.PackMode Orig='+PJUPackModeNames[Orig.PackMode]+' Rest='+PJUPackModeNames[Rest.PackMode]);
+  if Orig.ObjKind<>Rest.ObjKind then
+    Fail(Path+'.ObjKind Orig='+PJUObjKindNames[Orig.ObjKind]+' Rest='+PJUObjKindNames[Rest.ObjKind]);
+  CheckRestoredElement(Path+'.AncestorType',Orig.AncestorType,Rest.AncestorType);
+  CheckRestoredElement(Path+'.HelperForType',Orig.HelperForType,Rest.HelperForType);
+  AssertEquals(Path+'.IsForward',Orig.IsForward,Rest.IsForward);
+  AssertEquals(Path+'.IsExternal',Orig.IsExternal,Rest.IsExternal);
+  // irrelevant: IsShortDefinition
+  CheckRestoredElement(Path+'.GUIDExpr',Orig.GUIDExpr,Rest.GUIDExpr);
+  CheckRestoredElementList(Path+'.Members',Orig.Members,Rest.Members);
+  AssertEquals(Path+'.Modifiers',Orig.Modifiers.Text,Rest.Modifiers.Text);
+  CheckRestoredElementList(Path+'.Interfaces',Orig.Interfaces,Rest.Interfaces);
+  CheckRestoredElementList(Path+'.GenericTemplateTypes',Orig.GenericTemplateTypes,Rest.GenericTemplateTypes);
+  AssertEquals(Path+'.ExternalNameSpace',Orig.ExternalNameSpace,Rest.ExternalNameSpace);
+  AssertEquals(Path+'.ExternalName',Orig.ExternalName,Rest.ExternalName);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredArgument(const Path: string; Orig,
+  Rest: TPasArgument);
+begin
+  if Orig.Access<>Rest.Access then
+    Fail(Path+'.Access Orig='+PJUArgumentAccessNames[Orig.Access]+' Rest='+PJUArgumentAccessNames[Rest.Access]);
+  CheckRestoredElement(Path+'.ArgType',Orig.ArgType,Rest.ArgType);
+  CheckRestoredElement(Path+'.ValueExpr',Orig.ValueExpr,Rest.ValueExpr);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredProcedureType(const Path: string;
+  Orig, Rest: TPasProcedureType);
+begin
+  CheckRestoredElementList(Path+'.Args',Orig.Args,Rest.Args);
+  if Orig.CallingConvention<>Rest.CallingConvention then
+    Fail(Path+'.CallingConvention Orig='+PJUCallingConventionNames[Orig.CallingConvention]+' Rest='+PJUCallingConventionNames[Rest.CallingConvention]);
+  if Orig.Modifiers<>Rest.Modifiers then
+    Fail(Path+'.Modifiers');
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredResultElement(const Path: string;
+  Orig, Rest: TPasResultElement);
+begin
+  CheckRestoredElement(Path+'.ResultType',Orig.ResultType,Rest.ResultType);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredFunctionType(const Path: string;
+  Orig, Rest: TPasFunctionType);
+begin
+  CheckRestoredElement(Path+'.ResultEl',Orig.ResultEl,Rest.ResultEl);
+  CheckRestoredProcedureType(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredStringType(const Path: string;
+  Orig, Rest: TPasStringType);
+begin
+  AssertEquals(Path+'.LengthExpr',Orig.LengthExpr,Rest.LengthExpr);
 end;
 end;
 
 
 procedure TCustomTestPrecompile.CheckRestoredVariable(const Path: string; Orig,
 procedure TCustomTestPrecompile.CheckRestoredVariable(const Path: string; Orig,
@@ -427,22 +787,62 @@ begin
   CheckRestoredElement(Path+'.Expr',Orig.Expr,Rest.Expr);
   CheckRestoredElement(Path+'.Expr',Orig.Expr,Rest.Expr);
 end;
 end;
 
 
-procedure TCustomTestPrecompile.CheckRestoredPrimitiveExpr(const Path: string;
-  Orig, Rest: TPrimitiveExpr);
+procedure TCustomTestPrecompile.CheckRestoredExportSymbol(const Path: string;
+  Orig, Rest: TPasExportSymbol);
 begin
 begin
-  AssertEquals(Path+'.Value',Orig.Value,Rest.Value);
-  CheckRestoredExpr(Path,Orig,Rest);
+  CheckRestoredElement(Path+'.ExportName',Orig.ExportName,Rest.ExportName);
+  CheckRestoredElement(Path+'.ExportIndex',Orig.ExportIndex,Rest.ExportIndex);
 end;
 end;
 
 
-procedure TCustomTestPrecompile.CheckRestoredExpr(const Path: string; Orig,
-  Rest: TPasExpr);
+procedure TCustomTestPrecompile.CheckRestoredConst(const Path: string; Orig,
+  Rest: TPasConst);
 begin
 begin
-  if Orig.Kind<>Rest.Kind then
-    Fail(Path+'.Kind');
-  if Orig.OpCode<>Rest.OpCode then
-    Fail(Path+'.OpCode');
-  CheckRestoredElement(Path+'.Format1',Orig.format1,Rest.format1);
-  CheckRestoredElement(Path+'.Format2',Orig.format2,Rest.format2);
+  AssertEquals(Path+': IsConst',Orig.IsConst,Rest.IsConst);
+  CheckRestoredVariable(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredProperty(const Path: string; Orig,
+  Rest: TPasProperty);
+begin
+  CheckRestoredElement(Path+'.IndexExpr',Orig.IndexExpr,Rest.IndexExpr);
+  CheckRestoredElement(Path+'.ReadAccessor',Orig.ReadAccessor,Rest.ReadAccessor);
+  CheckRestoredElement(Path+'.WriteAccessor',Orig.WriteAccessor,Rest.WriteAccessor);
+  CheckRestoredElement(Path+'.ImplementsFunc',Orig.ImplementsFunc,Rest.ImplementsFunc);
+  CheckRestoredElement(Path+'.DispIDExpr',Orig.DispIDExpr,Rest.DispIDExpr);
+  CheckRestoredElement(Path+'.StoredAccessor',Orig.StoredAccessor,Rest.StoredAccessor);
+  CheckRestoredElement(Path+'.DefaultExpr',Orig.DefaultExpr,Rest.DefaultExpr);
+  CheckRestoredElementList(Path+'.Args',Orig.Args,Rest.Args);
+  // not needed: ReadAccessorName, WriteAccessorName, ImplementsName, StoredAccessorName
+  AssertEquals(Path+'.DispIDReadOnly',Orig.DispIDReadOnly,Rest.DispIDReadOnly);
+  AssertEquals(Path+'.IsDefault',Orig.IsDefault,Rest.IsDefault);
+  AssertEquals(Path+'.IsNodefault',Orig.IsNodefault,Rest.IsNodefault);
+  CheckRestoredVariable(Path,Orig,Rest);
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredProcedure(const Path: string;
+  Orig, Rest: TPasProcedure);
+begin
+  CheckRestoredElement(Path+'.ProcType',Orig.ProcType,Rest.ProcType);
+  CheckRestoredElement(Path+'.PublicName',Orig.PublicName,Rest.PublicName);
+  CheckRestoredElement(Path+'.LibrarySymbolName',Orig.LibrarySymbolName,Rest.LibrarySymbolName);
+  CheckRestoredElement(Path+'.LibraryExpr',Orig.LibraryExpr,Rest.LibraryExpr);
+  CheckRestoredElement(Path+'.DispIDExpr',Orig.DispIDExpr,Rest.DispIDExpr);
+  AssertEquals(Path+'.AliasName',Orig.AliasName,Rest.AliasName);
+  if Orig.Modifiers<>Rest.Modifiers then
+    Fail(Path+'.Modifiers');
+  AssertEquals(Path+'.MessageName',Orig.MessageName,Rest.MessageName);
+  if Orig.MessageType<>Rest.MessageType then
+    Fail(Path+'.MessageType Orig='+PJUProcedureMessageTypeNames[Orig.MessageType]+' Rest='+PJUProcedureMessageTypeNames[Rest.MessageType]);
+  // ToDo: Body
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredOperator(const Path: string; Orig,
+  Rest: TPasOperator);
+begin
+  if Orig.OperatorType<>Rest.OperatorType then
+    Fail(Path+'.OperatorType Orig='+PJUOperatorTypeNames[Orig.OperatorType]+' Rest='+PJUOperatorTypeNames[Rest.OperatorType]);
+  AssertEquals(Path+'.TokenBased',Orig.TokenBased,Rest.TokenBased);
+  CheckRestoredProcedure(Path,Orig,Rest);
 end;
 end;
 
 
 procedure TCustomTestPrecompile.CheckRestoredReference(const Path: string;
 procedure TCustomTestPrecompile.CheckRestoredReference(const Path: string;