ORun.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:30k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  Oberon virtual machine unit
  3.  (C) 2004-2007 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
  4.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  5.  The unit contains VM class
  6. *)
  7. {$DEFINE DEBUG}
  8. unit ORun;
  9. interface
  10. uses
  11.   SysUtils,
  12. {$IFDEF DEBUG} Dialogs, Classes, {$ENDIF}
  13.   OTypes, OScan, OBasics;
  14. {$IFDEF DEBUG} var Debug: string; DItems: TStringList; {$ENDIF}
  15. type
  16.   TBinModuleSign = array[0..3] of Char;
  17.   TStackItem = Integer;
  18.   TOberonVM = class
  19.     Data: TRTData;
  20.     TotalStack, StackCapacity, StackCapacityStep, StackBase: Integer;
  21.     Stack: array of TStackItem;                                  // Stack
  22. //    Comp: TCompiler;
  23. // Implementation specific
  24.     MaxSet: Integer;
  25.     El2Set: array of Longword;                                   // For set optimisation
  26.     constructor Create;
  27.     destructor Destroy; override;
  28. {$IFDEF DEBUG}
  29.     function ItemToStr(Index: Integer): string;   // Converts PIN item to string in debug purposes
  30.     function GetVar(const Location, Offset, Index: Integer): Integer;
  31. {$ENDIF}
  32.     function Save(const Stream: TDStream): Integer;
  33.     function Load(const Stream: TDStream): Integer;
  34.     function SetExtVarAddr(const VarIndex: Integer; const Addr: Pointer): Boolean;
  35.     procedure Run;
  36.     function Compute: TStackItem;
  37.   private
  38.     procedure ExpandStack(const Amount: Integer);
  39.     procedure Push(Item: TStackItem);
  40.     procedure PushS(Item: Single);
  41.     function Pop: TStackItem;
  42.     function PopS: Single;
  43.     procedure RunTimeError(ErrorNumber: Integer);
  44.     function AddII(Value1, Value2: Integer): Integer;
  45.     function AddRR(Value1, Value2: Single): Single;
  46.     function AddIR(Value1: Integer; Value2: Single): Single;
  47.     function AddRI(Value1: Single; Value2: Integer): Single;
  48.     function AddSS(Value1, Value2: Integer): Integer;
  49.     function AddStrStr(Value1, Value2: Integer): Integer;
  50.     function SubII(Value1, Value2: Integer): Integer;
  51.     function SubRR(Value1, Value2: Single): Single;
  52.     function SubIR(Value1: Integer; Value2: Single): Single;
  53.     function SubRI(Value1: Single; Value2: Integer): Single;
  54.     function SubSS(Value1, Value2: Integer): Integer;
  55.     function MulII(Value1, Value2: Integer): Integer;
  56.     function MulRR(Value1, Value2: Single): Single;
  57.     function MulIR(Value1: Integer; Value2: Single): Single;
  58.     function MulRI(Value1: Single; Value2: Integer): Single;
  59.     function MulSS(Value1, Value2: Integer): Integer;
  60.     function DivII(Value1, Value2: Integer): Single;
  61.     function DivRR(Value1, Value2: Single): Single;
  62.     function DivIR(Value1: Integer; Value2: Single): Single;
  63.     function DivRI(Value1: Single; Value2: Integer): Single;
  64.     function DivSS(Value1, Value2: Integer): Integer;
  65.     function OrII(Value1, Value2: Integer): Integer;
  66.     function AndII(Value1, Value2: Integer): Integer;
  67.     function IDivII(Value1, Value2: Integer): Integer;
  68.     function ModII(Value1, Value2: Integer): Integer;
  69.     function NegI(Value1: Integer): Integer;
  70.     function NegR(Value1: Single): Single;
  71.     function NegS(Value1: Integer): Integer;
  72.     function InvI(Value1: Integer): Integer;
  73.     function InvB(Value1: Integer): Integer;
  74.     function Equal(Value1, Value2: Integer): Integer;
  75.     function EqualRI(Value1: Single; Value2: Integer): Integer;
  76.     function GreaterII(Value1, Value2: Integer): Integer;
  77.     function GreaterIR(Value1: Integer; Value2: Single): Integer;
  78.     function GreaterRI(Value1: Single; Value2: Integer): Integer;
  79.     function GreaterRR(Value1, Value2: Single): Integer;
  80.     function LessII(Value1, Value2: Integer): Integer;
  81.     function LessIR(Value1: Integer; Value2: Single): Integer;
  82.     function LessRI(Value1: Single; Value2: Integer): Integer;
  83.     function LessRR(Value1, Value2: Single): Integer;
  84.     function GreaterEqualII(Value1, Value2: Integer): Integer;
  85.     function GreaterEqualIR(Value1: Integer; Value2: Single): Integer;
  86.     function GreaterEqualRI(Value1: Single; Value2: Integer): Integer;
  87.     function GreaterEqualRR(Value1, Value2: Single): Integer;
  88.     function LessEqualII(Value1, Value2: Integer): Integer;
  89.     function LessEqualIR(Value1: Integer; Value2: Single): Integer;
  90.     function LessEqualRI(Value1: Single; Value2: Integer): Integer;
  91.     function LessEqualRR(Value1, Value2: Single): Integer;
  92.     function NotEqual(Value1, Value2: Integer): Integer;
  93.     function NotEqualRI(Value1: Single; Value2: Integer): Integer;
  94.     function GreaterEqual(Value1, Value2: Integer): Integer;
  95.     function LessEqual(Value1, Value2: Integer): Integer;
  96.     function TestIn(Value1, Value2: Integer): Integer;
  97.     procedure DoAssign4(Value1, Value2: Integer);
  98.     procedure DoStackAssign4(Value1, Value2: Integer);
  99.     procedure DoGoto(var IP: Integer);
  100.     procedure DoZeroJump(Value1: Integer; var IP: Integer);
  101.     procedure DoCall(const Dest: Integer; var IP: Integer);
  102.     procedure DoReturn(var IP: Integer);
  103.     procedure DoExit(const Dest: Integer; var IP: Integer);
  104.     function ConstructSet(const TotalElements: Integer): Integer;
  105. // For scripting support
  106.     procedure DoExtAssign4(Value1, Value2: Integer);
  107.   end;
  108. const
  109.  BinModuleSign: TBinModuleSign = ('O', '2', 'B', 'M');
  110. implementation
  111. {$IFDEF DEBUG}
  112. function TOberonVM.ItemToStr(Index: Integer): string;
  113. var j: Integer; Len: Nat16; First: Boolean;
  114.   function GetVarName(NS: PNamespace; Ofs: Integer): string;
  115.   var i, ind, Bound: Integer;
  116.   begin
  117.     Result := 'Unknown';
  118.     for i := 0 to NS.TotalVariables-1 do begin
  119.       Bound := Data.Variables[NS.Variables[i]].Index + Data.Types[Data.Variables[NS.Variables[i]].TypeID].Size;
  120.       if Bound > Ofs then begin
  121.         ind := i;
  122.   {    if Data.Variables[NS.Variables[i]].Index >= Ofs then begin
  123.         if (Data.Variables[NS.Variables[i]].Index > Ofs) then begin
  124.           ind := i-1;
  125.           if ind < 0 then Exit;
  126.         end else ind := i;}
  127.         if Data.Types[Data.Variables[NS.Variables[ind]].TypeID].Kind = tkRecord then
  128.          Result := Data.Variables[NS.Variables[ind]].Name+'.'+GetVarName(Data.Types[Data.Variables[NS.Variables[ind]].TypeID].Namespace,
  129.                               Ofs-Data.Variables[NS.Variables[ind]].Index) else
  130.           Result := Data.Variables[NS.Variables[ind]].Name;
  131.         Exit;
  132.       end;
  133.     end;
  134.   {  ind := NS.TotalVariables-1;
  135.     Result := Data.Variables[NS.Variables[ind]].Name+'.'+GetVarName(Data.Types[Data.Variables[NS.Variables[ind]].TypeID].Namespace,
  136.                               Ofs-Data.Variables[NS.Variables[ind]].Index);}
  137.   end;
  138.   function GetGlobalVarName(Ofs: Integer): string;
  139.   begin
  140.     Result := GetVarName(Data.Namespace, Ofs);
  141.   end;
  142. begin
  143. //  Result := '';
  144.   case Data.PIN[Index] and $FFFF of
  145.     dtBoolean: if Boolean((@Data.PIN[Index+1])^) then Result := 'True' else Result := 'False';
  146.     dtChar: Result := Char((@Data.PIN[Index+1])^);
  147.     dtInt8, dtInt16, dtInt32, dtInt, dtNat8, dtNat16, dtNat32, dtNat: Result := IntToStr(Data.PIN[Index+1])+',';
  148.     dtSingle, dtDouble, dtReal: Result := FloatToStr(Single((@Data.PIN[Index+1])^));
  149.     dtString: begin
  150.       Move(Pointer(Int32(Data.Data)+Data.PIN[Index+1])^, Len, 2);
  151.       SetLength(Result, Len);
  152.       if Len > 0 then Move(Pointer(Int32(Data.Data)+Data.PIN[Index+1]+2)^, Result[1], Len);
  153.     end;
  154.     dtSet: Result := 'SET of ' + IntToStr(Longword(Data.PIN[Index] shr 16)) + ' elements';
  155.     aoNull: Result := ' Null ';
  156.     aoAddII: Result := ' +(ii) ';
  157.     aoAddIR: Result := ' +(ir) ';
  158.     aoAddRI: Result := ' +(ri) ';
  159.     aoAddRR: Result := ' +(rr) ';
  160.     aoAddSS: Result := ' +(ss) ';
  161.     aoSubII: Result := ' -(ii) ';
  162.     aoSubIR: Result := ' -(ir) ';
  163.     aoSubRI: Result := ' -(ri) ';
  164.     aoSubRR: Result := ' -(rr) ';
  165.     aoSubSS: Result := ' -(ss) ';
  166.     aoMulII: Result := ' *(ii) ';
  167.     aoMulIR: Result := ' *(ir) ';
  168.     aoMulRI: Result := ' *(ri) ';
  169.     aoMulRR: Result := ' *(rr) ';
  170.     aoMulSS: Result := ' *(ss) ';
  171.     aoDivII: Result := ' /(ii) ';
  172.     aoDivIR: Result := ' /(ir) ';
  173.     aoDivRI: Result := ' /(ri) ';
  174.     aoDivRR: Result := ' /(rr) ';
  175.     aoDivSS: Result := ' /(ss) ';
  176.     aoOrII: Result := ' OR(ii) ';
  177.     aoOrBB: Result := ' OR(bb) ';
  178.     aoAndII: Result := ' &(ii) ';
  179.     aoAndBB: Result := ' &(bb) ';
  180.     aoIDivII: Result := ' DIV(ii) ';
  181.     aoModII: Result := ' MOD(ii) ';
  182.     aoNegI: Result := ' Neg(i) ';
  183.     aoNegR: Result := ' Neg(r) ';
  184.     aoNegS: Result := ' Neg(s) ';
  185.     aoInvI: Result := ' ~(i) ';
  186.     aoInvB: Result := ' ~(b) ';
  187.     arEqualII: Result := ' =(ii) ';
  188.     arEqualIR: Result := ' =(ir) ';
  189.     arEqualRI: Result := ' =(ri) ';
  190.     arEqualRR: Result := ' =(rr) ';
  191.     arGreaterII: Result := ' >(ii) ';
  192.     arGreaterIR: Result := ' >(ir) ';
  193.     arGreaterRI: Result := ' >(ri) ';
  194.     arGreaterRR: Result := ' >(rr) ';
  195.     arLessII: Result := ' <(ii) ';
  196.     arLessIR: Result := ' <(ir) ';
  197.     arLessRI: Result := ' <(ri) ';
  198.     arLessRR: Result := ' <(rr) ';
  199.     arGreaterEqualII: Result := ' >=(ii) ';
  200.     arGreaterEqualIR: Result := ' >=(ir) ';
  201.     arGreaterEqualRI: Result := ' >=(ri) ';
  202.     arGreaterEqualRR: Result := ' >=(rr) ';
  203.     arLessEqualII: Result := ' <=(ii) ';
  204.     arLessEqualIR: Result := ' <=(ir) ';
  205.     arLessEqualRI: Result := ' <=(ri) ';
  206.     arLessEqualRR: Result := ' <=(rr) ';
  207.     arNotEqualII: Result := ' #(ii) ';
  208.     arNotEqualIR: Result := ' #(ir) ';
  209.     arNotEqualRI: Result := ' #(ri) ';
  210.     arNotEqualRR: Result := ' #(rr) ';
  211.     aoAssign1: Result := ' :=[1b] ';
  212.     aoAssign2: Result := ' :=[2b] ';
  213.     aoAssign4: Result := ' :=[4b] ';
  214.     aoAssign4RI: Result := ' :=[r4b] ';
  215.     aoAssignSize: Result := ' :=[?b] ';
  216.     aoStackAssign4: Result := ' [s]:= ';
  217.     aoStackAssign4RI: Result := ' [s]:=[r] ';
  218.     aoStackAssignSize: Result := ' [s]:=[?b] ';
  219.     aoGoto: Result := ' Goto ';
  220.     aoJumpIfZero: Result := ' JumpIfZero ';
  221.     aoCall: Result := ' Call ';
  222.     aoReturnF: Result := ' Function return ';
  223.     aoReturnP: Result := ' Procedure return ';
  224.     dtVariable, dtVariableRef: Result := GetGlobalVarName(Data.PIN[Index+1]) + ' [' + IntToStr(Data.PIN[Index+1]) + ']';
  225.     dtVariableByOfs: Result := 'ARR: '+GetGlobalVarName(Data.PIN[Index+1]) + ' [' + IntToStr(Data.PIN[Index+1]) + ']';
  226.     dtStackVariable: Result := 'Local variable';//Data.Variables[Data.PIN[Index+1]].Name+'[s],';
  227.     dtStackVariableByOfs: Result := 'Local array';//Data.Variables[Data.PIN[Index+1]].Name+'[s],';
  228.     aoSetStackBase: Result := 'Set stack base (- ' + IntToStr(Data.PIN[Index+1])+' parameters)';
  229.     aoExpandStack: Result := 'Expand stack by ' + IntToStr(Data.PIN[Index+1]);
  230.   end;
  231. end;
  232. function TOberonVM.GetVar(const Location, Offset, Index: Integer): Integer;
  233. begin
  234.   case Data.Types[Data.Variables[Index].TypeID].Size of
  235.     1: Result := Data.BaseData[Data.Variables[Index].Index+Offset + Integer(Data.Data)];
  236.     2: Result := Word((@Data.BaseData[Data.Variables[Index].Index+Offset + Integer(Data.Data)])^);
  237.     4: case Location of
  238.       ilGlobal: Result := Int32((@Data.BaseData[Data.Variables[Index].Index+Offset + Integer(Data.Data)])^);
  239.       ilExternal: Result := Int32((@Data.BaseData[Data.Variables[Index].Index+Offset])^);
  240.     end;
  241.   end;
  242. end;
  243. {$ENDIF}
  244. procedure TOberonVM.ExpandStack(const Amount: Integer);
  245. begin
  246.   Inc(TotalStack, Amount);
  247.   if TotalStack > StackCapacity then begin
  248.     Inc(StackCapacity, StackCapacityStep); SetLength(Stack, StackCapacity);
  249.   end;
  250. end;
  251. procedure TOberonVM.Push(Item: TStackItem);
  252. begin
  253.   ExpandStack(1);
  254.   Stack[TotalStack-1] := Item;
  255. end;
  256. procedure TOberonVM.PushS(Item: Single);
  257. begin
  258.   ExpandStack(1);
  259.   Stack[TotalStack-1] := TStackItem((@Item)^);
  260. end;
  261. function TOberonVM.Pop: TStackItem;
  262. begin
  263.   if TotalStack = 0 then begin
  264.     RunTimeError(rteStackEmpty); Exit; 
  265.   end;
  266.   Result := Stack[TotalStack-1];
  267.   Dec(TotalStack);
  268. end;
  269. function TOberonVM.PopS: Single;
  270. begin
  271.   if TotalStack = 0 then Exit;
  272.   Result := Single((@Stack[TotalStack-1])^);
  273.   Dec(TotalStack);
  274. end;
  275. function TOberonVM.Save(const Stream: TDStream): Integer;
  276. const InvalidUID: Integer = -1;
  277.   function SaveNamespace(NS: PNamespace): Integer;
  278.   var i: Integer;
  279.   begin
  280.     Result :=  feCannotWrite;
  281.     if Stream.Write(NS.Name, SizeOf(NS.Name)) <> feOK then Exit;
  282.     if Stream.Write(NS.UID, SizeOf(NS.UID)) <> feOK then Exit;
  283.     if Stream.Write(NS.Kind, SizeOf(NS.Kind)) <> feOK then Exit;
  284.     if Stream.Write(NS.ParamCount, SizeOf(NS.ParamCount)) <> feOK then Exit;
  285.     if Stream.Write(NS.ID, SizeOf(NS.ID)) <> feOK then Exit;
  286.     if Stream.Write(NS.StackLength, SizeOf(NS.StackLength)) <> feOK then Exit;
  287.     if Stream.Write(NS.TotalConstants, SizeOf(NS.TotalConstants)) <> feOK then Exit;
  288.     if NS.TotalConstants > 0 then if Stream.Write(NS.Constants[0], SizeOf(Longword)*NS.TotalConstants) <> feOK then Exit;
  289.     if Stream.Write(NS.TotalVariables, SizeOf(NS.TotalVariables)) <> feOK then Exit;
  290.     if NS.TotalVariables > 0 then if Stream.Write(NS.Variables[0], SizeOf(Longword)*NS.TotalVariables) <> feOK then Exit;
  291.     if Stream.Write(NS.TotalTypes, SizeOf(NS.TotalTypes)) <> feOK then Exit;
  292.     if NS.TotalTypes > 0 then if Stream.Write(NS.Types[0], SizeOf(Longword)*NS.TotalTypes) <> feOK then Exit;
  293.     if Stream.Write(NS.TotalProcedures, SizeOf(NS.TotalProcedures)) <> feOK then Exit;
  294.     for i := 0 to NS.TotalProcedures-1 do if SaveNamespace(NS.Procedures[i]) <> feOK then Exit;
  295.     if NS.Parent <> nil then begin
  296.       if Stream.Write(NS.Parent.ID, SizeOf(NS.Parent.ID)) <> feOK then Exit;
  297.     end else begin
  298.       if Stream.Write(InvalidUID, SizeOf(InvalidUID)) <> feOK then Exit;
  299.     end;
  300.     Result := feOK;
  301.   end;
  302. var i, Ind: Integer;
  303. begin
  304.   Result := feCannotWrite;
  305.   if Stream.Write(BinModuleSign, SizeOf(TBinModuleSign)) <> feOK then Exit;
  306.   if Stream.Write(Data.EntryPIN, SizeOf(Data.EntryPIN)) <> feOK then Exit;
  307.   if Stream.Write(Data.PINItems, SizeOf(Data.PINItems)) <> feOK then Exit;
  308.   if Stream.Write(Data.PIN[0], SizeOf(TPINItem)*Data.PINItems) <> feOK then Exit;
  309.   if Stream.Write(Data.TotalExternalVariables, SizeOf(Data.TotalExternalVariables)) <> feOK then Exit;
  310.   if Stream.Write(Data.ExternalVarsOfs, SizeOf(Data.ExternalVarsOfs)) <> feOK then Exit;
  311.   if SaveNamespace(Data.Namespace) <> feOK then Exit;
  312.   if Stream.Write(Data.BaseData, SizeOf(Data.BaseData)) <> feOK then Exit;
  313.   if Stream.Write(Data.DataLength, SizeOf(Data.DataLength)) <> feOK then Exit;
  314.   if Data.DataLength > 0 then
  315.    if Stream.Write(Data.Data[0], Data.DataLength * SizeOf(Data.Data[0])) <> feOK then Exit;
  316.   if Stream.Write(Data.TotalTypes, SizeOf(Data.TotalTypes)) <> feOK then Exit;
  317.   for i := 0 to Data.TotalTypes-1 do begin
  318.     if Stream.Write(Data.Types[i]^, SizeOf(Data.Types[i]^)-SizeOf(Data.Types[i].Namespace)) <> feOK then Exit;
  319.     if Data.Types[i].Namespace <> nil then begin
  320.       if Stream.Write(Data.Types[i].Namespace.UID, SizeOf(Data.Types[i].Namespace.UID)) <> feOK then Exit;
  321.       if SaveNamespace(Data.Types[i].Namespace) <> feOK then Exit;
  322.     end else begin
  323.       if Stream.Write(InvalidUID, SizeOf(InvalidUID)) <> feOK then Exit;
  324.     end;
  325.   end;
  326.   if Stream.Write(Data.TotalProcedures, SizeOf(Data.TotalProcedures)) <> feOK then Exit;
  327.   for i := 0 to Data.TotalProcedures-1 do begin
  328.     if Stream.Write(Data.Procedures[i], SizeOf(Data.Procedures[i])-SizeOf(Data.Procedures[i].Namespace)) <> feOK then Exit;
  329.     if Stream.Write(Data.Procedures[i].Namespace.UID, SizeOf(Data.Procedures[i].Namespace.UID)) <> feOK then Exit;
  330.   end;
  331.   if Stream.Write(Data.TotalVariables, SizeOf(Data.TotalVariables)) <> feOK then Exit;
  332.   for i := 0 to Data.TotalVariables-1 do begin
  333.     if Stream.Write(Data.Variables[i], SizeOf(Data.Variables[i])-SizeOf(Data.Variables[i].Namespace){-SizeOf(Data.Variables[i].Index)}) <> feOK then Exit;
  334. {    if (Data.Variables[i].Location = ilGlobal) and (Data.Variables[i].Namespace.Parent = nil) then
  335.      Ind := Data.Variables[i].Index - Integer(Data.Data) else
  336.       Ind := Data.Variables[i].Index;
  337.     if Stream.Write(Ind, SizeOf(Ind)) <> feOK then Exit;}
  338.     if Stream.Write(Data.Variables[i].Namespace.UID, SizeOf(Data.Variables[i].Namespace.UID)) <> feOK then Exit;
  339.   end;
  340.   if Stream.Write(Data.TotalConstants, SizeOf(Data.TotalConstants)) <> feOK then Exit;
  341.   for i := 0 to Data.TotalConstants-1 do begin
  342.     if Stream.Write(Data.Constants[i], SizeOf(Data.Constants[i])-SizeOf(Data.Constants[i].Namespace){-SizeOf(Data.Constants[i].Index)}) <> feOK then Exit;
  343. //    Ind := Data.Constants[i].Index - Integer(Data.Data);
  344. //    if Stream.Write(Ind, SizeOf(Ind)) <> feOK then Exit;
  345.     if Stream.Write(Data.Constants[i].Namespace.UID, SizeOf(Data.Constants[i].Namespace.UID)) <> feOK then Exit;
  346.   end;
  347.   Result := feOK;
  348. end;
  349. function TOberonVM.Load(const Stream: TDStream): Integer;
  350. function GetNamespace(ID: Integer): PNamespace;
  351. function SearchID(FirstNS: PNamespace; ID: Integer): PNamespace;
  352. var i: Integer;
  353. begin
  354.   Result := nil;
  355.   if (ID < 0) or (FirstNS = nil) then Exit;
  356.   if FirstNS.UID = ID then begin
  357.     Result := FirstNS; Exit;
  358.   end;
  359.   for i := 0 to FirstNS.TotalProcedures-1 do begin
  360.     Result := SearchID(FirstNS.Procedures[i], ID);
  361.     if Result <> nil then Exit;
  362.   end;
  363. end;
  364. var i: Integer;
  365. begin
  366.   for i := 0 to Data.TotalTypes-1 do begin
  367.     Result := SearchID(Data.Types[i].Namespace, ID);
  368.     if Result <> nil then Exit;
  369.   end;
  370.   Result := SearchID(Data.Namespace, ID);
  371. end;
  372. function LoadNamespace(var NS: PNamespace): Integer;
  373. var i, ID: Integer;
  374. begin
  375.   Result :=  feCannotRead;
  376. {  UID: Integer;
  377.   Name: TName;
  378.   Kind: Int32;                     // Procedure or record
  379.   ParamCount: Int32;
  380.   ID: Int32;                       // Index in Data.Procedures
  381.   StackLength: Int32;              // Length of variables declared local and in child namespaces
  382.   TotalConstants, TotalVariables, TotalProcedures, TotalTypes: Int32;
  383.   Constants, Variables, Types: array of Longword;
  384.   Procedures: array of PNameSpace;
  385.   Parent: PNamespace;}
  386.   New(NS);
  387.   if Stream.Read(NS.Name, SizeOf(NS.Name)) <> feOK then Exit;
  388.   if Stream.Read(NS.UID, SizeOf(NS.UID)) <> feOK then Exit;
  389.   if Stream.Read(NS.Kind, SizeOf(NS.Kind)) <> feOK then Exit;
  390.   if Stream.Read(NS.ParamCount, SizeOf(NS.ParamCount)) <> feOK then Exit;
  391.   if Stream.Read(NS.ID, SizeOf(NS.ID)) <> feOK then Exit;
  392.   if Stream.Read(NS.StackLength, SizeOf(NS.StackLength)) <> feOK then Exit;
  393.   if Stream.Read(NS.TotalConstants, SizeOf(NS.TotalConstants)) <> feOK then Exit;
  394.   SetLength(NS.Constants, NS.TotalConstants);
  395.   if NS.TotalConstants > 0 then
  396.    if Stream.Read(NS.Constants[0], SizeOf(Longword)*NS.TotalConstants) <> feOK then Exit;
  397.   if Stream.Read(NS.TotalVariables, SizeOf(NS.TotalVariables)) <> feOK then Exit;
  398.   SetLength(NS.Variables, NS.TotalVariables);
  399.   if NS.TotalVariables > 0 then
  400.    if Stream.Read(NS.Variables[0], SizeOf(Longword)*NS.TotalVariables) <> feOK then Exit;
  401.   if Stream.Read(NS.TotalTypes, SizeOf(NS.TotalTypes)) <> feOK then Exit;
  402.   SetLength(NS.Types, NS.TotalTypes);
  403.   if NS.TotalTypes > 0 then
  404.    if Stream.Read(NS.Types[0], SizeOf(Longword)*NS.TotalTypes) <> feOK then Exit;
  405.   if Stream.Read(NS.TotalProcedures, SizeOf(NS.TotalProcedures)) <> feOK then Exit;
  406.   SetLength(NS.Procedures, NS.TotalProcedures);
  407.   for i := 0 to NS.TotalProcedures-1 do NS.Procedures[i] := nil;
  408.   for i := 0 to NS.TotalProcedures-1 do if LoadNamespace(NS.Procedures[i]) <> feOK then Exit;
  409.   if Stream.Read(ID, SizeOf(ID)) <> feOK then Exit;
  410.   NS.Parent := GetNamespace(ID);
  411.   Result := feOK;
  412. end;
  413. var i, ID, Ind: Integer; Sign: TBinModuleSign;
  414. begin
  415.   Result := feCannotRead;
  416. {$IFDEF DEBUG}
  417.   DItems.Clear;
  418. {$ENDIF}
  419.   StackCapacity := 256; SetLength(Stack, StackCapacity);
  420.   if Stream.Read(Sign, SizeOf(TBinModuleSign)) <> feOK then Exit;
  421.   if Sign <> BinModuleSign then begin
  422.     Result := feInvalidFileFormat; Exit;
  423.   end;
  424.   if Stream.Read(Data.EntryPIN, SizeOf(Data.EntryPIN)) <> feOK then Exit;
  425.   if Stream.Read(Data.PINItems, SizeOf(Data.PINItems)) <> feOK then Exit;
  426.   SetLength(Data.PIN, Data.PINItems);
  427.   if Data.PINItems > 0 then
  428.    if Stream.Read(Data.PIN[0], SizeOf(TPINItem)*Data.PINItems) <> feOK then Exit;
  429.   if Stream.Read(Data.TotalExternalVariables, SizeOf(Data.TotalExternalVariables)) <> feOK then Exit;
  430.   if Stream.Read(Data.ExternalVarsOfs, SizeOf(Data.ExternalVarsOfs)) <> feOK then Exit;
  431.   if LoadNamespace(Data.Namespace) <> feOK then Exit;
  432.   if Stream.Read(Data.BaseData, SizeOf(Data.BaseData)) <> feOK then Exit;
  433.   if Stream.Read(Data.DataLength, SizeOf(Data.DataLength)) <> feOK then Exit;
  434.   SetLength(Data.Data, Data.DataLength);
  435.   if Data.DataLength > 0 then
  436.    if Stream.Read(Data.Data[0], Data.DataLength * SizeOf(Data.Data[0])) <> feOK then Exit;
  437.   if Stream.Read(Data.TotalTypes, SizeOf(Data.TotalTypes)) <> feOK then Exit;
  438.   SetLength(Data.Types, Data.TotalTypes);
  439.   for i := 0 to Data.TotalTypes-1 do begin
  440.     New(Data.Types[i]);
  441.     Data.Types[i].Namespace := nil;
  442.   end;
  443.   for i := 0 to Data.TotalTypes-1 do begin
  444.     if Stream.Read(Data.Types[i]^, SizeOf(Data.Types[i]^)-SizeOf(Data.Types[i].Namespace)) <> feOK then Exit;
  445.     if Stream.Read(ID, SizeOf(ID)) <> feOK then Exit;
  446.     if ID <> -1 then LoadNamespace(Data.Types[i].Namespace);
  447.   end;
  448.   if Stream.Read(Data.TotalProcedures, SizeOf(Data.TotalProcedures)) <> feOK then Exit;
  449.   SetLength(Data.Procedures, Data.TotalProcedures);
  450.   for i := 0 to Data.TotalProcedures-1 do begin
  451.     if Stream.Read(Data.Procedures[i], SizeOf(Data.Procedures[i])-SizeOf(Data.Procedures[i].Namespace)) <> feOK then Exit;
  452.     if Stream.Read(ID, SizeOf(ID)) <> feOK then Exit;
  453.     Data.Procedures[i].Namespace := GetNamespace(ID);
  454.   end;
  455.   if Stream.Read(Data.TotalVariables, SizeOf(Data.TotalVariables)) <> feOK then Exit;
  456.   SetLength(Data.Variables, Data.TotalVariables);
  457.   for i := 0 to Data.TotalVariables-1 do begin
  458.     if Stream.Read(Data.Variables[i], SizeOf(Data.Variables[i])-SizeOf(Data.Variables[i].Namespace){-SizeOf(Data.Variables[i].Index)}) <> feOK then Exit;
  459. //    if Stream.Read(Ind, SizeOf(Ind)) <> feOK then Exit;
  460. //    Data.Variables[i].Index := Ind;
  461.     if Stream.Read(ID, SizeOf(ID)) <> feOK then Exit;
  462.     Data.Variables[i].Namespace := GetNamespace(ID);
  463.   end;
  464.   if Stream.Read(Data.TotalConstants, SizeOf(Data.TotalConstants)) <> feOK then Exit;
  465.   SetLength(Data.Constants, Data.TotalConstants);
  466.   for i := 0 to Data.TotalConstants-1 do begin
  467.     if Stream.Read(Data.Constants[i], SizeOf(Data.Constants[i])-SizeOf(Data.Constants[i].Namespace)) <> feOK then Exit;
  468. //    if Stream.Read(Ind, SizeOf(Ind)) <> feOK then Exit;
  469. //    Data.Constants[i].Index := Ind + Integer(Data.Data);
  470.     if Stream.Read(ID, SizeOf(ID)) <> feOK then Exit;
  471.     Data.Constants[i].Namespace := GetNamespace(ID);
  472.   end;
  473.   Result := feOK;
  474. end;
  475. function TOberonVM.SetExtVarAddr(const VarIndex: Integer; const Addr: Pointer): Boolean;
  476. begin
  477.   Result := False;
  478.   if (VarIndex < 0) or (VarIndex >= Data.TotalExternalVariables) then Exit;
  479.   Data.Variables[Data.ExternalVarsOfs + VarIndex].Index := Integer(Addr);
  480.   Result := True;
  481. end;
  482. {$I ExpComb.inc}
  483. procedure TOberonVM.Run;
  484. var IP, i1, i2: Integer; r1, r2: Single;
  485. begin
  486.   StackBase := 0; TotalStack := 0;
  487.   IP := Data.EntryPIN;
  488.   while IP < Data.PINItems do begin
  489.     case Data.PIN[IP] and $FF of
  490.       dtBoolean..dtString, dtVariableRef: begin Inc(IP); Push(Data.PIN[IP]); end;
  491.       dtSet: Push(ConstructSet(Data.PIN[IP] shr 16));
  492.       dtVariable: begin
  493.         Inc(IP); Push(TStackItem((@Data.BaseData[Integer(Data.Data) + Data.PIN[IP]])^));
  494.       end;
  495.       dtVariableByOfs: begin
  496.         Push(TStackItem((@Data.BaseData[Integer(Data.Data) + Pop])^));
  497.       end;
  498.       dtStackVariable: begin
  499.         Inc(IP); Push(TStackItem((@Stack[StackBase+Data.PIN[IP]])^));
  500.       end;
  501.       dtStackVariableByOfs: begin
  502.         Push(TStackItem((@Stack[StackBase+Pop])^));
  503.       end;
  504.       dtExtVariable: begin
  505.         Inc(IP); Push(TStackItem( (@Data.BaseData[Data.PIN[IP]])^));
  506. //        Inc(IP); Push(TStackItem( (@Data.BaseData[Data.Variables[Data.PIN[IP]].Index])^));
  507.       end;
  508.       dtExtVariableByOfs: begin
  509.         Push(TStackItem((@Data.BaseData[Pop])^));
  510. //        Inc(IP); Push(TStackItem( (@Data.BaseData[Data.PIN[IP] + Pop])^));
  511.       end;
  512.       aoAddII: begin i2 := Pop; i1 := Pop; Push(AddII(i1, i2)); end;
  513.       aoAddIR: begin r2 := PopS; i1 := Pop; PushS(AddIR(i1, r2)); end;
  514.       aoAddRI: begin i2 := Pop; r1 := PopS; PushS(AddRI(r1, i2)); end;
  515.       aoAddRR: begin r2 := PopS; r1 := PopS; PushS(AddRR(r1, r2)); end;
  516.       aoAddSS: begin i2 := Pop; i1 := Pop; Push(AddSS(i1, i2)); end;
  517.       aoSubII: begin i2 := Pop; i1 := Pop; Push(SubII(i1, i2)); end;
  518.       aoSubIR: begin r2 := PopS; i1 := Pop; PushS(SubIR(i1, r2)); end;
  519.       aoSubRI: begin i2 := Pop; r1 := PopS; PushS(SubRI(r1, i2)); end;
  520.       aoSubRR: begin r2 := PopS; r1 := PopS; PushS(SubRR(r1, r2)); end;
  521.       aoSubSS: begin i2 := Pop; i1 := Pop; Push(SubSS(i1, i2)); end;
  522.       aoMulII: begin i2 := Pop; i1 := Pop; Push(MulII(i1, i2)); end;
  523.       aoMulIR: begin r2 := PopS; i1 := Pop; PushS(MulIR(i1, r2)); end;
  524.       aoMulRI: begin i2 := Pop; r1 := PopS; PushS(MulRI(r1, i2)); end;
  525.       aoMulRR: begin r2 := PopS; r1 := PopS; PushS(MulRR(r1, r2)); end;
  526.       aoMulSS: begin i2 := Pop; i1 := Pop; Push(MulSS(i1, i2)); end;
  527.       aoDivII: begin i2 := Pop; i1 := Pop; PushS(DivII(i1, i2)); end;
  528.       aoDivIR: begin r2 := PopS; i1 := Pop; PushS(DivIR(i1, r2)); end;
  529.       aoDivRI: begin i2 := Pop; r1 := PopS; PushS(DivRI(r1, i2)); end;
  530.       aoDivRR: begin r2 := PopS; r1 := PopS; PushS(DivRR(r1, r2)); end;
  531.       aoDivSS: begin i2 := Pop; i1 := Pop; Push(DivSS(i1, i2)); end;
  532.       aoOrII, aoOrBB: Push(OrII(Pop, Pop));
  533.       aoAndII, aoAndBB: Push(AndII(Pop, Pop));
  534.       aoIDivII: Push(IDivII(Pop, Pop));
  535.       aoModII: Push(ModII(Pop, Pop));
  536.       aoNegI: Push(NegI(Pop));
  537.       aoNegR: PushS(NegR(PopS));
  538.       aoNegS: Push(NegS(Pop));
  539.       aoInvI: Push(InvI(Pop));
  540.       aoInvB: Push(InvB(Pop));
  541.       arEqualII, arEqualRR: begin i2 := Pop; i1 := Pop; Push(Equal(i1, i2)); end;
  542.       arEqualIR: begin r1 := PopS; i2 := Pop; Push(EqualRI(r1, i2)); end;
  543.       arEqualRI: begin i1 := Pop; r2 := PopS; Push(EqualRI(r2, i1)); end;
  544.       arGreaterII: begin i2 := Pop; i1 := Pop; Push(GreaterII(i1, i2)); end;
  545.       arGreaterIR: begin r2 := PopS; i1 := Pop; Push(GreaterIR(i1, r2)); end;
  546.       arGreaterRI: begin i2 := Pop; r1 := PopS; Push(GreaterRI(r1, i2)); end;
  547.       arGreaterRR: begin r2 := PopS; r1 := PopS; Push(GreaterRR(r1, r2)); end;
  548.       arLessII: begin i2 := Pop; i1 := Pop; Push(LessII(i1, i2)); end;
  549.       arLessIR: begin r2 := PopS; i1 := Pop; Push(LessIR(i1, r2)); end;
  550.       arLessRI: begin i2 := Pop; r1 := PopS; Push(LessRI(r1, i2)); end;
  551.       arLessRR: begin r2 := PopS; r1 := PopS; Push(LessRR(r1, r2)); end;
  552.       arGreaterEqualII: begin i2 := Pop; i1 := Pop; Push(GreaterEqualII(i1, i2)); end;
  553.       arGreaterEqualIR: begin r2 := PopS; i1 := Pop; Push(GreaterEqualIR(i1, r2)); end;
  554.       arGreaterEqualRI: begin i2 := Pop; r1 := PopS; Push(GreaterEqualRI(r1, i2)); end;
  555.       arGreaterEqualRR: begin r2 := PopS; r1 := PopS; Push(GreaterEqualRR(r1, r2)); end;
  556.       arLessEqualII: begin i2 := Pop; i1 := Pop; Push(LessEqualII(i1, i2)); end;
  557.       arLessEqualIR: begin r2 := PopS; i1 := Pop; Push(LessEqualIR(i1, r2)); end;
  558.       arLessEqualRI: begin i2 := Pop; r1 := PopS; Push(LessEqualRI(r1, i2)); end;
  559.       arLessEqualRR: begin r2 := PopS; r1 := PopS; Push(LessEqualRR(r1, r2)); end;
  560.       arNotEqualII, arNotEqualRR: begin i2 := Pop; i1 := Pop; Push(NotEqual(i1, i2)); end;
  561.       arNotEqualIR: begin i2 := Pop; i1 := Pop; Push(NotEqualRI(i1, i2)); end;
  562.       arNotEqualRI: begin i2 := Pop; i1 := Pop; Push(NotEqualRI(i2, i1)); end;
  563.       arIn: begin i2 := Pop; i1 := Pop; Push(TestIn(i1, i2)); end;
  564.       aoAssign1: ;//begin i2 := Pop; i1 := Pop; DoAssign4(i1, i2); end;
  565.       aoAssign2: ;
  566.       aoAssign4: begin i2 := Pop; i1 := Pop; DoAssign4(i1, i2); end;
  567.       aoAssign4RI: begin r2 := Pop; i1 := Pop; DoAssign4(i1, Integer((@r2)^)); end;
  568.       aoAssignSize: ;
  569.       aoStackAssign4: begin i2 := Pop; i1 := Pop; DoStackAssign4(i1, i2); end;
  570.       aoStackAssign4RI: begin r2 := Pop; i1 := Pop; DoStackAssign4(i1, Integer((@r2)^)); end;
  571.       aoStackAssignSize: ;
  572.       aoExtAssign4: begin i2 := Pop; i1 := Pop; DoExtAssign4(i1, i2); end;
  573.       aoExtAssign4RI: begin r2 := Pop; i1 := Pop; DoExtAssign4(i1, Integer((@r2)^)); end;
  574.       aoGoto: DoGoto(IP);
  575.       aoJumpIfZero: DoZeroJump(Pop, IP);
  576.       aoCall: begin DoCall(Pop, IP); Dec(IP); end;
  577.       aoReturnF: begin
  578.         i1 := Pop; DoReturn(IP); Push(i1);             // function only
  579.       end;
  580.       aoReturnP: DoReturn(IP);                         // procedure only
  581.       aoExit: begin DoExit(Pop, IP); end;
  582.       aoSetStackBase: begin Inc(IP); Push(StackBase); StackBase := TotalStack-Data.PIN[IP]-2; end;
  583.       aoExpandStack: begin Inc(IP); ExpandStack(Data.PIN[IP]); end;
  584. {        eoAdd, eoSub: Push(AddItems(Pop, Pop, Data.PIN[i].Value = eoSub));
  585.       eoOr: Push(OrItems(Pop, Pop));
  586.       eoAnd: Push(AndItems(Pop, Pop));
  587.       eoMul: Push(MulItems(Pop, Pop));
  588.       eoDiv: Push(DivItems(Pop, Pop));
  589.       eoIDiv: Push(IDivItems(Pop, Pop));
  590.       eoMod: Push(ModItems(Pop, Pop));
  591.       rEqual, rNotEqual: Push(TestEqual(Pop, Pop, Data.PIN[i].Value = rNotEqual));
  592.       rGreater, rLessEqual: Push(TestGreater(Pop, Pop, Data.PIN[i].Value = rLessEqual));
  593.       rLess, rGreaterEqual: Push(TestLess(Pop, Pop, Data.PIN[i].Value = rGreaterEqual));}
  594. // Standard functions
  595.       sfSin: Pushs(Sin(PopS));
  596.       sfCos: Pushs(Cos(PopS));
  597.       sfTan: begin r1 := PopS; PushS(Sin(r1)/Cos(r1)); end;
  598.       sfArcTan: PushS(ArcTan(PopS));
  599.       sfSqrt: PushS(Sqrt(PopS));
  600.       sfInvSqrt: PushS(InvSqrt(PopS));
  601.       sfRnd: PushS(Random);
  602.       sfEntier: Push(Round(PopS));
  603.       sfLn: Pushs(Ln(PopS));
  604.       sfBlend: begin
  605.         r1 := PopS; i1 := Pop; i2 := Pop;
  606.         Push(Integer(BlendColor(Cardinal(i2), Cardinal(i1), r1)));
  607.       end;
  608.     end;
  609.     Inc(IP);
  610.   end;
  611. end;
  612. function TOberonVM.Compute: TStackItem;
  613. begin
  614.   Run;
  615.   Result := Pop;
  616. end;
  617. constructor TOberonVM.Create;
  618. var i: Integer;
  619. begin
  620. {$IFDEF DEBUG}
  621.   DItems := TStringList.Create;
  622. {$ENDIF}
  623.   Data  := TRTData.Create;
  624.   StackCapacityStep := 256; StackCapacity := 256; SetLength(Stack, StackCapacity);
  625.   MaxSet := 31;
  626.   SetLength(El2Set, MaxSet);
  627.   for i := 0 to MaxSet-1 do El2Set[i] := 1 shl i;
  628.   Data.Namespace := nil;
  629. end;
  630. destructor TOberonVM.Destroy;
  631. begin
  632.   StackCapacity := 0; SetLength(Stack, StackCapacity);
  633.   SetLength(El2Set, 0);
  634. end;
  635. end.