1815 lines
46 KiB
ObjectPascal
1815 lines
46 KiB
ObjectPascal
{ * opCode * }
|
|
{ ****************************************************************************** }
|
|
{ * https://zpascal.net * }
|
|
{ * https://github.com/PassByYou888/zAI * }
|
|
{ * https://github.com/PassByYou888/ZServer4D * }
|
|
{ * https://github.com/PassByYou888/PascalString * }
|
|
{ * https://github.com/PassByYou888/zRasterization * }
|
|
{ * https://github.com/PassByYou888/CoreCipher * }
|
|
{ * https://github.com/PassByYou888/zSound * }
|
|
{ * https://github.com/PassByYou888/zChinese * }
|
|
{ * https://github.com/PassByYou888/zExpression * }
|
|
{ * https://github.com/PassByYou888/zGameWare * }
|
|
{ * https://github.com/PassByYou888/zAnalysis * }
|
|
{ * https://github.com/PassByYou888/FFMPEG-Header * }
|
|
{ * https://github.com/PassByYou888/zTranslate * }
|
|
{ * https://github.com/PassByYou888/InfiniteIoT * }
|
|
{ * https://github.com/PassByYou888/FastMD5 * }
|
|
{ ****************************************************************************** }
|
|
unit OpCode;
|
|
|
|
{$INCLUDE zDefine.inc}
|
|
|
|
interface
|
|
|
|
uses SysUtils, Variants, Math, CoreClasses, PascalStrings, DoStatusIO, ListEngine, UnicodeMixedLib, DataFrameEngine;
|
|
|
|
type
|
|
TOpValueType = (
|
|
ovtBool, ovtInt, ovtInt64, ovtUInt64, ovtWord, ovtByte, ovtSmallInt, ovtShortInt, ovtUInt,
|
|
ovtSingle, ovtDouble, ovtCurrency,
|
|
ovtString, ovtProc,
|
|
ovtUnknow);
|
|
|
|
TOpCode = class;
|
|
TOpCustomRunTime = class;
|
|
|
|
TOpParam = array of Variant;
|
|
|
|
TOnOpCall = function(var Param: TOpParam): Variant;
|
|
TOnOpMethod = function(var Param: TOpParam): Variant of object;
|
|
TOnObjectOpCall = function(OpRunTime: TOpCustomRunTime; var Param: TOpParam): Variant;
|
|
TOnObjectOpMethod = function(OpRunTime: TOpCustomRunTime; var Param: TOpParam): Variant of object;
|
|
|
|
{$IFDEF FPC}
|
|
TOnOpProc = function(var Param: TOpParam): Variant is nested;
|
|
TOnObjectOpProc = function(OpRunTime: TOpCustomRunTime; var Param: TOpParam): Variant is nested;
|
|
{$ELSE FPC}
|
|
TOnOpProc = reference to function(var Param: TOpParam): Variant;
|
|
TOnObjectOpProc = reference to function(OpRunTime: TOpCustomRunTime; var Param: TOpParam): Variant;
|
|
{$ENDIF FPC}
|
|
POpRTData = ^TOpRTData;
|
|
|
|
TOpRTData = record
|
|
Param: TOpParam;
|
|
Name, Description, Category: SystemString;
|
|
OnOpCall: TOnOpCall;
|
|
OnOpMethod: TOnOpMethod;
|
|
OnObjectOpCall: TOnObjectOpCall;
|
|
OnObjectOpMethod: TOnObjectOpMethod;
|
|
OnOpProc: TOnOpProc;
|
|
OnObjectOpProc: TOnObjectOpProc;
|
|
procedure Init;
|
|
end;
|
|
|
|
TOpCustomRunTime = class(TCoreClassObject)
|
|
protected
|
|
procedure FreeNotifyProc(p: Pointer);
|
|
|
|
function DoInt(var Param: TOpParam): Variant;
|
|
function DoFrac(var Param: TOpParam): Variant;
|
|
function DoExp(var Param: TOpParam): Variant;
|
|
function DoCos(var Param: TOpParam): Variant;
|
|
function DoSin(var Param: TOpParam): Variant;
|
|
function DoLn(var Param: TOpParam): Variant;
|
|
function DoArcTan(var Param: TOpParam): Variant;
|
|
function DoSqrt(var Param: TOpParam): Variant;
|
|
function DoSqr(var Param: TOpParam): Variant;
|
|
function DoTan(var Param: TOpParam): Variant;
|
|
function DoRound(var Param: TOpParam): Variant;
|
|
function DoTrunc(var Param: TOpParam): Variant;
|
|
function DoDeg(var Param: TOpParam): Variant;
|
|
function DoPower(var Param: TOpParam): Variant;
|
|
|
|
function DoPI(var Param: TOpParam): Variant;
|
|
function DoBool(var Param: TOpParam): Variant;
|
|
function DoTrue(var Param: TOpParam): Variant;
|
|
function DoFalse(var Param: TOpParam): Variant;
|
|
function DoRColor(var Param: TOpParam): Variant;
|
|
function DoVec2(var Param: TOpParam): Variant;
|
|
function DoVec3(var Param: TOpParam): Variant;
|
|
function DoVec4(var Param: TOpParam): Variant;
|
|
|
|
function DoRandom(var Param: TOpParam): Variant;
|
|
function DoRandomFloat(var Param: TOpParam): Variant;
|
|
|
|
function DoMax(var Param: TOpParam): Variant;
|
|
function DoMin(var Param: TOpParam): Variant;
|
|
function DoClamp(var Param: TOpParam): Variant;
|
|
function DoIfThen(var Param: TOpParam): Variant;
|
|
|
|
function DoStr(var Param: TOpParam): Variant;
|
|
|
|
function DoGetFirst(var Param: TOpParam): Variant;
|
|
function DoDeleteFirst(var Param: TOpParam): Variant;
|
|
function DoGetLast(var Param: TOpParam): Variant;
|
|
function DoDeleteLast(var Param: TOpParam): Variant;
|
|
|
|
function DoMultiple(var Param: TOpParam): Variant;
|
|
function DoPrint(var Param: TOpParam): Variant;
|
|
|
|
procedure InternalReg; virtual;
|
|
public
|
|
ProcList: THashList;
|
|
Trigger: POpRTData;
|
|
|
|
UserObject: TCoreClassObject;
|
|
UserData: Pointer;
|
|
|
|
constructor Create;
|
|
constructor CustomCreate(maxHashLen: Integer); virtual;
|
|
destructor Destroy; override;
|
|
|
|
function GetProcDescription(ProcName: SystemString): SystemString; overload;
|
|
function GetAllProcDescription(): TPascalStringList; overload;
|
|
function GetAllProcDescription(Category: U_String): TPascalStringList; overload;
|
|
|
|
function RegOpC(ProcName: SystemString; OnProc: TOnOpCall): POpRTData; overload;
|
|
function RegOpC(ProcName, ProcDescription: SystemString; OnProc: TOnOpCall): POpRTData; overload;
|
|
function RegOpM(ProcName: SystemString; OnProc: TOnOpMethod): POpRTData; overload;
|
|
function RegOpM(ProcName, ProcDescription: SystemString; OnProc: TOnOpMethod): POpRTData; overload;
|
|
function RegObjectOpC(ProcName: SystemString; OnProc: TOnObjectOpCall): POpRTData; overload;
|
|
function RegObjectOpC(ProcName, ProcDescription: SystemString; OnProc: TOnObjectOpCall): POpRTData; overload;
|
|
function RegObjectOpM(ProcName: SystemString; OnProc: TOnObjectOpMethod): POpRTData; overload;
|
|
function RegObjectOpM(ProcName, ProcDescription: SystemString; OnProc: TOnObjectOpMethod): POpRTData; overload;
|
|
function RegOpP(ProcName: SystemString; OnProc: TOnOpProc): POpRTData; overload;
|
|
function RegOpP(ProcName, ProcDescription: SystemString; OnProc: TOnOpProc): POpRTData; overload;
|
|
function RegObjectOpP(ProcName: SystemString; OnProc: TOnObjectOpProc): POpRTData; overload;
|
|
function RegObjectOpP(ProcName, ProcDescription: SystemString; OnProc: TOnObjectOpProc): POpRTData; overload;
|
|
end;
|
|
|
|
opClass = class of TOpCode;
|
|
|
|
TOpCode = class(TCoreClassObject)
|
|
private type
|
|
POpData = ^opData;
|
|
|
|
opData = record
|
|
Op: TOpCode;
|
|
Value: Variant;
|
|
ValueType: TOpValueType;
|
|
end;
|
|
protected
|
|
FParam: TCoreClassList;
|
|
FAutoFreeLink: Boolean;
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; virtual;
|
|
function GetParam(index: Integer): POpData;
|
|
procedure EvaluateParam(opRT: TOpCustomRunTime); overload;
|
|
procedure EvaluateParam(printLog: Boolean; opRT: TOpCustomRunTime); overload;
|
|
public
|
|
Owner: TOpCode;
|
|
ParsedInfo: SystemString;
|
|
ParsedLineNo: Integer;
|
|
|
|
constructor Create(AFreeLink: Boolean);
|
|
destructor Destroy; override;
|
|
|
|
procedure SaveToStream(stream: TCoreClassStream);
|
|
class function LoadFromStream(stream: TCoreClassStream; out LoadedOp: TOpCode): Boolean;
|
|
|
|
function AddValue(v: Variant): Integer; overload;
|
|
function AddValueT(v: Variant; VT: TOpValueType): Integer; overload;
|
|
function AddLink(Obj: TOpCode): Integer;
|
|
|
|
function CloneNewSelf: TOpCode;
|
|
|
|
property Param[index: Integer]: POpData read GetParam; default;
|
|
function Count: Integer;
|
|
|
|
function Execute: Variant; overload;
|
|
function Execute(opRT: TOpCustomRunTime): Variant; overload;
|
|
|
|
function OwnerRoot: TOpCode;
|
|
|
|
property AutoFreeLink: Boolean read FAutoFreeLink write FAutoFreeLink;
|
|
end;
|
|
|
|
op_Value = class sealed(TOpCode)
|
|
private
|
|
// a
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Proc = class sealed(TOpCode)
|
|
private
|
|
// proc(a,b,c...)
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Add_Prefix = class sealed(TOpCode)
|
|
private
|
|
// +proc
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Sub_Prefix = class sealed(TOpCode)
|
|
private
|
|
// -proc
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Add = class sealed(TOpCode)
|
|
private
|
|
// a + b + n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Sub = class sealed(TOpCode)
|
|
private
|
|
// a - b - n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Mul = class sealed(TOpCode)
|
|
private
|
|
// a * b * n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Div = class sealed(TOpCode)
|
|
private
|
|
// a / b / n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_IntDiv = class sealed(TOpCode)
|
|
private
|
|
// a div b div n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Pow = class sealed(TOpCode)
|
|
private
|
|
// a pow b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Mod = class sealed(TOpCode)
|
|
private
|
|
// a mod b mod n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Or = class sealed(TOpCode)
|
|
private
|
|
// a or b or n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_And = class sealed(TOpCode)
|
|
private
|
|
// a and b and n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Xor = class sealed(TOpCode)
|
|
private
|
|
// a xor b xor n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Shl = class sealed(TOpCode)
|
|
private
|
|
// a shl b shl n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Shr = class sealed(TOpCode)
|
|
private
|
|
// a shr b shr n...
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Equal = class sealed(TOpCode)
|
|
private
|
|
// a = b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_LessThan = class sealed(TOpCode)
|
|
private
|
|
// a < b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_EqualOrLessThan = class sealed(TOpCode)
|
|
private
|
|
// a <= b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_GreaterThan = class sealed(TOpCode)
|
|
private
|
|
// a > b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_EqualOrGreaterThan = class sealed(TOpCode)
|
|
private
|
|
// a >= b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_NotEqual = class sealed(TOpCode)
|
|
private
|
|
// a <> b
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Symbol_Sub = class sealed(TOpCode)
|
|
private
|
|
// -a
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
op_Symbol_Add = class sealed(TOpCode)
|
|
private
|
|
// +a
|
|
function DoExecute(opRT: TOpCustomRunTime): Variant; override;
|
|
end;
|
|
|
|
function LoadOpFromStream(stream: TCoreClassStream; out LoadedOp: TOpCode): Boolean;
|
|
|
|
var
|
|
DefaultOpRT: TOpCustomRunTime;
|
|
|
|
implementation
|
|
|
|
uses Geometry2DUnit, Geometry3DUnit;
|
|
|
|
type
|
|
opRegData = record
|
|
opClass: opClass;
|
|
OpName: TPascalString;
|
|
hash: Cardinal;
|
|
end;
|
|
|
|
POpRegData = ^opRegData;
|
|
|
|
var
|
|
OpList: TCoreClassList;
|
|
|
|
procedure TOpRTData.Init;
|
|
begin
|
|
SetLength(Param, 0);
|
|
Name := '';
|
|
Description := '';
|
|
Category := '';
|
|
OnOpCall := nil;
|
|
OnOpMethod := nil;
|
|
OnObjectOpCall := nil;
|
|
OnObjectOpMethod := nil;
|
|
OnOpProc := nil;
|
|
OnObjectOpProc := nil;
|
|
end;
|
|
|
|
function GetRegistedOp(Name: TPascalString): POpRegData;
|
|
var
|
|
i: Integer;
|
|
p: POpRegData;
|
|
hash: Cardinal;
|
|
begin
|
|
Result := nil;
|
|
hash := FastHashPPascalString(@Name);
|
|
for i := 0 to OpList.Count - 1 do
|
|
begin
|
|
p := OpList[i];
|
|
if (p^.hash = hash) and (SameText(Name, p^.OpName)) then
|
|
Exit(p);
|
|
end;
|
|
end;
|
|
|
|
procedure RegisterOp(c: opClass);
|
|
var
|
|
p: POpRegData;
|
|
begin
|
|
if GetRegistedOp(c.ClassName) <> nil then
|
|
raise Exception.Create('same op ' + c.ClassName);
|
|
new(p);
|
|
p^.opClass := c;
|
|
p^.OpName := p^.opClass.ClassName;
|
|
p^.hash := FastHashPPascalString(@p^.OpName);
|
|
OpList.Add(p);
|
|
end;
|
|
|
|
procedure _FreeOp;
|
|
var
|
|
i: Integer;
|
|
p: POpRegData;
|
|
begin
|
|
for i := 0 to OpList.Count - 1 do
|
|
begin
|
|
p := OpList[i];
|
|
Dispose(p);
|
|
end;
|
|
DisposeObject(OpList);
|
|
end;
|
|
|
|
function LoadOpFromStream(stream: TCoreClassStream; out LoadedOp: TOpCode): Boolean;
|
|
|
|
function LoadFromDataFrame_(CurDataEng: TDataFrameEngine): TOpCode;
|
|
var
|
|
AName: SystemString;
|
|
RegPtr: POpRegData;
|
|
i, cnt: Integer;
|
|
NeedNewOp: Boolean;
|
|
newDataEng: TDataFrameEngine;
|
|
v: Variant;
|
|
VT: TOpValueType;
|
|
begin
|
|
AName := CurDataEng.Reader.ReadString;
|
|
RegPtr := GetRegistedOp(AName);
|
|
if RegPtr <> nil then
|
|
begin
|
|
Result := RegPtr^.opClass.Create(True);
|
|
Result.ParsedInfo := CurDataEng.Reader.ReadString;
|
|
Result.ParsedLineNo := CurDataEng.Reader.ReadInteger;
|
|
cnt := CurDataEng.Reader.ReadInteger;
|
|
for i := 0 to cnt - 1 do
|
|
begin
|
|
NeedNewOp := CurDataEng.Reader.ReadBool;
|
|
|
|
if NeedNewOp then
|
|
begin
|
|
// create new TOpCode
|
|
newDataEng := TDataFrameEngine.Create;
|
|
CurDataEng.Reader.ReadDataFrame(newDataEng);
|
|
Result.AddLink(LoadFromDataFrame_(newDataEng));
|
|
DisposeObject(newDataEng);
|
|
end
|
|
else
|
|
begin
|
|
v := CurDataEng.Reader.ReadVariant;
|
|
VT := TOpValueType(CurDataEng.Reader.ReadInteger);
|
|
Result.AddValueT(v, VT);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
raise Exception.Create('opCode failed');
|
|
end;
|
|
|
|
var
|
|
DataEng: TDataFrameEngine;
|
|
DataEdition: Integer;
|
|
begin
|
|
Result := False;
|
|
DataEng := TDataFrameEngine.Create;
|
|
try
|
|
DataEng.DecodeFrom(stream, True);
|
|
DataEdition := DataEng.Reader.ReadInteger;
|
|
if DataEdition = 1 then
|
|
begin
|
|
LoadedOp := LoadFromDataFrame_(DataEng);
|
|
Result := True;
|
|
end
|
|
else
|
|
LoadedOp := nil;
|
|
except
|
|
end;
|
|
DisposeObject(DataEng);
|
|
end;
|
|
|
|
procedure TOpCustomRunTime.FreeNotifyProc(p: Pointer);
|
|
begin
|
|
SetLength(POpRTData(p)^.Param, 0);
|
|
Dispose(POpRTData(p));
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoInt(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Int(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoFrac(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Frac(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoExp(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Exp(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoCos(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Cos(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoSin(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Sin(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoLn(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := ln(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoArcTan(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := ArcTan(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoSqrt(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Sqrt(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoSqr(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Sqr(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoTan(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Tan(v);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoRound(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Round(Double(v));
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoTrunc(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := Trunc(Double(v));
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoDeg(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
Result := NormalizeDegAngle(TGeoFloat(v));
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoPower(var Param: TOpParam): Variant;
|
|
var
|
|
v: Variant;
|
|
i: Integer;
|
|
begin
|
|
if length(Param) = 2 then
|
|
Result := Power(Param[0], Param[1])
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoPI(var Param: TOpParam): Variant;
|
|
begin
|
|
Result := PI;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoBool(var Param: TOpParam): Variant;
|
|
function v2b(const v: Variant): Boolean;
|
|
var
|
|
n: TPascalString;
|
|
begin
|
|
if VarIsStr(v) then
|
|
begin
|
|
n := VarToStr(v);
|
|
n := n.DeleteChar(#32#9);
|
|
if n.Same('True') or n.Same('Yes') or n.Same('1') then
|
|
Result := True
|
|
else
|
|
Result := False;
|
|
end
|
|
else if VarIsOrdinal(v) then
|
|
Result := Boolean(v)
|
|
else if VarIsFloat(v) then
|
|
Result := Boolean(Round(Double(v)))
|
|
else
|
|
Result := Boolean(v);
|
|
end;
|
|
|
|
var
|
|
n: Boolean;
|
|
i: Integer;
|
|
begin
|
|
n := True;
|
|
for i := low(Param) to high(Param) do
|
|
n := n and v2b(Param[i]);
|
|
Result := n;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoTrue(var Param: TOpParam): Variant;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoFalse(var Param: TOpParam): Variant;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoRColor(var Param: TOpParam): Variant;
|
|
var
|
|
buff: array [0 .. 3] of SystemString;
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to 2 do
|
|
buff[i] := '0.0';
|
|
buff[3] := '1.0';
|
|
|
|
for i := Low(Param) to high(Param) do
|
|
buff[i] := VarToStr(Param[i]);
|
|
|
|
Result := Format('RColor(%s,%s,%s,%s)', [buff[0], buff[1], buff[2], buff[3]]);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoVec2(var Param: TOpParam): Variant;
|
|
var
|
|
buff: array [0 .. 1] of SystemString;
|
|
i: Integer;
|
|
begin
|
|
for i := Low(buff) to high(buff) do
|
|
buff[i] := '0.0';
|
|
|
|
for i := Low(Param) to high(Param) do
|
|
buff[i] := VarToStr(Param[i]);
|
|
|
|
Result := Format('Vec2(%s,%s)', [buff[0], buff[1]]);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoVec3(var Param: TOpParam): Variant;
|
|
var
|
|
buff: array [0 .. 2] of SystemString;
|
|
i: Integer;
|
|
begin
|
|
for i := Low(buff) to high(buff) do
|
|
buff[i] := '0.0';
|
|
|
|
for i := Low(Param) to high(Param) do
|
|
buff[i] := VarToStr(Param[i]);
|
|
|
|
Result := Format('Vec3(%s,%s,%s)', [buff[0], buff[1], buff[2]]);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoVec4(var Param: TOpParam): Variant;
|
|
var
|
|
buff: array [0 .. 3] of SystemString;
|
|
i: Integer;
|
|
begin
|
|
for i := Low(buff) to high(buff) do
|
|
buff[i] := '0.0';
|
|
|
|
for i := Low(Param) to high(Param) do
|
|
buff[i] := VarToStr(Param[i]);
|
|
|
|
Result := Format('Vec4(%s,%s,%s,%s)', [buff[0], buff[1], buff[2], buff[3]]);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoRandom(var Param: TOpParam): Variant;
|
|
var
|
|
v: Integer;
|
|
i: Integer;
|
|
begin
|
|
v := 0;
|
|
for i := low(Param) to high(Param) do
|
|
v := v + Param[i];
|
|
|
|
if v <> 0 then
|
|
Result := MT19937Rand32(v)
|
|
else
|
|
Result := MT19937Rand32(MaxInt);
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoRandomFloat(var Param: TOpParam): Variant;
|
|
begin
|
|
Result := MT19937RandF;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoMax(var Param: TOpParam): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if length(Param) = 0 then
|
|
begin
|
|
Result := NULL;
|
|
Exit;
|
|
end;
|
|
Result := Param[0];
|
|
for i := 1 to length(Param) - 1 do
|
|
if Param[i] > Result then
|
|
Result := Param[i];
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoMin(var Param: TOpParam): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if length(Param) = 0 then
|
|
begin
|
|
Result := NULL;
|
|
Exit;
|
|
end;
|
|
Result := Param[0];
|
|
for i := 1 to length(Param) - 1 do
|
|
if Param[i] < Result then
|
|
Result := Param[i];
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoClamp(var Param: TOpParam): Variant;
|
|
var
|
|
minv_, maxv_: Variant;
|
|
begin
|
|
if length(Param) <> 3 then
|
|
begin
|
|
if length(Param) > 0 then
|
|
Result := Param[0]
|
|
else
|
|
Result := NULL;
|
|
Exit;
|
|
end;
|
|
|
|
if Param[1] > Param[2] then
|
|
begin
|
|
minv_ := Param[2];
|
|
maxv_ := Param[1];
|
|
end
|
|
else
|
|
begin
|
|
minv_ := Param[1];
|
|
maxv_ := Param[2];
|
|
end;
|
|
|
|
if Param[0] < minv_ then
|
|
Result := minv_
|
|
else if Param[0] > maxv_ then
|
|
Result := maxv_
|
|
else
|
|
Result := Param[0];
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoIfThen(var Param: TOpParam): Variant;
|
|
begin
|
|
if length(Param) <> 3 then
|
|
begin
|
|
Result := NULL;
|
|
Exit;
|
|
end;
|
|
if Boolean(Param[0]) = True then
|
|
Result := Param[1]
|
|
else
|
|
Result := Param[2];
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoStr(var Param: TOpParam): Variant;
|
|
var
|
|
n: TPascalString;
|
|
i: Integer;
|
|
begin
|
|
n := '';
|
|
for i := low(Param) to high(Param) do
|
|
n.Append(VarToStr(Param[i]));
|
|
Result := n;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoGetFirst(var Param: TOpParam): Variant;
|
|
begin
|
|
if length(Param) = 2 then
|
|
Result := umlGetFirstStr(VarToStr(Param[0]), VarToStr(Param[1])).Text
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoDeleteFirst(var Param: TOpParam): Variant;
|
|
begin
|
|
if length(Param) = 2 then
|
|
Result := umlDeleteFirstStr(VarToStr(Param[0]), VarToStr(Param[1])).Text
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoGetLast(var Param: TOpParam): Variant;
|
|
begin
|
|
if length(Param) = 2 then
|
|
Result := umlGetLastStr(VarToStr(Param[0]), VarToStr(Param[1])).Text
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoDeleteLast(var Param: TOpParam): Variant;
|
|
begin
|
|
if length(Param) = 2 then
|
|
Result := umlDeleteLastStr(VarToStr(Param[0]), VarToStr(Param[1])).Text
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoMultiple(var Param: TOpParam): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if length(Param) >= 2 then
|
|
begin
|
|
Result := True;
|
|
for i := 1 to length(Param) - 1 do
|
|
Result := Result and umlMultipleMatch(VarToStr(Param[0]), VarToStr(Param[i]));
|
|
end
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
function TOpCustomRunTime.DoPrint(var Param: TOpParam): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := low(Param) to high(Param) do
|
|
begin
|
|
DoStatusNoLn(Param[i]);
|
|
if i < high(Param) then
|
|
DoStatusNoLn(#32);
|
|
end;
|
|
|
|
DoStatusNoLn;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TOpCustomRunTime.InternalReg;
|
|
begin
|
|
ProcList.OnFreePtr := {$IFDEF FPC}@{$ENDIF FPC}FreeNotifyProc;
|
|
RegOpM('Int', 'Int(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoInt)^.Category := 'Base Math';
|
|
RegOpM('Frac', 'Frac(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoFrac)^.Category := 'Base Math';
|
|
RegOpM('Exp', 'Exp(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoExp)^.Category := 'Base Math';
|
|
RegOpM('Cos', 'Cos(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoCos)^.Category := 'Base Math';
|
|
RegOpM('Sin', 'Sin(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoSin)^.Category := 'Base Math';
|
|
RegOpM('Ln', 'Ln(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoLn)^.Category := 'Base Math';
|
|
RegOpM('ArcTan', 'ArcTan(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoArcTan)^.Category := 'Base Math';
|
|
RegOpM('Sqrt', 'Sqrt(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoSqrt)^.Category := 'Base Math';
|
|
RegOpM('Sqr', 'Sqr(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoSqr)^.Category := 'Base Math';
|
|
RegOpM('Tan', 'Tan(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoTan)^.Category := 'Base Math';
|
|
RegOpM('Round', 'Round(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoRound)^.Category := 'Base Math';
|
|
RegOpM('Trunc', 'Trunc(0..n): math function', {$IFDEF FPC}@{$ENDIF FPC}DoTrunc)^.Category := 'Base Math';
|
|
RegOpM('Deg', 'Deg(0..n): NormalizeDegAngle function', {$IFDEF FPC}@{$ENDIF FPC}DoDeg)^.Category := 'Base Math';
|
|
RegOpM('Power', 'Power(float,float): Power: Raise base to any power function', {$IFDEF FPC}@{$ENDIF FPC}DoPower)^.Category := 'Base Math';
|
|
|
|
RegOpM('PI', 'PI(): return PI', {$IFDEF FPC}@{$ENDIF FPC}DoPI)^.Category := 'Base Math';
|
|
|
|
RegOpM('Bool', 'Bool(n..n): convert any variant as bool', {$IFDEF FPC}@{$ENDIF FPC}DoBool)^.Category := 'Base Math';
|
|
RegOpM('Boolean', 'Boolean(n..n): convert any variant as bool', {$IFDEF FPC}@{$ENDIF FPC}DoBool)^.Category := 'Base Math';
|
|
|
|
RegOpM('True', 'True(): return true', {$IFDEF FPC}@{$ENDIF FPC}DoTrue)^.Category := 'Base Math';
|
|
RegOpM('False', 'False(): return false', {$IFDEF FPC}@{$ENDIF FPC}DoFalse)^.Category := 'Base Math';
|
|
|
|
RegOpM('RColor', 'RColor(R,G,B,A): return RColor string', {$IFDEF FPC}@{$ENDIF FPC}DoRColor)^.Category := 'Base Math';
|
|
RegOpM('Vec2', 'Vec2(X,Y): return Vec2 string', {$IFDEF FPC}@{$ENDIF FPC}DoVec2)^.Category := 'Base Math';
|
|
RegOpM('Vec3', 'Vec3(X,Y,Z): return Vec3 string', {$IFDEF FPC}@{$ENDIF FPC}DoVec3)^.Category := 'Base Math';
|
|
RegOpM('Vec4', 'Vec4(X,Y,Z,W): return Vec4 string', {$IFDEF FPC}@{$ENDIF FPC}DoVec4)^.Category := 'Base Math';
|
|
|
|
RegOpM('Random', 'Random(0..n): return number', {$IFDEF FPC}@{$ENDIF FPC}DoRandom)^.Category := 'Base Math';
|
|
RegOpM('RandomFloat', 'RandomFloat(): return float', {$IFDEF FPC}@{$ENDIF FPC}DoRandomFloat)^.Category := 'Base Math';
|
|
RegOpM('RandomF', 'RandomF(): return float', {$IFDEF FPC}@{$ENDIF FPC}DoRandomFloat)^.Category := 'Base Math';
|
|
|
|
RegOpM('Max', 'Max(0..n): return max value', {$IFDEF FPC}@{$ENDIF FPC}DoMax)^.Category := 'Base Math';
|
|
RegOpM('Min', 'Min(0..n): return min value', {$IFDEF FPC}@{$ENDIF FPC}DoMin)^.Category := 'Base Math';
|
|
RegOpM('Clamp', 'Clamp(value, min, max): return clamp value', {$IFDEF FPC}@{$ENDIF FPC}DoClamp)^.Category := 'Base Math';
|
|
RegOpM('IfThen', 'IfThen(bool, if true then of value, if false then of value): return if value', {$IFDEF FPC}@{$ENDIF FPC}DoIfThen)^.Category := 'Base Math';
|
|
|
|
RegOpM('Str', 'Str(n..n): convert any variant as string', {$IFDEF FPC}@{$ENDIF FPC}DoStr)^.Category := 'Base String';
|
|
RegOpM('Base String', 'String(n..n): convert any variant as string', {$IFDEF FPC}@{$ENDIF FPC}DoStr)^.Category := 'Base String';
|
|
RegOpM('Text', 'Text(n..n): convert any variant as string', {$IFDEF FPC}@{$ENDIF FPC}DoStr)^.Category := 'Base String';
|
|
|
|
RegOpM('GetFirst', 'GetFirst(string, split Char): return first split segment', {$IFDEF FPC}@{$ENDIF FPC}DoGetFirst)^.Category := 'Base String';
|
|
RegOpM('First', 'First(string, split Char): return first split segment', {$IFDEF FPC}@{$ENDIF FPC}DoGetFirst)^.Category := 'Base String';
|
|
RegOpM('DeleteFirst', 'DeleteFirst(string, split Char): return removed at after first split segment of value', {$IFDEF FPC}@{$ENDIF FPC}DoDeleteFirst)^.Category := 'Base String';
|
|
RegOpM('GetLast', 'GetLast(string, split Char): return last split segment', {$IFDEF FPC}@{$ENDIF FPC}DoGetLast)^.Category := 'Base String';
|
|
RegOpM('Last', 'Last(string, split Char): return last split segment', {$IFDEF FPC}@{$ENDIF FPC}DoGetLast)^.Category := 'Base String';
|
|
RegOpM('DeleteLast', 'DeleteLast(string, split Char): return removed at after last split segment of value', {$IFDEF FPC}@{$ENDIF FPC}DoDeleteLast)^.Category := 'Base String';
|
|
|
|
RegOpM('MultipleMatch', 'MultipleMatch(multile exp, n..n): return bool', {$IFDEF FPC}@{$ENDIF FPC}DoMultiple)^.Category := 'Base String';
|
|
RegOpM('Multiple', 'MultipleMatch(multile exp, n..n): return bool', {$IFDEF FPC}@{$ENDIF FPC}DoMultiple)^.Category := 'Base String';
|
|
|
|
RegOpM('Print', 'Print(n..n): output to console', {$IFDEF FPC}@{$ENDIF FPC}DoPrint)^.Category := 'Base String';
|
|
RegOpM('DoStatus', 'DoStatus(n..n): output to console', {$IFDEF FPC}@{$ENDIF FPC}DoPrint)^.Category := 'Base String';
|
|
end;
|
|
|
|
constructor TOpCustomRunTime.Create;
|
|
begin
|
|
CustomCreate(512);
|
|
end;
|
|
|
|
constructor TOpCustomRunTime.CustomCreate(maxHashLen: Integer);
|
|
begin
|
|
inherited Create;
|
|
ProcList := THashList.CustomCreate(maxHashLen);
|
|
ProcList.AutoFreeData := True;
|
|
|
|
Trigger := nil;
|
|
|
|
UserObject := nil;
|
|
UserData := nil;
|
|
|
|
InternalReg;
|
|
end;
|
|
|
|
destructor TOpCustomRunTime.Destroy;
|
|
begin
|
|
DisposeObject(ProcList);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TOpCustomRunTime.GetProcDescription(ProcName: SystemString): SystemString;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
Result := ProcName + '(): no Descripion';
|
|
p := ProcList[ProcName];
|
|
if p <> nil then
|
|
if p^.Description <> '' then
|
|
Result := p^.Description;
|
|
end;
|
|
|
|
function TOpCustomRunTime.GetAllProcDescription(): TPascalStringList;
|
|
begin
|
|
Result := GetAllProcDescription('*');
|
|
end;
|
|
|
|
function TOpCustomRunTime.GetAllProcDescription(Category: U_String): TPascalStringList;
|
|
var
|
|
arry: THashDataArray;
|
|
hl: THashObjectList;
|
|
ns, tmp: TPascalStringList;
|
|
|
|
i, j: Integer;
|
|
p: POpRTData;
|
|
n: TPascalString;
|
|
begin
|
|
Result := TPascalStringList.Create;
|
|
arry := ProcList.GetHashDataArray();
|
|
|
|
hl := THashObjectList.CustomCreate(True, 256);
|
|
for i := Low(arry) to High(arry) do
|
|
begin
|
|
p := arry[i]^.Data;
|
|
if not hl.Exists(p^.Category) then
|
|
hl.FastAdd(p^.Category, TPascalStringList.Create);
|
|
tmp := hl[p^.Category] as TPascalStringList;
|
|
|
|
if p^.Description <> '' then
|
|
n := p^.Description
|
|
else
|
|
n := p^.Name + '(): no Descripion';
|
|
|
|
tmp.Add(n);
|
|
end;
|
|
SetLength(arry, 0);
|
|
|
|
ns := TPascalStringList.Create;
|
|
hl.GetListData(ns);
|
|
for i := 0 to ns.Count - 1 do
|
|
if umlMultipleMatch(Category, ns[i]) then
|
|
begin
|
|
Result.Add(PFormat('%s:', [ns[i].Text]));
|
|
tmp := ns.Objects[i] as TPascalStringList;
|
|
for j := 0 to tmp.Count - 1 do
|
|
Result.Add(' ' + tmp[j]);
|
|
Result.Add('');
|
|
end;
|
|
n := '';
|
|
DisposeObject(ns);
|
|
DisposeObject(hl);
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegOpC(ProcName: SystemString; OnProc: TOnOpCall): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.OnOpCall := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegOpC(ProcName, ProcDescription: SystemString; OnProc: TOnOpCall): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.Description := ProcDescription;
|
|
p^.OnOpCall := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegOpM(ProcName: SystemString; OnProc: TOnOpMethod): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.OnOpMethod := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegOpM(ProcName, ProcDescription: SystemString; OnProc: TOnOpMethod): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.Description := ProcDescription;
|
|
p^.OnOpMethod := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegObjectOpC(ProcName: SystemString; OnProc: TOnObjectOpCall): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.OnObjectOpCall := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegObjectOpC(ProcName, ProcDescription: SystemString; OnProc: TOnObjectOpCall): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.Description := ProcDescription;
|
|
p^.OnObjectOpCall := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegObjectOpM(ProcName: SystemString; OnProc: TOnObjectOpMethod): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.OnObjectOpMethod := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegObjectOpM(ProcName, ProcDescription: SystemString; OnProc: TOnObjectOpMethod): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.Description := ProcDescription;
|
|
p^.OnObjectOpMethod := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegOpP(ProcName: SystemString; OnProc: TOnOpProc): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.OnOpProc := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegOpP(ProcName, ProcDescription: SystemString; OnProc: TOnOpProc): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.Description := ProcDescription;
|
|
p^.OnOpProc := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegObjectOpP(ProcName: SystemString; OnProc: TOnObjectOpProc): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.OnObjectOpProc := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCustomRunTime.RegObjectOpP(ProcName, ProcDescription: SystemString; OnProc: TOnObjectOpProc): POpRTData;
|
|
var
|
|
p: POpRTData;
|
|
begin
|
|
new(p);
|
|
p^.Init;
|
|
p^.Name := ProcName;
|
|
p^.Description := ProcDescription;
|
|
p^.OnObjectOpProc := OnProc;
|
|
ProcList.Add(ProcName, p, True);
|
|
Result := p;
|
|
end;
|
|
|
|
function TOpCode.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := NULL;
|
|
end;
|
|
|
|
function TOpCode.GetParam(index: Integer): POpData;
|
|
begin
|
|
Result := FParam[index];
|
|
end;
|
|
|
|
procedure TOpCode.EvaluateParam(opRT: TOpCustomRunTime);
|
|
begin
|
|
EvaluateParam(False, opRT);
|
|
end;
|
|
|
|
procedure TOpCode.EvaluateParam(printLog: Boolean; opRT: TOpCustomRunTime);
|
|
var
|
|
i: Integer;
|
|
p: POpData;
|
|
begin
|
|
for i := 0 to FParam.Count - 1 do
|
|
begin
|
|
p := FParam[i];
|
|
if p^.Op <> nil then
|
|
begin
|
|
try
|
|
p^.Op.EvaluateParam(printLog, opRT);
|
|
except
|
|
end;
|
|
|
|
try
|
|
p^.Value := p^.Op.DoExecute(opRT);
|
|
|
|
if printLog then
|
|
DoStatus('%s value:%s', [ClassName, VarToStr(p^.Value)]);
|
|
except
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TOpCode.Create(AFreeLink: Boolean);
|
|
begin
|
|
inherited Create;
|
|
Owner := nil;
|
|
FParam := TCoreClassList.Create;
|
|
FAutoFreeLink := AFreeLink;
|
|
ParsedInfo := '';
|
|
ParsedLineNo := 0;
|
|
end;
|
|
|
|
destructor TOpCode.Destroy;
|
|
var
|
|
i: Integer;
|
|
p: POpData;
|
|
begin
|
|
if FParam <> nil then
|
|
begin
|
|
for i := 0 to FParam.Count - 1 do
|
|
begin
|
|
p := FParam[i];
|
|
if (FAutoFreeLink) and (p^.Op <> nil) then
|
|
DisposeObject(p^.Op);
|
|
Dispose(p);
|
|
end;
|
|
FParam.Clear;
|
|
DisposeObject(FParam);
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TOpCode.SaveToStream(stream: TCoreClassStream);
|
|
procedure SaveToDataFrame(Op: TOpCode; CurDataEng: TDataFrameEngine);
|
|
var
|
|
i: Integer;
|
|
p: POpData;
|
|
newDataEng: TDataFrameEngine;
|
|
begin
|
|
CurDataEng.WriteString(Op.ClassName);
|
|
CurDataEng.WriteString(Op.ParsedInfo);
|
|
CurDataEng.WriteInteger(Op.ParsedLineNo);
|
|
CurDataEng.WriteInteger(Op.Count);
|
|
for i := 0 to Op.Count - 1 do
|
|
begin
|
|
p := Op[i];
|
|
if p^.Op <> nil then
|
|
begin
|
|
CurDataEng.WriteBool(True);
|
|
newDataEng := TDataFrameEngine.Create;
|
|
SaveToDataFrame(p^.Op, newDataEng);
|
|
CurDataEng.WriteDataFrame(newDataEng);
|
|
DisposeObject(newDataEng);
|
|
end
|
|
else
|
|
begin
|
|
CurDataEng.WriteBool(False);
|
|
CurDataEng.WriteVariant(p^.Value);
|
|
CurDataEng.WriteInteger(Integer(p^.ValueType));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
DataEng: TDataFrameEngine;
|
|
begin
|
|
DataEng := TDataFrameEngine.Create;
|
|
DataEng.WriteInteger(1);
|
|
SaveToDataFrame(Self, DataEng);
|
|
DataEng.EncodeTo(stream, True);
|
|
DisposeObject(DataEng);
|
|
end;
|
|
|
|
class function TOpCode.LoadFromStream(stream: TCoreClassStream; out LoadedOp: TOpCode): Boolean;
|
|
begin
|
|
Result := LoadOpFromStream(stream, LoadedOp);
|
|
end;
|
|
|
|
function TOpCode.AddValue(v: Variant): Integer;
|
|
var
|
|
p: POpData;
|
|
begin
|
|
new(p);
|
|
p^.Op := nil;
|
|
|
|
p^.Value := v;
|
|
|
|
case VarType(v) of
|
|
varSmallInt: p^.ValueType := ovtSmallInt;
|
|
varInteger: p^.ValueType := ovtInt;
|
|
varSingle: p^.ValueType := ovtSingle;
|
|
varDouble: p^.ValueType := ovtDouble;
|
|
varCurrency: p^.ValueType := ovtCurrency;
|
|
varBoolean: p^.ValueType := ovtBool;
|
|
varShortInt: p^.ValueType := ovtShortInt;
|
|
varByte: p^.ValueType := ovtByte;
|
|
varWord: p^.ValueType := ovtWord;
|
|
varLongWord: p^.ValueType := ovtUInt;
|
|
varInt64: p^.ValueType := ovtInt64;
|
|
varUInt64: p^.ValueType := ovtUInt64;
|
|
else
|
|
begin
|
|
if VarIsStr(v) then
|
|
p^.ValueType := ovtString
|
|
else
|
|
p^.ValueType := ovtUnknow;
|
|
end;
|
|
end;
|
|
|
|
Result := FParam.Add(p);
|
|
end;
|
|
|
|
function TOpCode.AddValueT(v: Variant; VT: TOpValueType): Integer;
|
|
var
|
|
p: POpData;
|
|
begin
|
|
new(p);
|
|
p^.Op := nil;
|
|
p^.Value := v;
|
|
p^.ValueType := VT;
|
|
Result := FParam.Add(p);
|
|
end;
|
|
|
|
function TOpCode.AddLink(Obj: TOpCode): Integer;
|
|
var
|
|
p: POpData;
|
|
begin
|
|
new(p);
|
|
|
|
if Obj.Owner <> nil then
|
|
p^.Op := Obj.CloneNewSelf
|
|
else
|
|
p^.Op := Obj;
|
|
|
|
p^.Op.Owner := Self;
|
|
|
|
p^.Value := NULL;
|
|
p^.ValueType := ovtUnknow;
|
|
Result := FParam.Add(p);
|
|
end;
|
|
|
|
function TOpCode.CloneNewSelf: TOpCode;
|
|
var
|
|
i: Integer;
|
|
p: POpData;
|
|
begin
|
|
Result := opClass(Self.ClassType).Create(True);
|
|
Result.ParsedInfo := Self.ParsedInfo;
|
|
Result.ParsedLineNo := Self.ParsedLineNo;
|
|
|
|
for i := 0 to FParam.Count - 1 do
|
|
begin
|
|
p := FParam[i];
|
|
if p^.Op <> nil then
|
|
Result.AddLink(p^.Op.CloneNewSelf)
|
|
else
|
|
Result.AddValueT(p^.Value, p^.ValueType);
|
|
end;
|
|
end;
|
|
|
|
function TOpCode.Count: Integer;
|
|
begin
|
|
Result := FParam.Count;
|
|
end;
|
|
|
|
function TOpCode.Execute: Variant;
|
|
begin
|
|
Result := Execute(DefaultOpRT);
|
|
end;
|
|
|
|
function TOpCode.Execute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
try
|
|
EvaluateParam(opRT);
|
|
except
|
|
Result := NULL;
|
|
Exit;
|
|
end;
|
|
|
|
try
|
|
Result := DoExecute(opRT);
|
|
except
|
|
Result := NULL;
|
|
end;
|
|
end;
|
|
|
|
function TOpCode.OwnerRoot: TOpCode;
|
|
begin
|
|
if Owner = nil then
|
|
Result := Self
|
|
else
|
|
Result := Owner.OwnerRoot;
|
|
end;
|
|
|
|
{ op_Value }
|
|
|
|
function op_Value.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value;
|
|
end;
|
|
|
|
{ op_Proc }
|
|
function op_Proc.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
p: POpRTData;
|
|
i: Integer;
|
|
begin
|
|
Result := NULL;
|
|
if (opRT = nil) then
|
|
opRT := DefaultOpRT;
|
|
|
|
p := opRT.ProcList[VarToStr(Param[0]^.Value)];
|
|
if p = nil then
|
|
begin
|
|
if opRT = DefaultOpRT then
|
|
Exit;
|
|
p := DefaultOpRT.ProcList[VarToStr(Param[0]^.Value)];
|
|
if p = nil then
|
|
Exit;
|
|
end;
|
|
|
|
if length(p^.Param) <> Count - 1 then
|
|
SetLength(p^.Param, Count - 1);
|
|
|
|
for i := 1 to Count - 1 do
|
|
p^.Param[i - 1] := Param[i]^.Value;
|
|
|
|
opRT.Trigger := p;
|
|
|
|
if Assigned(p^.OnOpCall) then
|
|
Result := p^.OnOpCall(p^.Param);
|
|
if Assigned(p^.OnOpMethod) then
|
|
Result := p^.OnOpMethod(p^.Param);
|
|
if Assigned(p^.OnObjectOpCall) then
|
|
Result := p^.OnObjectOpCall(opRT, p^.Param);
|
|
if Assigned(p^.OnObjectOpMethod) then
|
|
Result := p^.OnObjectOpMethod(opRT, p^.Param);
|
|
if Assigned(p^.OnOpProc) then
|
|
Result := p^.OnOpProc(p^.Param);
|
|
if Assigned(p^.OnObjectOpProc) then
|
|
Result := p^.OnObjectOpProc(opRT, p^.Param);
|
|
end;
|
|
|
|
{ op_Add_Prefix }
|
|
|
|
function op_Add_Prefix.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result + Param[i]^.Value;
|
|
Result := - - Result;
|
|
end;
|
|
|
|
{ op_Sub_Prefix }
|
|
|
|
function op_Sub_Prefix.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result + Param[i]^.Value;
|
|
Result := -Result;
|
|
end;
|
|
|
|
{ op_Add }
|
|
|
|
function op_Add.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
|
|
function Fast_VarIsStr(var v: Variant): Boolean; {$IFDEF INLINE_ASM} inline; {$ENDIF}
|
|
var
|
|
p: pVarData;
|
|
begin
|
|
// optimized
|
|
p := @TVarData(v);
|
|
while p^.VType = varByRef or varVariant do
|
|
p := pVarData(p^.VPointer);
|
|
Result := (p^.VType = varOleStr) or (p^.VType = varString) or (p^.VType = varUString);
|
|
end;
|
|
|
|
var
|
|
i: Integer;
|
|
n1, n2: TPascalString;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
|
|
if Fast_VarIsStr(Result) then
|
|
begin
|
|
// optimized
|
|
n1 := VarToStr(Result);
|
|
for i := 1 to Count - 1 do
|
|
begin
|
|
try
|
|
n1.Append(VarToStr(Param[i]^.Value));
|
|
except
|
|
end;
|
|
end;
|
|
Result := n1.Text;
|
|
end
|
|
else
|
|
begin
|
|
for i := 1 to Count - 1 do
|
|
begin
|
|
try
|
|
if Fast_VarIsStr(Result) then
|
|
begin
|
|
// SystemString combine
|
|
n1 := VarToStr(Result);
|
|
if not umlIsNumber(n1) then
|
|
begin
|
|
Result := n1 + VarToStr(Param[i]^.Value);
|
|
Continue;
|
|
end
|
|
end;
|
|
|
|
if Fast_VarIsStr(Param[i]^.Value) then
|
|
begin
|
|
// SystemString combine
|
|
n2 := VarToStr(Param[i]^.Value);
|
|
if not umlIsNumber(n2) then
|
|
begin
|
|
Result := VarToStr(Result) + n2;
|
|
Continue;
|
|
end
|
|
end;
|
|
|
|
// logic compute
|
|
Result := Result + Param[i]^.Value;
|
|
except
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ op_Sub }
|
|
|
|
function op_Sub.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result - Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_Mul }
|
|
|
|
function op_Mul.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result * Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_Div }
|
|
|
|
function op_Div.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result / Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_IntDiv }
|
|
|
|
function op_IntDiv.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result div Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_Pow }
|
|
function op_Pow.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Power(Result, Param[i]^.Value);
|
|
end;
|
|
|
|
{ op_Mod }
|
|
|
|
function op_Mod.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result mod Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_Or }
|
|
|
|
function op_Or.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result or Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_And }
|
|
|
|
function op_And.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result and Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_Xor }
|
|
|
|
function op_Xor.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := Result xor Param[i]^.Value;
|
|
end;
|
|
|
|
{ op_shl }
|
|
|
|
function op_Shl.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := UInt64(Result) shl UInt64(Param[i]^.Value);
|
|
end;
|
|
|
|
{ op_shr }
|
|
|
|
function op_Shr.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Count = 0 then
|
|
Exit(NULL);
|
|
Result := Param[0]^.Value;
|
|
for i := 1 to Count - 1 do
|
|
Result := UInt64(Result) shr UInt64(Param[i]^.Value);
|
|
end;
|
|
|
|
{ op_Equal }
|
|
|
|
function op_Equal.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value = Param[1]^.Value;
|
|
end;
|
|
|
|
{ op_LessThan }
|
|
|
|
function op_LessThan.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value < Param[1]^.Value;
|
|
end;
|
|
|
|
{ op_EqualOrLessThan }
|
|
|
|
function op_EqualOrLessThan.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value <= Param[1]^.Value;
|
|
end;
|
|
|
|
{ op_GreaterThan }
|
|
|
|
function op_GreaterThan.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value > Param[1]^.Value;
|
|
end;
|
|
|
|
{ op_EqualOrGreaterThan }
|
|
|
|
function op_EqualOrGreaterThan.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value >= Param[1]^.Value;
|
|
end;
|
|
|
|
{ op_NotEqual }
|
|
|
|
function op_NotEqual.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value <> Param[1]^.Value;
|
|
end;
|
|
|
|
{ op_Symbol_Sub }
|
|
|
|
function op_Symbol_Sub.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := -Param[0]^.Value;
|
|
end;
|
|
|
|
{ op_Symbol_Add }
|
|
|
|
function op_Symbol_Add.DoExecute(opRT: TOpCustomRunTime): Variant;
|
|
begin
|
|
Result := Param[0]^.Value;
|
|
end;
|
|
|
|
initialization
|
|
|
|
DefaultOpRT := TOpCustomRunTime.Create;
|
|
OleVariantInt64AsDouble := True;
|
|
|
|
OpList := TCoreClassList.Create;
|
|
|
|
RegisterOp(op_Value);
|
|
RegisterOp(op_Proc);
|
|
RegisterOp(op_Add_Prefix);
|
|
RegisterOp(op_Sub_Prefix);
|
|
RegisterOp(op_Add);
|
|
RegisterOp(op_Sub);
|
|
RegisterOp(op_Mul);
|
|
RegisterOp(op_Div);
|
|
RegisterOp(op_IntDiv);
|
|
RegisterOp(op_Mod);
|
|
RegisterOp(op_Or);
|
|
RegisterOp(op_And);
|
|
RegisterOp(op_Xor);
|
|
RegisterOp(op_Shl);
|
|
RegisterOp(op_Shr);
|
|
RegisterOp(op_Equal);
|
|
RegisterOp(op_LessThan);
|
|
RegisterOp(op_EqualOrLessThan);
|
|
RegisterOp(op_GreaterThan);
|
|
RegisterOp(op_EqualOrGreaterThan);
|
|
RegisterOp(op_NotEqual);
|
|
RegisterOp(op_Symbol_Sub);
|
|
RegisterOp(op_Symbol_Add);
|
|
|
|
finalization
|
|
|
|
DisposeObject(DefaultOpRT);
|
|
_FreeOp;
|
|
|
|
end.
|