base_symbol.pas
来自「Delphi脚本控件」· PAS 代码 · 共 2,415 行 · 第 1/4 页
PAS
2,415 行
////////////////////////////////////////////////////////////////////////////
// PAXScript Interpreter
// Author: Alexander Baranovsky (ab@cable.netlux.org)
// ========================================================================
// Copyright (c) Alexander Baranovsky, 2003-2005. All rights reserved.
// Code Version: 3.0
// ========================================================================
// Unit: BASE_SYMBOL.pas
// ========================================================================
////////////////////////////////////////////////////////////////////////////
{$I PaxScript.def}
unit BASE_SYMBOL;
interface
uses
{$IFDEF VARIANTS}
Variants,
{$ENDIF}
SysUtils, Classes,
BASE_CONSTS,
BASE_SYS, BASE_CLASS;
type
TPAXSymbolRec = packed record
Address: Pointer;
Position: Integer;
StartPosition: Integer;
Next: Integer;
Level: Integer;
PName: Integer;
PType: Integer;
Count: Integer;
Local: Integer;
Kind: Integer;
Module: Integer;
CallConv: Integer;
Misc: Integer;
Owner: Integer;
TypeNameIndex: Integer;
Imported: Boolean;
Rank: ShortInt;
Global: Boolean;
JSIndex: Boolean;
IsVirtual: Boolean;
end;
TPAXSymbolTable = class
private
Scripter: Pointer;
Mem: Pointer;
fCard: Integer;
StateStack: TPAXStack;
procedure SetName(I: Integer; const Name: String);
function GetName(I: Integer): String;
function GetFullName(I: Integer): String;
procedure SetNameIndex(I, Value: Integer);
function GetNameIndex(I: Integer): Integer;
procedure SetKind(I, AKind: Integer);
function GetKind(I: Integer): Integer;
procedure SetCount(I, ACount: Integer);
function GetCount(I: Integer): Integer;
procedure SetRank(I, ARank: Integer);
function GetRank(I: Integer): Integer;
procedure SetNext(I, Value: Integer);
function GetNext(I: Integer): Integer;
procedure SetModule(I, Value: Integer);
function GetModule(I: Integer): Integer;
procedure SetPosition(I, Value: Integer);
function GetStartPosition(I: Integer): Integer;
procedure SetStartPosition(I, Value: Integer);
function GetPosition(I: Integer): Integer;
procedure SetLevel(I: Integer; Value: Integer);
function GetLevel(I: Integer): Integer;
procedure SetType(I, AType: Integer);
function GetType(I: Integer): Integer;
procedure SetImported(I: Integer; Value: Boolean);
function GetImported(I: Integer): Boolean;
procedure SetGlobal(I: Integer; Value: Boolean);
function GetGlobal(I: Integer): Boolean;
procedure SetAddr(I: Integer; Address: Pointer);
function GetAddr(I: Integer): Pointer;
function GetStrKind(I: Integer): String;
procedure SetByRef(ParamID: Integer; Value: Integer);
function GetByRef(ParamID: Integer): Integer;
function GetStrType(I: Integer): String;
procedure SetTypeSub(SubID: Integer; Value: TPAXTypeSub);
function GetTypeSub(SubID: Integer): TPAXTypeSub;
function GetMemberAccess(RefID: Integer): TPAXMemberAccess;
procedure SetMemberAccess(RefID: Integer; Value: TPAXMemberAccess);
procedure SetCallConv(I, Value: Integer);
function GetCallConv(I: Integer): Integer;
procedure SetTypeNameIndex(I, Value: Integer);
function GetTypeNameIndex(I: Integer): Integer;
procedure SetCard(Value: Integer);
procedure CheckMem;
function NameList: TPaxNameList;
function GetJSIndex(I: Integer): Boolean;
procedure SetJSIndex(I: Integer; Value: Boolean);
public
A: array of TPAXSymbolRec;
RootNamespaceID: Integer;
MemBoundVar: Integer;
MemSize: Integer;
CreateCard: Integer;
CreateMemBoundVar: Integer;
MaxLocalVars: Integer;
IDfalse: Integer;
IDtrue: Integer;
IDundefined: Integer;
constructor Create(AScripter: Pointer);
destructor Destroy; override;
procedure SaveToStream(S: TStream; I1, I2: Integer);
procedure LoadFromStream(S: TStream;
DS: Integer = 0; DP: Integer = 0);
procedure Reset;
procedure ResetCompileStage;
procedure EraseTail(K: Integer);
procedure InitRunStage;
procedure ResetRunStage;
function AllocateVar(I: Integer): Pointer;
function GetSizeOf(I: Integer): Integer;
function AppLabel: Integer;
procedure LinkVariables(SubID: Integer; HasResult: Boolean);
function GetParamID(SubID: Integer; N: Integer): Integer;
function GetResultID(SubID: Integer): Integer;
function GetThisID(SubID: Integer): Integer;
function GetDllID(SubID: Integer): Integer;
function GetDllProcID(SubID: Integer): Integer;
procedure AllocateSub(SubID: Integer);
function GetSubCount: Integer;
procedure AllocateSubroutines;
procedure DeallocateSub(SubID: Integer);
function IsLocalVar(SubID, ID: Integer): Boolean;
procedure SetLocal(ID: Integer);
function IsLocal(ID: Integer): Boolean;
procedure Erase(I: Integer);
procedure SaveState;
procedure RestoreState;
procedure ReallocateMem(NewSize: Integer);
function GetStrVal(I: Integer): String;
function GetAlias(ID: Integer): Variant;
function GetParamTypeName(SubID, ParamIndex: Integer): String;
function GetParamName(SubID, ParamIndex: Integer): String;
function GetTypeName(ID: Integer): String;
function GetVariant(ID: Integer): Variant;
procedure ClearVariant(ID: Integer);
procedure ClearVariantValue(ID: Integer);
procedure PutVariant(ID: Integer; const Val: Variant);
function AppVariant(const Val: Variant; HasAddress: Boolean = true): Integer;
function AppVariantConst(const Val: Variant; Dup: Boolean = false): Integer;
function GetUserData(ID: Integer): Integer;
function CodeNumberConst(Val: Variant): Integer;
function CodeStringConst(const Val: String): Integer;
function GetMemberRec(RefID: Integer; ma: TPAXMemberAccess): TPAXMemberRec;
function GetMemberRecEx(RefID: Integer; ma: TPAXMemberAccess;
var FoundInBaseClass: Boolean;
var SO: TPaxScriptObject): TPAXMemberRec;
function IsFormalParamID(ID: Integer): Boolean;
function GetOverloadedSubID(RefID: Integer; ma: TPAXMemberAccess;
ParamCount: Integer): Integer;
procedure SetReference(RefID: Integer; const Base: Variant; ma: TPAXMemberAccess);
function AppReference(const Base: Variant; ANameIndex: Integer; ma: TPAXMemberAccess): Integer;
function GetValue(ID: Integer): Variant;
procedure PutValue(ID: Integer; const Val: Variant);
function LookUpID(const Name: String; aLevel: Integer; UpCase: Boolean = true): Integer;
function LookUpSubID(const Name: String; aLevel: Integer; UpCase: Boolean = true): Integer;
function LookupConstID(const Value: Variant): Integer;
function IsOutsideMemAddress(A: Pointer): boolean;
function IsInsideMemAddress(A: Pointer): boolean;
function IsExternalAddress(A: Pointer): boolean;
function IsInternalAddress(A: Pointer): boolean;
procedure IncCard;
procedure DecCard;
procedure CheckLength; overload;
procedure CheckLength(Value: Integer); overload;
procedure Dump(const FileName: String);
procedure SetupSubs(StartRecNo: Integer);
function TypeCast(TypeID: Integer; const Value: Variant): Variant;
function IsVirtual(SubId: Integer): Boolean;
function GetAddressEx(ID: Integer): Pointer;
procedure InitGlobalVars;
property Name[I: Integer]: String read GetName write SetName;
property FullName[I: Integer]: String read GetFullName;
property Kind[I: Integer]: Integer read GetKind write SetKind;
property Count[I: Integer]: Integer read GetCount write SetCount;
property Rank[I: Integer]: Integer read GetRank write SetRank;
property Next[I: Integer]: Integer read GetNext write SetNext;
property Module[I: Integer]: Integer read GetModule write SetModule;
property Position[I: Integer]: Integer read GetPosition write SetPosition;
property StartPosition[I: Integer]: Integer read GetStartPosition write SetStartPosition;
property Level[I: Integer]: Integer read GetLevel write SetLevel;
property PType[I: Integer]: Integer read GetType write SetType;
property Address[I: Integer]: Pointer read GetAddr write SetAddr;
property ByRef[I: Integer]: Integer read GetByRef write SetByRef;
property TypeSub[I: Integer]: TPAXTypeSub read GetTypeSub write SetTypeSub;
property NameIndex[I: Integer]: Integer read GetNameIndex write SetNameIndex;
property VariantValue[I: Integer]: Variant read GetValue write PutValue;
property MemberAccess[RefID: Integer]: TPAXMemberAccess read GetMemberAccess write SetMemberAccess;
property CallConv[SubID: Integer]: Integer read GetCallConv write SetCallConv;
property TypeNameIndex[ID: Integer]: Integer read GetTypeNameIndex write SetTypeNameIndex;
property Imported[I: Integer]: Boolean read GetImported write SetImported;
property Global[I: Integer]: Boolean read GetGlobal write SetGlobal;
property JSIndex[I: Integer]: Boolean read GetJSIndex write SetJSIndex;
property Card: Integer read fCard write SetCard;
end;
function _GetName(NameIndex: Integer; Scripter: Pointer): String;
implementation
uses
BASE_SCRIPTER, BASE_CODE, BASE_EXTERN;
constructor TPAXSymbolTable.Create(AScripter: Pointer);
var
I: Integer;
begin
StateStack := TPAXStack.Create;
Scripter := AScripter;
MemSize := FirstMemSize;
Mem := AllocMem(MemSize);
MemBoundVar := 0;
SetLength(A, FirstSymbolCard);
for I:=0 to FirstSymbolCard - 1 do
FillChar(A[I], SizeOf(TPAXSymbolRec), 0);
fCard := -1;
for I:=0 to PAXTypes.Count - 1 do
begin
AppVariant(Undefined, true);
SetName(I, PAXTypes[I]);
SetKind(I, kindTYPE);
end;
SetName(AppVariantConst(ord(maAny)), '_maAny_');
SetName(AppVariantConst(ord(maMyBase)), '_maMyBase_');
SetName(AppVariantConst(ord(maMyClass)), '_maMyClass_');
IDtrue := AppVariant(true);
SetName(IDtrue, 'true');
IDfalse := AppVariant(false);
SetName(IDfalse, 'false');
IDundefined := AppVariant(undefined);
RootNameSpaceID := AppVariant(Undefined);
Name[RootNameSpaceID] := RootNamespaceName;
Kind[RootNameSpaceID] := KindTYPE;
CreateCard := Card;
CreateMemBoundVar := MemBoundVar;
MaxLocalVars := 0;
end;
procedure TPAXSymbolTable.SetCard(Value: Integer);
begin
fCard := Value;
CheckLength;
end;
procedure TPAXSymbolTable.IncCard;
begin
Inc(fCard);
CheckLength;
end;
procedure TPAXSymbolTable.DecCard;
begin
Dec(fCard);
end;
procedure TPAXSymbolTable.CheckLength;
var
L, I: Integer;
begin
L := Length(A);
if L < Card + 10 then
begin
SetLength(A, Card + DeltaSymbolCard);
for I:=fCard + 1 to Length(A) - 1 do
FillChar(A[I], SizeOf(TPAXSymbolRec), 0);
end;
end;
procedure TPAXSymbolTable.CheckLength(Value: Integer);
var
L, I: Integer;
begin
L := Length(A);
if value >= L then
begin
SetLength(A, value + DeltaSymbolCard);
for I:=fCard + 1 to Length(A) - 1 do
FillChar(A[I], SizeOf(TPAXSymbolRec), 0);
end;
end;
procedure TPAXSymbolTable.SaveToStream(S: TStream; I1, I2: Integer);
var
I, J, K, L: Integer;
ClassRec: TPAXClassRec;
ClassList: TPAXClassList;
MemberRec: TPAXMemberRec;
SO: TPAXScriptObject;
FInstance: TPAXDelegate;
ClassRecList: TPaxIds;
begin
ClassList := TPAXBaseScripter(Scripter).ClassList;
ClassRecList := TPaxIds.Create(false);
SaveInteger(I1, S);
SaveInteger(I2, S);
SaveInteger(MaxLocalVars, S);
for I:=I1 to I2 do
if Kind[I] = KindTYPE then
begin
ClassRec := ClassList.FindClass(I);
if ClassRec <> nil then
ClassRecList.Add(I);
end;
for I:=I1 to I2 do
begin
S.WriteBuffer(A[I], SizeOF(A[I]));
SaveString(Name[I], S);
end;
SaveInteger(ClassRecList.Count, S);
for J:=0 to ClassRecList.Count - 1 do
begin
I := ClassRecList[J];
L := Level[I];
ClassRec := ClassList.FindClass(I);
ClassRec.SaveToStream(S);
if Kind[L] = KindTYPE then
begin
ClassRec := ClassList.FindClass(L);
MemberRec := ClassRec.GetMember(NameIndex[I]);
MemberRec.SaveToStream(S);
end;
end;
ClassRecList.Free;
for I:=I1 to I2 do
begin
K := Kind[I];
L := Level[I];
if K = KindVAR then
begin
if L = RootNamespaceID then
begin
ClassRec := ClassList[0];
MemberRec := ClassRec.GetMember(NameIndex[I]);
if MemberRec = nil then
SaveInteger(0, S)
else
begin
if MemberRec.IsSource then
begin
SaveInteger(1, S);
MemberRec.SaveToStream(S);
end
else
SaveInteger(0, S);
end;
end;
end
else if K = KindCONST then
begin
SaveVariant(GetVariant(I), S);
end
else if K = KindSUB then
begin
SO := VariantToScriptObject(GetVariant(I));
FInstance := TPAXDelegate(SO.Instance);
SaveInteger(FInstance.N, S);
if L = RootNamespaceID then
begin
ClassRec := ClassList[0];
MemberRec := ClassRec.GetMember(NameIndex[I]);
MemberRec.SaveToStream(S);
end;
end;
end;
end;
procedure TPAXSymbolTable.LoadFromStream(S: TStream;
DS: Integer = 0; DP: Integer = 0);
var
I1, I2, I, J, K, L, Temp: Integer;
St: String;
ClassRec: TPAXClassRec;
ClassList: TPAXClassList;
MemberRec: TPAXMemberRec;
Shift: Boolean;
begin
Shift := (DS <> 0) or (DP <> 0);
ClassList := TPAXBaseScripter(Scripter).ClassList;
I1 := LoadInteger(S);
I2 := LoadInteger(S);
MaxLocalVars := LoadInteger(S);
ReallocateMem((I2 + MaxLocalVars * 2) * _SizeVariant + DeltaMemSize);
for I:=I1 to I2 do
begin
IncCard;
S.ReadBuffer(A[Card], SizeOf(A[Card]));
St := LoadString(S);
Name[Card] := St;
AllocateVar(Card);
if Shift then
begin
if A[Card].Level > RootNamespaceID then
Inc(A[Card].Level, DS);
if A[Card].Next > RootNamespaceID then
Inc(A[Card].Next, DS);
if A[Card].PType > RootNamespaceID then
Inc(A[Card].PType, DS);
end;
end;
K := LoadInteger(S);
for J:=1 to K do
begin
ClassRec := TPAXClassRec.Create(Scripter, ckClass);
ClassRec.LoadFromStream(S, DS, DP);
ClassList.AddObject(ClassRec.ClassID, ClassRec);
I := ClassRec.ClassID;
L := Level[I];
if Kind[L] = KindTYPE then
begin
ClassRec := ClassList.FindClass(L);
MemberRec := TPAXMemberRec.Create(I, ClassRec);
MemberRec.LoadFromStream(S, DS, DP);
ClassRec.MemberList.AddObject(NameIndex[I], MemberRec);
end;
end;
for I:=I1 + DS to I2 + DS do
begin
K := Kind[I];
L := Level[I];
if K = KindVAR then
begin
if L = RootNamespaceID then
begin
Temp := LoadInteger(S);
if Temp <> 0 then
begin
ClassRec := ClassList[0];
MemberRec := TPAXMemberRec.Create(I, ClassRec);
MemberRec.LoadFromStream(S, DS, DP);
ClassRec.MemberList.AddObject(NameIndex[I], MemberRec);
end;
end;
end
else if K = KindCONST then
begin
PutVariant(I, LoadVariant(S));
end
else if K = KindSUB then
begin
Temp := LoadInteger(S);
if Temp > 0 then
Inc(Temp, DP);
PutVariant(I, Temp);
if L = RootNamespaceID then
begin
ClassRec := ClassList[0];
MemberRec := TPAXMemberRec.Create(I, ClassRec);
MemberRec.LoadFromStream(S, DS, DP);
ClassRec.MemberList.AddObject(NameIndex[I], MemberRec);
end;
end;
end;
end;
procedure TPAXSymbolTable.Reset;
begin
FillChar(Mem^, MemSize, 0);
MemBoundVar := CreateMemBoundVar;
EraseTail(CreateCard);
StateStack.Clear;
end;
procedure TPAXSymbolTable.EraseTail(K: Integer);
var
I: Integer;
P: Pointer;
begin
for I:=Card downto K + 1 do
if Level[I] >= 0 then
begin
P := A[I].Address;
if P <> nil then
begin
try
if IsInsideMemAddress(P) then
ClearVariant(I);
finally
FillChar(A[I], SizeOf(TPAXSymbolRec), 0);
end;
end;
end;
Card := K;
end;
function TPAXSymbolTable.IsFormalParamID(ID: Integer): Boolean;
var
I, SubID: Integer;
begin
result := false;
if ID <= 0 then
Exit;
SubID := GetLevel(ID);
if GetKind(SubID) <> KindSUB then
Exit;
for I:=1 to GetCount(SubID) do
if GetParamID(SubID, I) = ID then
result := true;
end;
function TPAXSymbolTable.CodeStringConst(const Val: String): Integer;
var
I: Integer;
begin
for I:=PAXTypes.Count + 1 to Card do
if GetType(I) > 0 then
if GetKind(I) = kindCONST then
if VarType(Variant(GetAddr(I)^)) = varString then
if Val = Variant(GetAddr(I)^) then
begin
result := I;
Exit;
end;
// result := AppVariantConst(Val);
IncCard;
with A[Card] do
begin
PName := 0;
PType := GetPAXtype(Val);
Kind := kindCONST;
Address := Pointer(Integer(Mem) + MemBoundVar);
Inc(MemBoundVar, SizeOf(Variant));
FillChar(Address^, SizeOf(Variant), 0);
Variant(Address^) := Val;// StrPas(PChar(Val));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?