You've already forked lazarus-ccr
8769 lines
263 KiB
ObjectPascal
8769 lines
263 KiB
ObjectPascal
![]() |
{-----------------------------------------------------------------------------
|
||
|
The contents of this file are subject to the Mozilla Public License
|
||
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
||
|
with the License. You may obtain a copy of the License at
|
||
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
||
|
|
||
|
Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
||
|
the specific language governing rights and limitations under the License.
|
||
|
|
||
|
The Original Code is: JvInterpreter.PAS, released on 2002-07-04.
|
||
|
|
||
|
The Initial Developers of the Original Code are: Andrei Prygounkov <a dott prygounkov att gmx dott de>
|
||
|
Copyright (c) 1999, 2002 Andrei Prygounkov
|
||
|
All Rights Reserved.
|
||
|
|
||
|
Contributor(s): Dmitry Osinovsky, Peter Thornqvist, Olga Kobzar
|
||
|
Peter Schraut (http://www.console-de.de)
|
||
|
Ivan Ravin (ivan_ra)
|
||
|
|
||
|
Portions created by Dmitry Osinovsky and Olga Kobzar are
|
||
|
Copyright (C) 2003 ProgramBank Ltd.
|
||
|
All Rights Reserved.
|
||
|
|
||
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
||
|
located at http://jvcl.delphi-jedi.org
|
||
|
|
||
|
component : JvInterpreterProgram and more..
|
||
|
description : JVCL Interpreter version 2
|
||
|
|
||
|
Known Issues:
|
||
|
String fields in records binded from Delphi don't work
|
||
|
-----------------------------------------------------------------------------}
|
||
|
// $Id$
|
||
|
|
||
|
{ history (JVCL Library versions):
|
||
|
1.10:
|
||
|
- first release;
|
||
|
1.12:
|
||
|
- method HandleException removed as bugged;
|
||
|
- method UpdateExceptionPos now fill error message
|
||
|
with error Unit name and Line pos;
|
||
|
- fixed bug in TJvInterpreterUnit.Assignment method;
|
||
|
- new public property BaseErrLine used in UpdateExceptionPos;
|
||
|
1.17.7:
|
||
|
- local "const" statement for functions;
|
||
|
- global variables and constants - scope on all units - not normal !;
|
||
|
- OnGetValue and OnSetValue now called before call to Adapter;
|
||
|
- fixed bug with "Break" statement inside "for" loop;
|
||
|
1.17.10:
|
||
|
- fixed(?) bug with "begin/end" statement in "else" part of "if" statement;
|
||
|
- fixed few bugs in ole automation support;
|
||
|
1.21.2 (RALib 1.21 Update 2):
|
||
|
- fixed bug with multiple external functions defintions
|
||
|
(greetings to Peter Fischer-Haaser)
|
||
|
- fixed AV-bug in TJvInterpreterFunction.InFunction if errors in source occurred
|
||
|
(greetings to Andre N Belokon)
|
||
|
1.21.4 (RALib 1.21 Update 4):
|
||
|
- fixed bugs in "if" and "while" with "begin" statements;
|
||
|
- "div" and "mod" now working;
|
||
|
1.21.6 (RALib 1.21 Update 6):
|
||
|
- fixed bug with incorrect error line and unit name if erorr
|
||
|
occurred in used unit
|
||
|
(greetings to Dmitry Mokrushin)
|
||
|
- add parameters check (not fully functional - only count checked)
|
||
|
in source fucntion calls;
|
||
|
1.31.2 (RALib 1.31 Update 2):
|
||
|
- fixed bug: sometimes compare-operators ('=', '>', ...)
|
||
|
in expressions do not working.
|
||
|
1.31.4 (RALib 1.31 Update 4):
|
||
|
- fixed bug: plus and minus operators after symbol ']' not working.
|
||
|
1.31.5 (RALib 1.31 Update 5):
|
||
|
- function Statement1 is changed; this remove many bugs and add new ones.
|
||
|
- fixed many bug in exception handling statements and in nested
|
||
|
"begin/end" statements;
|
||
|
- fixed error with source function with TObject (and descendants)
|
||
|
returning values;
|
||
|
1.41.1:
|
||
|
- another fix for bug with incorrect error line and unit name
|
||
|
if erorr occurred in used unit;
|
||
|
- fixed bug with "Break" statement;
|
||
|
- "exit" statement;
|
||
|
- "repeat" loop;
|
||
|
1.50:
|
||
|
- behavior of "UseGlobalAdapter" property was changed; in previous versions
|
||
|
each TJvInterpreterExpression component creates its own copy of GlobalAdapter and
|
||
|
then manage it own copy, but now TJvInterpreterExpression manages two adapters:
|
||
|
own and global, so GlobalJvInterpreterAdapter now is used by all TJvInterpreterExpressions;
|
||
|
performance of "Compile" function increased (there is no necessity
|
||
|
more to Assign adapters) (20 msec on my machine with JvInterpreter_all unit)
|
||
|
and memory requirement decreased;
|
||
|
- sorting in TJvInterpreterAdapter dramatically increase its performance speed;
|
||
|
- fixed bug in "except/on" statement;
|
||
|
1.51:
|
||
|
- arrays as local and global variables. supports simple types (Integer,
|
||
|
double, string, tdatetime, object).
|
||
|
Added by Andrej Olejnik (olej att asset dott sk);
|
||
|
- type conversion with Integer, string, TObject,... keywords;
|
||
|
1.51.2:
|
||
|
- array support was rewritten;
|
||
|
enhanced indexes support: default indexed properties,
|
||
|
access to chars in strings. Many changes are made to make this possible:
|
||
|
new methods: GetElement, SetElement;
|
||
|
- record support is simplified;
|
||
|
- new property TJvInterpreterExpression.Error provide extended error information
|
||
|
about non-interpreter errors.
|
||
|
- "case" statement; not fully implemented - only one expression for one block.
|
||
|
1.52:
|
||
|
- TJvInterpreterExpression.JvInterpreterAdapter property renamed to Adapter;
|
||
|
- new public property TJvInterpreterExpression.SharedAdapter, setting to
|
||
|
GlobalJvInterpreterAdapter by default. This allows to create set of global adapters,
|
||
|
shared between TJvInterpreterExpression components;
|
||
|
- property TJvInterpreterExpression.GlobalAdapter removed; setting SharedAdapter
|
||
|
to nil has same effect as GlobalAdapter := False;
|
||
|
- fixed memory bug in event handling;
|
||
|
- new: unit name in uses list can be placed in quotes and contains any symbols;
|
||
|
- fixed bug: selector in case-statement not working with variables (only constants)
|
||
|
1.53:
|
||
|
- fixed bug: "Type mistmatch error" in expressions with OleAutomation objects;
|
||
|
- fixed bug: error while assign function's result to object's published property;
|
||
|
- call to external functions (placed in dll) in previous versions always
|
||
|
return Integer, now it can return Boolean, if declared so;
|
||
|
1.54:
|
||
|
- new: in call to external function var-parameters are supported for
|
||
|
Integer type;
|
||
|
- new: after call to external function (placed in dll) last win32 error
|
||
|
is restored correctly; in previous versions it was overriden by call to
|
||
|
FreeLibrary;
|
||
|
- fixed bug: memory leak: global variables and constants not allways be freed;
|
||
|
1.60:
|
||
|
- bug fixed in case-statement;
|
||
|
- new: global variables and constants in different units now can have
|
||
|
identical names;
|
||
|
- new: constants, variables and functions can have prefix with unit name
|
||
|
and point to determine appropriate unit;
|
||
|
- new: class declaration for forms (needed for TJvInterpreterFm component);
|
||
|
- bug fixed: record variables do not work;
|
||
|
1.61:
|
||
|
- bug fixed: variable types are not always kept the same when
|
||
|
assigning values to them;
|
||
|
thanks to Ritchie Annand (RitchieA att malibugroup dott com);
|
||
|
- bug fixed: exceptions, raised in dll calls produce AV.
|
||
|
fix: exception of class Exception is raised.
|
||
|
- new internal: LocalVars property in TJvInterpreterFunction (it is used in TJvInterpreterFm).
|
||
|
2.00:
|
||
|
- Delphi 6 compatibility;
|
||
|
- Kylix 1 compatibility;
|
||
|
- exception handling was rewriten in more portable way,
|
||
|
ChangeTopException function is not used anymore;
|
||
|
- fixed bug: intefrace section was not processed correct
|
||
|
(Thanks to Ivan Ravin);
|
||
|
Upcoming JVCL 3.00
|
||
|
- major code cleanups
|
||
|
- introduced data type system for variables and record fields initializations
|
||
|
- interface (IInterface, IUnknown) method call support, see AddIntfGet
|
||
|
- record declaration support
|
||
|
- arrays of records, arrays of arrays
|
||
|
- dynamic arrays
|
||
|
- variant array support
|
||
|
- arrays as parameters to Delphi procedures (sorry, no support for arrays
|
||
|
as procedure parameters)
|
||
|
- fixed record bugs with Delphi 6
|
||
|
- fixed OLE bugs
|
||
|
- (rom) added fix for default properties from ivan_ra 26 Dec 2003
|
||
|
|
||
|
- (wap) fixed bug: memory leak in local-function LeaveFunction, part of
|
||
|
TJvInterpreterFunction.InFunction. See code marker VARLEAKFIX.
|
||
|
(Fix suggested by ivan_ra att mail dott ru)
|
||
|
|
||
|
- bug fixed: exceptions, raised in Assign nil to Method property - dejoy-2004-3-13
|
||
|
- fixed Character '"' error in SkipToEnd from dejoy 2004-5-25;
|
||
|
|
||
|
- peter schraut added shl, shr and xor support
|
||
|
}
|
||
|
|
||
|
unit JvInterpreter;
|
||
|
|
||
|
{$mode Delphi}
|
||
|
|
||
|
{.$DEFINE JvInterpreter_DEBUG}
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
LCLType, LCLIntf, LCLProc, dynlibs,
|
||
|
SysUtils, Classes, Variants,
|
||
|
JvJCLUtils, JvInterpreterParser;
|
||
|
|
||
|
const
|
||
|
// (rom) renamed to longer names
|
||
|
{ max arguments to functions - small values increase performance }
|
||
|
cJvInterpreterMaxArgs = 32;
|
||
|
|
||
|
{ max fields allowed in records }
|
||
|
cJvInterpreterMaxRecFields = 32;
|
||
|
|
||
|
// (rom) added
|
||
|
cJvInterpreterStackMax = 199;
|
||
|
|
||
|
{ Max available dimensions for arrays }
|
||
|
JvInterpreter_MAX_ARRAY_DIMENSION = 10;
|
||
|
|
||
|
type
|
||
|
PBool = ^LongBool;
|
||
|
|
||
|
{$IFNDEF COMPILER12_UP}
|
||
|
// NativeInt = Integer; // also redeclare for Delphi 2007 where it is declared as Int64
|
||
|
{$ENDIF ~COMPILER12_UP}
|
||
|
|
||
|
{ argument definition }
|
||
|
PValueArray = ^TValueArray;
|
||
|
TValueArray = array [0..cJvInterpreterMaxArgs] of Variant;
|
||
|
PTypeArray = ^TTypeArray;
|
||
|
TTypeArray = array [0..cJvInterpreterMaxArgs] of Word;
|
||
|
PNameArray = ^TNameArray;
|
||
|
TNameArray = array [0..cJvInterpreterMaxArgs] of string;
|
||
|
|
||
|
TJvInterpreterArgs = class;
|
||
|
IJvInterpreterDataType = interface;
|
||
|
|
||
|
TJvInterpreterGetValue = procedure(Sender: TObject; Identifier: string; var Value: Variant;
|
||
|
Args: TJvInterpreterArgs; var Done: Boolean) of object;
|
||
|
TJvInterpreterSetValue = procedure(Sender: TObject; Identifier: string;
|
||
|
const Value: Variant; Args: TJvInterpreterArgs; var Done: Boolean) of object;
|
||
|
TJvInterpreterGetUnitSource = procedure(UnitName: string; var Source: string;
|
||
|
var Done: Boolean) of object;
|
||
|
|
||
|
TJvInterpreterAdapterGetValue = procedure(var Value: Variant; Args: TJvInterpreterArgs);
|
||
|
TJvInterpreterAdapterSetValue = procedure(const Value: Variant; Args: TJvInterpreterArgs);
|
||
|
TJvInterpreterAdapterNewRecord = procedure(var Value: Pointer);
|
||
|
TJvInterpreterAdapterDisposeRecord = procedure(const Value: Pointer);
|
||
|
TJvInterpreterAdapterCopyRecord = procedure(var Dest: Pointer; const Source: Pointer);
|
||
|
|
||
|
POpenArray = ^TOpenArray;
|
||
|
TOpenArray = array [0..cJvInterpreterMaxArgs] of TVarRec;
|
||
|
|
||
|
TJvInterpreterRecField = record
|
||
|
Identifier: string;
|
||
|
Offset: Integer;
|
||
|
Typ: Word;
|
||
|
DataType: IJvInterpreterDataType;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterArgs = class(TObject)
|
||
|
private
|
||
|
FVarNames: TNameArray;
|
||
|
FHasVars: Boolean;
|
||
|
{ open array parameter support }
|
||
|
{ allocates memory only if necessary }
|
||
|
FOAV: PValueArray; { open array values }
|
||
|
public
|
||
|
Identifier: string;
|
||
|
Count: Integer;
|
||
|
Types: TTypeArray;
|
||
|
Values: TValueArray;
|
||
|
Names: TNameArray;
|
||
|
HasResult: Boolean; { = False, if result not needed - used by calls
|
||
|
to OLE automation servers }
|
||
|
Assignment: Boolean; { internal }
|
||
|
Obj: TObject;
|
||
|
ObjTyp: Word; { varObject, varClass, varUnknown }
|
||
|
ObjRefHolder: Variant; { if ObjType is varDispatch or varUnknown,
|
||
|
then we need to hold a reference to it }
|
||
|
|
||
|
Indexed: Boolean; // if True then Args contain Indexes to Identifier
|
||
|
ReturnIndexed: Boolean; // established by GetValue function, indicating
|
||
|
// what Args used as indexed (matters only if Indexed = True)
|
||
|
public
|
||
|
{ open array parameter support }
|
||
|
OA: POpenArray; { open array }
|
||
|
OAS: Integer; { open array size }
|
||
|
destructor Destroy; override;
|
||
|
procedure Clear;
|
||
|
procedure OpenArray(const Index: Integer);
|
||
|
procedure Delete(const Index: Integer);
|
||
|
end;
|
||
|
|
||
|
{ function descriptor }
|
||
|
TJvInterpreterFunctionDesc = class(TObject)
|
||
|
private
|
||
|
FUnitName: string;
|
||
|
FIdentifier: string;
|
||
|
FClassIdentifier: string; { class name, if function declared as
|
||
|
TClassIdentifier.Identifier}
|
||
|
FParamCount: Integer; { - 1..cJvInterpreterMaxArgs }
|
||
|
FParamTypes: TTypeArray;
|
||
|
FParamTypeNames: TNameArray;
|
||
|
FParamNames: TNameArray;
|
||
|
FResTyp: Word;
|
||
|
FResTypName: string;
|
||
|
FResDataType: IJvInterpreterDataType;
|
||
|
FPosBeg: Integer; { position in source }
|
||
|
FPosEnd: Integer;
|
||
|
function GetParamName(Index: Integer): string;
|
||
|
function GetParamType(Index: Integer): Word;
|
||
|
function GetParamTypeNames(Index: Integer): string;
|
||
|
function GetDefine: string;
|
||
|
public
|
||
|
{$WARNINGS OFF} // Delphi 2009+ has a class function UnitName
|
||
|
property UnitName: string read FUnitName;
|
||
|
{$WARNINGS ON}
|
||
|
property Identifier: string read FIdentifier;
|
||
|
property ClassIdentifier: string read FClassIdentifier;
|
||
|
property Define: string read GetDefine;
|
||
|
property ParamCount: Integer read FParamCount;
|
||
|
property ParamTypes[Index: Integer]: Word read GetParamType;
|
||
|
property ParamNames[Index: Integer]: string read GetParamName;
|
||
|
property ParamTypeNames[Index: Integer]: string read GetParamTypeNames;
|
||
|
property ResTyp: Word read FResTyp;
|
||
|
property ResTypName: string read FResTypName;
|
||
|
property ResDataType: IJvInterpreterDataType read FResDataType;
|
||
|
property PosBeg: Integer read FPosBeg;
|
||
|
property PosEnd: Integer read FPosEnd;
|
||
|
end;
|
||
|
|
||
|
TSimpleEvent = procedure of object;
|
||
|
TJvInterpreterExpression = class;
|
||
|
EJvInterpreterError = class;
|
||
|
|
||
|
TJvInterpreterEvent = class(TObject)
|
||
|
private
|
||
|
FOwner: TJvInterpreterExpression;
|
||
|
FInstance: TObject;
|
||
|
FUnitName: string;
|
||
|
FFunctionName: string;
|
||
|
FPropName: string;
|
||
|
FArgs: TJvInterpreterArgs;
|
||
|
function GetArgs: TJvInterpreterArgs;
|
||
|
protected
|
||
|
constructor Create(AOwner: TJvInterpreterExpression; AInstance: TObject;
|
||
|
const AUnitName, AFunctionName, APropName: string); virtual;
|
||
|
function CallFunction(Args: TJvInterpreterArgs; Params: array of Variant): Variant;
|
||
|
property Args: TJvInterpreterArgs read GetArgs;
|
||
|
property Owner: TJvInterpreterExpression read FOwner;
|
||
|
property Instance: TObject read FInstance;
|
||
|
{$WARNINGS OFF} // Delphi 2009+ has a class function UnitName
|
||
|
property UnitName: string read FUnitName;
|
||
|
{$WARNINGS ON}
|
||
|
property FunctionName: string read FFunctionName;
|
||
|
property PropName: string read FPropName;
|
||
|
public
|
||
|
destructor Destroy; override;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterEventClass = class of TJvInterpreterEvent;
|
||
|
|
||
|
{ variable holder }
|
||
|
TJvInterpreterVar = class(TObject)
|
||
|
public
|
||
|
UnitName: string;
|
||
|
Identifier: string;
|
||
|
Typ: string;
|
||
|
VTyp: Word;
|
||
|
Value: Variant;
|
||
|
public
|
||
|
destructor Destroy; override;
|
||
|
end;
|
||
|
|
||
|
{ variables list }
|
||
|
TJvInterpreterVarList = class(TList)
|
||
|
public
|
||
|
destructor Destroy; override;
|
||
|
procedure Clear; override;
|
||
|
procedure AddVar(const UnitName, Identifier, Typ: string; VTyp: Word;
|
||
|
const Value: Variant; DataType: IJvInterpreterDataType);
|
||
|
function FindVar(const UnitName, Identifier: string): TJvInterpreterVar;
|
||
|
procedure DeleteVar(const UnitName, Identifier: string);
|
||
|
function GetValue(const Identifier: string; var Value: Variant; Args: TJvInterpreterArgs): Boolean;
|
||
|
function SetValue(const Identifier: string; const Value: Variant; Args: TJvInterpreterArgs): Boolean;
|
||
|
procedure Assign(source: TJvInterpreterVarList);
|
||
|
end;
|
||
|
{ notes about TJvInterpreterVarList implementation:
|
||
|
- list must allow to contain more than one Var with same name;
|
||
|
- FindVar must return last added Var with given name;
|
||
|
- DeleteVar must delete last added Var with given name; }
|
||
|
|
||
|
TJvInterpreterIdentifier = class(TObject)
|
||
|
public
|
||
|
UnitName: string;
|
||
|
Identifier: string;
|
||
|
Data: Pointer; // provided by user when call to adapter's addxxx methods
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterIdentifierList = class(TList)
|
||
|
private
|
||
|
FDuplicates: TDuplicates;
|
||
|
public
|
||
|
function IndexOf(const UnitName, Identifier: string): TJvInterpreterIdentifier;
|
||
|
function Find(const Identifier: string; var Index: Integer): Boolean;
|
||
|
procedure Sort(Compare: TListSortCompare = nil); virtual;
|
||
|
property Duplicates: TDuplicates read FDuplicates write FDuplicates;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterMethodList = class(TJvInterpreterIdentifierList)
|
||
|
public
|
||
|
procedure Sort(Compare: TListSortCompare = nil); override;
|
||
|
end;
|
||
|
|
||
|
IJvInterpreterDataType = interface
|
||
|
['{8C5E4071-65AB-11D7-B235-00A0D2043DC7}']
|
||
|
procedure Init(var V: Variant);
|
||
|
function GetTyp: Word;
|
||
|
end;
|
||
|
|
||
|
//move from implementation section to interface section
|
||
|
TParamCount = -1..cJvInterpreterMaxArgs;
|
||
|
|
||
|
TCallConvention = set of (ccFastCall, ccStdCall, ccCDecl, ccDynamic,
|
||
|
ccVirtual, ccClass);
|
||
|
|
||
|
{ Adapter classes - translates data from JvInterpreter calls to Delphi functions }
|
||
|
TJvInterpreterSrcUnit = class(TJvInterpreterIdentifier)
|
||
|
private
|
||
|
FSource: string;
|
||
|
FUsesList: TNameArray;
|
||
|
public
|
||
|
function UsesList: TNameArray;
|
||
|
property Source: string read FSource;
|
||
|
// Removed because BCB doesn't support it
|
||
|
//property UsesList: TNameArray read FUsesList;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterMethod = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
FClassType: TClass;
|
||
|
ParamCount: TParamCount;
|
||
|
ParamTypes: TTypeArray; { varInteger, varString, .. }
|
||
|
ResTyp: Word; { varInteger, varString, .. }
|
||
|
Func: Pointer; { TJvInterpreterAdapterGetValue or TJvInterpreterAdapterSetValue }
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterIntfMethod = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
IID: TGUID;
|
||
|
ParamCount: TParamCount;
|
||
|
ParamTypes: TTypeArray; { varInteger, varString, .. }
|
||
|
ResTyp: Word; { varInteger, varString, .. }
|
||
|
Func: Pointer; { TJvInterpreterAdapterGetValue or TJvInterpreterAdapterSetValue }
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterDMethod = class(TJvInterpreterMethod)
|
||
|
protected
|
||
|
ResTyp: Word;
|
||
|
CallConvention: TCallConvention;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterClass = class(TJvInterpreterIdentifier)
|
||
|
private
|
||
|
FClassFields:TJvInterpreterVarList;
|
||
|
protected
|
||
|
FClassType: TClass;
|
||
|
public
|
||
|
property ClassFields:TJvInterpreterVarList read FClassFields;
|
||
|
constructor Create;
|
||
|
destructor Destroy; override;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterConst = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
Value: Variant;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterRecFields = array [0..cJvInterpreterMaxRecFields] of TJvInterpreterRecField;
|
||
|
|
||
|
TJvInterpreterRecord = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
RecordSize: Integer; { SizeOf(Rec^) }
|
||
|
FieldCount: Integer;
|
||
|
Fields: TJvInterpreterRecFields;
|
||
|
CreateFunc: TJvInterpreterAdapterNewRecord;
|
||
|
DestroyFunc: TJvInterpreterAdapterDisposeRecord;
|
||
|
CopyFunc: TJvInterpreterAdapterCopyRecord;
|
||
|
procedure AddField(const UnitName, Identifier, Typ: string; VTyp: Word;
|
||
|
const Value: Variant; DataType: IJvInterpreterDataType);
|
||
|
procedure NewRecord(var Value: Variant);
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterRecMethod = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
ParamCount: TParamCount;
|
||
|
ParamTypes: TTypeArray; { varInteger, varString and so one .. }
|
||
|
ResTyp: Word; { varInteger, varString, .. }
|
||
|
Func: Pointer; { TJvInterpreterAdapterGetValue or TJvInterpreterAdapterSetValue }
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterRecHolder = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
FRecordType: string;
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
Rec: Pointer; { data }
|
||
|
public
|
||
|
constructor Create(const ARecordType: string; ARec: Pointer);
|
||
|
destructor Destroy; override;
|
||
|
property RecordType: string read FRecordType;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterArrayValues = array [0..JvInterpreter_MAX_ARRAY_DIMENSION - 1] of Integer;
|
||
|
|
||
|
PJvInterpreterArrayRec = ^TJvInterpreterArrayRec;
|
||
|
TJvInterpreterArrayRec = packed record
|
||
|
Dimension: Integer; {number of dimensions}
|
||
|
BeginPos: TJvInterpreterArrayValues; {starting range for all dimensions}
|
||
|
EndPos: TJvInterpreterArrayValues; {ending range for all dimensions}
|
||
|
ItemType: Integer; {array type}
|
||
|
DT: IJvInterpreterDataType;
|
||
|
ElementSize: Integer; {size of element in bytes}
|
||
|
Size: Integer; {number of elements in array}
|
||
|
Memory: Pointer; {pointer to memory representation of array}
|
||
|
end;
|
||
|
|
||
|
{ interpreter function }
|
||
|
TJvInterpreterSrcFunction = class(TJvInterpreterIdentifier)
|
||
|
private
|
||
|
FFunctionDesc: TJvInterpreterFunctionDesc;
|
||
|
public
|
||
|
constructor Create;
|
||
|
destructor Destroy; override;
|
||
|
property FunctionDesc: TJvInterpreterFunctionDesc read FFunctionDesc; //Move From Private section
|
||
|
end;
|
||
|
|
||
|
{ external function }
|
||
|
TJvInterpreterExtFunction = class(TJvInterpreterSrcFunction)
|
||
|
protected
|
||
|
DllInstance: HINST;
|
||
|
DllName: string;
|
||
|
FunctionName: string;
|
||
|
{or}
|
||
|
FunctionIndex: Integer;
|
||
|
function CallDll(Args: TJvInterpreterArgs): Variant;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterEventDesc = class(TJvInterpreterIdentifier)
|
||
|
protected
|
||
|
EventClass: TJvInterpreterEventClass;
|
||
|
Code: Pointer;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterRecordDataType = class(TInterfacedObject, IJvInterpreterDataType)
|
||
|
protected
|
||
|
FRecordDesc: TJvInterpreterRecord;
|
||
|
public
|
||
|
constructor Create(ARecordDesc: TJvInterpreterRecord);
|
||
|
procedure Init(var V: Variant);
|
||
|
function GetTyp: Word;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterArrayDataType = class(TInterfacedObject, IJvInterpreterDataType)
|
||
|
protected
|
||
|
FArrayBegin, FArrayEnd: TJvInterpreterArrayValues;
|
||
|
FDimension: Integer;
|
||
|
FArrayType: Integer;
|
||
|
FDT: IJvInterpreterDataType;
|
||
|
public
|
||
|
constructor Create(AArrayBegin, AArrayEnd: TJvInterpreterArrayValues;
|
||
|
ADimension: Integer; AArrayType: Integer; ADT: IJvInterpreterDataType);
|
||
|
procedure Init(var V: Variant);
|
||
|
function GetTyp: Word;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterSimpleDataType = class(TInterfacedObject, IJvInterpreterDataType)
|
||
|
protected
|
||
|
FTyp: TVarType;
|
||
|
public
|
||
|
constructor Create(ATyp: TVarType);
|
||
|
procedure Init(var V: Variant);
|
||
|
function GetTyp: Word;
|
||
|
end;
|
||
|
|
||
|
PMethod = ^TMethod;
|
||
|
|
||
|
{ function context - stack }
|
||
|
PFunctionContext = ^TFunctionContext;
|
||
|
TFunctionContext = record
|
||
|
PrevFunContext: PFunctionContext;
|
||
|
LocalVars: TJvInterpreterVarList;
|
||
|
Fun: TJvInterpreterSrcFunction;
|
||
|
end;
|
||
|
|
||
|
{ TJvInterpreterAdapter - route JvInterpreter calls to Delphi functions }
|
||
|
TJvInterpreterAdapter = class(TObject)
|
||
|
private
|
||
|
FOwner: TJvInterpreterExpression;
|
||
|
FSrcUnitList: TJvInterpreterIdentifierList; // JvInterpreter-units sources
|
||
|
FExtUnitList: TJvInterpreterIdentifierList; // internal units; like "system" in delphi
|
||
|
FGetList: TJvInterpreterIdentifierList; // methods
|
||
|
FSetList: TJvInterpreterIdentifierList; // write properties
|
||
|
FIGetList: TJvInterpreterIdentifierList; // read indexed properties
|
||
|
FISetList: TJvInterpreterIdentifierList; // write indexed properties
|
||
|
FIDGetList: TJvInterpreterIdentifierList; // read default indexed properties
|
||
|
FIDSetList: TJvInterpreterIdentifierList; // write default indexed properties
|
||
|
FIntfGetList: TJvInterpreterIdentifierList; // interface methods
|
||
|
FIntfSetList: TJvInterpreterIdentifierList; // interface write properties
|
||
|
FIntfIGetList: TJvInterpreterIdentifierList; // interface read indexed properties
|
||
|
FIntfISetList: TJvInterpreterIdentifierList; // interface write indexed properties
|
||
|
FIntfIDGetList: TJvInterpreterIdentifierList; // interface read default indexed properties
|
||
|
FIntfIDSetList: TJvInterpreterIdentifierList; // interface write default indexed properties
|
||
|
FDirectGetList: TJvInterpreterIdentifierList; // direct get list
|
||
|
FClassList: TJvInterpreterIdentifierList; // delphi classes
|
||
|
FConstList: TJvInterpreterIdentifierList; // delphi consts
|
||
|
FFunctionList: TJvInterpreterIdentifierList; // functions, procedures
|
||
|
FRecordList: TJvInterpreterIdentifierList; // records
|
||
|
FRecordGetList: TJvInterpreterIdentifierList; // read record field
|
||
|
FRecordSetList: TJvInterpreterIdentifierList; // write record field
|
||
|
FOnGetList: TJvInterpreterIdentifierList; // chain
|
||
|
FOnSetList: TJvInterpreterIdentifierList; // chain
|
||
|
FSrcFunctionList: TJvInterpreterIdentifierList; // functions, procedures in JvInterpreter-source
|
||
|
FExtFunctionList: TJvInterpreterIdentifierList;
|
||
|
FEventHandlerList: TJvInterpreterIdentifierList;
|
||
|
FEventList: TJvInterpreterIdentifierList;
|
||
|
FSrcVarList: TJvInterpreterVarList; // variables, constants in JvInterpreter-source
|
||
|
FSrcClassList: TJvInterpreterIdentifierList; // JvInterpreter-source classes
|
||
|
FDisableExternalFunctions: Boolean;
|
||
|
FSorted: Boolean;
|
||
|
procedure CheckArgs(var Args: TJvInterpreterArgs; ParamCount: Integer;
|
||
|
var ParamTypes: TTypeArray);
|
||
|
function GetRec(const RecordType: string): TObject;
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
function DispatchCall(const Identifier: string; var Value: Variant;
|
||
|
Args: TJvInterpreterArgs; Get: Boolean): Boolean; stdcall;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
function GetValueRTTI(const Identifier: string; var Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
function SetValueRTTI(const Identifier: string; const Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
protected
|
||
|
procedure CheckAction(Expression: TJvInterpreterExpression; Args: TJvInterpreterArgs;
|
||
|
Data: Pointer); virtual;
|
||
|
function GetValue(Expression: TJvInterpreterExpression; const Identifier: string;
|
||
|
var Value: Variant; Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function SetValue(Expression: TJvInterpreterExpression; const Identifier: string;
|
||
|
const Value: Variant; Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function GetElement(Expression: TJvInterpreterExpression; const Variable: Variant;
|
||
|
var Value: Variant; var Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function SetElement(Expression: TJvInterpreterExpression; var Variable: Variant;
|
||
|
const Value: Variant; var Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function NewRecord(const RecordType: string; var Value: Variant): Boolean; virtual;
|
||
|
function FindFunDesc(const UnitName, Identifier: string;
|
||
|
const ClassIdentifier:string=''): TJvInterpreterFunctionDesc; virtual;
|
||
|
procedure CurUnitChanged(const NewUnitName: string; var Source: string); virtual;
|
||
|
function UnitExists(const Identifier: string): Boolean; virtual;
|
||
|
function IsEvent(Obj: TObject; const Identifier: string): Boolean; virtual;
|
||
|
function NewEvent(const UnitName, FunctionName, EventType: string;
|
||
|
AOwner: TJvInterpreterExpression; AObject: TObject;
|
||
|
const APropName: string): TSimpleEvent; virtual;
|
||
|
procedure ClearSource; dynamic;
|
||
|
procedure ClearNonSource; dynamic;
|
||
|
procedure Sort; dynamic;
|
||
|
protected
|
||
|
{ for internal use }
|
||
|
procedure AddSrcClass(JvInterpreterSrcClass: TJvInterpreterIdentifier); virtual;
|
||
|
function GetSrcClass(const Identifier: string): TJvInterpreterIdentifier; virtual;
|
||
|
public
|
||
|
constructor Create(AOwner: TJvInterpreterExpression);
|
||
|
destructor Destroy; override;
|
||
|
function SetRecord(var Value: Variant): Boolean; virtual;
|
||
|
procedure Clear; dynamic;
|
||
|
procedure Assign(Source: TJvInterpreterAdapter); dynamic;
|
||
|
procedure AddSrcUnit(const Identifier, Source, UsesList: string); dynamic;
|
||
|
procedure AddSrcUnitEx(const Identifier, Source, UsesList: string;
|
||
|
Data: Pointer); dynamic;
|
||
|
procedure AddExtUnit(const Identifier: string); dynamic;
|
||
|
procedure AddExtUnitEx(const Identifier: string; Data: Pointer); dynamic;
|
||
|
procedure AddClass(const UnitName: string; AClassType: TClass; const Identifier: string); dynamic;
|
||
|
procedure AddClassEx(const UnitName: string; AClassType: TClass; const Identifier: string;
|
||
|
Data: Pointer); dynamic;
|
||
|
procedure AddIntfGet(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word);
|
||
|
procedure AddIntfGetEx(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
procedure AddIntfIGet(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word);
|
||
|
procedure AddIntfIGetEx(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
procedure AddIntfIDGet(IID: TGUID;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word);
|
||
|
procedure AddIntfIDGetEx(IID: TGUID;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
procedure AddGet(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word); dynamic;
|
||
|
procedure AddGetEx(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer); dynamic;
|
||
|
procedure AddSet(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word); dynamic;
|
||
|
procedure AddSetEx(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer); dynamic;
|
||
|
procedure AddIGet(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word); dynamic;
|
||
|
procedure AddIGetEx(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer); dynamic;
|
||
|
procedure AddISet(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word); dynamic;
|
||
|
procedure AddISetEx(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer); dynamic;
|
||
|
procedure AddIDGet(AClassType: TClass;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word); dynamic;
|
||
|
procedure AddIDGetEx(AClassType: TClass;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer); dynamic;
|
||
|
procedure AddIDSet(AClassType: TClass;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word); dynamic;
|
||
|
procedure AddIDSetEx(AClassType: TClass;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer); dynamic;
|
||
|
procedure AddIntfSet(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word);
|
||
|
procedure AddIntfSetEx(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer);
|
||
|
procedure AddIntfISet(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word);
|
||
|
procedure AddIntfISetEx(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer);
|
||
|
procedure AddIntfIDSet(IID: TGUID;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word);
|
||
|
procedure AddIntfIDSetEx(IID: TGUID;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer);
|
||
|
procedure AddFunction(const UnitName, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word); dynamic;
|
||
|
procedure AddFunctionEx(const UnitName, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer); dynamic;
|
||
|
{ function AddDGet under construction - don't use it }
|
||
|
procedure AddDGet(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: Pointer; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; CallConvention: TCallConvention); dynamic;
|
||
|
procedure AddDGetEx(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: Pointer; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; CallConvention: TCallConvention; Data: Pointer); dynamic;
|
||
|
procedure AddRec(const UnitName, Identifier: string; RecordSize: Integer;
|
||
|
Fields: array of TJvInterpreterRecField; CreateFunc: TJvInterpreterAdapterNewRecord;
|
||
|
DestroyFunc: TJvInterpreterAdapterDisposeRecord;
|
||
|
CopyFunc: TJvInterpreterAdapterCopyRecord); dynamic;
|
||
|
procedure AddRecEx(const UnitName, Identifier: string; RecordSize: Integer;
|
||
|
Fields: array of TJvInterpreterRecField; CreateFunc: TJvInterpreterAdapterNewRecord;
|
||
|
DestroyFunc: TJvInterpreterAdapterDisposeRecord; CopyFunc: TJvInterpreterAdapterCopyRecord;
|
||
|
Data: Pointer); dynamic;
|
||
|
procedure AddRecGet(const UnitName, RecordType, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word); dynamic;
|
||
|
procedure AddRecGetEx(const UnitName, RecordType, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer); dynamic;
|
||
|
procedure AddRecSet(const UnitName, RecordType, Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word); dynamic;
|
||
|
procedure AddRecSetEx(const UnitName, RecordType, Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer); dynamic;
|
||
|
procedure AddConst(const UnitName, Identifier: string; Value: Variant); dynamic;
|
||
|
procedure AddConstEx(const AUnitName, AIdentifier: string; AValue: Variant;
|
||
|
AData: Pointer); dynamic;
|
||
|
procedure AddExtFun(const UnitName, Identifier: string; DllInstance: HINST;
|
||
|
const DllName, FunctionName: string; FunctionIndex: Integer; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word); dynamic;
|
||
|
procedure AddExtFunEx(const AUnitName, AIdentifier: string; ADllInstance: HINST;
|
||
|
const ADllName, AFunctionName: string; AFunIndex: Integer; AParamCount: Integer;
|
||
|
AParamTypes: array of Word; AResTyp: Word; AData: Pointer); dynamic;
|
||
|
procedure AddSrcFun(const UnitName, Identifier: string;
|
||
|
ClassIdentifier: string;
|
||
|
PosBeg, PosEnd: Integer; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ParamTypeNames: array of string;
|
||
|
ParamNames: array of string; ResTyp: Word; const AResTypName: string;
|
||
|
AResDataType: IJvInterpreterDataType; Data: Pointer); dynamic;
|
||
|
procedure AddSrcFunEx(const AUnitName, AIdentifier: string;
|
||
|
AClassIdentifier: string;
|
||
|
APosBeg, APosEnd: Integer; AParamCount: Integer; AParamTypes: array of Word;
|
||
|
AParamTypeNames: array of string;
|
||
|
AParamNames: array of string; AResTyp: Word; const AResTypName: string;
|
||
|
AResDataType: IJvInterpreterDataType; AData: Pointer); dynamic;
|
||
|
procedure AddHandler(const UnitName, Identifier: string;
|
||
|
EventClass: TJvInterpreterEventClass; Code: Pointer); dynamic;
|
||
|
procedure AddHandlerEx(const AUnitName, AIdentifier: string;
|
||
|
AEventClass: TJvInterpreterEventClass; ACode: Pointer; AData: Pointer); dynamic;
|
||
|
procedure AddEvent(const UnitName: string; AClassType: TClass;
|
||
|
const Identifier: string); dynamic;
|
||
|
procedure AddEventEx(const AUnitName: string; AClassType: TClass;
|
||
|
const AIdentifier: string; AData: Pointer); dynamic;
|
||
|
procedure AddSrcVar(const UnitName, Identifier, Typ: string; VTyp: Word;
|
||
|
const Value: Variant; DataType: IJvInterpreterDataType); dynamic;
|
||
|
procedure AddOnGet(Method: TJvInterpreterGetValue); dynamic;
|
||
|
procedure AddOnSet(Method: TJvInterpreterSetValue); dynamic;
|
||
|
public
|
||
|
property DisableExternalFunctions: Boolean read FDisableExternalFunctions write FDisableExternalFunctions;
|
||
|
property SrcUnitList: TJvInterpreterIdentifierList read FSrcUnitList;
|
||
|
property ExtUnitList: TJvInterpreterIdentifierList read FExtUnitList;
|
||
|
property GetList: TJvInterpreterIdentifierList read FGetList;
|
||
|
property SetList: TJvInterpreterIdentifierList read FSetList;
|
||
|
property IGetList: TJvInterpreterIdentifierList read FIGetList;
|
||
|
property ISetList: TJvInterpreterIdentifierList read FISetList;
|
||
|
property IDGetList: TJvInterpreterIdentifierList read FIDGetList;
|
||
|
property IDSetList: TJvInterpreterIdentifierList read FIDSetList;
|
||
|
property IntfGetList: TJvInterpreterIdentifierList read FIntfGetList;
|
||
|
property IntfSetList: TJvInterpreterIdentifierList read FIntfSetList;
|
||
|
property IntfIGetList: TJvInterpreterIdentifierList read FIntfIGetList;
|
||
|
property IntfISetList: TJvInterpreterIdentifierList read FIntfISetList;
|
||
|
property IntfIDGetList: TJvInterpreterIdentifierList read FIntfIDGetList;
|
||
|
property IntfIDSetList: TJvInterpreterIdentifierList read FIntfIDSetList;
|
||
|
property DirectGetList: TJvInterpreterIdentifierList read FDirectGetList;
|
||
|
property ClassList: TJvInterpreterIdentifierList read FClassList;
|
||
|
property ConstList: TJvInterpreterIdentifierList read FConstList;
|
||
|
property FunctionList: TJvInterpreterIdentifierList read FFunctionList;
|
||
|
property RecordList: TJvInterpreterIdentifierList read FRecordList;
|
||
|
property RecordGetList: TJvInterpreterIdentifierList read FRecordGetList;
|
||
|
property RecordSetList: TJvInterpreterIdentifierList read FRecordSetList;
|
||
|
property OnGetList: TJvInterpreterIdentifierList read FOnGetList;
|
||
|
property OnSetList: TJvInterpreterIdentifierList read FOnSetList;
|
||
|
property SrcFunctionList: TJvInterpreterIdentifierList read FSrcFunctionList;
|
||
|
property ExtFunctionList: TJvInterpreterIdentifierList read FExtFunctionList;
|
||
|
property EventHandlerList: TJvInterpreterIdentifierList read FEventHandlerList;
|
||
|
property EventList: TJvInterpreterIdentifierList read FEventList;
|
||
|
property SrcVarList: TJvInterpreterVarList read FSrcVarList;
|
||
|
property SrcClassList: TJvInterpreterIdentifierList read FSrcClassList;
|
||
|
end;
|
||
|
|
||
|
TStackPtr = -1..cJvInterpreterStackMax;
|
||
|
|
||
|
{ Expression evaluator }
|
||
|
TJvInterpreterExpression = class(TComponent) //TJvComponent)
|
||
|
private
|
||
|
FParser: TJvInterpreterParser;
|
||
|
FVResult: Variant;
|
||
|
FExpStack: array [0..cJvInterpreterStackMax] of Variant;
|
||
|
FExpStackPtr: TStackPtr;
|
||
|
FToken: Variant;
|
||
|
FBacked: Boolean;
|
||
|
FTTyp: TTokenKind;
|
||
|
FTokenStr: string;
|
||
|
FPrevTTyp: TTokenKind;
|
||
|
FAllowAssignment: Boolean;
|
||
|
FArgs: TJvInterpreterArgs; { data }
|
||
|
FCurrArgs: TJvInterpreterArgs; { pointer to current }
|
||
|
FPStream: TStream; { parsed source }
|
||
|
FParsed: Boolean;
|
||
|
FAdapter: TJvInterpreterAdapter;
|
||
|
FSharedAdapter: TJvInterpreterAdapter;
|
||
|
FCompiled: Boolean;
|
||
|
FBaseErrLine: Integer;
|
||
|
FOnGetValue: TJvInterpreterGetValue;
|
||
|
FOnSetValue: TJvInterpreterSetValue;
|
||
|
FLastError: EJvInterpreterError;
|
||
|
FDisableExternalFunctions: Boolean;
|
||
|
function GetSource: string;
|
||
|
procedure SetSource(const Value: string);
|
||
|
procedure SetCurPos(Value: Integer);
|
||
|
function GetCurPos: Integer;
|
||
|
function GetTokenStr: string;
|
||
|
procedure ReadArgs;
|
||
|
procedure InternalGetValue(Obj: Pointer; ObjTyp: Word; var Result: Variant);
|
||
|
function CallFunction(const FunctionName: string;
|
||
|
Args: TJvInterpreterArgs; Params: array of Variant): Variant; virtual; abstract;
|
||
|
function CallFunctionEx(Instance: TObject; const UnitName: string;
|
||
|
const FunctionName: string; Args: TJvInterpreterArgs; Params: array of Variant): Variant; virtual; abstract;
|
||
|
procedure SetDisableExternalFunctions(const Value: Boolean);
|
||
|
protected
|
||
|
procedure UpdateExceptionPos(E: Exception; const UnitName: string);
|
||
|
procedure Init; dynamic;
|
||
|
procedure ErrorExpected(const Exp: string);
|
||
|
procedure ErrorNotImplemented(const Msg: string);
|
||
|
function PosBeg: Integer;
|
||
|
function PosEnd: Integer;
|
||
|
procedure Back;
|
||
|
procedure SafeBack; {? please don't use ?}
|
||
|
function CreateAdapter: TJvInterpreterAdapter; dynamic;
|
||
|
procedure ParseToken;
|
||
|
procedure ReadToken;
|
||
|
procedure WriteToken;
|
||
|
procedure Parse;
|
||
|
function Expression1: Variant;
|
||
|
function Expression2(const ExpType: Word): Variant;
|
||
|
function SetExpression1: Variant;
|
||
|
procedure NextToken;
|
||
|
function GetValue(const Identifier: string; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function SetValue(const Identifier: string; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function GetElement(const Variable: Variant; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
function SetElement(var Variable: Variant; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; virtual;
|
||
|
procedure SourceChanged; dynamic;
|
||
|
procedure SetAdapter(Adapter: TJvInterpreterAdapter);
|
||
|
property Token: Variant read FToken;
|
||
|
property TTyp: TTokenKind read FTTyp;
|
||
|
property PrevTTyp: TTokenKind read FPrevTTyp;
|
||
|
property TokenStr: string read GetTokenStr;
|
||
|
property CurPos: Integer read GetCurPos write SetCurPos;
|
||
|
property Compiled: Boolean read FCompiled;
|
||
|
public
|
||
|
constructor Create(AOwner: TComponent); override;
|
||
|
destructor Destroy; override;
|
||
|
procedure Run; dynamic;
|
||
|
property Source: string read GetSource write SetSource;
|
||
|
property VResult: Variant read FVResult;
|
||
|
property OnGetValue: TJvInterpreterGetValue read FOnGetValue write FOnGetValue;
|
||
|
property OnSetValue: TJvInterpreterSetValue read FOnSetValue write FOnSetValue;
|
||
|
property Adapter: TJvInterpreterAdapter read FAdapter;
|
||
|
property SharedAdapter: TJvInterpreterAdapter read FSharedAdapter;
|
||
|
property BaseErrLine: Integer read FBaseErrLine write FBaseErrLine;
|
||
|
property LastError: EJvInterpreterError read FLastError;
|
||
|
property DisableExternalFunctions: Boolean read FDisableExternalFunctions write SetDisableExternalFunctions;
|
||
|
end;
|
||
|
|
||
|
TParserState = record
|
||
|
CurPos: Integer;
|
||
|
Token: Variant;
|
||
|
TTyp: TTokenKind;
|
||
|
PrevTTyp: TTokenKind;
|
||
|
Backed: Boolean;
|
||
|
AllowAssignment: Boolean;
|
||
|
end;
|
||
|
|
||
|
TJvInterpreterAddVarFunc = procedure(const UnitName,
|
||
|
Identifier, Typ: string; VTyp: Word; const Value: Variant;
|
||
|
ADataType: IJvInterpreterDataType) of object;
|
||
|
|
||
|
{ Function executor }
|
||
|
TJvInterpreterFunction = class(TJvInterpreterExpression)
|
||
|
private
|
||
|
FCurUnitName: string;
|
||
|
FCurInstance: TObject;
|
||
|
FBreak: Boolean;
|
||
|
FContinue: Boolean;
|
||
|
FExit: Boolean;
|
||
|
FFunctionStack: TList;
|
||
|
FFunctionContext: Pointer; { PFunctionContext }
|
||
|
FSS: TStringList;
|
||
|
FStateStack: array [0..cJvInterpreterStackMax] of TParserState;
|
||
|
FStateStackPtr: TStackPtr;
|
||
|
FEventList: TList;
|
||
|
function GetLocalVars: TJvInterpreterVarList;
|
||
|
function GetFunStackCount: Integer;
|
||
|
function GetDebugPointerToGlobalVars: TJvInterpreterVarList;
|
||
|
function GetDebugPointerToFunStack: Pointer;
|
||
|
protected
|
||
|
procedure Init; override;
|
||
|
procedure PushState;
|
||
|
procedure PopState;
|
||
|
procedure RemoveState;
|
||
|
procedure DoOnStatement; virtual;
|
||
|
procedure InFunction(FunctionDesc: TJvInterpreterFunctionDesc);
|
||
|
procedure InterpretStatement;
|
||
|
procedure SkipStatement;
|
||
|
procedure SkipToEnd;
|
||
|
procedure SkipToUntil;
|
||
|
procedure SkipIdentifier;
|
||
|
procedure FindToken(ATTyp: TTokenKind);
|
||
|
procedure InterpretVar(AddVarFunc: TJvInterpreterAddVarFunc);
|
||
|
procedure InterpretConst(AddVarFunc: TJvInterpreterAddVarFunc);
|
||
|
procedure InterpretIdentifier;
|
||
|
procedure InterpretBegin;
|
||
|
procedure InterpretIf;
|
||
|
procedure InterpretWhile;
|
||
|
procedure InterpretRepeat;
|
||
|
procedure InterpretFor;
|
||
|
procedure InterpretCase;
|
||
|
procedure InterpretTry;
|
||
|
procedure InterpretRaise;
|
||
|
function ParseDataType: IJvInterpreterDataType;
|
||
|
function NewEvent(const UnitName, FunctionName, EventType: string;
|
||
|
Instance: TObject; const APropName: string): TSimpleEvent;
|
||
|
function FindEvent(const UnitName: string; Instance: TObject;
|
||
|
const PropName: string): TJvInterpreterEvent;
|
||
|
procedure InternalSetValue(const Identifier: string);
|
||
|
function GetValue(const Identifier: string; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; override;
|
||
|
function SetValue(const Identifier: string; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; override;
|
||
|
property LocalVars: TJvInterpreterVarList read GetLocalVars;
|
||
|
property EventList: TList read FEventList;
|
||
|
public
|
||
|
constructor Create(AOwner: TComponent); override;
|
||
|
destructor Destroy; override;
|
||
|
procedure Run; override;
|
||
|
property CurUnitName: string read FCurUnitName;
|
||
|
property CurInstance: TObject read FCurInstance;
|
||
|
property FunStackCount: Integer read GetFunStackCount;
|
||
|
property DebugPointerToFunStack: Pointer read GetDebugPointerToFunStack;
|
||
|
property DebugPointerToGlobalVars: TJvInterpreterVarList read GetDebugPointerToGlobalVars;
|
||
|
end;
|
||
|
|
||
|
TUnitSection =
|
||
|
(usUnknown, usInterface, usImplementation, usInitialization, usFinalization);
|
||
|
|
||
|
{ Unit executor }
|
||
|
TJvInterpreterUnit = class(TJvInterpreterFunction)
|
||
|
private
|
||
|
FClearUnits: Boolean;
|
||
|
FEventHandlerList: TList;
|
||
|
FOnGetUnitSource: TJvInterpreterGetUnitSource;
|
||
|
FUnitSection: TUnitSection;
|
||
|
protected
|
||
|
procedure Init; override;
|
||
|
procedure ReadFunctionHeader(FunctionDesc: TJvInterpreterFunctionDesc);
|
||
|
procedure InterpretUses(var UsesList: string);
|
||
|
procedure ReadUnit(const UnitName: string);
|
||
|
procedure InterpretFunction;
|
||
|
procedure InterpretUnit;
|
||
|
procedure InterpretType;
|
||
|
procedure InterpretClass(const Identifier: string);
|
||
|
function GetValue(const Identifier: string; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; override;
|
||
|
function SetValue(const Identifier: string; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean; override;
|
||
|
function GetUnitSource(const UnitName: string; var Source: string): Boolean; dynamic;
|
||
|
procedure ExecFunction(Fun: TJvInterpreterFunctionDesc);
|
||
|
procedure SourceChanged; override;
|
||
|
procedure InterpretRecord(const Identifier: string);
|
||
|
property EventHandlerList: TList read FEventHandlerList;
|
||
|
public
|
||
|
constructor Create(AOwner: TComponent); override;
|
||
|
destructor Destroy; override;
|
||
|
procedure Run; override;
|
||
|
procedure DeclareExternalFunction(const Declaration: string);
|
||
|
procedure Compile;
|
||
|
function CallFunction(const FunctionName: string; Args: TJvInterpreterArgs;
|
||
|
Params: array of Variant): Variant; override;
|
||
|
function CallFunctionEx(Instance: TObject; const UnitName: string;
|
||
|
const FunctionName: string; Args: TJvInterpreterArgs;
|
||
|
Params: array of Variant): Variant; override;
|
||
|
function FunctionExists(const UnitName: string;
|
||
|
const FunctionName: string): Boolean;
|
||
|
property OnGetUnitSource: TJvInterpreterGetUnitSource read FOnGetUnitSource
|
||
|
write FOnGetUnitSource;
|
||
|
property UnitSection: TUnitSection read FUnitSection;
|
||
|
end;
|
||
|
|
||
|
{ main JvInterpreter component }
|
||
|
TJvInterpreterProgram = class(TJvInterpreterUnit)
|
||
|
private
|
||
|
FPas: TStringList;
|
||
|
FOnStatement: TNotifyEvent;
|
||
|
function GetPas: TStrings;
|
||
|
procedure SetPas(Value: TStrings);
|
||
|
protected
|
||
|
procedure DoOnStatement; override;
|
||
|
public
|
||
|
constructor Create(AOwner: TComponent); override;
|
||
|
destructor Destroy; override;
|
||
|
procedure Run; override;
|
||
|
published
|
||
|
property Pas: TStrings read GetPas write SetPas;
|
||
|
property OnGetValue;
|
||
|
property OnSetValue;
|
||
|
property OnGetUnitSource;
|
||
|
property OnStatement: TNotifyEvent read FOnStatement write FOnStatement;
|
||
|
end;
|
||
|
|
||
|
TJvSimpleVariantType = class(TCustomVariantType)
|
||
|
public
|
||
|
procedure Clear(var V: TVarData); override;
|
||
|
procedure Copy(var Dest: TVarData; const Source: TVarData;
|
||
|
const Indirect: Boolean); override;
|
||
|
procedure CastTo(var Dest: TVarData; const Source: TVarData;
|
||
|
const AVarType: TVarType); override;
|
||
|
end;
|
||
|
|
||
|
TJvRecordVariantType = class(TJvSimpleVariantType);
|
||
|
TJvObjectVariantType = class(TJvSimpleVariantType);
|
||
|
TJvClassVariantType = class(TJvSimpleVariantType);
|
||
|
TJvPointerVariantType = class(TJvSimpleVariantType);
|
||
|
TJvSetVariantType = class(TJvSimpleVariantType);
|
||
|
TJvArrayVariantType = class(TJvSimpleVariantType);
|
||
|
|
||
|
EJvInterpreterError = class(Exception)
|
||
|
private
|
||
|
FExceptionPos: Boolean;
|
||
|
FErrCode: Integer;
|
||
|
FErrPos: Integer;
|
||
|
FErrName1: string;
|
||
|
FErrName2: string;
|
||
|
FErrUnitName: string;
|
||
|
FErrLine: Integer;
|
||
|
FErrMessage: string;
|
||
|
public
|
||
|
constructor Create(const AErrCode: Integer; const AErrPos: Integer;
|
||
|
const AErrName1, AErrName2: string);
|
||
|
procedure Assign(E: Exception);
|
||
|
procedure Clear;
|
||
|
property ErrCode: Integer read FErrCode;
|
||
|
property ErrPos: Integer read FErrPos;
|
||
|
property ErrName1: string read FErrName1;
|
||
|
property ErrName2: string read FErrName2;
|
||
|
property ErrUnitName: string read FErrUnitName;
|
||
|
property ErrLine: Integer read FErrLine;
|
||
|
property ErrMessage: string read FErrMessage;
|
||
|
end;
|
||
|
|
||
|
{Error raising routines}
|
||
|
procedure JvInterpreterError(const AErrCode: Integer; const AErrPos: Integer);
|
||
|
procedure JvInterpreterErrorN(const AErrCode: Integer; const AErrPos: Integer;
|
||
|
const AErrName: string);
|
||
|
procedure JvInterpreterErrorN2(const AErrCode: Integer; const AErrPos: Integer;
|
||
|
const AErrName1, AErrName2: string);
|
||
|
|
||
|
{Utilities functions}
|
||
|
//function LoadStr2(const ResID: Integer): string;
|
||
|
|
||
|
{ RFD - RecordFieldDefinition - return record needed for TJvInterpreterAdapter.AddRec
|
||
|
Fields parameter }
|
||
|
function RFD(const Identifier: string; Offset: Integer; Typ: Word): TJvInterpreterRecField;
|
||
|
|
||
|
{ raise error ieNotImplemented }
|
||
|
procedure NotImplemented(const Msg: string);
|
||
|
|
||
|
{ clear list of TObject }
|
||
|
procedure ClearList(List: TList);
|
||
|
|
||
|
{ additional variant types - TVarData.VType }
|
||
|
|
||
|
function varRecord: TVarType;
|
||
|
function varObject: TVarType;
|
||
|
function varClass: TVarType;
|
||
|
function varPointer: TVarType;
|
||
|
function varSet: TVarType;
|
||
|
function varArray: TVarType;
|
||
|
|
||
|
type
|
||
|
TJvInterpreterShiftStateCastType = {$IFDEF COMPILER14_UP}Word{$ELSE}Byte{$ENDIF};
|
||
|
|
||
|
{ V2O - converts variant to object }
|
||
|
function V2O(const V: Variant): TObject;
|
||
|
|
||
|
{ O2V - converts object to variant }
|
||
|
function O2V(O: TObject): Variant;
|
||
|
|
||
|
{ V2C - converts variant to class }
|
||
|
function V2C(const V: Variant): TClass;
|
||
|
|
||
|
{ O2V - converts class to variant }
|
||
|
function C2V(C: TClass): Variant;
|
||
|
|
||
|
{ V2P - converts variant to pointer }
|
||
|
function V2P(const V: Variant): Pointer;
|
||
|
|
||
|
{ P2V - converts pointer to variant }
|
||
|
function P2V(P: Pointer): Variant;
|
||
|
|
||
|
{ V2AB - converts variant to byte array }
|
||
|
function V2AB(const V: Variant): TDynByteArray;
|
||
|
|
||
|
{ AB2V - converts byte array to variant }
|
||
|
function AB2V(const AB: TDynByteArray): Variant;
|
||
|
|
||
|
{ R2V - create record holder and put it into variant }
|
||
|
function R2V(const ARecordType: string; ARec: Pointer): Variant;
|
||
|
|
||
|
{ V2R - returns pointer to record from variant, containing record holder }
|
||
|
function V2R(const V: Variant): Pointer;
|
||
|
|
||
|
{ P2R - returns pointer to record from record holder, typically Args.Obj }
|
||
|
function P2R(const P: Pointer): Pointer;
|
||
|
|
||
|
{ S2V - converts Integer to set and put it into variant }
|
||
|
function S2V(const I: Integer): Variant;
|
||
|
|
||
|
{ V2S - give a set from variant and converts it to Integer }
|
||
|
function V2S(V: Variant): Integer;
|
||
|
|
||
|
procedure V2OA(V: Variant; var OA: TOpenArray; var OAValues: TValueArray;
|
||
|
var Size: Integer);
|
||
|
|
||
|
function TypeName2VarTyp(const TypeName: string): Word;
|
||
|
|
||
|
{ copy variant variable with all JvInterpreter variant extension }
|
||
|
procedure JvInterpreterVarCopy(var Dest: Variant; const Source: Variant);
|
||
|
|
||
|
{ copy variant variable for assignment }
|
||
|
procedure JvInterpreterVarAssignment(var Dest: Variant; const Source: Variant);
|
||
|
|
||
|
function JvInterpreterVarAsType(const V: Variant; const VarType: Integer): Variant;
|
||
|
|
||
|
{ properly free var variable and set it content to empty }
|
||
|
procedure JvInterpreterVarFree(var V: Variant);
|
||
|
|
||
|
{ compare strings }
|
||
|
function Cmp(const S1, S2: string): Boolean;
|
||
|
|
||
|
{ For dynamic array support}
|
||
|
procedure JvInterpreterArraySetLength(AArray: Variant; ASize: Integer);
|
||
|
function JvInterpreterArrayLength(const AArray: Variant): Integer;
|
||
|
function JvInterpreterArrayLow(const AArray: Variant): Integer;
|
||
|
function JvInterpreterArrayHigh(const AArray: Variant): Integer;
|
||
|
procedure JvInterpreterArrayElementDelete(AArray: Variant; AElement: Integer);
|
||
|
procedure JvInterpreterArrayElementInsert(AArray: Variant; AElement: Integer; Value: Variant);
|
||
|
|
||
|
function GlobalJvInterpreterAdapter: TJvInterpreterAdapter;
|
||
|
|
||
|
const
|
||
|
prArgsNoCheck = -1;
|
||
|
noInstance = HINST(0);
|
||
|
RFDNull: TJvInterpreterRecField = (Identifier: ''; Offset: 0; Typ: 0);
|
||
|
|
||
|
varByConst = $8000;
|
||
|
|
||
|
{JvInterpreter error codes}
|
||
|
ieOk = 0; { Okay - no errors }
|
||
|
ieUnknown = 1;
|
||
|
ieInternal = 2;
|
||
|
ieUserBreak = 3; { internal }
|
||
|
ieRaise = 4; { internal }
|
||
|
ieErrorPos = 5;
|
||
|
ieExternal = 6; { non-interpreter error }
|
||
|
ieAccessDenied = 7;
|
||
|
ieExpressionStackOverflow = 8;
|
||
|
|
||
|
{ register-time errors }
|
||
|
ieRegisterBase = 30;
|
||
|
ieRecordNotDefined = ieRegisterBase + 1;
|
||
|
|
||
|
{ run-time errors }
|
||
|
ieRuntimeBase = 50;
|
||
|
ieStackOverFlow = ieRuntimeBase + 2;
|
||
|
ieTypeMistmatch = ieRuntimeBase + 3;
|
||
|
ieIntegerOverflow = ieRuntimeBase + 4;
|
||
|
ieMainUndefined = ieRuntimeBase + 5;
|
||
|
ieUnitNotFound = ieRuntimeBase + 6;
|
||
|
ieEventNotRegistered = ieRuntimeBase + 7;
|
||
|
ieDfmNotFound = ieRuntimeBase + 8;
|
||
|
|
||
|
{ syntax errors (now run-timed) }
|
||
|
ieSyntaxBase = 100;
|
||
|
ieBadRemark = ieSyntaxBase + 1; { Bad remark - detected by parser }
|
||
|
ieIdentifierExpected = ieSyntaxBase + 2;
|
||
|
ieExpected = ieSyntaxBase + 3;
|
||
|
ieUnknownIdentifier = ieSyntaxBase + 4;
|
||
|
ieBooleanRequired = ieSyntaxBase + 5;
|
||
|
ieClassRequired = ieSyntaxBase + 6;
|
||
|
ieNotAllowedBeforeElse = ieSyntaxBase + 7;
|
||
|
ieIntegerRequired = ieSyntaxBase + 8;
|
||
|
ieROCRequired = ieSyntaxBase + 9;
|
||
|
ieMissingOperator = ieSyntaxBase + 10;
|
||
|
ieIdentifierRedeclared = ieSyntaxBase + 11;
|
||
|
|
||
|
{ array indexes }
|
||
|
ieArrayBase = 170;
|
||
|
ieArrayIndexOutOfBounds = ieArrayBase + 1;
|
||
|
ieArrayTooManyParams = ieArrayBase + 2;
|
||
|
ieArrayNotEnoughParams = ieArrayBase + 3;
|
||
|
ieArrayBadDimension = ieArrayBase + 4;
|
||
|
ieArrayBadRange = ieArrayBase + 5;
|
||
|
ieArrayRequired = ieArrayBase + 6;
|
||
|
|
||
|
{ function call errors (now run-timed) }
|
||
|
ieFunctionBase = 180;
|
||
|
ieTooManyParams = ieFunctionBase + 1;
|
||
|
ieNotEnoughParams = ieFunctionBase + 2;
|
||
|
ieIncompatibleTypes = ieFunctionBase + 3;
|
||
|
ieDllErrorLoadLibrary = ieFunctionBase + 4;
|
||
|
ieDllInvalidArgument = ieFunctionBase + 5;
|
||
|
ieDllInvalidResult = ieFunctionBase + 6;
|
||
|
ieDllFunctionNotFound = ieFunctionBase + 7;
|
||
|
ieDirectInvalidArgument = ieFunctionBase + 8;
|
||
|
ieDirectInvalidResult = ieFunctionBase + 9;
|
||
|
ieDirectInvalidConvention = ieFunctionBase + 10;
|
||
|
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
ieOleAuto = ieFunctionBase + 21;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
ieUserBase = $300;
|
||
|
|
||
|
irExpression = 301;
|
||
|
irIdentifier = 302;
|
||
|
irDeclaration = 303;
|
||
|
irEndOfFile = 304;
|
||
|
irClass = 305;
|
||
|
irIntegerConstant = 306;
|
||
|
irIntegerValue = 307;
|
||
|
irStringConstant = 308;
|
||
|
irStatement = 309;
|
||
|
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
Types,
|
||
|
TypInfo,
|
||
|
{$IFDEF CPUX64}
|
||
|
System.Rtti,
|
||
|
{$ENDIF CPUX64}
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
OleConst, ActiveX, ComObj,
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
JvConsts, JvInterpreterConst, JvJVCLUtils, JvResources, JvTypes,
|
||
|
JvInterpreterFm; // required uses for class method support
|
||
|
|
||
|
var
|
||
|
FieldGlobalJvInterpreterAdapter: TJvInterpreterAdapter = nil;
|
||
|
|
||
|
function GlobalJvInterpreterAdapter: TJvInterpreterAdapter;
|
||
|
begin
|
||
|
if not Assigned(FieldGlobalJvInterpreterAdapter) then
|
||
|
FieldGlobalJvInterpreterAdapter := TJvInterpreterAdapter.Create(nil);
|
||
|
Result := FieldGlobalJvInterpreterAdapter;
|
||
|
end;
|
||
|
|
||
|
{ internal structures }
|
||
|
|
||
|
|
||
|
|
||
|
{$IFDEF JvInterpreter_DEBUG}
|
||
|
var
|
||
|
ObjCount: Integer = 0;
|
||
|
{$ENDIF JvInterpreter_DEBUG}
|
||
|
|
||
|
var
|
||
|
GlobalVariantRecordInstance: TJvRecordVariantType = nil;
|
||
|
GlobalVariantObjectInstance: TJvObjectVariantType = nil;
|
||
|
GlobalVariantClassInstance: TJvClassVariantType = nil;
|
||
|
GlobalVariantPointerInstance: TJvPointerVariantType = nil;
|
||
|
GlobalVariantSetInstance: TJvSetVariantType = nil;
|
||
|
GlobalVariantArrayInstance: TJvArrayVariantType = nil;
|
||
|
|
||
|
function VariantRecordInstance: TJvRecordVariantType;
|
||
|
begin
|
||
|
if not Assigned(GlobalVariantRecordInstance) then
|
||
|
GlobalVariantRecordInstance := TJvRecordVariantType.Create;
|
||
|
Result := GlobalVariantRecordInstance;
|
||
|
end;
|
||
|
|
||
|
function VariantObjectInstance: TJvObjectVariantType;
|
||
|
begin
|
||
|
if not Assigned(GlobalVariantObjectInstance) then
|
||
|
GlobalVariantObjectInstance := TJvObjectVariantType.Create;
|
||
|
Result := GlobalVariantObjectInstance;
|
||
|
end;
|
||
|
|
||
|
function VariantClassInstance: TJvClassVariantType;
|
||
|
begin
|
||
|
if not Assigned(GlobalVariantClassInstance) then
|
||
|
GlobalVariantClassInstance := TJvClassVariantType.Create;
|
||
|
Result := GlobalVariantClassInstance;
|
||
|
end;
|
||
|
|
||
|
function VariantPointerInstance: TJvPointerVariantType;
|
||
|
begin
|
||
|
if not Assigned(GlobalVariantPointerInstance) then
|
||
|
GlobalVariantPointerInstance := TJvPointerVariantType.Create;
|
||
|
Result := GlobalVariantPointerInstance;
|
||
|
end;
|
||
|
|
||
|
function VariantSetInstance: TJvSetVariantType;
|
||
|
begin
|
||
|
if not Assigned(GlobalVariantSetInstance) then
|
||
|
GlobalVariantSetInstance := TJvSetVariantType.Create;
|
||
|
Result := GlobalVariantSetInstance;
|
||
|
end;
|
||
|
|
||
|
function VariantArrayInstance: TJvArrayVariantType;
|
||
|
begin
|
||
|
if not Assigned(GlobalVariantArrayInstance) then
|
||
|
GlobalVariantArrayInstance := TJvArrayVariantType.Create;
|
||
|
Result := GlobalVariantArrayInstance;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvSimpleVariantType } ===============================================
|
||
|
|
||
|
procedure TJvSimpleVariantType.CastTo(var Dest: TVarData;
|
||
|
const Source: TVarData; const AVarType: TVarType);
|
||
|
begin
|
||
|
//support only inherited classes
|
||
|
Dest.VPointer := Source.VPointer;
|
||
|
//inherited;
|
||
|
end;
|
||
|
|
||
|
procedure TJvSimpleVariantType.Clear(var V: TVarData);
|
||
|
begin
|
||
|
SimplisticClear(V);
|
||
|
end;
|
||
|
|
||
|
procedure TJvSimpleVariantType.Copy(var Dest: TVarData;
|
||
|
const Source: TVarData; const Indirect: Boolean);
|
||
|
begin
|
||
|
SimplisticCopy(Dest, Source, Indirect);
|
||
|
end;
|
||
|
|
||
|
function varRecord: TVarType;
|
||
|
begin
|
||
|
Result := VariantRecordInstance.VarType;
|
||
|
end;
|
||
|
|
||
|
function varObject: TVarType;
|
||
|
begin
|
||
|
Result := VariantObjectInstance.VarType;
|
||
|
end;
|
||
|
|
||
|
function varClass: TVarType;
|
||
|
begin
|
||
|
Result := VariantClassInstance.VarType;
|
||
|
end;
|
||
|
|
||
|
function varPointer: TVarType;
|
||
|
begin
|
||
|
Result := VariantPointerInstance.VarType;
|
||
|
end;
|
||
|
|
||
|
function varSet: TVarType;
|
||
|
begin
|
||
|
Result := VariantSetInstance.VarType;
|
||
|
end;
|
||
|
|
||
|
function varArray: TVarType;
|
||
|
begin
|
||
|
Result := VariantArrayInstance.VarType;
|
||
|
end;
|
||
|
|
||
|
//=== EJvInterpreterError ====================================================
|
||
|
|
||
|
function LoadStr2(const ResID: Integer): string;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := Low(JvInterpreterErrors) to High(JvInterpreterErrors) do
|
||
|
if JvInterpreterErrors[I].ID = ResID then
|
||
|
begin
|
||
|
Result := JvInterpreterErrors[I].Description;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterError(const AErrCode: Integer; const AErrPos: Integer);
|
||
|
begin
|
||
|
raise EJvInterpreterError.Create(AErrCode, AErrPos, '', '');
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterErrorN(const AErrCode: Integer; const AErrPos: Integer;
|
||
|
const AErrName: string);
|
||
|
begin
|
||
|
raise EJvInterpreterError.Create(AErrCode, AErrPos, AErrName, '');
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterErrorN2(const AErrCode: Integer; const AErrPos: Integer;
|
||
|
const AErrName1, AErrName2: string);
|
||
|
begin
|
||
|
raise EJvInterpreterError.Create(AErrCode, AErrPos, AErrName1, AErrName2);
|
||
|
end;
|
||
|
|
||
|
constructor EJvInterpreterError.Create(const AErrCode: Integer;
|
||
|
const AErrPos: Integer; const AErrName1, AErrName2: string);
|
||
|
begin
|
||
|
inherited Create('');
|
||
|
FErrCode := AErrCode;
|
||
|
FErrPos := AErrPos;
|
||
|
FErrName1 := AErrName1;
|
||
|
FErrName2 := AErrName2;
|
||
|
{ function LoadStr don't work sometimes :-( }
|
||
|
Message := Format(LoadStr2(ErrCode), [ErrName1, ErrName2]);
|
||
|
FErrMessage := Message;
|
||
|
end;
|
||
|
|
||
|
procedure EJvInterpreterError.Assign(E: Exception);
|
||
|
begin
|
||
|
Message := E.Message;
|
||
|
if E is EJvInterpreterError then
|
||
|
begin
|
||
|
FErrCode := (E as EJvInterpreterError).ErrCode;
|
||
|
FErrPos := (E as EJvInterpreterError).ErrPos;
|
||
|
FErrName1 := (E as EJvInterpreterError).ErrName1;
|
||
|
FErrName2 := (E as EJvInterpreterError).ErrName2;
|
||
|
FErrMessage := (E as EJvInterpreterError).ErrMessage;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure EJvInterpreterError.Clear;
|
||
|
begin
|
||
|
FExceptionPos := False;
|
||
|
FErrName1 := '';
|
||
|
FErrName2 := '';
|
||
|
FErrPos := -1;
|
||
|
FErrLine := -1;
|
||
|
FErrUnitName := '';
|
||
|
end;
|
||
|
|
||
|
function V2O(const V: Variant): TObject;
|
||
|
begin
|
||
|
Result := TVarData(V).VPointer;
|
||
|
end;
|
||
|
|
||
|
function O2V(O: TObject): Variant;
|
||
|
begin
|
||
|
TVarData(Result).VType := varObject;
|
||
|
TVarData(Result).VPointer := O;
|
||
|
end;
|
||
|
|
||
|
function V2C(const V: Variant): TClass;
|
||
|
begin
|
||
|
Result := TVarData(V).VPointer;
|
||
|
end;
|
||
|
|
||
|
function C2V(C: TClass): Variant;
|
||
|
begin
|
||
|
TVarData(Result).VType := varClass;
|
||
|
TVarData(Result).VPointer := C;
|
||
|
end;
|
||
|
|
||
|
function V2P(const V: Variant): Pointer;
|
||
|
begin
|
||
|
Result := TVarData(V).VPointer;
|
||
|
end;
|
||
|
|
||
|
function P2V(P: Pointer): Variant;
|
||
|
begin
|
||
|
TVarData(Result).VType := varPointer;
|
||
|
TVarData(Result).VPointer := P;
|
||
|
end;
|
||
|
|
||
|
function V2AB(const V: Variant): TDynByteArray;
|
||
|
var
|
||
|
liLen: integer;
|
||
|
lp: PByte;
|
||
|
begin
|
||
|
liLen := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
|
||
|
SetLength(result, liLen);
|
||
|
lp := VarArrayLock(V);
|
||
|
Move(lp^, result[0], liLen);
|
||
|
end;
|
||
|
|
||
|
function AB2V(const AB: TDynByteArray): Variant;
|
||
|
var
|
||
|
liLen: integer;
|
||
|
lp: PByte;
|
||
|
begin
|
||
|
liLen := Length(AB);
|
||
|
result := VarArrayCreate([0, liLen - 1], varByte);
|
||
|
lp := VarArrayLock(result);
|
||
|
Move(AB[0], lp^, liLen);
|
||
|
end;
|
||
|
|
||
|
function R2V(const ARecordType: string; ARec: Pointer): Variant;
|
||
|
begin
|
||
|
TVarData(Result).VPointer := TJvInterpreterRecHolder.Create(ARecordType, ARec);
|
||
|
TVarData(Result).VType := varRecord;
|
||
|
end;
|
||
|
|
||
|
function V2R(const V: Variant): Pointer;
|
||
|
begin
|
||
|
if (TVarData(V).VType <> varRecord) or
|
||
|
not (TObject(TVarData(V).VPointer) is TJvInterpreterRecHolder) then
|
||
|
JvInterpreterError(ieROCRequired, -1);
|
||
|
Result := TJvInterpreterRecHolder(TVarData(V).VPointer).Rec;
|
||
|
end;
|
||
|
|
||
|
function P2R(const P: Pointer): Pointer;
|
||
|
begin
|
||
|
if not (TObject(P) is TJvInterpreterRecHolder) then
|
||
|
JvInterpreterError(ieROCRequired, -1);
|
||
|
Result := TJvInterpreterRecHolder(P).Rec;
|
||
|
end;
|
||
|
|
||
|
function S2V(const I: Integer): Variant;
|
||
|
begin
|
||
|
Result := I;
|
||
|
TVarData(Result).VType := varSet;
|
||
|
end;
|
||
|
|
||
|
function V2S(V: Variant): Integer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if (TVarData(V).VType and System.varArray) = 0 then
|
||
|
Result := TVarData(V).VInteger
|
||
|
else
|
||
|
begin
|
||
|
{ JvInterpreter thinks about all function parameters, started
|
||
|
with '[' symbol that they are open arrays;
|
||
|
but it may be set constant, so we must convert it now }
|
||
|
Result := 0;
|
||
|
for I := VarArrayLowBound(V, 1) to VarArrayHighBound(V, 1) do
|
||
|
Result := Result or 1 shl Integer(V[I]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function RFD(const Identifier: string; Offset: Integer; Typ: Word): TJvInterpreterRecField;
|
||
|
begin
|
||
|
Result.Identifier := Identifier;
|
||
|
Result.Offset := Offset;
|
||
|
Result.Typ := Typ;
|
||
|
end;
|
||
|
|
||
|
procedure NotImplemented(const Msg: string);
|
||
|
begin
|
||
|
JvInterpreterErrorN(ieInternal, -1, Msg + RsENotImplemented);
|
||
|
end;
|
||
|
|
||
|
//RWare: added check for "char", otherwise function with ref variable
|
||
|
//of type char causes AV, like KeyPress event handler
|
||
|
|
||
|
function Typ2Size(ATyp: Word): Integer;
|
||
|
begin
|
||
|
Result := 0;
|
||
|
case ATyp of
|
||
|
varInteger:
|
||
|
Result := SizeOf(Integer);
|
||
|
varDouble:
|
||
|
Result := SizeOf(Double);
|
||
|
varByte:
|
||
|
Result := SizeOf(Byte);
|
||
|
varSmallint:
|
||
|
Result := SizeOf(Smallint);
|
||
|
varDate:
|
||
|
Result := SizeOf(Double);
|
||
|
varEmpty, varVariant, varOleStr, varDispatch, varUnknown:
|
||
|
Result := SizeOf(TVarData);
|
||
|
else
|
||
|
if ATyp = varObject then
|
||
|
Result := SizeOf(TObject);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TypeName2VarTyp(const TypeName: string): Word;
|
||
|
begin
|
||
|
// (rom) reimplemented for speed
|
||
|
// (rom) LongBool added (untested)
|
||
|
Result := varEmpty;
|
||
|
if TypeName <> '' then
|
||
|
begin
|
||
|
case TypeName[1] of
|
||
|
'A', 'a':
|
||
|
if Cmp(TypeName, 'AnsiString') then
|
||
|
Result := varString;
|
||
|
'B', 'b':
|
||
|
if Cmp(TypeName, 'boolean') or Cmp(TypeName, 'bool') then
|
||
|
Result := varBoolean
|
||
|
else
|
||
|
if Cmp(TypeName, 'byte') then
|
||
|
Result := varByte;
|
||
|
'C', 'c':
|
||
|
if Cmp(TypeName, 'char') then {+RWare}
|
||
|
Result := varString;
|
||
|
'D', 'd':
|
||
|
if Cmp(TypeName, 'dword') then
|
||
|
Result := varInteger
|
||
|
else
|
||
|
if Cmp(TypeName, 'double') then
|
||
|
Result := varDouble;
|
||
|
'I', 'i':
|
||
|
if Cmp(TypeName, 'integer') then
|
||
|
Result := varInteger;
|
||
|
'L', 'l':
|
||
|
if Cmp(TypeName, 'longint') then
|
||
|
Result := varInteger
|
||
|
else
|
||
|
if Cmp(TypeName, 'longbool') then
|
||
|
Result := varBoolean;
|
||
|
'P', 'p':
|
||
|
if Cmp(TypeName, 'PChar') then
|
||
|
Result := varString;
|
||
|
'S', 's':
|
||
|
if Cmp(TypeName, 'string') or Cmp(TypeName, 'ShortString') then
|
||
|
Result := varString
|
||
|
else
|
||
|
if Cmp(TypeName, 'smallint') then
|
||
|
Result := varSmallint;
|
||
|
'T', 't':
|
||
|
if Cmp(TypeName, 'TObject') then
|
||
|
Result := varObject
|
||
|
else
|
||
|
if Cmp(TypeName, 'tdatetime') then
|
||
|
Result := varDate;
|
||
|
'W', 'w':
|
||
|
if Cmp(TypeName, 'word') then
|
||
|
Result := varSmallint
|
||
|
else
|
||
|
if Cmp(TypeName, 'wordbool') then
|
||
|
Result := varBoolean;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure ClearList(List: TList);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if Assigned(List) then
|
||
|
begin
|
||
|
for I := 0 to List.Count - 1 do
|
||
|
TObject(List[I]).Free;
|
||
|
List.Clear;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure ClearMethodList(List: TList);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to List.Count - 1 do
|
||
|
Dispose(PMethod(List[I]));
|
||
|
List.Clear;
|
||
|
end;
|
||
|
|
||
|
// (rom) JvUtil added to uses and functions deleted
|
||
|
|
||
|
function Cmp(const S1, S2: string): Boolean;
|
||
|
begin
|
||
|
// Direct call to CompareString is faster than AnsiCompareText.
|
||
|
Result := (Length(S1) = Length(S2)) and
|
||
|
(AnsiCompareText(S1, S2) = 0);
|
||
|
//(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1), -1, PChar(S2), -1) = 2);
|
||
|
end;
|
||
|
|
||
|
{************* Some code from RAStream unit **************}
|
||
|
|
||
|
procedure StringSaveToStream(Stream: TStream; const S: string);
|
||
|
var
|
||
|
L: Integer;
|
||
|
UTF8Str: UTF8String;
|
||
|
begin
|
||
|
UTF8Str := UTF8Encode(S);
|
||
|
L := Length(UTF8Str);
|
||
|
Stream.WriteBuffer(L, SizeOf(L));
|
||
|
if L > 0 then
|
||
|
Stream.WriteBuffer(UTF8Str[1], L);
|
||
|
end;
|
||
|
|
||
|
function StringLoadFromStream(Stream: TStream): string;
|
||
|
var
|
||
|
L: Integer;
|
||
|
UTF8Str: UTF8String;
|
||
|
begin
|
||
|
Stream.ReadBuffer(L, SizeOf(L));
|
||
|
SetLength(UTF8Str, L);
|
||
|
if L > 0 then
|
||
|
Stream.ReadBuffer(UTF8Str[1], L);
|
||
|
Result := UTF8Str;
|
||
|
// Result := UTF8ToString(UTF8Str);
|
||
|
end;
|
||
|
|
||
|
procedure IntSaveToStream(Stream: TStream; AInt: Integer);
|
||
|
begin
|
||
|
Stream.WriteBuffer(AInt, SizeOf(AInt));
|
||
|
end;
|
||
|
|
||
|
function IntLoadFromStream(Stream: TStream): Integer;
|
||
|
begin
|
||
|
Stream.ReadBuffer(Result, SizeOf(Result));
|
||
|
end;
|
||
|
|
||
|
procedure WordSaveToStream(Stream: TStream; AWord: Word);
|
||
|
begin
|
||
|
Stream.WriteBuffer(AWord, SizeOf(AWord));
|
||
|
end;
|
||
|
|
||
|
function WordLoadFromStream(Stream: TStream): Word;
|
||
|
begin
|
||
|
Stream.ReadBuffer(Result, SizeOf(Result));
|
||
|
end;
|
||
|
|
||
|
procedure ExtendedSaveToStream(Stream: TStream; AExt: Extended);
|
||
|
begin
|
||
|
Stream.WriteBuffer(AExt, SizeOf(AExt));
|
||
|
end;
|
||
|
|
||
|
function ExtendedLoadFromStream(Stream: TStream): Extended;
|
||
|
begin
|
||
|
Stream.ReadBuffer(Result, SizeOf(Result));
|
||
|
end;
|
||
|
|
||
|
procedure BoolSaveToStream(Stream: TStream; ABool: Boolean);
|
||
|
var
|
||
|
B: Integer;
|
||
|
begin
|
||
|
B := Ord(ABool);
|
||
|
Stream.WriteBuffer(B, SizeOf(B));
|
||
|
end;
|
||
|
|
||
|
function BoolLoadFromStream(Stream: TStream): Boolean;
|
||
|
var
|
||
|
B: Integer;
|
||
|
begin
|
||
|
Stream.ReadBuffer(B, SizeOf(B));
|
||
|
Result := (B <> 0);
|
||
|
end;
|
||
|
|
||
|
{################## from RAStream unit ##################}
|
||
|
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
{************* Some code from Delphi's OleAuto unit **************}
|
||
|
|
||
|
const
|
||
|
{ Maximum number of dispatch arguments }
|
||
|
MaxDispArgs = 64;
|
||
|
|
||
|
{ Special variant type codes }
|
||
|
varStrArg = $0048;
|
||
|
|
||
|
{ Parameter type masks }
|
||
|
atVarMask = $3F;
|
||
|
atTypeMask = $7F;
|
||
|
atByRef = $80;
|
||
|
|
||
|
{ Call GetIDsOfNames method on the given IDispatch interface }
|
||
|
|
||
|
procedure GetIDsOfNames(Dispatch: IDispatch; Names: PChar;
|
||
|
NameCount: Integer; DispIDs: PDispIDList);
|
||
|
var
|
||
|
I, N: Integer;
|
||
|
Ch: WideChar;
|
||
|
P: PWideChar;
|
||
|
NameRefs: array [0..MaxDispArgs - 1] of PWideChar;
|
||
|
WideNames: array [0..1023] of WideChar;
|
||
|
R: Integer;
|
||
|
begin
|
||
|
I := 0;
|
||
|
N := 0;
|
||
|
repeat
|
||
|
P := @WideNames[I];
|
||
|
if N = 0 then
|
||
|
NameRefs[0] := P
|
||
|
else
|
||
|
NameRefs[NameCount - N] := P;
|
||
|
repeat
|
||
|
MultiByteToWideChar(0,0,@Names[I], 1, @ch, 1);
|
||
|
WideNames[I] := Ch;
|
||
|
Inc(I);
|
||
|
until Char(Ch) = #0;
|
||
|
Inc(N);
|
||
|
until N = NameCount;
|
||
|
{ if Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, NameCount,
|
||
|
LOCALE_SYSTEM_DEFAULT, DispIDs) <> 0 then }
|
||
|
R := Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, NameCount,
|
||
|
LOCALE_SYSTEM_DEFAULT, DispIDs);
|
||
|
if R <> 0 then
|
||
|
raise EOleError.CreateResFmt(@SNoMethod, [Names]);
|
||
|
end;
|
||
|
|
||
|
{ Central call dispatcher }
|
||
|
|
||
|
procedure VarDispInvoke(Result: PVariant; const Dispatch: Pointer;
|
||
|
Names: PChar; CallDesc: PCallDesc; ParamTypes: Pointer); cdecl;
|
||
|
var
|
||
|
DispIDs: array [0..MaxDispArgs - 1] of Integer;
|
||
|
begin
|
||
|
GetIDsOfNames(IDispatch(Dispatch), Names, CallDesc^.NamedArgCount + 1, PDispIDList(@DispIDs[0]));
|
||
|
if Result <> nil then
|
||
|
VarClear(Result^);
|
||
|
DispatchInvoke(IDispatch(Dispatch), CallDesc, PDispIDList(@DispIDs[0]), ParamTypes, Result);
|
||
|
end;
|
||
|
|
||
|
{################## from OleAuto unit ##################}
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
type
|
||
|
TFunc = procedure;
|
||
|
{$IFNDEF CPU64}
|
||
|
TiFunc = function: Integer;
|
||
|
TfFunc = function: Boolean;
|
||
|
TwFunc = function: Word;
|
||
|
{$ENDIF ~CPU64}
|
||
|
|
||
|
function CallDllIns(Ins: HINST; const FuncName: string; Args: TJvInterpreterArgs;
|
||
|
ParamDesc: TTypeArray; ResTyp: Word): Variant;
|
||
|
var
|
||
|
Func: TFunc;
|
||
|
{$IFNDEF CPU64}
|
||
|
iFunc: TiFunc;
|
||
|
fFunc: TfFunc;
|
||
|
wFunc: TwFunc;
|
||
|
{$ELSE}
|
||
|
Params: TArray<System.Rtti.TValue>;
|
||
|
{$ENDIF ~CPU64}
|
||
|
I: Integer;
|
||
|
AInt: Integer;
|
||
|
// Abyte : Byte;
|
||
|
AWord: Word;
|
||
|
APointer: Pointer;
|
||
|
Str: string;
|
||
|
begin
|
||
|
Result := Null;
|
||
|
Func := GetProcAddress(Ins, PChar(FuncName));
|
||
|
{$IFNDEF CPU64}
|
||
|
iFunc := @Func;
|
||
|
fFunc := @Func;
|
||
|
wFunc := @Func;
|
||
|
{$ENDIF ~CPU64}
|
||
|
if Assigned(Func) then
|
||
|
begin
|
||
|
try
|
||
|
{$IFNDEF CPU64}
|
||
|
for I := Args.Count - 1 downto 0 do { 'stdcall' call conversion }
|
||
|
{$ELSE}
|
||
|
SetLength(Params, Args.Count);
|
||
|
for I := 0 to Args.Count - 1 do
|
||
|
{$ENDIF ~CPU64}
|
||
|
begin
|
||
|
if (ParamDesc[I] and varByRef) = 0 then
|
||
|
case ParamDesc[I] of
|
||
|
varInteger, { ttByte,} varBoolean:
|
||
|
begin
|
||
|
AInt := Args.Values[I];
|
||
|
{$IFNDEF CPU64}
|
||
|
asm
|
||
|
push AInt
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
Params[I] := TValue.From(AInt);
|
||
|
{$ENDIF ~CPU64}
|
||
|
end;
|
||
|
varSmallint:
|
||
|
begin
|
||
|
AWord := Word(Args.Values[I]);
|
||
|
{$IFNDEF CPU64}
|
||
|
asm
|
||
|
push AWord
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
Params[I] := TValue.From(AWord);
|
||
|
{$ENDIF ~CPU64}
|
||
|
end;
|
||
|
varString:
|
||
|
begin
|
||
|
APointer := PChar(string(Args.Values[I]));
|
||
|
{$IFNDEF CPU64}
|
||
|
asm
|
||
|
push APointer
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
Params[I] := TValue.From(APointer);
|
||
|
{$ENDIF ~CPU64}
|
||
|
end;
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDllInvalidArgument, -1, FuncName);
|
||
|
end
|
||
|
else
|
||
|
case ParamDesc[I] and not varByRef of
|
||
|
varInteger, { ttByte,} varBoolean:
|
||
|
begin
|
||
|
APointer := @TVarData(Args.Values[I]).VInteger;
|
||
|
{$IFNDEF CPU64}
|
||
|
asm
|
||
|
push APointer
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
Params[I] := TValue.From(APointer);
|
||
|
{$ENDIF ~CPU64}
|
||
|
end;
|
||
|
varSmallint:
|
||
|
begin
|
||
|
APointer := @TVarData(Args.Values[I]).vSmallInt;
|
||
|
{$IFNDEF CPU64}
|
||
|
asm
|
||
|
push APointer
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
Params[I] := TValue.From(APointer);
|
||
|
{$ENDIF ~CPU64}
|
||
|
end;
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDllInvalidArgument, -1, FuncName);
|
||
|
end
|
||
|
end;
|
||
|
|
||
|
case ResTyp of
|
||
|
varSmallint:
|
||
|
{$IFNDEF CPU64}
|
||
|
Result := wFunc();
|
||
|
{$ELSE}
|
||
|
Result := System.Rtti.Invoke(@Func, Params, System.TypInfo.TCallConv.ccStdCall, TypeInfo(SmallInt), True).AsType<SmallInt>();
|
||
|
{$ENDIF ~CPU64}
|
||
|
varInteger:
|
||
|
{$IFNDEF CPU64}
|
||
|
Result := iFunc();
|
||
|
{$ELSE}
|
||
|
Result := System.Rtti.Invoke(@Func, Params, System.TypInfo.TCallConv.ccStdCall, TypeInfo(Integer), True).AsType<Integer>();
|
||
|
{$ENDIF ~CPU64}
|
||
|
varBoolean:
|
||
|
{$IFNDEF CPU64}
|
||
|
Result := Boolean(Ord(fFunc()));
|
||
|
{$ELSE}
|
||
|
Result := Boolean(Ord(System.Rtti.Invoke(@Func, Params, System.TypInfo.TCallConv.ccStdCall, TypeInfo(Boolean), True).AsType<Boolean>()));
|
||
|
{$ENDIF ~CPU64}
|
||
|
varEmpty:
|
||
|
{$IFNDEF CPU64}
|
||
|
Func();
|
||
|
{$ELSE}
|
||
|
System.Rtti.Invoke(@Func, Params, System.TypInfo.TCallConv.ccStdCall, nil, True);
|
||
|
{$ENDIF ~CPU64}
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDllInvalidResult, -1, FuncName);
|
||
|
end;
|
||
|
except
|
||
|
on E: EJvInterpreterError do
|
||
|
raise E;
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
Str := E.Message;
|
||
|
UniqueString(Str);
|
||
|
raise EJVCLException.Create(Str);
|
||
|
end;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterError(ieDllFunctionNotFound, -1);
|
||
|
end;
|
||
|
|
||
|
function CallDll(const DllName, FuncName: string; Args: TJvInterpreterArgs;
|
||
|
ParamDesc: TTypeArray; ResTyp: Word): Variant;
|
||
|
var
|
||
|
Ins: HMODULE;
|
||
|
LastError: DWORD;
|
||
|
begin
|
||
|
Result := False;
|
||
|
Ins := SafeLoadLibrary(DllName);
|
||
|
if Ins = 0 then
|
||
|
JvInterpreterErrorN(ieDllErrorLoadLibrary, -1, DllName);
|
||
|
try
|
||
|
Result := CallDllIns(Ins, FuncName, Args, ParamDesc, ResTyp);
|
||
|
(************* NOT CONVERTED ***
|
||
|
LastError := GetLastError;
|
||
|
*******************************)
|
||
|
finally
|
||
|
FreeLibrary(Ins);
|
||
|
end;
|
||
|
(************** NOT CONVERTED ***
|
||
|
SetLastError(LastError);
|
||
|
********************************)
|
||
|
end;
|
||
|
|
||
|
procedure ConvertParamTypes(InParams: array of Word; var OutParams: TTypeArray);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := Low(InParams) to High(InParams) do
|
||
|
OutParams[I] := InParams[I];
|
||
|
end;
|
||
|
|
||
|
procedure ConvertParamNames(InParams: array of string;
|
||
|
var OutParams: TNameArray);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := Low(InParams) to High(InParams) do
|
||
|
OutParams[I] := InParams[I];
|
||
|
end;
|
||
|
|
||
|
{ ************************* Array support ************************* }
|
||
|
|
||
|
function GetArraySize(Dimension: Integer; BeginPos, EndPos: TJvInterpreterArrayValues): Integer;
|
||
|
var
|
||
|
A: Integer;
|
||
|
begin
|
||
|
Result := 1;
|
||
|
for A := 0 to Dimension - 1 do
|
||
|
begin
|
||
|
Result := Result * ((EndPos[A] - BeginPos[A]) + 1);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ Calculate starting position of element in memory }
|
||
|
|
||
|
function GetArrayOffset(Dimension: Integer; BeginPos, EndPos: TJvInterpreterArrayValues;
|
||
|
Element: TJvInterpreterArrayValues): Integer;
|
||
|
var
|
||
|
A: Integer;
|
||
|
LastDim: Integer;
|
||
|
begin
|
||
|
Result := 0;
|
||
|
LastDim := 1;
|
||
|
for A := 0 to Dimension - 1 do
|
||
|
begin
|
||
|
if (Element[A] < BeginPos[A]) or (Element[A] > EndPos[A]) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
Result := Result + (LastDim * (Element[A] - BeginPos[A]));
|
||
|
LastDim := LastDim * (EndPos[A] - BeginPos[A] + 1);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{Allocate memory for new array}
|
||
|
|
||
|
function JvInterpreterArrayInit(const Dimension: Integer;
|
||
|
const BeginPos, EndPos: TJvInterpreterArrayValues;
|
||
|
const ItemType: Integer; DataType: IJvInterpreterDataType): PJvInterpreterArrayRec;
|
||
|
var
|
||
|
PP: PJvInterpreterArrayRec;
|
||
|
SS: TStringList;
|
||
|
AA: Integer;
|
||
|
ArraySize: Integer;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if (Dimension < 1) or (Dimension > cJvInterpreterMaxArgs) then
|
||
|
JvInterpreterError(ieArrayBadDimension, -1);
|
||
|
for AA := 0 to Dimension - 1 do
|
||
|
begin
|
||
|
// For dynamic arrays BeginPos[AA] <= EndPos[AA]
|
||
|
if (not (BeginPos[AA] <= EndPos[AA])) and
|
||
|
(Dimension <> 1) and (BeginPos[AA] <> 0) and (EndPos[AA] <> -1) then
|
||
|
JvInterpreterError(ieArrayBadRange, -1);
|
||
|
end;
|
||
|
|
||
|
New(PP);
|
||
|
PP^.BeginPos := BeginPos;
|
||
|
PP^.EndPos := EndPos;
|
||
|
PP^.ItemType := ItemType;
|
||
|
PP^.DT := DataType;
|
||
|
ArraySize := GetArraySize(Dimension, BeginPos, EndPos);
|
||
|
PP^.Size := ArraySize;
|
||
|
PP^.Dimension := Dimension;
|
||
|
|
||
|
if ItemType <> varString then
|
||
|
PP^.ElementSize := Typ2Size(ItemType)
|
||
|
else
|
||
|
begin
|
||
|
PP^.ElementSize := 0;
|
||
|
SS := TStringList.Create;
|
||
|
for AA := 1 to ArraySize do
|
||
|
SS.Add('');
|
||
|
PP^.Memory := SS;
|
||
|
end;
|
||
|
|
||
|
if ItemType <> varString then
|
||
|
begin
|
||
|
GetMem(PP^.Memory, ArraySize * PP^.ElementSize);
|
||
|
//ZeroMemory(PP^.Memory, ArraySize * PP^.ElementSize);
|
||
|
FillChar(PP^.Memory^, ArraySize * PP^.ElementSize, 0);
|
||
|
if ItemType = varEmpty then
|
||
|
for I := 0 to ArraySize - 1 do
|
||
|
PP^.DT.Init(Variant(PVarData(PAnsiChar(PP^.Memory) + I * PP^.ElementSize)^));
|
||
|
end;
|
||
|
Result := PP;
|
||
|
end;
|
||
|
|
||
|
{ Free memory for array }
|
||
|
|
||
|
procedure JvInterpreterArrayFree(JvInterpreterArrayRec: PJvInterpreterArrayRec);
|
||
|
var
|
||
|
I: Integer;
|
||
|
ArraySize: Integer;
|
||
|
begin
|
||
|
if not Assigned(JvInterpreterArrayRec) then
|
||
|
Exit;
|
||
|
ArraySize := GetArraySize(JvInterpreterArrayRec^.Dimension,
|
||
|
JvInterpreterArrayRec^.BeginPos, JvInterpreterArrayRec^.EndPos);
|
||
|
if JvInterpreterArrayRec^.ItemType <> varString then
|
||
|
begin
|
||
|
if JvInterpreterArrayRec^.ItemType = varEmpty then
|
||
|
for I := 0 to ArraySize - 1 do
|
||
|
JvInterpreterVarFree(Variant(PVarData(PAnsiChar(JvInterpreterArrayRec^.Memory) + I *
|
||
|
JvInterpreterArrayRec^.ElementSize)^));
|
||
|
FreeMem(JvInterpreterArrayRec^.Memory, (JvInterpreterArrayRec^.Size) *
|
||
|
JvInterpreterArrayRec^.ElementSize);
|
||
|
Dispose(JvInterpreterArrayRec);
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
TStringList(JvInterpreterArrayRec^.Memory).Clear;
|
||
|
TStringList(JvInterpreterArrayRec^.Memory).Free;
|
||
|
Dispose(JvInterpreterArrayRec);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ Set element for array }
|
||
|
|
||
|
procedure JvInterpreterArraySetElement(Element: TJvInterpreterArrayValues; Value: Variant;
|
||
|
JvInterpreterArrayRec: PJvInterpreterArrayRec);
|
||
|
var
|
||
|
Offset: Integer;
|
||
|
P: Pointer;
|
||
|
begin
|
||
|
if JvInterpreterArrayRec^.Dimension > 1 then
|
||
|
Offset := GetArrayOffset(JvInterpreterArrayRec^.Dimension, JvInterpreterArrayRec^.BeginPos,
|
||
|
JvInterpreterArrayRec^.EndPos, Element)
|
||
|
else
|
||
|
Offset := Element[0] - JvInterpreterArrayRec^.BeginPos[0];
|
||
|
P := Pointer(PAnsiChar(JvInterpreterArrayRec^.Memory) + (Offset * JvInterpreterArrayRec^.ElementSize));
|
||
|
case JvInterpreterArrayRec^.ItemType of
|
||
|
varInteger:
|
||
|
PInteger(P)^ := Value;
|
||
|
varDouble:
|
||
|
PDouble(P)^ := Value;
|
||
|
varByte:
|
||
|
PByte(P)^ := Value;
|
||
|
varSmallint:
|
||
|
PSmallInt(P)^ := Value;
|
||
|
varDate:
|
||
|
PDouble(P)^ := Value;
|
||
|
varString:
|
||
|
begin
|
||
|
Value := VarAsType(Value, varString);
|
||
|
TStringList(JvInterpreterArrayRec^.Memory).Strings[Offset] := Value;
|
||
|
end;
|
||
|
varEmpty:
|
||
|
JvInterpreterVarAssignment(Variant(PVarData(P)^), Value);
|
||
|
else
|
||
|
if JvInterpreterArrayRec^.ItemType = varObject then
|
||
|
TObject(P^) := V2O(Value);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ Get element for array }
|
||
|
|
||
|
function JvInterpreterArrayGetElement(Element: TJvInterpreterArrayValues;
|
||
|
JvInterpreterArrayRec: PJvInterpreterArrayRec): Variant;
|
||
|
var
|
||
|
Offset: Integer;
|
||
|
P: Pointer;
|
||
|
begin
|
||
|
if JvInterpreterArrayRec^.Dimension > 1 then
|
||
|
Offset := GetArrayOffset(JvInterpreterArrayRec^.Dimension, JvInterpreterArrayRec^.BeginPos,
|
||
|
JvInterpreterArrayRec^.EndPos, Element)
|
||
|
else
|
||
|
Offset := Element[0] - JvInterpreterArrayRec^.BeginPos[0];
|
||
|
P := Pointer(PAnsiChar(JvInterpreterArrayRec^.Memory) + (Offset * JvInterpreterArrayRec^.ElementSize));
|
||
|
case JvInterpreterArrayRec^.ItemType of
|
||
|
varInteger:
|
||
|
Result := Integer(P^);
|
||
|
varDouble:
|
||
|
Result := Double(P^);
|
||
|
varByte:
|
||
|
Result := Byte(P^);
|
||
|
varSmallint:
|
||
|
Result := Smallint(P^);
|
||
|
varDate:
|
||
|
Result := TDateTime(P^);
|
||
|
varString:
|
||
|
Result := TStringList(JvInterpreterArrayRec^.Memory).Strings[Offset];
|
||
|
varEmpty:
|
||
|
JvInterpreterVarCopy(Result, Variant(PVarData(P)^));
|
||
|
else
|
||
|
if JvInterpreterArrayRec^.ItemType = varObject then
|
||
|
Result := O2V(TObject(P^));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ For dynamic array support }
|
||
|
|
||
|
procedure JvInterpreterArraySetLength(AArray: Variant; ASize: Integer);
|
||
|
var
|
||
|
I: Integer;
|
||
|
OldSize: Integer;
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(AArray).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryDynamicArraysSupportIsMadeForO);
|
||
|
OldSize := ArrayRec^.Size;
|
||
|
if OldSize > ASize then
|
||
|
begin
|
||
|
for I := ASize to OldSize - 1 do
|
||
|
if ArrayRec^.ItemType = varEmpty then
|
||
|
JvInterpreterVarFree(Variant((PVarData(PAnsiChar(ArrayRec^.Memory) + I * ArrayRec^.ElementSize))^));
|
||
|
ArrayRec^.EndPos[0] := ArrayRec^.EndPos[0] - (OldSize - ASize);
|
||
|
ArrayRec^.Size := GetArraySize(1, ArrayRec^.BeginPos, ArrayRec^.EndPos);
|
||
|
ReallocMem(ArrayRec^.Memory, ASize * ArrayRec^.ElementSize);
|
||
|
end
|
||
|
else
|
||
|
if OldSize < ASize then
|
||
|
begin
|
||
|
ReallocMem(ArrayRec^.Memory, ASize * ArrayRec^.ElementSize);
|
||
|
FillChar((PAnsiChar(ArrayRec^.Memory) + OldSize * ArrayRec^.ElementSize)^,
|
||
|
(ASize - OldSize) * ArrayRec^.ElementSize, 0);
|
||
|
for I := OldSize to ASize - 1 do
|
||
|
if ArrayRec^.ItemType = varEmpty then
|
||
|
ArrayRec^.DT.Init(Variant(Pointer(PAnsiChar(ArrayRec^.Memory) + I * ArrayRec^.ElementSize)^));
|
||
|
ArrayRec^.EndPos[0] := ArrayRec^.EndPos[0] + (ASize - OldSize);
|
||
|
ArrayRec^.Size := GetArraySize(ArrayRec^.Dimension, ArrayRec^.BeginPos, ArrayRec^.EndPos);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function JvInterpreterArrayLength(const AArray: Variant): Integer;
|
||
|
var
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(AArray).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryForOneDimensionalArraysOnly);
|
||
|
Result := ArrayRec^.Size;
|
||
|
end;
|
||
|
|
||
|
function JvInterpreterArrayLow(const AArray: Variant): Integer;
|
||
|
var
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(AArray).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryForOneDimensionalArraysOnly);
|
||
|
Result := ArrayRec^.BeginPos[0];
|
||
|
end;
|
||
|
|
||
|
function JvInterpreterArrayHigh(const AArray: Variant): Integer;
|
||
|
var
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(AArray).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryForOneDimensionalArraysOnly);
|
||
|
Result := ArrayRec^.EndPos[0];
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterArrayElementDelete(AArray: Variant; AElement: Integer);
|
||
|
var
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(AArray).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryForOneDimensionalArraysOnly);
|
||
|
if (AElement < ArrayRec^.BeginPos[0]) or (AElement > ArrayRec^.EndPos[0]) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
ArrayRec^.EndPos[0] := ArrayRec^.EndPos[0] - 1;
|
||
|
ArrayRec^.Size := GetArraySize(ArrayRec^.Dimension, ArrayRec^.BeginPos, ArrayRec^.EndPos);
|
||
|
if ArrayRec^.ItemType = varEmpty then
|
||
|
JvInterpreterVarFree(Variant(PVarData(PAnsiChar(ArrayRec^.Memory) +
|
||
|
(AElement - ArrayRec^.BeginPos[0]) * ArrayRec^.ElementSize)^));
|
||
|
Move((PAnsiChar(ArrayRec^.Memory) + (AElement - ArrayRec^.BeginPos[0] + 1) * ArrayRec^.ElementSize)^,
|
||
|
(PAnsiChar(ArrayRec^.Memory) + (AElement - ArrayRec^.BeginPos[0]) * ArrayRec^.ElementSize)^,
|
||
|
(ArrayRec^.EndPos[0] - AElement + 1) * ArrayRec^.ElementSize);
|
||
|
ReallocMem(ArrayRec^.Memory, ArrayRec^.Size * ArrayRec^.ElementSize);
|
||
|
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterArrayElementInsert(AArray: Variant; AElement: Integer; Value: Variant);
|
||
|
var
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(AArray).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryForOneDimensionalArraysOnly);
|
||
|
if (AElement < ArrayRec^.BeginPos[0]) or (AElement > ArrayRec^.EndPos[0]) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
ArrayRec^.EndPos[0] := ArrayRec^.EndPos[0] + 1;
|
||
|
ArrayRec^.Size := GetArraySize(ArrayRec^.Dimension, ArrayRec^.BeginPos, ArrayRec^.EndPos);
|
||
|
ReallocMem(ArrayRec^.Memory, ArrayRec^.Size * ArrayRec^.ElementSize);
|
||
|
Move((PAnsiChar(ArrayRec^.Memory) + (AElement - ArrayRec^.BeginPos[0]) * ArrayRec^.ElementSize)^,
|
||
|
(PAnsiChar(ArrayRec^.Memory) + (AElement - ArrayRec^.BeginPos[0] + 1) * ArrayRec^.ElementSize)^,
|
||
|
(ArrayRec^.EndPos[0] - AElement) * ArrayRec^.ElementSize);
|
||
|
if ArrayRec^.ItemType = varEmpty then
|
||
|
ArrayRec^.DT.Init(Variant(PVarData(PAnsiChar(ArrayRec^.Memory) +
|
||
|
(AElement - ArrayRec^.BeginPos[0]) * ArrayRec^.ElementSize)^));
|
||
|
JvInterpreterVarAssignment(Variant(PVarData(PAnsiChar(ArrayRec^.Memory) +
|
||
|
(AElement - ArrayRec^.BeginPos[0]) * ArrayRec^.ElementSize)^), Value);
|
||
|
end;
|
||
|
|
||
|
procedure V2OA(V: Variant; var OA: TOpenArray; var OAValues: TValueArray;
|
||
|
var Size: Integer);
|
||
|
var
|
||
|
I: Integer;
|
||
|
ArrayRec: PJvInterpreterArrayRec;
|
||
|
Element: TJvInterpreterArrayValues;
|
||
|
ElementVariant: Variant;
|
||
|
begin
|
||
|
if TVarData(V).VType = varArray then
|
||
|
//JvInterpreterError(ieTypeMistmatch, -1);
|
||
|
begin
|
||
|
ArrayRec := PJvInterpreterArrayRec(TVarData(V).VPointer);
|
||
|
if ArrayRec^.Dimension > 1 then
|
||
|
raise EJVCLException.CreateRes(@RsESorryForOneDimensionalArraysOnly);
|
||
|
Size := ArrayRec^.Size;
|
||
|
for I := 0 to Size - 1 do
|
||
|
begin
|
||
|
Element[0] := I;
|
||
|
ElementVariant := JvInterpreterArrayGetElement(Element, ArrayRec);
|
||
|
case TVarData(ElementVariant).VType of
|
||
|
varInteger, varSmallint:
|
||
|
begin
|
||
|
OAValues[I] := ElementVariant;
|
||
|
OA[I].VInteger := ElementVariant;
|
||
|
OA[I].VType := vtInteger;
|
||
|
end;
|
||
|
varString, varOleStr:
|
||
|
begin
|
||
|
// OA[I].vPChar := PChar(string(V[I]));
|
||
|
// OA[I].VType := vtPChar;
|
||
|
OAValues[I] := ElementVariant;
|
||
|
OA[I].VVariant := @OAValues[I];
|
||
|
OA[I].VType := vtVariant;
|
||
|
end;
|
||
|
varBoolean:
|
||
|
begin
|
||
|
OAValues[I] := ElementVariant;
|
||
|
OA[I].VBoolean := ElementVariant;
|
||
|
OA[I].VType := vtBoolean;
|
||
|
end;
|
||
|
varDouble, varCurrency:
|
||
|
begin
|
||
|
OAValues[i] := V[i];
|
||
|
VarCast(OAValues[I], OAValues[I], varCurrency);
|
||
|
OA[i].vCurrency := @TVarData(OAValues[i]).vCurrency;
|
||
|
OA[i].VType := vtCurrency;
|
||
|
end;
|
||
|
else
|
||
|
OAValues[I] := ElementVariant;
|
||
|
OA[I].VVariant := @OAValues[I];
|
||
|
OA[I].VType := vtVariant;
|
||
|
end;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
Size := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
|
||
|
for I := VarArrayLowBound(V, 1) to VarArrayHighBound(V, 1) do
|
||
|
begin
|
||
|
case TVarData(V[I]).VType of
|
||
|
varInteger, varSmallint:
|
||
|
begin
|
||
|
OAValues[I] := V[I];
|
||
|
OA[I].VInteger := V[I];
|
||
|
OA[I].VType := vtInteger;
|
||
|
end;
|
||
|
varString, varOleStr:
|
||
|
begin
|
||
|
OAValues[I] := V[I];
|
||
|
OA[I].VVariant := @OAValues[I];
|
||
|
OA[I].VType := vtVariant;
|
||
|
end;
|
||
|
varBoolean:
|
||
|
begin
|
||
|
OAValues[I] := V[I];
|
||
|
OA[I].VBoolean := V[I];
|
||
|
OA[I].VType := vtBoolean;
|
||
|
end;
|
||
|
varDouble, varCurrency:
|
||
|
begin
|
||
|
OAValues[i] := V[i];
|
||
|
VarCast(OAValues[I], OAValues[I], varCurrency);
|
||
|
OA[i].vCurrency := @TVarData(OAValues[i]).vCurrency;
|
||
|
OA[i].VType := vtCurrency;
|
||
|
end;
|
||
|
else
|
||
|
OAValues[I] := V[I];
|
||
|
OA[I].VVariant := @OAValues[I];
|
||
|
OA[I].VType := vtVariant;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end;
|
||
|
|
||
|
{ ########################## Array support ########################## }
|
||
|
|
||
|
{ ************************ extended variants ************************ }
|
||
|
|
||
|
function JvInterpreterVarAsType(const V: Variant; const VarType: Integer): Variant;
|
||
|
begin
|
||
|
if (TVarData(V).VType = varEmpty) or (TVarData(V).VType = varNull) then
|
||
|
begin
|
||
|
case VarType of
|
||
|
varString, varOleStr:
|
||
|
Result := '';
|
||
|
varInteger, varSmallint, varByte:
|
||
|
Result := 0;
|
||
|
varBoolean:
|
||
|
Result := False;
|
||
|
varSingle, varDouble, varCurrency, varDate:
|
||
|
Result := 0.0;
|
||
|
varVariant:
|
||
|
Result := Null;
|
||
|
else
|
||
|
Result := VarAsType(V, VarType);
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if TVarData(V).VType = varArray then
|
||
|
begin
|
||
|
TVarData(Result) := TVarData(V);
|
||
|
TVarData(Result).VType := VarType;
|
||
|
end
|
||
|
else
|
||
|
if (VarType = varEmpty) and not VarIsEmpty(V) then
|
||
|
Result := V // because any cast to unassigned = unassigned
|
||
|
else
|
||
|
Result := VarAsType(V, VarType);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterVarAssignment(var Dest: Variant; const Source: Variant);
|
||
|
var
|
||
|
I: Integer;
|
||
|
DestRecHolder: TJvInterpreterRecHolder;
|
||
|
SourceRecHolder: TJvInterpreterRecHolder;
|
||
|
begin
|
||
|
if TVarData(Source).VType = varArray then
|
||
|
begin
|
||
|
NotImplemented(RsArrayToArrayAssignment);
|
||
|
// TVarData(Dest) := TVarData(Source);
|
||
|
end
|
||
|
else
|
||
|
if TVarData(Source).VType = varRecord then
|
||
|
begin
|
||
|
DestRecHolder := TJvInterpreterRecHolder(TVarData(Dest).VPointer);
|
||
|
SourceRecHolder := TJvInterpreterRecHolder(TVarData(Source).VPointer);
|
||
|
for I := 0 to SourceRecHolder.JvInterpreterRecord.FieldCount - 1 do
|
||
|
if SourceRecHolder.JvInterpreterRecord.Fields[I].Typ = varEmpty then
|
||
|
JvInterpreterVarAssignment(Variant(PVarData(PAnsiChar(DestRecHolder.Rec) +
|
||
|
DestRecHolder.JvInterpreterRecord.Fields[I].Offset)^),
|
||
|
Variant(PVarData(PAnsiChar(SourceRecHolder.Rec) +
|
||
|
SourceRecHolder.JvInterpreterRecord.Fields[I].Offset)^))
|
||
|
else
|
||
|
Move((PAnsiChar(SourceRecHolder.Rec) +
|
||
|
SourceRecHolder.JvInterpreterRecord.Fields[I].Offset)^,
|
||
|
(PAnsiChar(DestRecHolder.Rec) +
|
||
|
DestRecHolder.JvInterpreterRecord.Fields[I].Offset)^,
|
||
|
Typ2Size(SourceRecHolder.JvInterpreterRecord.Fields[I].Typ));
|
||
|
end
|
||
|
else
|
||
|
Dest := Source;
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterVarCopy(var Dest: Variant; const Source: Variant);
|
||
|
begin
|
||
|
if (TVarData(Source).VType = varArray) or (TVarData(Source).VType = varRecord) then
|
||
|
TVarData(Dest) := TVarData(Source)
|
||
|
else
|
||
|
Dest := Source;
|
||
|
end;
|
||
|
|
||
|
procedure JvInterpreterVarFree(var V: Variant);
|
||
|
var
|
||
|
TempType: TVarType;
|
||
|
begin
|
||
|
TempType := TVarData(V).VType;
|
||
|
if TempType = varArray then
|
||
|
JvInterpreterArrayFree(PJvInterpreterArrayRec(TVarData(V).VPointer))
|
||
|
else
|
||
|
if TempType = varRecord then
|
||
|
TJvInterpreterRecHolder(TVarData(V).VPointer).Free;
|
||
|
varclear(V);
|
||
|
end;
|
||
|
|
||
|
{
|
||
|
function VarAsType2(const V: Variant; VarType: Integer): Variant;
|
||
|
begin
|
||
|
if TVarData(V).VType = varNull then
|
||
|
Result := VarAsType(Unassigned,VarType)
|
||
|
else
|
||
|
Result := VarAsType(V,VarType);
|
||
|
end;
|
||
|
}
|
||
|
|
||
|
function Var2Type(V: Variant; const VarType: Integer): Variant;
|
||
|
begin
|
||
|
if (TVarData(V).VType = varEmpty) or (TVarData(V).VType = varNull) then
|
||
|
begin
|
||
|
case VarType of
|
||
|
varString, varOleStr:
|
||
|
Result := '';
|
||
|
varInteger, varSmallint, varByte:
|
||
|
Result := 0;
|
||
|
varBoolean:
|
||
|
Result := False;
|
||
|
varSingle, varDouble, varCurrency, varDate:
|
||
|
Result := 0.0;
|
||
|
varVariant:
|
||
|
Result := Null;
|
||
|
else
|
||
|
Result := VarAsType(V, VarType);
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
Result := VarAsType(V, VarType);
|
||
|
if (VarType = varInteger) and (TVarData(V).VType = varBoolean) then
|
||
|
Result := Ord(V = True);
|
||
|
end;
|
||
|
{ ######################## extended variants ######################## }
|
||
|
|
||
|
//=== { TJvInterpreterVar } ==================================================
|
||
|
|
||
|
destructor TJvInterpreterVar.Destroy;
|
||
|
begin
|
||
|
JvInterpreterVarFree(Value);
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterVarList } ==============================================
|
||
|
|
||
|
destructor TJvInterpreterVarList.Destroy;
|
||
|
begin
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterVarList.Clear;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to Count - 1 do
|
||
|
TJvInterpreterVar(Items[I]).Free;
|
||
|
inherited Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterVarList.AddVar(const UnitName, Identifier, Typ: string; VTyp: Word;
|
||
|
const Value: Variant; DataType: IJvInterpreterDataType);
|
||
|
var
|
||
|
VarRec: TJvInterpreterVar;
|
||
|
begin
|
||
|
if FindVar(UnitName, Identifier) <> nil then
|
||
|
JvInterpreterErrorN(ieIdentifierRedeclared, -1, Identifier);
|
||
|
VarRec := TJvInterpreterVar.Create;
|
||
|
VarRec.Identifier := Identifier;
|
||
|
VarRec.UnitName := UnitName;
|
||
|
JvInterpreterVarCopy(VarRec.Value, Value);
|
||
|
VarRec.Typ := Typ;
|
||
|
VarRec.VTyp := VTyp;
|
||
|
Insert(0, VarRec);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterVarList.FindVar(const UnitName, Identifier: string): TJvInterpreterVar;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to Count - 1 do
|
||
|
begin
|
||
|
Result := TJvInterpreterVar(Items[I]);
|
||
|
{ if UnitName = '', any unit allowed }
|
||
|
if Cmp(Result.Identifier, Identifier) and
|
||
|
(Cmp(Result.UnitName, UnitName) or (UnitName = '')) then
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterVarList.DeleteVar(const UnitName, Identifier: string);
|
||
|
var
|
||
|
I: Integer;
|
||
|
VarRec: TJvInterpreterVar;
|
||
|
begin
|
||
|
for I := 0 to Count - 1 do
|
||
|
begin
|
||
|
VarRec := TJvInterpreterVar(Items[I]);
|
||
|
if Cmp(VarRec.Identifier, Identifier) and
|
||
|
(Cmp(VarRec.UnitName, UnitName) or (UnitName = '')) then
|
||
|
begin
|
||
|
JvInterpreterVarFree(VarRec.Value);
|
||
|
VarRec.Free;
|
||
|
Delete(I);
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterVarList.GetValue(const Identifier: string; var Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
V: TJvInterpreterVar;
|
||
|
begin
|
||
|
if Args.Obj = nil then
|
||
|
V := FindVar('', Identifier)
|
||
|
else
|
||
|
if (Args.ObjTyp = varObject) and (Args.Obj is TJvInterpreterSrcUnit) then
|
||
|
V := FindVar((Args.Obj as TJvInterpreterSrcUnit).Identifier, Identifier)
|
||
|
else
|
||
|
V := nil;
|
||
|
Result := V <> nil;
|
||
|
if Result then
|
||
|
JvInterpreterVarCopy(Value, V.Value);
|
||
|
end;
|
||
|
|
||
|
(*
|
||
|
function TJvInterpreterVarList.SetValue(Identifier: string; const Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
V: TJvInterpreterVar;
|
||
|
begin
|
||
|
V := FindVar('', Identifier);
|
||
|
Result := (V <> nil) and (Args.Obj = nil);
|
||
|
if Result then
|
||
|
JvInterpreterVarAssignment(V.Value, Value);
|
||
|
end; { SetValue }
|
||
|
*)
|
||
|
|
||
|
function TJvInterpreterVarList.SetValue(const Identifier: string; const Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
V: TJvInterpreterVar;
|
||
|
begin
|
||
|
V := FindVar('', Identifier);
|
||
|
Result := (V <> nil) and (Args.Obj = nil);
|
||
|
if Result then
|
||
|
{ If 0, then it's probably an object }
|
||
|
{ If a Variant, then we don't care about typecasting }
|
||
|
{ We only want to typecast if the types are not the same, for speed }
|
||
|
if (V.VTyp <> 0) and
|
||
|
(V.VTyp <> varVariant) and
|
||
|
(TVarData(Value).VType <> V.VTyp) then
|
||
|
begin
|
||
|
{ Is it a passed-by-reference variable? }
|
||
|
if V.VTyp and varByRef > 0 then
|
||
|
begin
|
||
|
JvInterpreterVarAssignment(V.Value, JvInterpreterVarAsType(Value, V.VTyp and not varByRef));
|
||
|
V.VTyp := V.VTyp or varByRef;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterVarAssignment(V.Value, JvInterpreterVarAsType(Value, V.VTyp))
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterVarAssignment(V.Value, Value);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterVarList.Assign(source: TJvInterpreterVarList);
|
||
|
var
|
||
|
I: Integer;
|
||
|
SrcVar: TJvInterpreterVar;
|
||
|
begin
|
||
|
Clear;
|
||
|
for I := 0 to Source.Count-1 do
|
||
|
begin
|
||
|
SrcVar := TJvInterpreterVar(Source[I]);
|
||
|
with SrcVar do
|
||
|
AddVar(UnitName, Identifier, Typ, VTyp, Value, nil); // DataType not used
|
||
|
//TJvInterpreterSimpleDataType.Create(varVariant);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterFunctionDesc } =========================================
|
||
|
|
||
|
function TJvInterpreterFunctionDesc.GetParamType(Index: Integer): Word;
|
||
|
begin
|
||
|
Result := FParamTypes[Index];
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunctionDesc.GetParamTypeNames(Index: Integer): string;
|
||
|
begin
|
||
|
Result := FParamTypeNames[Index];
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunctionDesc.GetDefine: string;
|
||
|
var
|
||
|
Fun, S, T: string;
|
||
|
Param, Ret: string;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
Result := '';
|
||
|
if FIdentifier = '' then
|
||
|
Exit;
|
||
|
|
||
|
T := '%s %s(%s)%s;';
|
||
|
|
||
|
if FResTyp = varEmpty then
|
||
|
begin
|
||
|
Fun := 'procedure';
|
||
|
Ret := '';
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
Fun := 'function';
|
||
|
Ret := ': ' + ResTypName;
|
||
|
end;
|
||
|
|
||
|
for I := 0 to ParamCount - 1 do
|
||
|
begin
|
||
|
if (ParamTypes[I] and varByRef) = varByRef then
|
||
|
S := 'Var ' + ParamNames[I]
|
||
|
else
|
||
|
if (ParamTypes[I] and varByConst) = varByConst then
|
||
|
S := 'Const ' + ParamNames[I]
|
||
|
else
|
||
|
S := ParamNames[I];
|
||
|
|
||
|
Param := Param + S + ': ' + ParamTypeNames[I];
|
||
|
if I <> ParamCount - 1 then
|
||
|
Param := Param + '; ';
|
||
|
end;
|
||
|
Result := Format(T, [Fun, FIdentifier, Param, Ret]);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunctionDesc.GetParamName(Index: Integer): string;
|
||
|
begin
|
||
|
Result := FParamNames[Index];
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterRecHolder } ============================================
|
||
|
|
||
|
constructor TJvInterpreterRecHolder.Create(const ARecordType: string; ARec: Pointer);
|
||
|
begin
|
||
|
// (rom) added inherited Create
|
||
|
inherited Create;
|
||
|
Assert(ARecordType <> '');
|
||
|
FRecordType := ARecordType;
|
||
|
Rec := ARec;
|
||
|
{$IFDEF JvInterpreter_DEBUG}
|
||
|
Inc(ObjCount);
|
||
|
{$ENDIF JvInterpreter_DEBUG}
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterRecHolder.Destroy;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if Assigned(JvInterpreterRecord) then
|
||
|
begin
|
||
|
if Assigned(JvInterpreterRecord.DestroyFunc) then
|
||
|
JvInterpreterRecord.DestroyFunc(Rec)
|
||
|
else
|
||
|
begin
|
||
|
for I := 0 to JvInterpreterRecord.FieldCount - 1 do
|
||
|
begin
|
||
|
if JvInterpreterRecord.Fields[I].Typ = varEmpty then
|
||
|
JvInterpreterVarFree(Variant(PVarData(PAnsiChar(Rec) + JvInterpreterRecord.Fields[I].Offset)^));
|
||
|
end;
|
||
|
FreeMem(Rec, JvInterpreterRecord.RecordSize);
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
inherited Destroy;
|
||
|
{$IFDEF JvInterpreter_DEBUG}
|
||
|
Dec(ObjCount);
|
||
|
{$ENDIF JvInterpreter_DEBUG}
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterSrcFunction } ==========================================
|
||
|
|
||
|
constructor TJvInterpreterSrcFunction.Create;
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FFunctionDesc := TJvInterpreterFunctionDesc.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterSrcFunction.Destroy;
|
||
|
begin
|
||
|
FFunctionDesc.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterExtFunction } ==========================================
|
||
|
|
||
|
function TJvInterpreterExtFunction.CallDll(Args: TJvInterpreterArgs): Variant;
|
||
|
begin
|
||
|
if DllInstance > 0 then
|
||
|
Result := JvInterpreter.CallDllIns(DllInstance, FunctionName, Args, FunctionDesc.FParamTypes,
|
||
|
FunctionDesc.ResTyp)
|
||
|
else
|
||
|
Result := JvInterpreter.CallDll(DllName, FunctionName, Args, FunctionDesc.FParamTypes,
|
||
|
FunctionDesc.ResTyp)
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterEvent } ================================================
|
||
|
|
||
|
constructor TJvInterpreterEvent.Create(AOwner: TJvInterpreterExpression;
|
||
|
AInstance: TObject; const AUnitName, AFunctionName, APropName: string);
|
||
|
begin
|
||
|
// (rom) added inherited Create
|
||
|
inherited Create;
|
||
|
FOwner := AOwner;
|
||
|
FInstance := AInstance;
|
||
|
FUnitName := AUnitName;
|
||
|
FFunctionName := AFunctionName;
|
||
|
FPropName := APropName;
|
||
|
{$IFDEF JvInterpreter_DEBUG}
|
||
|
Inc(ObjCount);
|
||
|
{$ENDIF JvInterpreter_DEBUG}
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterEvent.Destroy;
|
||
|
begin
|
||
|
FArgs.Free;
|
||
|
inherited Destroy;
|
||
|
{$IFDEF JvInterpreter_DEBUG}
|
||
|
Dec(ObjCount);
|
||
|
{$ENDIF JvInterpreter_DEBUG}
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterEvent.GetArgs: TJvInterpreterArgs;
|
||
|
begin
|
||
|
if FArgs = nil then
|
||
|
FArgs := TJvInterpreterArgs.Create;
|
||
|
Result := FArgs;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterEvent.CallFunction(Args: TJvInterpreterArgs;
|
||
|
Params: array of Variant): Variant;
|
||
|
var
|
||
|
I: Integer;
|
||
|
NV: Variant;
|
||
|
begin
|
||
|
if Args = nil then
|
||
|
Args := Self.Args;
|
||
|
Args.Clear;
|
||
|
for I := Low(Params) to High(Params) do
|
||
|
begin
|
||
|
Args.Values[Args.Count] := Params[I];
|
||
|
Inc(Args.Count);
|
||
|
end;
|
||
|
NV := Null;
|
||
|
Result := FOwner.CallFunctionEx(FInstance, FUnitName, FFunctionName, Args, NV);
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterIdentifierList } =======================================
|
||
|
|
||
|
function TJvInterpreterIdentifierList.Find(const Identifier: string;
|
||
|
var Index: Integer): Boolean;
|
||
|
var
|
||
|
L, H, I, C: Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
L := 0;
|
||
|
H := Count - 1;
|
||
|
while L <= H do
|
||
|
begin
|
||
|
I := (L + H) shr 1;
|
||
|
C := AnsiStrIComp(PChar(TJvInterpreterIdentifier(List[I]).Identifier), PChar(Identifier));
|
||
|
if C < 0 then
|
||
|
L := I + 1
|
||
|
else
|
||
|
begin
|
||
|
H := I - 1;
|
||
|
if C = 0 then
|
||
|
begin
|
||
|
Result := True;
|
||
|
if Duplicates <> dupAccept then
|
||
|
L := I;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
Index := L;
|
||
|
end;
|
||
|
|
||
|
function SortIdentifier(Item1, Item2: Pointer): Integer;
|
||
|
begin
|
||
|
{ function AnsiStrIComp about 30% faster than AnsiCompareText }
|
||
|
{ Result := AnsiCompareText(TJvInterpreterIdentifier(Item1).Identifier,
|
||
|
TJvInterpreterIdentifier(Item2).Identifier); }
|
||
|
Result := AnsiStrIComp(PChar(TJvInterpreterIdentifier(Item1).Identifier),
|
||
|
PChar(TJvInterpreterIdentifier(Item2).Identifier));
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterIdentifierList.Sort(Compare: TListSortCompare = nil);
|
||
|
begin
|
||
|
if Assigned(Compare) then
|
||
|
inherited Sort(Compare)
|
||
|
else
|
||
|
inherited Sort(SortIdentifier);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterIdentifierList.IndexOf(const UnitName, Identifier: string): TJvInterpreterIdentifier;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := Count - 1 downto 0 do
|
||
|
begin
|
||
|
Result := TJvInterpreterIdentifier(Items[I]);
|
||
|
if Cmp(Result.Identifier, Identifier) and
|
||
|
(Cmp(Result.UnitName, UnitName) or (UnitName = '')) then
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterAdapter } ==============================================
|
||
|
|
||
|
constructor TJvInterpreterAdapter.Create(AOwner: TJvInterpreterExpression);
|
||
|
begin
|
||
|
// (rom) added inherited Create
|
||
|
inherited Create;
|
||
|
FOwner := AOwner;
|
||
|
FSrcUnitList := TJvInterpreterIdentifierList.Create;
|
||
|
FExtUnitList := TJvInterpreterIdentifierList.Create;
|
||
|
FIntfGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FIntfSetList := TJvInterpreterIdentifierList.Create;
|
||
|
FIntfIGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FIntfISetList := TJvInterpreterIdentifierList.Create;
|
||
|
FIntfIDGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FIntfIDSetList := TJvInterpreterIdentifierList.Create;
|
||
|
FGetList := TJvInterpreterMethodList.Create;
|
||
|
FSetList := TJvInterpreterMethodList.Create;
|
||
|
FIGetList := TJvInterpreterMethodList.Create;
|
||
|
FISetList := TJvInterpreterMethodList.Create;
|
||
|
FIDGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FIDSetList := TJvInterpreterIdentifierList.Create;
|
||
|
FDirectGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FClassList := TJvInterpreterIdentifierList.Create;
|
||
|
FConstList := TJvInterpreterIdentifierList.Create;
|
||
|
FFunctionList := TJvInterpreterMethodList.Create;
|
||
|
FRecordList := TJvInterpreterIdentifierList.Create;
|
||
|
FRecordGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FRecordSetList := TJvInterpreterIdentifierList.Create;
|
||
|
FOnGetList := TJvInterpreterIdentifierList.Create;
|
||
|
FOnSetList := TJvInterpreterIdentifierList.Create;
|
||
|
FExtFunctionList := TJvInterpreterIdentifierList.Create;
|
||
|
FSrcFunctionList := TJvInterpreterIdentifierList.Create;
|
||
|
FEventHandlerList := TJvInterpreterIdentifierList.Create;
|
||
|
FEventList := TJvInterpreterIdentifierList.Create;
|
||
|
FSrcVarList := TJvInterpreterVarList.Create;
|
||
|
FSrcClassList := TJvInterpreterIdentifierList.Create;
|
||
|
|
||
|
FIntfGetList.Duplicates := dupAccept;
|
||
|
FIntfSetList.Duplicates := dupAccept;
|
||
|
FIntfIGetList.Duplicates := dupAccept;
|
||
|
FIntfISetList.Duplicates := dupAccept;
|
||
|
FGetList.Duplicates := dupAccept;
|
||
|
FSetList.Duplicates := dupAccept;
|
||
|
FIGetList.Duplicates := dupAccept;
|
||
|
FISetList.Duplicates := dupAccept;
|
||
|
|
||
|
FDisableExternalFunctions := False;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterAdapter.Destroy;
|
||
|
begin
|
||
|
Clear;
|
||
|
FSrcUnitList.Free;
|
||
|
FExtUnitList.Free;
|
||
|
FIntfGetList.Free;
|
||
|
FIntfSetList.Free;
|
||
|
FIntfIGetList.Free;
|
||
|
FIntfISetList.Free;
|
||
|
FIntfIDGetList.Free;
|
||
|
FIntfIDSetList.Free;
|
||
|
FGetList.Free;
|
||
|
FSetList.Free;
|
||
|
FIGetList.Free;
|
||
|
FISetList.Free;
|
||
|
FIDGetList.Free;
|
||
|
FIDSetList.Free;
|
||
|
FDirectGetList.Free;
|
||
|
FClassList.Free;
|
||
|
FConstList.Free;
|
||
|
FFunctionList.Free;
|
||
|
FRecordList.Free;
|
||
|
FRecordGetList.Free;
|
||
|
FRecordSetList.Free;
|
||
|
FOnGetList.Free;
|
||
|
FOnSetList.Free;
|
||
|
FExtFunctionList.Free;
|
||
|
FSrcFunctionList.Free;
|
||
|
FEventHandlerList.Free;
|
||
|
FEventList.Free;
|
||
|
FSrcVarList.Free;
|
||
|
FSrcClassList.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.ClearSource;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
ClearList(FSrcUnitList);
|
||
|
ClearList(FSrcFunctionList);
|
||
|
FSrcVarList.Clear;
|
||
|
for I := 0 to FSrcClassList.Count-1 do
|
||
|
TJvInterpreterClass(FSrcClassList[I]).ClassFields.Clear;
|
||
|
ClearList(FSrcClassList);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.ClearNonSource;
|
||
|
begin
|
||
|
ClearList(FExtUnitList);
|
||
|
ClearList(FIntfGetList);
|
||
|
ClearList(FIntfSetList);
|
||
|
ClearList(FIntfIGetList);
|
||
|
ClearList(FIntfISetList);
|
||
|
ClearList(FIntfIDGetList);
|
||
|
ClearList(FIntfIDSetList);
|
||
|
ClearList(FGetList);
|
||
|
ClearList(FSetList);
|
||
|
ClearList(FIGetList);
|
||
|
ClearList(FISetList);
|
||
|
ClearList(FIDGetList);
|
||
|
ClearList(FIDSetList);
|
||
|
ClearList(FDirectGetList);
|
||
|
ClearList(FClassList);
|
||
|
ClearList(FConstList);
|
||
|
ClearList(FFunctionList);
|
||
|
ClearList(FRecordList);
|
||
|
ClearList(FRecordGetList);
|
||
|
ClearList(FRecordSetList);
|
||
|
ClearList(FExtFunctionList);
|
||
|
ClearList(FEventHandlerList);
|
||
|
ClearList(FEventList);
|
||
|
ClearMethodList(FOnGetList);
|
||
|
ClearMethodList(FOnSetList);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.Clear;
|
||
|
begin
|
||
|
ClearSource;
|
||
|
ClearNonSource;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.Assign(Source: TJvInterpreterAdapter);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if Source = Self then
|
||
|
Exit;
|
||
|
for I := 0 to Source.FGetList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FGetList[I]) do
|
||
|
AddGetEx(FClassType, Identifier, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FSetList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FSetList[I]) do
|
||
|
AddSetEx(FClassType, Identifier, Func, ParamCount, ParamTypes, Data);
|
||
|
for I := 0 to Source.FIGetList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FIGetList[I]) do
|
||
|
AddIGetEx(FClassType, Identifier, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FISetList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FISetList[I]) do
|
||
|
AddISetEx(FClassType, Identifier, Func, ParamCount, ParamTypes, Data);
|
||
|
for I := 0 to Source.FIDGetList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FIDGetList[I]) do
|
||
|
AddIDGetEx(FClassType, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FIDSetList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FIDSetList[I]) do
|
||
|
AddIDSetEx(FClassType, Func, ParamCount, ParamTypes, Data);
|
||
|
for I := 0 to Source.FIntfGetList.Count - 1 do
|
||
|
with TJvInterpreterIntfMethod(Source.FIntfGetList[I]) do
|
||
|
AddIntfGetEx(IID, Identifier, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FIntfSetList.Count - 1 do
|
||
|
with TJvInterpreterIntfMethod(Source.FIntfSetList[I]) do
|
||
|
AddIntfSetEx(IID, Identifier, Func, ParamCount, ParamTypes, Data);
|
||
|
for I := 0 to Source.FIntfIGetList.Count - 1 do
|
||
|
with TJvInterpreterIntfMethod(Source.FIntfIGetList[I]) do
|
||
|
AddIntfIGetEx(IID, Identifier, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FIntfISetList.Count - 1 do
|
||
|
with TJvInterpreterIntfMethod(Source.FIntfISetList[I]) do
|
||
|
AddIntfISetEx(IID, Identifier, Func, ParamCount, ParamTypes, Data);
|
||
|
for I := 0 to Source.FIntfIDGetList.Count - 1 do
|
||
|
with TJvInterpreterIntfMethod(Source.FIntfIDGetList[I]) do
|
||
|
AddIntfIDGetEx(IID, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FIntfIDSetList.Count - 1 do
|
||
|
with TJvInterpreterIntfMethod(Source.FIntfIDSetList[I]) do
|
||
|
AddIntfIDSetEx(IID, Func, ParamCount, ParamTypes, Data);
|
||
|
for I := 0 to Source.FDirectGetList.Count - 1 do
|
||
|
with TJvInterpreterDMethod(Source.FDirectGetList[I]) do
|
||
|
AddDGetEx(FClassType, Identifier, Func, ParamCount, ParamTypes, ResTyp,
|
||
|
CallConvention, Data);
|
||
|
for I := 0 to Source.FFunctionList.Count - 1 do
|
||
|
with TJvInterpreterMethod(Source.FFunctionList[I]) do
|
||
|
AddFunctionEx(UnitName, Identifier, Func, ParamCount, ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FExtUnitList.Count - 1 do
|
||
|
with TJvInterpreterIdentifier(Source.FExtUnitList[I]) do
|
||
|
AddExtUnitEx(Identifier, Data);
|
||
|
for I := 0 to Source.FClassList.Count - 1 do
|
||
|
begin
|
||
|
with TJvInterpreterClass(Source.FClassList[I]) do
|
||
|
AddClassEx(UnitName, FClassType, Identifier, Data);
|
||
|
TJvInterpreterClass(FClassList[FClassList.Count-1]).ClassFields.Assign(
|
||
|
TJvInterpreterClass(Source.FClassList[I]).ClassFields);
|
||
|
end;
|
||
|
|
||
|
for I := 0 to Source.FSrcFunctionList.Count - 1 do
|
||
|
with TJvInterpreterSrcFunction(Source.FSrcFunctionList[I]).FunctionDesc do
|
||
|
AddSrcFunEx(UnitName, Identifier, ClassIdentifier, PosBeg, PosEnd, ParamCount, FParamTypes,
|
||
|
FParamTypeNames, FParamNames, ResTyp, ResTypName, ResDataType,
|
||
|
TJvInterpreterSrcFunction(Source.FSrcFunctionList[I]).Data);
|
||
|
for I := 0 to Source.FSrcUnitList.Count - 1 do
|
||
|
begin
|
||
|
with TJvInterpreterSrcUnit(Source.FSrcUnitList[I]) do
|
||
|
AddSrcUnitEx(Identifier, Source, '', Data);
|
||
|
TJvInterpreterSrcUnit(FSrcUnitList[FSrcUnitList.Count - 1]).FUsesList:=
|
||
|
TJvInterpreterSrcUnit(Source.FSrcUnitList[I]).UsesList;
|
||
|
end;
|
||
|
|
||
|
for I := 0 to Source.FConstList.Count - 1 do
|
||
|
with TJvInterpreterConst(Source.FConstList[I]) do
|
||
|
AddConstEx(UnitName, Identifier, Value, Data);
|
||
|
for I := 0 to Source.FRecordList.Count - 1 do
|
||
|
with TJvInterpreterRecord(Source.FRecordList[I]) do
|
||
|
AddRecEx(UnitName, Identifier, RecordSize, Fields, CreateFunc,
|
||
|
DestroyFunc, CopyFunc, Data);
|
||
|
for I := 0 to Source.FRecordGetList.Count - 1 do
|
||
|
with TJvInterpreterRecMethod(Source.FRecordGetList[I]) do
|
||
|
AddRecGetEx(UnitName, JvInterpreterRecord.Identifier, Identifier, Func, ParamCount,
|
||
|
ParamTypes, ResTyp, Data);
|
||
|
for I := 0 to Source.FRecordSetList.Count - 1 do
|
||
|
with TJvInterpreterRecMethod(Source.FRecordSetList[I]) do
|
||
|
AddRecSetEx(UnitName, JvInterpreterRecord.Identifier, Identifier, Func, ParamCount,
|
||
|
ParamTypes, Data);
|
||
|
for I := 0 to Source.FExtFunctionList.Count - 1 do
|
||
|
with TJvInterpreterExtFunction(Source.FExtFunctionList[I]) do
|
||
|
AddExtFunEx(UnitName, Identifier, DllInstance, DllName, FunctionName, FunctionIndex,
|
||
|
FunctionDesc.FParamCount, FunctionDesc.FParamTypes, FunctionDesc.FResTyp, Data);
|
||
|
for I := 0 to Source.FEventHandlerList.Count - 1 do
|
||
|
with TJvInterpreterEventDesc(Source.FEventHandlerList[I]) do
|
||
|
AddHandlerEx(UnitName, Identifier, EventClass, Code, Data);
|
||
|
for I := 0 to Source.FEventList.Count - 1 do
|
||
|
with TJvInterpreterClass(Source.FEventList[I]) do
|
||
|
AddEventEx(UnitName, FClassType, Identifier, Data);
|
||
|
for I := 0 to Source.FOnGetList.Count - 1 do
|
||
|
AddOnGet(TJvInterpreterGetValue(PMethod(Source.FOnGetList[I])^));
|
||
|
for I := 0 to Source.FOnSetList.Count - 1 do
|
||
|
AddOnSet(TJvInterpreterSetValue(PMethod(Source.FOnSetList[I])^));
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSrcUnit(const Identifier, Source, UsesList: string);
|
||
|
begin
|
||
|
AddSrcUnitEx(Identifier, Source, UsesList, nil);
|
||
|
end;
|
||
|
|
||
|
{ if unit with name 'Identifier' already exists its source will be replaced }
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSrcUnitEx(const Identifier, Source, UsesList: string;
|
||
|
Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterUnit: TJvInterpreterSrcUnit;
|
||
|
S: string;
|
||
|
I: Integer;
|
||
|
JvInterpreterIdentifier: TJvInterpreterIdentifier;
|
||
|
begin
|
||
|
JvInterpreterUnit := nil;
|
||
|
for I := 0 to FSrcUnitList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterIdentifier := TJvInterpreterIdentifier(FSrcUnitList.Items[I]);
|
||
|
if Cmp(JvInterpreterIdentifier.Identifier, Identifier) then
|
||
|
begin
|
||
|
JvInterpreterUnit := TJvInterpreterSrcUnit(FSrcUnitList.Items[I]);
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
if JvInterpreterUnit = nil then
|
||
|
begin
|
||
|
JvInterpreterUnit := TJvInterpreterSrcUnit.Create;
|
||
|
FSrcUnitList.Add(JvInterpreterUnit);
|
||
|
end;
|
||
|
|
||
|
if JvInterpreterUnit.FSource = '' then
|
||
|
begin
|
||
|
JvInterpreterUnit.Identifier := Identifier;
|
||
|
JvInterpreterUnit.FSource := Source;
|
||
|
JvInterpreterUnit.Data := Data;
|
||
|
I := 0;
|
||
|
S := Trim(SubStrBySeparator(UsesList, I, ','));
|
||
|
while S <> '' do
|
||
|
begin
|
||
|
JvInterpreterUnit.FUsesList[I] := S;
|
||
|
Inc(I);
|
||
|
S := Trim(SubStrBySeparator(UsesList, I, ','));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddExtUnit(const Identifier: string);
|
||
|
begin
|
||
|
AddExtUnitEx(Identifier, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddExtUnitEx(const Identifier: string; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterUnit: TJvInterpreterIdentifier;
|
||
|
begin
|
||
|
JvInterpreterUnit := TJvInterpreterIdentifier.Create;
|
||
|
JvInterpreterUnit.Identifier := Identifier;
|
||
|
JvInterpreterUnit.Data := Data;
|
||
|
FExtUnitList.Add(JvInterpreterUnit);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddClass(const UnitName: string; AClassType: TClass;
|
||
|
const Identifier: string);
|
||
|
begin
|
||
|
AddClassEx(UnitName, AClassType, Identifier, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddClassEx(const UnitName: string; AClassType: TClass;
|
||
|
const Identifier: string; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterClass: TJvInterpreterClass;
|
||
|
begin
|
||
|
JvInterpreterClass := TJvInterpreterClass.Create;
|
||
|
JvInterpreterClass.FClassType := AClassType;
|
||
|
JvInterpreterClass.Identifier := Identifier;
|
||
|
JvInterpreterClass.Data := Data;
|
||
|
JvInterpreterClass.UnitName := UnitName;
|
||
|
FClassList.Add(JvInterpreterClass);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddGet(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word);
|
||
|
begin
|
||
|
AddGetEx(AClassType, Identifier, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddGetEx(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FGetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIGet(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word);
|
||
|
begin
|
||
|
AddIGetEx(AClassType, Identifier, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIGetEx(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIGetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIDGet(AClassType: TClass;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word);
|
||
|
begin
|
||
|
AddIDGetEx(AClassType, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIDGetEx(AClassType: TClass;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIDGetList.Add(JvInterpreterMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfGet(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word);
|
||
|
begin
|
||
|
AddIntfGetEx(IID, Identifier, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfGetEx(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod.Create;
|
||
|
JvInterpreterMethod.IID := IID;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIntfGetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfIGet(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word; ResTyp: Word);
|
||
|
begin
|
||
|
AddIntfIGetEx(IID, Identifier, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfIGetEx(IID: TGUID; const Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod.Create;
|
||
|
JvInterpreterMethod.IID := IID;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIntfIGetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfIDGet(IID: TGUID;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word; ResTyp: Word);
|
||
|
begin
|
||
|
AddIntfIDGetEx(IID, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfIDGetEx(IID: TGUID;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod.Create;
|
||
|
JvInterpreterMethod.IID := IID;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIntfIDGetList.Add(JvInterpreterMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddDGet(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: Pointer; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; CallConvention: TCallConvention);
|
||
|
begin
|
||
|
AddDGetEx(AClassType, Identifier, GetFunc, ParamCount, ParamTypes, ResTyp,
|
||
|
CallConvention, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddDGetEx(AClassType: TClass; const Identifier: string;
|
||
|
GetFunc: Pointer; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; CallConvention: TCallConvention; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterDMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterDMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
JvInterpreterMethod.CallConvention := CallConvention;
|
||
|
FDirectGetList.Add(JvInterpreterMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSet(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddSetEx(AClassType, Identifier, SetFunc, ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSetEx(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @SetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FSetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddISet(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddISetEx(AClassType, Identifier, SetFunc, ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddISetEx(AClassType: TClass; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @SetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FISetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIDSet(AClassType: TClass;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddIDSetEx(AClassType, SetFunc, ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIDSetEx(AClassType: TClass;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.FClassType := AClassType;
|
||
|
JvInterpreterMethod.Func := @SetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIDSetList.Add(JvInterpreterMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfSet(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddIntfSetEx(IID, Identifier, SetFunc, ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfSetEx(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod.Create;
|
||
|
JvInterpreterMethod.IID := IID;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @SetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIntfSetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfISet(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddIntfISetEx(IID, Identifier, SetFunc, ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfISetEx(IID: TGUID; const Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod.Create;
|
||
|
JvInterpreterMethod.IID := IID;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @SetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIntfISetList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfIDSet(IID: TGUID;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddIntfIDSetEx(IID, SetFunc, ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddIntfIDSetEx(IID: TGUID;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod.Create;
|
||
|
JvInterpreterMethod.IID := IID;
|
||
|
JvInterpreterMethod.Func := @SetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
FIntfIDSetList.Add(JvInterpreterMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddFunction(const UnitName, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word);
|
||
|
begin
|
||
|
AddFunctionEx(UnitName, Identifier, GetFunc, ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddFunctionEx(const UnitName, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod.Create;
|
||
|
JvInterpreterMethod.Identifier := Identifier;
|
||
|
JvInterpreterMethod.Func := @GetFunc;
|
||
|
JvInterpreterMethod.ParamCount := ParamCount;
|
||
|
JvInterpreterMethod.ResTyp := ResTyp;
|
||
|
JvInterpreterMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, JvInterpreterMethod.ParamTypes);
|
||
|
JvInterpreterMethod.UnitName := UnitName;
|
||
|
FFunctionList.Add(JvInterpreterMethod);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddRec(const UnitName, Identifier: string;
|
||
|
RecordSize: Integer; Fields: array of TJvInterpreterRecField;
|
||
|
CreateFunc: TJvInterpreterAdapterNewRecord;
|
||
|
DestroyFunc: TJvInterpreterAdapterDisposeRecord;
|
||
|
CopyFunc: TJvInterpreterAdapterCopyRecord);
|
||
|
begin
|
||
|
AddRecEx(UnitName, Identifier, RecordSize, Fields, CreateFunc, DestroyFunc, CopyFunc, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddRecEx(const UnitName, Identifier: string;
|
||
|
RecordSize: Integer; Fields: array of TJvInterpreterRecField;
|
||
|
CreateFunc: TJvInterpreterAdapterNewRecord;
|
||
|
DestroyFunc: TJvInterpreterAdapterDisposeRecord;
|
||
|
CopyFunc: TJvInterpreterAdapterCopyRecord;
|
||
|
Data: Pointer);
|
||
|
var
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
JvInterpreterRecord := TJvInterpreterRecord.Create;
|
||
|
JvInterpreterRecord.Identifier := Identifier;
|
||
|
JvInterpreterRecord.RecordSize := RecordSize;
|
||
|
JvInterpreterRecord.CreateFunc := CreateFunc;
|
||
|
JvInterpreterRecord.DestroyFunc := DestroyFunc;
|
||
|
JvInterpreterRecord.CopyFunc := CopyFunc;
|
||
|
JvInterpreterRecord.Data := Data;
|
||
|
for I := Low(Fields) to High(Fields) do
|
||
|
begin
|
||
|
JvInterpreterRecord.Fields[I] := Fields[I];
|
||
|
JvInterpreterRecord.Fields[I].DataType := nil;
|
||
|
end;
|
||
|
JvInterpreterRecord.FieldCount := High(Fields) - Low(Fields) + 1;
|
||
|
JvInterpreterRecord.UnitName := UnitName;
|
||
|
FRecordList.Add(JvInterpreterRecord);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddRecGet(const UnitName, RecordType, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word);
|
||
|
begin
|
||
|
AddRecGetEx(UnitName, RecordType, Identifier, GetFunc, ParamCount,
|
||
|
ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddRecGetEx(const UnitName, RecordType, Identifier: string;
|
||
|
GetFunc: TJvInterpreterAdapterGetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; ResTyp: Word; Data: Pointer);
|
||
|
var
|
||
|
RecMethod: TJvInterpreterRecMethod;
|
||
|
begin
|
||
|
RecMethod := TJvInterpreterRecMethod.Create;
|
||
|
RecMethod.JvInterpreterRecord := GetRec(RecordType) as TJvInterpreterRecord;
|
||
|
RecMethod.Identifier := Identifier;
|
||
|
RecMethod.Func := @GetFunc;
|
||
|
RecMethod.ParamCount := ParamCount;
|
||
|
RecMethod.ResTyp := ResTyp;
|
||
|
RecMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, RecMethod.ParamTypes);
|
||
|
RecMethod.UnitName := UnitName;
|
||
|
FRecordGetList.Add(RecMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddRecSet(const UnitName, RecordType, Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer; ParamTypes: array of Word);
|
||
|
begin
|
||
|
AddRecSetEx(UnitName, RecordType, Identifier, SetFunc,
|
||
|
ParamCount, ParamTypes, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddRecSetEx(const UnitName, RecordType, Identifier: string;
|
||
|
SetFunc: TJvInterpreterAdapterSetValue; ParamCount: Integer;
|
||
|
ParamTypes: array of Word; Data: Pointer);
|
||
|
var
|
||
|
RecMethod: TJvInterpreterRecMethod;
|
||
|
begin
|
||
|
RecMethod := TJvInterpreterRecMethod.Create;
|
||
|
RecMethod.JvInterpreterRecord := GetRec(RecordType) as TJvInterpreterRecord;
|
||
|
RecMethod.Identifier := Identifier;
|
||
|
RecMethod.Func := @SetFunc;
|
||
|
RecMethod.ParamCount := ParamCount;
|
||
|
RecMethod.Data := Data;
|
||
|
ConvertParamTypes(ParamTypes, RecMethod.ParamTypes);
|
||
|
RecMethod.UnitName := UnitName;
|
||
|
FRecordSetList.Add(RecMethod);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddConst(const UnitName, Identifier: string;
|
||
|
Value: Variant);
|
||
|
begin
|
||
|
AddConstEx(UnitName, Identifier, Value, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddConstEx(const AUnitName, AIdentifier: string;
|
||
|
AValue: Variant; AData: Pointer);
|
||
|
var
|
||
|
JvInterpreterConst: TJvInterpreterConst;
|
||
|
begin
|
||
|
JvInterpreterConst := TJvInterpreterConst.Create;
|
||
|
JvInterpreterConst.Identifier := AIdentifier;
|
||
|
JvInterpreterConst.Value := AValue;
|
||
|
JvInterpreterConst.Data := AData;
|
||
|
JvInterpreterConst.UnitName := AUnitName;
|
||
|
FConstList.Add(JvInterpreterConst);
|
||
|
FSorted := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddExtFun(const UnitName, Identifier: string;
|
||
|
DllInstance: HINST; const DllName, FunctionName: string; FunctionIndex: Integer;
|
||
|
ParamCount: Integer; ParamTypes: array of Word; ResTyp: Word);
|
||
|
begin
|
||
|
AddExtFunEx(UnitName, Identifier, DllInstance, DllName, FunctionName, FunctionIndex,
|
||
|
ParamCount, ParamTypes, ResTyp, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddExtFunEx(const AUnitName, AIdentifier: string;
|
||
|
ADllInstance: HINST; const ADllName, AFunctionName: string; AFunIndex: Integer;
|
||
|
AParamCount: Integer; AParamTypes: array of Word; AResTyp: Word; AData: Pointer);
|
||
|
var
|
||
|
JvInterpreterExtFun: TJvInterpreterExtFunction;
|
||
|
begin
|
||
|
JvInterpreterExtFun := TJvInterpreterExtFunction.Create;
|
||
|
with JvInterpreterExtFun do
|
||
|
begin
|
||
|
FunctionDesc.FUnitName := AUnitName;
|
||
|
Identifier := AIdentifier;
|
||
|
DllInstance := ADllInstance;
|
||
|
DllName := ADllName;
|
||
|
FunctionName := AFunctionName;
|
||
|
FunctionIndex := AFunIndex;
|
||
|
FunctionDesc.FParamCount := AParamCount;
|
||
|
FunctionDesc.FResTyp := AResTyp;
|
||
|
Data := AData;
|
||
|
ConvertParamTypes(AParamTypes, FunctionDesc.FParamTypes);
|
||
|
end;
|
||
|
JvInterpreterExtFun.UnitName := AUnitName;
|
||
|
FExtFunctionList.Add(JvInterpreterExtFun);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSrcFun(const UnitName, Identifier: string;
|
||
|
ClassIdentifier: string;
|
||
|
PosBeg, PosEnd: Integer; ParamCount: Integer; ParamTypes: array of Word;
|
||
|
ParamTypeNames: array of string;
|
||
|
ParamNames: array of string; ResTyp: Word; const AResTypName: string;
|
||
|
AResDataType: IJvInterpreterDataType;
|
||
|
Data: Pointer);
|
||
|
begin
|
||
|
AddSrcFunEx(UnitName, Identifier, ClassIdentifier, PosBeg, PosEnd, ParamCount, ParamTypes,
|
||
|
ParamTypeNames,
|
||
|
ParamNames, ResTyp, AResTypName, AResDataType, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSrcFunEx(const AUnitName, AIdentifier: string;
|
||
|
AClassIdentifier: string;
|
||
|
APosBeg, APosEnd: Integer; AParamCount: Integer; AParamTypes: array of Word;
|
||
|
AParamTypeNames: array of string;
|
||
|
AParamNames: array of string; AResTyp: Word; const AResTypName: string;
|
||
|
AResDataType: IJvInterpreterDataType;
|
||
|
AData: Pointer);
|
||
|
var
|
||
|
JvInterpreterSrcFun: TJvInterpreterSrcFunction;
|
||
|
begin
|
||
|
JvInterpreterSrcFun := TJvInterpreterSrcFunction.Create;
|
||
|
with JvInterpreterSrcFun do
|
||
|
begin
|
||
|
FunctionDesc.FUnitName := AUnitName;
|
||
|
FunctionDesc.FIdentifier := AIdentifier;
|
||
|
FunctionDesc.FPosBeg := APosBeg;
|
||
|
FunctionDesc.FPosEnd := APosEnd;
|
||
|
FunctionDesc.FParamCount := AParamCount;
|
||
|
FunctionDesc.FResTyp := AResTyp;
|
||
|
FunctionDesc.FResTypName := AResTypName;
|
||
|
FunctionDesc.FResDataType := AResDataType;
|
||
|
FunctionDesc.FClassIdentifier := AClassIdentifier; // class method support
|
||
|
Identifier := AIdentifier;
|
||
|
Data := AData;
|
||
|
ConvertParamTypes(AParamTypes, FunctionDesc.FParamTypes);
|
||
|
ConvertParamNames(AParamNames, FunctionDesc.FParamNames);
|
||
|
ConvertParamNames(AParamTypeNames, FunctionDesc.FParamTypeNames);
|
||
|
FunctionDesc.FResTyp := AResTyp;
|
||
|
end;
|
||
|
JvInterpreterSrcFun.UnitName := AUnitName; // Code Insight
|
||
|
FSrcFunctionList.Add(JvInterpreterSrcFun);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddHandler(const UnitName, Identifier: string;
|
||
|
EventClass: TJvInterpreterEventClass; Code: Pointer);
|
||
|
begin
|
||
|
AddHandlerEx(UnitName, Identifier, EventClass, Code, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddHandlerEx(const AUnitName, AIdentifier: string;
|
||
|
AEventClass: TJvInterpreterEventClass; ACode: Pointer; AData: Pointer);
|
||
|
var
|
||
|
JvInterpreterEventDesc: TJvInterpreterEventDesc;
|
||
|
begin
|
||
|
JvInterpreterEventDesc := TJvInterpreterEventDesc.Create;
|
||
|
with JvInterpreterEventDesc do
|
||
|
begin
|
||
|
UnitName := AUnitName;
|
||
|
Identifier := AIdentifier;
|
||
|
EventClass := AEventClass;
|
||
|
Code := ACode;
|
||
|
Data := AData;
|
||
|
end;
|
||
|
FEventHandlerList.Add(JvInterpreterEventDesc);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddEvent(const UnitName: string; AClassType: TClass;
|
||
|
const Identifier: string);
|
||
|
begin
|
||
|
AddEventEx(UnitName, AClassType, Identifier, nil);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddEventEx(const AUnitName: string; AClassType: TClass;
|
||
|
const AIdentifier: string; AData: Pointer);
|
||
|
var
|
||
|
JvInterpreterEvent: TJvInterpreterClass;
|
||
|
begin
|
||
|
JvInterpreterEvent := TJvInterpreterClass.Create;
|
||
|
with JvInterpreterEvent do
|
||
|
begin
|
||
|
UnitName := AUnitName;
|
||
|
Identifier := AIdentifier;
|
||
|
FClassType := AClassType;
|
||
|
Data := AData;
|
||
|
end;
|
||
|
FEventList.Add(JvInterpreterEvent);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSrcVar(const UnitName, Identifier, Typ: string;
|
||
|
VTyp: Word; const Value: Variant; DataType: IJvInterpreterDataType);
|
||
|
begin
|
||
|
FSrcVarList.AddVar(UnitName, Identifier, Typ, VTyp, Value, DataType);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddSrcClass(JvInterpreterSrcClass: TJvInterpreterIdentifier);
|
||
|
begin
|
||
|
FSrcClassList.Add(JvInterpreterSrcClass);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.GetSrcClass(const Identifier: string): TJvInterpreterIdentifier;
|
||
|
begin
|
||
|
Result := FSrcClassList.IndexOf('', Identifier);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddOnGet(Method: TJvInterpreterGetValue);
|
||
|
var
|
||
|
PM: PMethod;
|
||
|
begin
|
||
|
New(PM);
|
||
|
PM^ := TMethod(Method);
|
||
|
FOnGetList.Add(PM);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.AddOnSet(Method: TJvInterpreterSetValue);
|
||
|
var
|
||
|
PM: PMethod;
|
||
|
begin
|
||
|
New(PM);
|
||
|
PM^ := TMethod(Method);
|
||
|
FOnSetList.Add(PM);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.GetRec(const RecordType: string): TObject;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to FRecordList.Count - 1 do
|
||
|
begin
|
||
|
Result := FRecordList[I];
|
||
|
if Cmp(TJvInterpreterRecord(Result).Identifier, RecordType) then
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.CheckArgs(var Args: TJvInterpreterArgs; ParamCount: Integer;
|
||
|
var ParamTypes: TTypeArray);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if ParamCount = prArgsNoCheck then
|
||
|
Exit;
|
||
|
if Args.Count > ParamCount then
|
||
|
JvInterpreterError(ieTooManyParams, -1);
|
||
|
if Args.Count < ParamCount then
|
||
|
JvInterpreterError(ieNotEnoughParams, -1);
|
||
|
|
||
|
Args.FHasVars := False;
|
||
|
Args.Types := ParamTypes;
|
||
|
for I := 0 to Args.Count - 1 do
|
||
|
if (Args.FVarNames[I] <> '') and ((ParamTypes[I] and varByRef) <> 0) then
|
||
|
begin
|
||
|
Args.FHasVars := True;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.CheckAction(Expression: TJvInterpreterExpression;
|
||
|
Args: TJvInterpreterArgs; Data: Pointer);
|
||
|
begin
|
||
|
// abstract
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.FindFunDesc(const UnitName: string;
|
||
|
const Identifier: string;
|
||
|
const ClassIdentifier:string=''): TJvInterpreterFunctionDesc;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := FSrcFunctionList.Count - 1 downto 0 do
|
||
|
begin
|
||
|
Result := TJvInterpreterSrcFunction(FSrcFunctionList.Items[I]).FunctionDesc;
|
||
|
if Cmp(Result.Identifier, Identifier) and
|
||
|
(Cmp(Result.ClassIdentifier, ClassIdentifier) or (ClassIdentifier='')) and // Class methods support
|
||
|
(Cmp(Result.UnitName, UnitName) or (UnitName = '')) then
|
||
|
Exit;
|
||
|
end;
|
||
|
if (UnitName <> '') and (ClassIdentifier='') then // Class methods support
|
||
|
Result := FindFunDesc('', Identifier)
|
||
|
else
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.GetValue(Expression: TJvInterpreterExpression; const Identifier: string;
|
||
|
var Value: Variant; Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
|
||
|
function GetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
Result := GetValueRTTI(Identifier, Value, Args);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
|
||
|
if FGetList.Find(Identifier, i) then
|
||
|
for I := I to FGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FGetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
(((Args.ObjTyp = varObject) and
|
||
|
(Args.Obj is JvInterpreterMethod.FClassType)) or
|
||
|
((Args.ObjTyp = varClass) and
|
||
|
(TClass(Args.Obj) = JvInterpreterMethod.FClassType))) {?!} then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
if Cmp(Identifier, 'Free') then
|
||
|
begin
|
||
|
Result := True;
|
||
|
Args.Obj.Free;
|
||
|
Args.Obj := nil;
|
||
|
Value := Null;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IntfGetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
Intf: IUnknown;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if FIntfGetList.Find(Identifier, I) then
|
||
|
for I := I to FIntfGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod(FIntfGetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
((Args.ObjTyp = varUnknown) and
|
||
|
(IUnknown(Pointer(Args.Obj)).QueryInterface(JvInterpreterMethod.IID, Intf) = S_OK)) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount,
|
||
|
JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IGetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
if FIGetList.Find(Identifier, I) then
|
||
|
for I := I to FIGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FIGetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
(((Args.ObjTyp = varObject) and
|
||
|
(Args.Obj is JvInterpreterMethod.FClassType)) or
|
||
|
((Args.ObjTyp = varClass) and
|
||
|
(TClass(Args.Obj) = JvInterpreterMethod.FClassType))) {?!} then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Args.ReturnIndexed := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function IntfIGetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
Intf: IUnknown;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if FIntfIGetList.Find(Identifier, I) then
|
||
|
for I := I to FIntfIGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod(FIntfIGetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
((Args.ObjTyp = varUnknown) and
|
||
|
(IUnknown(Pointer(Args.Obj)).QueryInterface(JvInterpreterMethod.IID, Intf) = S_OK)) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount,
|
||
|
JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Args.ReturnIndexed := True;
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ function DGetMethod is under construction }
|
||
|
|
||
|
function DGetMethod: Boolean;
|
||
|
var
|
||
|
JvInterpreterMethod: TJvInterpreterDMethod;
|
||
|
I, J: Integer;
|
||
|
AInt: Integer;
|
||
|
AWord: Word;
|
||
|
iRes: Integer;
|
||
|
Func: Pointer;
|
||
|
{$IFNDEF CPU64}
|
||
|
RegEAX, RegEDX, RegECX: Integer;
|
||
|
{$ELSE}
|
||
|
Params: TArray<System.Rtti.TValue>;
|
||
|
{$ENDIF ~CPU64}
|
||
|
begin
|
||
|
Result := False;
|
||
|
{$IFNDEF CPU64}
|
||
|
iRes := 0;
|
||
|
{$ENDIF ~CPU64}
|
||
|
for I := 0 to FDirectGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterDMethod(FDirectGetList[I]);
|
||
|
Func := JvInterpreterMethod.Func;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
(((Args.ObjTyp = varObject) and
|
||
|
(Args.Obj is JvInterpreterMethod.FClassType)) { or
|
||
|
((Args.ObjTyp = varClass) and
|
||
|
(TClass(Args.Obj) = JvInterpreterMethod.FClassType))}) and
|
||
|
Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
{$IFNDEF CPU64}
|
||
|
if ccFastCall in JvInterpreterMethod.CallConvention then
|
||
|
begin
|
||
|
{ !!! Delphi fast-call !!! }
|
||
|
{ push parameters to stack }
|
||
|
for J := 2 to JvInterpreterMethod.ParamCount - 1 do
|
||
|
if (JvInterpreterMethod.ParamTypes[J] = varInteger) or
|
||
|
(JvInterpreterMethod.ParamTypes[J] = varObject) or
|
||
|
(JvInterpreterMethod.ParamTypes[J] = varPointer) or
|
||
|
(JvInterpreterMethod.ParamTypes[J] = varBoolean) {?} then
|
||
|
begin
|
||
|
AInt := Args.Values[J];
|
||
|
asm
|
||
|
push AInt
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
if JvInterpreterMethod.ParamTypes[J] = varSmallint then
|
||
|
begin
|
||
|
AWord := Word(Args.Values[J]);
|
||
|
asm
|
||
|
push AWord
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDirectInvalidArgument, -1, Identifier);
|
||
|
|
||
|
RegEAX := Integer(Args.Obj);
|
||
|
if JvInterpreterMethod.ParamCount > 0 then
|
||
|
if (JvInterpreterMethod.ParamTypes[0] = varInteger) or
|
||
|
(JvInterpreterMethod.ParamTypes[0] = varObject) or
|
||
|
(JvInterpreterMethod.ParamTypes[0] = varPointer) or
|
||
|
(JvInterpreterMethod.ParamTypes[0] = varBoolean) or
|
||
|
(JvInterpreterMethod.ParamTypes[0] = varSmallint) or
|
||
|
(JvInterpreterMethod.ParamTypes[0] = varString) then
|
||
|
RegEDX := TVarData(Args.Values[0]).VInteger
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDirectInvalidArgument, -1, Identifier);
|
||
|
|
||
|
if JvInterpreterMethod.ParamCount > 1 then
|
||
|
if (JvInterpreterMethod.ParamTypes[1] = varInteger) or
|
||
|
(JvInterpreterMethod.ParamTypes[1] = varObject) or
|
||
|
(JvInterpreterMethod.ParamTypes[1] = varPointer) or
|
||
|
(JvInterpreterMethod.ParamTypes[1] = varBoolean) or
|
||
|
(JvInterpreterMethod.ParamTypes[1] = varSmallint) or
|
||
|
(JvInterpreterMethod.ParamTypes[1] = varString) then
|
||
|
RegECX := TVarData(Args.Values[1]).VInteger
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDirectInvalidArgument, -1, Identifier);
|
||
|
|
||
|
if (JvInterpreterMethod.ResTyp = varSmallint) or
|
||
|
(JvInterpreterMethod.ResTyp = varInteger) or
|
||
|
(JvInterpreterMethod.ResTyp = varBoolean) or
|
||
|
(JvInterpreterMethod.ResTyp = varEmpty) or
|
||
|
(JvInterpreterMethod.ResTyp = varObject) or
|
||
|
(JvInterpreterMethod.ResTyp = varPointer) then
|
||
|
asm
|
||
|
mov EAX, RegEAX
|
||
|
mov EDX, RegEDX
|
||
|
mov ECX, RegECX
|
||
|
call Func
|
||
|
mov iRes, EAX
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDirectInvalidResult, -1, Identifier);
|
||
|
{$ELSE}
|
||
|
SetLength(Params, 1 + JvInterpreterMethod.ParamCount);
|
||
|
Params[0] := TValue.From(Args.Obj);
|
||
|
for J := 0 to JvInterpreterMethod.ParamCount - 1 do
|
||
|
begin
|
||
|
if (JvInterpreterMethod.ParamTypes[J] = varInteger) or
|
||
|
(JvInterpreterMethod.ParamTypes[J] = varBoolean) {?} then
|
||
|
begin
|
||
|
AInt := Args.Values[J];
|
||
|
Params[1 + J] := TValue.From(AInt);
|
||
|
end
|
||
|
else if JvInterpreterMethod.ParamTypes[J] = varSmallint then
|
||
|
begin
|
||
|
AWord := Word(Args.Values[J]);
|
||
|
Params[1 + J] := TValue.From(AWord);
|
||
|
end
|
||
|
else if (JvInterpreterMethod.ParamTypes[J] = varObject) or
|
||
|
(JvInterpreterMethod.ParamTypes[J] = varString) or
|
||
|
(JvInterpreterMethod.ParamTypes[J] = varPointer) then
|
||
|
begin
|
||
|
Params[1 + J] := TValue.From(TVarData(Args.Values[J]).VPointer);
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDirectInvalidArgument, -1, Identifier);
|
||
|
end;
|
||
|
iRes := System.Rtti.Invoke(Func, Params, System.TypInfo.TCallConv.ccReg, TypeInfo(Integer), False).AsType<Integer>();
|
||
|
{$ENDIF ~CPU64}
|
||
|
|
||
|
{ clear result }
|
||
|
if (JvInterpreterMethod.ResTyp = varInteger) or
|
||
|
(JvInterpreterMethod.ResTyp = varObject) then
|
||
|
Value := iRes
|
||
|
else
|
||
|
if JvInterpreterMethod.ResTyp = varSmallint then
|
||
|
Value := iRes and $0000FFFF
|
||
|
else
|
||
|
if JvInterpreterMethod.ResTyp = varBoolean then
|
||
|
begin
|
||
|
Value := iRes and $000000FF;
|
||
|
TVarData(Value).VType := varBoolean;
|
||
|
end
|
||
|
else
|
||
|
if JvInterpreterMethod.ResTyp = varEmpty then
|
||
|
Value := Null;
|
||
|
{$IFNDEF CPU64}
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterErrorN(ieDirectInvalidConvention, -1, Identifier);
|
||
|
{$ENDIF ~CPU64}
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function GetRecord: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
Rec: PAnsiChar;
|
||
|
JvInterpreterRecMethod: TJvInterpreterRecMethod;
|
||
|
begin
|
||
|
Result := False;
|
||
|
JvInterpreterRecord := (Args.Obj as TJvInterpreterRecHolder).JvInterpreterRecord;
|
||
|
for I := 0 to JvInterpreterRecord.FieldCount - 1 do
|
||
|
if Cmp(JvInterpreterRecord.Fields[I].Identifier, Identifier) then
|
||
|
begin
|
||
|
Rec := P2R(Args.Obj);
|
||
|
with JvInterpreterRecord.Fields[I] do
|
||
|
case Typ of
|
||
|
varSmallint:
|
||
|
Value := Smallint(PWord(Rec + Offset)^);
|
||
|
varInteger:
|
||
|
Value := PInteger(Rec + Offset)^;
|
||
|
varSingle:
|
||
|
Value := PSingle(Rec + Offset)^;
|
||
|
varDouble:
|
||
|
Value := PDouble(Rec + Offset)^;
|
||
|
varCurrency:
|
||
|
Value := PCurrency(Rec + Offset)^;
|
||
|
varDate:
|
||
|
Value := PDateTime(Rec + Offset)^;
|
||
|
varOleStr:
|
||
|
Value := PWideString(Rec + Offset)^;
|
||
|
varBoolean:
|
||
|
Value := PBool(Rec + Offset)^;
|
||
|
varVariant:
|
||
|
Value := PVariant(Rec + Offset)^;
|
||
|
varString:
|
||
|
Value := PString(Rec + Offset)^;
|
||
|
varEmpty:
|
||
|
JvInterpreterVarCopy(Value, Variant(PVarData(Rec + Offset)^));
|
||
|
end;
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
for I := 0 to FRecordGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterRecMethod := TJvInterpreterRecMethod(FRecordGetList[I]);
|
||
|
if (JvInterpreterRecMethod.JvInterpreterRecord = JvInterpreterRecord) and
|
||
|
Cmp(JvInterpreterRecMethod.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckArgs(Args, JvInterpreterRecMethod.ParamCount, JvInterpreterRecMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterRecMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end
|
||
|
end;
|
||
|
|
||
|
function GetConst: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterConst: TJvInterpreterConst;
|
||
|
begin
|
||
|
if Cmp(Identifier, kwNIL) then
|
||
|
begin
|
||
|
Value := P2V(nil);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
if Cmp(Identifier, 'Null') then
|
||
|
begin
|
||
|
Value := Null;
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := FConstList.Find(Identifier, I);
|
||
|
if Result then
|
||
|
begin
|
||
|
JvInterpreterConst := TJvInterpreterConst(FConstList[I]);
|
||
|
CheckAction(Expression, Args, JvInterpreterConst.Data);
|
||
|
Value := JvInterpreterConst.Value;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function GetClass: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterClass: TJvInterpreterClass;
|
||
|
begin
|
||
|
Result := FClassList.Find(Identifier, I);
|
||
|
if Result then
|
||
|
begin
|
||
|
JvInterpreterClass := TJvInterpreterClass(FClassList[I]);
|
||
|
if Args.Count = 0 then
|
||
|
Value := C2V(JvInterpreterClass.FClassType)
|
||
|
else
|
||
|
if Args.Count = 1 then
|
||
|
{ typecasting }
|
||
|
begin
|
||
|
CheckAction(Expression, Args, JvInterpreterClass.Data);
|
||
|
Value := Args.Values[0];
|
||
|
if TVarData(Value).VType <> varClass then
|
||
|
TVarData(Value).VType := varObject;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterError(ieTooManyParams, -1);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function GetFun: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
Result := FFunctionList.Find(Identifier, I);
|
||
|
if Result then
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FFunctionList[I]);
|
||
|
if Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function GetExtFun: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterExtFun: TJvInterpreterExtFunction;
|
||
|
begin
|
||
|
if DisableExternalFunctions then
|
||
|
begin
|
||
|
Result := False;
|
||
|
Exit;
|
||
|
end;
|
||
|
for I := 0 to FExtFunctionList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterExtFun := TJvInterpreterExtFunction(FExtFunctionList[I]);
|
||
|
if Cmp(JvInterpreterExtFun.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterExtFun.Data);
|
||
|
CheckArgs(Args, JvInterpreterExtFun.FunctionDesc.ParamCount,
|
||
|
JvInterpreterExtFun.FunctionDesc.FParamTypes);
|
||
|
Value := JvInterpreterExtFun.CallDll(Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function GetSrcVar: Boolean;
|
||
|
begin
|
||
|
Result := FSrcVarList.GetValue(Identifier, Value, Args);
|
||
|
end;
|
||
|
|
||
|
function GetSrcUnit: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterSrcUnit: TJvInterpreterSrcUnit;
|
||
|
FParams: TTypeArray;
|
||
|
begin
|
||
|
for I := 0 to FSrcUnitList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterSrcUnit := TJvInterpreterSrcUnit(FSrcUnitList[I]);
|
||
|
if Cmp(JvInterpreterSrcUnit.Identifier, Identifier) then
|
||
|
begin
|
||
|
CheckArgs(Args, 0, FParams);
|
||
|
Value := O2V(JvInterpreterSrcUnit);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
function GetOleAutoFun: Boolean;
|
||
|
var
|
||
|
FParams: TTypeArray;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if Cmp(Identifier, 'CreateOleObject') or
|
||
|
Cmp(Identifier, 'GetActiveOleObject') or
|
||
|
Cmp(Identifier, 'GetOleObject') then
|
||
|
begin
|
||
|
FParams[0] := varString;
|
||
|
CheckArgs(Args, 1, FParams);
|
||
|
if Cmp(Identifier, 'CreateOleObject') then
|
||
|
Value := CreateOleObject(Args.Values[0])
|
||
|
else
|
||
|
if Cmp(Identifier, 'GetActiveOleObject') then
|
||
|
Value := GetActiveOleObject(Args.Values[0])
|
||
|
else { GetOleObject }
|
||
|
begin
|
||
|
try
|
||
|
Value := GetActiveOleObject(Args.Values[0])
|
||
|
except
|
||
|
on E: EOleError do
|
||
|
Value := CreateOleObject(Args.Values[0])
|
||
|
end;
|
||
|
end;
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
function TypeCast: Boolean;
|
||
|
var
|
||
|
VT: Word;
|
||
|
begin
|
||
|
VT := TypeName2VarTyp(Identifier);
|
||
|
Result := VT <> varEmpty;
|
||
|
if Result then
|
||
|
begin
|
||
|
Value := Args.Values[0];
|
||
|
TVarData(Value).VType := VT;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := True;
|
||
|
if not FSorted then
|
||
|
Sort;
|
||
|
|
||
|
if Args.Indexed then
|
||
|
begin
|
||
|
if Args.ObjTyp = varRecord then
|
||
|
begin
|
||
|
if (Args.Obj is TJvInterpreterRecHolder) and GetRecord then
|
||
|
begin
|
||
|
Args.ReturnIndexed := False;
|
||
|
Exit;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
if (Args.Obj <> nil) and ((Args.ObjTyp = varObject) or (Args.ObjTyp = varClass)) then
|
||
|
begin
|
||
|
if IGetMethod then
|
||
|
Exit;
|
||
|
I := Args.Count;
|
||
|
try // try to get indexed property
|
||
|
Args.Count := 0;
|
||
|
Result := GetMethod or DGetMethod;
|
||
|
finally
|
||
|
Args.Count := I;
|
||
|
end;
|
||
|
if Result then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varUnknown then
|
||
|
begin
|
||
|
if IntfIGetMethod then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varDispatch then
|
||
|
{ Ole automation call }
|
||
|
begin
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
Result := DispatchCall(Identifier, Value, Args, True);
|
||
|
if Result then
|
||
|
begin
|
||
|
Args.ReturnIndexed := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
NotImplemented(RsOleAutomationCall);
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if Args.Obj <> nil then
|
||
|
begin
|
||
|
{ methods }
|
||
|
if (Args.ObjTyp = varObject) or (Args.ObjTyp = varClass) then
|
||
|
begin
|
||
|
if GetMethod or DGetMethod then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varUnknown then
|
||
|
begin
|
||
|
if IntfGetMethod then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varRecord then
|
||
|
begin
|
||
|
if (Args.Obj is TJvInterpreterRecHolder) and GetRecord then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varDispatch then
|
||
|
{ Ole automation call }
|
||
|
begin
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
Result := DispatchCall(Identifier, Value, Args, True);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
{$ELSE}
|
||
|
NotImplemented(RsOleAutomationCall);
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
{ classes }
|
||
|
if GetClass then
|
||
|
Exit;
|
||
|
{ constants }
|
||
|
if GetConst then
|
||
|
Exit;
|
||
|
{ classless functions and procedures }
|
||
|
if GetFun then
|
||
|
Exit;
|
||
|
{ external functions }
|
||
|
if GetExtFun then
|
||
|
Exit;
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
if GetOleAutoFun then
|
||
|
Exit;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
if TypeCast then
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ source variables and constants }
|
||
|
if GetSrcVar then
|
||
|
Exit;
|
||
|
|
||
|
if not ((Args.Obj <> nil) and ((Args.ObjTyp = varObject) or (Args.ObjTyp = varClass))) then
|
||
|
if GetSrcUnit then
|
||
|
Exit;
|
||
|
|
||
|
for I := 0 to FOnGetList.Count - 1 do { Iterate }
|
||
|
begin
|
||
|
TJvInterpreterGetValue(FOnGetList[I]^)(Self, Identifier, Value, Args, Result);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.SetValue(Expression: TJvInterpreterExpression; const Identifier: string;
|
||
|
const Value: Variant; Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
V: Variant;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
function SetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
Result := SetValueRTTI(Identifier, Value, Args);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
for I := 0 to FSetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FSetList[I]);
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
(Args.Obj is JvInterpreterMethod.FClassType) and
|
||
|
Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function ISetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if FISetList.Find(Identifier, I) then
|
||
|
for I := I to FISetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FISetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
(Args.Obj is JvInterpreterMethod.FClassType) and
|
||
|
Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Args.ReturnIndexed := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IntfSetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
Intf: IUnknown;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if FIntfSetList.Find(Identifier, I) then
|
||
|
for I := I to FIntfSetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod(FIntfSetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
((Args.ObjTyp = varUnknown) and
|
||
|
(IUnknown(Pointer(Args.Obj)).QueryInterface(JvInterpreterMethod.IID, Intf) = S_OK)) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount,
|
||
|
JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IntfISetMethod: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
Intf: IUnknown;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if FIntfISetList.Find(Identifier, I) then
|
||
|
for I := I to FIntfISetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod(FIntfISetList[I]);
|
||
|
if not Cmp(JvInterpreterMethod.Identifier, Identifier) then
|
||
|
Break;
|
||
|
if Assigned(JvInterpreterMethod.Func) and
|
||
|
((Args.ObjTyp = varUnknown) and
|
||
|
(IUnknown(Pointer(Args.Obj)).QueryInterface(JvInterpreterMethod.IID, Intf) = S_OK)) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount,
|
||
|
JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Args.ReturnIndexed := True;
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function SetRecord: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
JvInterpreterRecMethod: TJvInterpreterRecMethod;
|
||
|
Rec: PAnsiChar;
|
||
|
begin
|
||
|
Result := False;
|
||
|
JvInterpreterRecord := (Args.Obj as TJvInterpreterRecHolder).JvInterpreterRecord;
|
||
|
for I := 0 to JvInterpreterRecord.FieldCount - 1 do
|
||
|
if Cmp(JvInterpreterRecord.Fields[I].Identifier, Identifier) then
|
||
|
begin
|
||
|
Rec := P2R(Args.Obj);
|
||
|
with JvInterpreterRecord.Fields[I] do
|
||
|
case Typ of
|
||
|
varSmallint:
|
||
|
PWord(Rec + Offset)^ := Word(Value);
|
||
|
varInteger:
|
||
|
PInteger(Rec + Offset)^ := Value;
|
||
|
varSingle:
|
||
|
PSingle(Rec + Offset)^ := Value;
|
||
|
varDouble:
|
||
|
PDouble(Rec + Offset)^ := Value;
|
||
|
varCurrency:
|
||
|
PCurrency(Rec + Offset)^ := Value;
|
||
|
varDate:
|
||
|
PDateTime(Rec + Offset)^ := Value;
|
||
|
varOleStr:
|
||
|
PWideString(Rec + Offset)^ := Value;
|
||
|
varBoolean:
|
||
|
PBool(Rec + Offset)^ := Value;
|
||
|
varVariant:
|
||
|
PVariant(Rec + Offset)^ := Value;
|
||
|
varString:
|
||
|
PString(Rec + Offset)^ := Value;
|
||
|
varEmpty:
|
||
|
JvInterpreterVarAssignment(Variant(PVarData(Rec + Offset)^), Value);
|
||
|
end;
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
for I := 0 to FRecordSetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterRecMethod := TJvInterpreterRecMethod(FRecordSetList[I]);
|
||
|
if (JvInterpreterRecMethod.JvInterpreterRecord = JvInterpreterRecord) and
|
||
|
Cmp(JvInterpreterRecMethod.Identifier, Identifier) then
|
||
|
begin
|
||
|
Args.Identifier := Identifier;
|
||
|
CheckArgs(Args, JvInterpreterRecMethod.ParamCount, JvInterpreterRecMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterRecMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function SetSrcVar: Boolean;
|
||
|
begin
|
||
|
Result := FSrcVarList.SetValue(Identifier, Value, Args);
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := True;
|
||
|
if not FSorted then
|
||
|
Sort;
|
||
|
|
||
|
if Args.Indexed then
|
||
|
begin
|
||
|
if (Args.Obj <> nil) and ((Args.ObjTyp = varObject) or (Args.ObjTyp = varClass)) then
|
||
|
begin
|
||
|
if ISetMethod then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varUnknown then
|
||
|
begin
|
||
|
if IntfISetMethod then
|
||
|
Exit;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if Args.Obj <> nil then
|
||
|
begin
|
||
|
{ methods }
|
||
|
if (Args.ObjTyp = varObject) or (Args.ObjTyp = varClass) then
|
||
|
begin
|
||
|
if SetMethod then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
{ interface methods }
|
||
|
if (Args.ObjTyp = varUnknown) then
|
||
|
begin
|
||
|
if IntfSetMethod then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varRecord then
|
||
|
begin
|
||
|
if (Args.Obj is TJvInterpreterRecHolder) and SetRecord then
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if Args.ObjTyp = varDispatch then
|
||
|
{ Ole automation call }
|
||
|
begin
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
V := Value;
|
||
|
Result := DispatchCall(Identifier, V, Args, False);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
{$ELSE}
|
||
|
NotImplemented(RsOleAutomationCall);
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ source variables and constants }
|
||
|
if SetSrcVar then
|
||
|
Exit;
|
||
|
|
||
|
for I := 0 to FOnSetList.Count - 1 do { Iterate }
|
||
|
begin
|
||
|
TJvInterpreterSetValue(FOnSetList[I]^)(Self, Identifier, Value, Args, Result);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.GetElement(Expression: TJvInterpreterExpression;
|
||
|
const Variable: Variant; var Value: Variant; var Args: TJvInterpreterArgs): Boolean;
|
||
|
|
||
|
function GetID: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
Obj: TObject;
|
||
|
begin
|
||
|
Obj := V2O(Variable);
|
||
|
for I := 0 to FIDGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FIDGetList[I]);
|
||
|
if Obj is JvInterpreterMethod.FClassType then
|
||
|
begin
|
||
|
Args.Obj := Obj;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function IntfGetID: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
Intf: IUnknown;
|
||
|
OIntf: IUnknown;
|
||
|
begin
|
||
|
Intf := IUnknown(Variable);
|
||
|
for I := 0 to FIntfIDGetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod(FIntfIDGetList[I]);
|
||
|
if Intf.QueryInterface(JvInterpreterMethod.IID, OIntf) = S_OK then
|
||
|
begin
|
||
|
Args.Obj := Pointer(Intf);
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterGetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := True;
|
||
|
{ default indexed properties }
|
||
|
if TVarData(Variable).VType = varObject then
|
||
|
begin
|
||
|
if GetID then
|
||
|
Exit;
|
||
|
Result := False;
|
||
|
end
|
||
|
else
|
||
|
if TVarData(Variable).VType = varUnknown then
|
||
|
begin
|
||
|
if IntfGetID then
|
||
|
Exit;
|
||
|
Result := False;
|
||
|
end
|
||
|
else
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.SetElement(Expression: TJvInterpreterExpression;
|
||
|
var Variable: Variant; const Value: Variant; var Args: TJvInterpreterArgs): Boolean;
|
||
|
|
||
|
function SetID: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterMethod;
|
||
|
Obj: TObject;
|
||
|
begin
|
||
|
Obj := V2O(Variable);
|
||
|
for I := 0 to FIDSetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterMethod(FIDSetList[I]);
|
||
|
if Obj is JvInterpreterMethod.FClassType then
|
||
|
begin
|
||
|
Args.Obj := Obj;
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function IntfSetID: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterMethod: TJvInterpreterIntfMethod;
|
||
|
Intf: IUnknown;
|
||
|
OIntf: IUnknown;
|
||
|
begin
|
||
|
Intf := IUnknown(Variable);
|
||
|
for I := 0 to FIntfIDSetList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterMethod := TJvInterpreterIntfMethod(FIntfIDSetList[I]);
|
||
|
if Intf.QueryInterface(JvInterpreterMethod.IID, OIntf) = S_OK then
|
||
|
begin
|
||
|
Args.Obj := Pointer(Intf);
|
||
|
CheckAction(Expression, Args, JvInterpreterMethod.Data);
|
||
|
CheckArgs(Args, JvInterpreterMethod.ParamCount, JvInterpreterMethod.ParamTypes);
|
||
|
TJvInterpreterAdapterSetValue(JvInterpreterMethod.Func)(Value, Args);
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := True;
|
||
|
{ default indexed properties }
|
||
|
if TVarData(Variable).VType = varObject then
|
||
|
begin
|
||
|
if SetID then
|
||
|
Exit;
|
||
|
Result := False;
|
||
|
end
|
||
|
else
|
||
|
if TVarData(Variable).VType = varUnknown then
|
||
|
begin
|
||
|
if IntfSetID then
|
||
|
Exit;
|
||
|
Result := False;
|
||
|
end
|
||
|
else
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.SetRecord(var Value: Variant): Boolean;
|
||
|
var
|
||
|
RecHolder: TJvInterpreterRecHolder;
|
||
|
begin
|
||
|
if TVarData(Value).VType = varRecord then
|
||
|
begin
|
||
|
RecHolder := TJvInterpreterRecHolder(TVarData(Value).VPointer);
|
||
|
RecHolder.JvInterpreterRecord := TJvInterpreterRecord(GetRec(RecHolder.RecordType));
|
||
|
Result := Assigned(RecHolder.JvInterpreterRecord);
|
||
|
end
|
||
|
else
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.NewRecord(const RecordType: string;
|
||
|
var Value: Variant): Boolean;
|
||
|
var
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
begin
|
||
|
JvInterpreterRecord := TJvInterpreterRecord(GetRec(RecordType));
|
||
|
if JvInterpreterRecord = nil then
|
||
|
Result := False
|
||
|
else
|
||
|
begin
|
||
|
JvInterpreterRecord.NewRecord(Value);
|
||
|
Result := True;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
function TJvInterpreterAdapter.DispatchCall(const Identifier: string; var Value: Variant;
|
||
|
Args: TJvInterpreterArgs; Get: Boolean): Boolean; stdcall;
|
||
|
var
|
||
|
CallDesc: TCallDesc;
|
||
|
ParamTypes: array [0..MaxDispArgs * 4 - 1] of Byte;
|
||
|
Ptr: Integer;
|
||
|
TypePtr: Integer;
|
||
|
PVRes: PVariant;
|
||
|
Names: string;
|
||
|
I: Integer;
|
||
|
|
||
|
procedure AddParam(const Param: Variant);
|
||
|
var
|
||
|
Int: Integer;
|
||
|
Wrd: WordBool;
|
||
|
Poin: Pointer;
|
||
|
Dbl: Double;
|
||
|
TempDisp : IDispatch; //ComObj
|
||
|
|
||
|
procedure AddParam1(Typ: Byte; ParamSize: Integer; const Param);
|
||
|
begin
|
||
|
{ CallDesc.ArgTypes[Ptr] := Typ;
|
||
|
Move(Param, ParamTypes[Ptr], ParamSize);
|
||
|
Inc(Ptr, ParamSize); }
|
||
|
CallDesc.ArgTypes[TypePtr] := Typ;
|
||
|
Move(Param, ParamTypes[Ptr], ParamSize);
|
||
|
Inc(Ptr, ParamSize);
|
||
|
Inc(TypePtr);
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
case TVarData(Param).VType of
|
||
|
varInteger:
|
||
|
begin
|
||
|
Int := Param;
|
||
|
AddParam1(varInteger, SizeOf(Int), Int);
|
||
|
end;
|
||
|
varDouble, varCurrency:
|
||
|
begin
|
||
|
Dbl := Param;
|
||
|
AddParam1(varDouble, SizeOf(Dbl), Dbl);
|
||
|
end;
|
||
|
varString:
|
||
|
begin
|
||
|
Poin := V2P(Param);
|
||
|
AddParam1(varStrArg, SizeOf(Poin), Poin);
|
||
|
end;
|
||
|
varBoolean:
|
||
|
begin
|
||
|
Wrd := WordBool(Param);
|
||
|
AddParam1(varBoolean, SizeOf(Wrd), Wrd);
|
||
|
end;
|
||
|
varDispatch:
|
||
|
begin
|
||
|
TempDisp := Param;//VarToInterface(Param).IFace);
|
||
|
AddParam1(varDispatch, SizeOf(TempDisp), TempDisp);
|
||
|
end;
|
||
|
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := True;
|
||
|
{ Call method through Ole Automation }
|
||
|
with CallDesc do
|
||
|
begin
|
||
|
if Get then
|
||
|
CallType := DISPATCH_METHOD or DISPATCH_PROPERTYGET
|
||
|
else
|
||
|
CallType := DISPATCH_PROPERTYPUT;
|
||
|
ArgCount := Args.Count;
|
||
|
NamedArgCount := 0; { named args not supported by JvInterpreter }
|
||
|
end;
|
||
|
Names := Identifier + #00;
|
||
|
Ptr := 0;
|
||
|
TypePtr := 0;
|
||
|
if not Get then
|
||
|
begin
|
||
|
AddParam(Value);
|
||
|
Inc(CallDesc.ArgCount);
|
||
|
end;
|
||
|
for I := 0 to Args.Count - 1 do
|
||
|
AddParam(Args.Values[I]);
|
||
|
Value := Null;
|
||
|
{ When calling procedures(without result) PVRes must be nil }
|
||
|
if Args.HasResult and Get then
|
||
|
PVRes := @Value
|
||
|
else
|
||
|
PVRes := nil;
|
||
|
try
|
||
|
{ call }
|
||
|
// (rom) absolute removed
|
||
|
VarDispInvoke(PVRes, Args.Obj, PChar(Names), @CallDesc, @ParamTypes[0]);
|
||
|
Ptr := 0;
|
||
|
TypePtr := 0;
|
||
|
except
|
||
|
on E: EOleError do
|
||
|
JvInterpreterErrorN2(ieOleAuto, -1, Identifier, E.Message);
|
||
|
end;
|
||
|
if Get and (TVarData(Value).VType = varOleStr) then
|
||
|
Value := VarAsType(Value, varString);
|
||
|
end;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
function TJvInterpreterAdapter.GetValueRTTI(const Identifier: string; var Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
TypeInf: PTypeInfo;
|
||
|
PropInf: PPropInfo;
|
||
|
PropTyp: TypInfo.TTypeKind;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if (Args.ObjTyp <> varObject) or (Args.Obj = nil) then
|
||
|
Exit;
|
||
|
TypeInf := Args.Obj.ClassInfo;
|
||
|
if TypeInf = nil then
|
||
|
Exit;
|
||
|
PropInf := GetPropInfo(TypeInf, Identifier);
|
||
|
if PropInf = nil then
|
||
|
Exit;
|
||
|
PropTyp := PropInf.PropType^.Kind;
|
||
|
case PropTyp of
|
||
|
tkInteger, tkEnumeration:
|
||
|
Value := GetOrdProp(Args.Obj, PropInf);
|
||
|
tkChar, tkWChar:
|
||
|
Value := Char(GetOrdProp(Args.Obj, PropInf));
|
||
|
tkFloat:
|
||
|
Value := GetFloatProp(Args.Obj, PropInf);
|
||
|
{$IFDEF UNICODE} tkUString, {$ENDIF}
|
||
|
tkString, tkLString, tkWString:
|
||
|
Value := GetStrProp(Args.Obj, PropInf);
|
||
|
tkClass:
|
||
|
Value := O2V(TObject(GetOrdProp(Args.Obj, PropInf)));
|
||
|
tkSet:
|
||
|
Value := S2V(GetOrdProp(Args.Obj, PropInf));
|
||
|
tkInterface:
|
||
|
Value := GetInterfaceProp(Args.Obj, PropInf)
|
||
|
else
|
||
|
Exit;
|
||
|
end;
|
||
|
if PropInf^.PropType^.Name = 'Boolean' then
|
||
|
TVarData(Value).VType := varBoolean;
|
||
|
Result := True;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.SetValueRTTI(const Identifier: string; const Value: Variant;
|
||
|
Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
TypeInf: PTypeInfo;
|
||
|
PropInf: PPropInfo;
|
||
|
PropTyp: TypInfo.TTypeKind;
|
||
|
Obj: TObject;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if (Args.ObjTyp <> varObject) or (Args.Obj = nil) then
|
||
|
Exit;
|
||
|
Obj := Args.Obj;
|
||
|
TypeInf := Obj.ClassInfo;
|
||
|
if TypeInf = nil then
|
||
|
Exit;
|
||
|
PropInf := GetPropInfo(TypeInf, Identifier);
|
||
|
if PropInf = nil then
|
||
|
Exit;
|
||
|
PropTyp := PropInf.PropType^.Kind;
|
||
|
case PropTyp of
|
||
|
tkInteger, tkEnumeration:
|
||
|
SetOrdProp(Args.Obj, PropInf, Var2Type(Value, varInteger));
|
||
|
tkChar, tkWChar:
|
||
|
SetOrdProp(Args.Obj, PropInf, Integer(string(Value)[1]));
|
||
|
tkFloat:
|
||
|
SetFloatProp(Args.Obj, PropInf, Value);
|
||
|
{$IFDEF UNICODE} tkUString, {$ENDIF}
|
||
|
tkString, tkLString, tkWString:
|
||
|
SetStrProp(Args.Obj, PropInf, VarToStr(Value));
|
||
|
tkClass:
|
||
|
SetOrdProp(Args.Obj, PropInf, NativeInt(V2O(Value)));
|
||
|
tkSet:
|
||
|
SetOrdProp(Args.Obj, PropInf, V2S(Value));
|
||
|
tkInterface:
|
||
|
SetInterfaceProp(Args.Obj, PropInf, Value);
|
||
|
else
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := True;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.CurUnitChanged(const NewUnitName: string; var Source: string);
|
||
|
var
|
||
|
I: Integer;
|
||
|
JvInterpreterUnitSource: TJvInterpreterSrcUnit;
|
||
|
begin
|
||
|
for I := 0 to FSrcUnitList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterUnitSource := TJvInterpreterSrcUnit(FSrcUnitList.Items[I]);
|
||
|
if Cmp(TJvInterpreterSrcUnit(JvInterpreterUnitSource).Identifier, NewUnitName) then
|
||
|
begin
|
||
|
Source := TJvInterpreterSrcUnit(JvInterpreterUnitSource).FSource;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Source := '';
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.UnitExists(const Identifier: string): Boolean;
|
||
|
var
|
||
|
JvInterpreterIdentifier: TJvInterpreterIdentifier;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
Result := True;
|
||
|
for I := 0 to FSrcUnitList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterIdentifier := TJvInterpreterIdentifier(FSrcUnitList.Items[I]);
|
||
|
if Cmp(JvInterpreterIdentifier.Identifier, Identifier) then
|
||
|
Exit;
|
||
|
end;
|
||
|
for I := 0 to FExtUnitList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterIdentifier := TJvInterpreterIdentifier(FExtUnitList.Items[I]);
|
||
|
if Cmp(JvInterpreterIdentifier.Identifier, Identifier) then
|
||
|
Exit;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.NewEvent(const UnitName: string; const FunctionName,
|
||
|
EventType: string; AOwner: TJvInterpreterExpression; AObject: TObject;
|
||
|
const APropName: string): TSimpleEvent;
|
||
|
var
|
||
|
Event: TJvInterpreterEvent;
|
||
|
I: Integer;
|
||
|
JvInterpreterEventDesc: TJvInterpreterEventDesc;
|
||
|
begin
|
||
|
for I := 0 to FEventHandlerList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterEventDesc := TJvInterpreterEventDesc(FEventHandlerList.Items[I]);
|
||
|
if Cmp(JvInterpreterEventDesc.Identifier, EventType) then
|
||
|
begin
|
||
|
Event := JvInterpreterEventDesc.EventClass.Create(AOwner, AObject, UnitName, FunctionName, APropName);
|
||
|
TMethod(Result).Code := JvInterpreterEventDesc.Code;
|
||
|
TMethod(Result).Data := Event;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterAdapter.IsEvent(Obj: TObject; const Identifier: string): Boolean;
|
||
|
var
|
||
|
JvInterpreterClass: TJvInterpreterClass;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to FEventList.Count - 1 do
|
||
|
begin
|
||
|
JvInterpreterClass := TJvInterpreterClass(FEventList[I]);
|
||
|
if (Obj is JvInterpreterClass.FClassType) and
|
||
|
Cmp(JvInterpreterClass.Identifier, Identifier) then
|
||
|
begin
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterAdapter.Sort;
|
||
|
begin
|
||
|
FConstList.Sort;
|
||
|
FClassList.Sort;
|
||
|
FFunctionList.Sort;
|
||
|
FGetList.Sort;
|
||
|
FSetList.Sort;
|
||
|
FIntfGetList.Sort;
|
||
|
FIntfSetList.Sort;
|
||
|
FIGetList.Sort;
|
||
|
FISetList.Sort;
|
||
|
FIntfIGetList.Sort;
|
||
|
FIntfISetList.Sort;
|
||
|
FSorted := True;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterArgs } =================================================
|
||
|
|
||
|
destructor TJvInterpreterArgs.Destroy;
|
||
|
begin
|
||
|
if OA <> nil then
|
||
|
Dispose(OA);
|
||
|
if FOAV <> nil then
|
||
|
Dispose(FOAV);
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterArgs.Clear;
|
||
|
begin
|
||
|
Count := 0;
|
||
|
Obj := nil;
|
||
|
ObjTyp := 0;
|
||
|
FHasVars := False;
|
||
|
Indexed := False;
|
||
|
ReturnIndexed := False;
|
||
|
ObjRefHolder := Unassigned;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterArgs.OpenArray(const Index: Integer);
|
||
|
begin
|
||
|
if OA = nil then
|
||
|
New(OA);
|
||
|
if FOAV = nil then
|
||
|
New(FOAV);
|
||
|
V2OA(Values[Index], OA^, FOAV^, OAS);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterArgs.Delete(const Index: Integer);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := Index to Count - 2 do
|
||
|
begin
|
||
|
Types[I] := Types[I + 1];
|
||
|
Values[I] := Values[I + 1];
|
||
|
Names[I] := Names[I + 1];
|
||
|
end;
|
||
|
Dec(Count);
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterExpression } ===========================================
|
||
|
|
||
|
constructor TJvInterpreterExpression.Create(AOwner: TComponent);
|
||
|
begin
|
||
|
inherited Create(AOwner);
|
||
|
FParser := TJvInterpreterParser.Create;
|
||
|
FPStream := TStringStream.Create('');
|
||
|
FArgs := TJvInterpreterArgs.Create;
|
||
|
FAdapter := CreateAdapter;
|
||
|
FDisableExternalFunctions := False;
|
||
|
FAdapter.DisableExternalFunctions := False;
|
||
|
FSharedAdapter := GlobalJvInterpreterAdapter;
|
||
|
FLastError := EJvInterpreterError.Create(-1, -1, '', '');
|
||
|
FAllowAssignment := True;
|
||
|
FCompiled := False;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterExpression.Destroy;
|
||
|
begin
|
||
|
JvInterpreterVarFree(FVResult);
|
||
|
FAdapter.Free;
|
||
|
FArgs.Free;
|
||
|
FPStream.Free;
|
||
|
FParser.Free;
|
||
|
FLastError.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.UpdateExceptionPos(E: Exception; const UnitName: string);
|
||
|
|
||
|
procedure NoName(E: EJvInterpreterError);
|
||
|
begin
|
||
|
if not E.FExceptionPos then
|
||
|
begin
|
||
|
if E.FErrPos = -1 then
|
||
|
E.FErrPos := CurPos;
|
||
|
if E.FErrUnitName = '' then
|
||
|
E.FErrUnitName := UnitName;
|
||
|
if E.FErrUnitName <> '' then
|
||
|
begin
|
||
|
{ first line has number 1 }
|
||
|
E.FErrLine := GetLineByPos(FParser.Source, E.FErrPos) + BaseErrLine + 1;
|
||
|
E.Message := Format(LoadStr2(ieErrorPos), [E.FErrUnitName, E.FErrLine, E.FErrMessage]);
|
||
|
E.FExceptionPos := True;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
if E is EJvInterpreterError then
|
||
|
begin
|
||
|
NoName(E as EJvInterpreterError);
|
||
|
FLastError.Assign(E as EJvInterpreterError);
|
||
|
end
|
||
|
else
|
||
|
if not FLastError.FExceptionPos then
|
||
|
begin
|
||
|
FLastError.FErrCode := ieExternal;
|
||
|
FLastError.Message := E.Message;
|
||
|
FLastError.FErrMessage := E.Message;
|
||
|
NoName(FLastError);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.Init;
|
||
|
begin
|
||
|
JvInterpreterVarFree(FVResult);
|
||
|
FExpStackPtr := -1;
|
||
|
// Parse;
|
||
|
FParser.Init;
|
||
|
FBacked := False;
|
||
|
FCurrArgs := FArgs;
|
||
|
FAdapter.ClearNonSource;
|
||
|
FLastError.Clear;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.GetSource: string;
|
||
|
begin
|
||
|
Result := FParser.Source;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.SetSource(const Value: string);
|
||
|
begin
|
||
|
FParser.Source := Value;
|
||
|
SourceChanged;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.SourceChanged;
|
||
|
begin
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.SetAdapter(Adapter: TJvInterpreterAdapter);
|
||
|
begin
|
||
|
FAdapter := Adapter;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.SetCurPos(Value: Integer);
|
||
|
begin
|
||
|
if FParsed then
|
||
|
FPStream.Position := Value
|
||
|
else
|
||
|
FParser.Pos := Value;
|
||
|
FBacked := False;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.GetCurPos: Integer;
|
||
|
begin
|
||
|
if FParsed then
|
||
|
Result := FPStream.Position
|
||
|
else
|
||
|
Result := FParser.Pos;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.ErrorExpected(const Exp: string);
|
||
|
begin
|
||
|
if TokenStr <> '' then
|
||
|
JvInterpreterErrorN2(ieExpected, PosBeg, Exp, '''' + TokenStr + '''')
|
||
|
else
|
||
|
JvInterpreterErrorN2(ieExpected, PosBeg, Exp, LoadStr2(irEndOfFile));
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.ErrorNotImplemented(const Msg: string);
|
||
|
begin
|
||
|
JvInterpreterErrorN(ieInternal, PosBeg, Msg + RsENotImplemented);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.PosBeg: Integer;
|
||
|
begin
|
||
|
Result := CurPos - Length(TokenStr);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.PosEnd: Integer;
|
||
|
begin
|
||
|
Result := CurPos;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.GetTokenStr: string;
|
||
|
begin
|
||
|
if FParsed and (TTyp <> ttUnknown) then
|
||
|
Result := TypToken(TTyp)
|
||
|
else
|
||
|
Result := FTokenStr;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.Parse;
|
||
|
begin
|
||
|
FPStream.Size := 0;
|
||
|
FPStream.Position := 0;
|
||
|
FParser.Init;
|
||
|
repeat
|
||
|
ParseToken;
|
||
|
WriteToken;
|
||
|
until FTTyp = ttEmpty;
|
||
|
FParsed := True;
|
||
|
FPStream.Position := 0;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.WriteToken;
|
||
|
begin
|
||
|
WordSaveToStream(FPStream, Word(FTTyp));
|
||
|
case FTTyp of
|
||
|
ttInteger:
|
||
|
IntSaveToStream(FPStream, FToken);
|
||
|
ttString:
|
||
|
StringSaveToStream(FPStream, FToken);
|
||
|
ttTrue, ttFalse:
|
||
|
BoolSaveToStream(FPStream, FToken);
|
||
|
ttDouble:
|
||
|
ExtendedSaveToStream(FPStream, FToken);
|
||
|
ttIdentifier:
|
||
|
StringSaveToStream(FPStream, FToken);
|
||
|
ttUnknown:
|
||
|
StringSaveToStream(FPStream, FTokenStr);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.ReadToken;
|
||
|
begin
|
||
|
FTTyp := Smallint(WordLoadFromStream(FPStream));
|
||
|
case FTTyp of
|
||
|
ttInteger:
|
||
|
FToken := IntLoadFromStream(FPStream);
|
||
|
ttString:
|
||
|
FToken := StringLoadFromStream(FPStream);
|
||
|
ttTrue, ttFalse:
|
||
|
FToken := BoolLoadFromStream(FPStream);
|
||
|
ttDouble:
|
||
|
FToken := ExtendedLoadFromStream(FPStream);
|
||
|
ttIdentifier:
|
||
|
FToken := StringLoadFromStream(FPStream);
|
||
|
ttUnknown:
|
||
|
FTokenStr := StringLoadFromStream(FPStream);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.NextToken;
|
||
|
begin
|
||
|
if FBacked then
|
||
|
FBacked := False
|
||
|
else
|
||
|
begin
|
||
|
FPrevTTyp := FTTyp;
|
||
|
if FParsed then
|
||
|
ReadToken
|
||
|
else
|
||
|
ParseToken;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.ParseToken;
|
||
|
var
|
||
|
{$IFDEF DELPHI7_UP}
|
||
|
FS: TFormatSettings;
|
||
|
{$ELSE}
|
||
|
OldDecimalSeparator: Char;
|
||
|
{$ENDIF DELPHI7_UP}
|
||
|
Dob: Extended;
|
||
|
Int: Integer;
|
||
|
ValueInt64: Int64;
|
||
|
Stub: Integer;
|
||
|
begin
|
||
|
FTokenStr := FParser.Token;
|
||
|
FTTyp := TokenTyp(FTokenStr);
|
||
|
case TTyp of
|
||
|
ttInteger:
|
||
|
begin
|
||
|
Val(FTokenStr, Int, Stub);
|
||
|
if Stub <> 0 then
|
||
|
begin
|
||
|
Val(FTokenStr, ValueInt64, Stub);
|
||
|
FToken := ValueInt64;
|
||
|
if Stub <> 0 then
|
||
|
JvInterpreterError(ieIntegerRequired, FParser.Pos);
|
||
|
end
|
||
|
else
|
||
|
FToken := Int;
|
||
|
end;
|
||
|
ttDouble:
|
||
|
begin
|
||
|
{$IFDEF DELPHI7_UP}
|
||
|
FS.ThousandSeparator := ',';
|
||
|
FS.DecimalSeparator := '.';
|
||
|
if not TextToFloat(PChar(FTokenStr), Dob, fvExtended, FS) then
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
{$ELSE}
|
||
|
OldDecimalSeparator := DecimalSeparator;
|
||
|
DecimalSeparator := '.';
|
||
|
if not TextToFloat(PChar(FTokenStr), Dob, fvExtended) then
|
||
|
begin
|
||
|
DecimalSeparator := OldDecimalSeparator;
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
end
|
||
|
else
|
||
|
DecimalSeparator := OldDecimalSeparator;
|
||
|
{$ENDIF DELPHI7_UP}
|
||
|
FToken := Dob;
|
||
|
end;
|
||
|
ttString:
|
||
|
FToken := Copy(TokenStr, 2, Length(FTokenStr) - 2);
|
||
|
ttFalse:
|
||
|
FToken := False;
|
||
|
ttTrue:
|
||
|
FToken := True;
|
||
|
ttIdentifier:
|
||
|
FToken := FTokenStr;
|
||
|
{-----olej-----}
|
||
|
ttArray:
|
||
|
FToken := FTokenStr;
|
||
|
{-----olej-----}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.Back;
|
||
|
begin
|
||
|
// JvInterpreterError(ieInternal, -2);
|
||
|
if FBacked then
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
FBacked := True;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.SafeBack;
|
||
|
begin
|
||
|
if not FBacked then
|
||
|
Back;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.CreateAdapter: TJvInterpreterAdapter;
|
||
|
begin
|
||
|
Result := TJvInterpreterAdapter.Create(Self);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.Expression1: Variant;
|
||
|
var
|
||
|
OldExpStackPtr: Integer;
|
||
|
|
||
|
procedure PushExp(var Value: Variant);
|
||
|
begin
|
||
|
Inc(FExpStackPtr);
|
||
|
if FExpStackPtr > High(FExpStack) then
|
||
|
JvInterpreterError(ieExpressionStackOverflow, -1);
|
||
|
JvInterpreterVarCopy(FExpStack[FExpStackPtr], Value);
|
||
|
end;
|
||
|
|
||
|
function PopExp: Variant;
|
||
|
begin
|
||
|
if FExpStackPtr = -1 then
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
JvInterpreterVarCopy(Result, FExpStack[FExpStackPtr]);
|
||
|
Dec(FExpStackPtr);
|
||
|
end;
|
||
|
|
||
|
{ function Expression called recursively very often, so placing it
|
||
|
as local function (not class method) improves performance }
|
||
|
|
||
|
function Expression(const OpTyp: TTokenKind): Variant;
|
||
|
var
|
||
|
Tmp: Variant;
|
||
|
PrevTTyp: Integer;
|
||
|
begin
|
||
|
Result := Unassigned;
|
||
|
if OpTyp <> ttUnknown then
|
||
|
NextToken;
|
||
|
PrevTTyp := TTyp;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttInteger, ttDouble, ttFalse, ttTrue, ttIdentifier:
|
||
|
begin
|
||
|
Result := Token;
|
||
|
if TTyp = ttIdentifier then
|
||
|
begin
|
||
|
FCurrArgs.Clear;
|
||
|
InternalGetValue(nil, 0, Result);
|
||
|
end;
|
||
|
NextToken;
|
||
|
if TTyp in [ttInteger, ttDouble, ttString,
|
||
|
ttFalse, ttTrue, ttIdentifier] then
|
||
|
JvInterpreterError(ieMissingOperator, PosEnd {!!});
|
||
|
if Prior(TTyp) < Prior(OpTyp) then
|
||
|
Exit;
|
||
|
end;
|
||
|
ttString:
|
||
|
begin
|
||
|
Result := '';
|
||
|
repeat
|
||
|
Result := Result + Token;
|
||
|
NextToken;
|
||
|
if TTyp in [ttInteger, ttDouble, ttFalse, ttTrue, ttIdentifier] then
|
||
|
JvInterpreterError(ieMissingOperator, PosEnd {!!});
|
||
|
until TTyp <> ttString;
|
||
|
if Prior(TTyp) < Prior(OpTyp) then
|
||
|
Exit;
|
||
|
end;
|
||
|
|
||
|
// [peter schraut: added ttShl case on 2005/08/14]
|
||
|
ttShl:
|
||
|
if priorShl > Prior(OpTyp) then
|
||
|
Result := PopExp shl Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
|
||
|
// [peter schraut: added ttShr case on 2005/08/14]
|
||
|
ttShr:
|
||
|
if priorShr > Prior(OpTyp) then
|
||
|
Result := PopExp shr Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
|
||
|
// [peter schraut: added ttXor case on 2005/08/14]
|
||
|
ttXor:
|
||
|
if priorXor > Prior(OpTyp) then
|
||
|
Result := PopExp xor Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
|
||
|
ttMul:
|
||
|
if priorMul > Prior(OpTyp) then
|
||
|
Result := PopExp * Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttPlus:
|
||
|
{ proceed differently depending on type }
|
||
|
if not (FPrevTTyp in [ttInteger, ttDouble, ttString, ttFalse, ttTrue,
|
||
|
ttIdentifier, ttRB, ttRS]) then
|
||
|
{ unary plus }
|
||
|
Result := Expression(ttNot) { highest priority }
|
||
|
else
|
||
|
if priorPlus > Prior(OpTyp) then
|
||
|
begin
|
||
|
Tmp := PopExp;
|
||
|
if TVarData(Tmp).VType = varSet then
|
||
|
begin
|
||
|
Result := TVarData(Tmp).VInteger or
|
||
|
TVarData(Expression(TTyp)).VInteger;
|
||
|
TVarData(Result).VType := varSet;
|
||
|
end
|
||
|
else
|
||
|
Result := Tmp + Expression(TTyp)
|
||
|
end
|
||
|
else
|
||
|
Exit;
|
||
|
ttMinus:
|
||
|
{ proceed differently depending on type }
|
||
|
if not (FPrevTTyp in [ttInteger, ttDouble, ttString, ttFalse, ttTrue,
|
||
|
ttIdentifier, ttRB, ttRS]) then
|
||
|
{ unary minus }
|
||
|
Result := -Expression(ttNot) { highest priority }
|
||
|
else
|
||
|
if priorMinus > Prior(OpTyp) then
|
||
|
begin
|
||
|
Tmp := PopExp;
|
||
|
if TVarData(Tmp).VType = varSet then
|
||
|
begin
|
||
|
Result := TVarData(Tmp).VInteger and
|
||
|
not TVarData(Expression(TTyp)).VInteger;
|
||
|
TVarData(Result).VType := varSet;
|
||
|
end
|
||
|
else
|
||
|
Result := Tmp - Expression(TTyp)
|
||
|
end
|
||
|
else
|
||
|
Exit;
|
||
|
ttDiv:
|
||
|
if priorDiv > Prior(OpTyp) then
|
||
|
Result := PopExp / Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttIntDiv:
|
||
|
if priorIntDiv > Prior(OpTyp) then
|
||
|
Result := PopExp div Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttMod:
|
||
|
if priorMod > Prior(OpTyp) then
|
||
|
Result := PopExp mod Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttOr:
|
||
|
if priorOr > Prior(OpTyp) then
|
||
|
Result := PopExp or Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttAnd:
|
||
|
if priorAnd > Prior(OpTyp) then
|
||
|
Result := PopExp and Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttNot:
|
||
|
{ 'Not' has highest priority, so we have no need to check this }
|
||
|
// if priorNot > Prior(OpTyp) then
|
||
|
Result := not Expression(TTyp);
|
||
|
// else Exit;
|
||
|
ttEqu:
|
||
|
{ proceed differently depending on type }
|
||
|
if priorEqu > Prior(OpTyp) then
|
||
|
begin
|
||
|
Tmp := PopExp;
|
||
|
if (TVarData(Tmp).VType = varObject) or (TVarData(Tmp).VType = varClass) or
|
||
|
(TVarData(Tmp).VType = varSet) or (TVarData(Tmp).VType = varPointer) then
|
||
|
Result := TVarData(Tmp).VInteger = TVarData(Expression(TTyp)).VInteger
|
||
|
else
|
||
|
Result := Tmp = Expression(TTyp)
|
||
|
end
|
||
|
else
|
||
|
Exit;
|
||
|
ttNotEqu:
|
||
|
{ proceed differently depending on a types }
|
||
|
if priorNotEqu > Prior(OpTyp) then
|
||
|
begin
|
||
|
Tmp := PopExp;
|
||
|
if (TVarData(Tmp).VType = varObject) or (TVarData(Tmp).VType = varClass) or
|
||
|
(TVarData(Tmp).VType = varSet) or (TVarData(Tmp).VType = varPointer) then
|
||
|
Result := TVarData(Tmp).VInteger <>
|
||
|
TVarData(Expression(TTyp)).VInteger
|
||
|
else
|
||
|
if TVarData(Tmp).VType = varUnknown then
|
||
|
Result := TVarData(Tmp).VUnknown <> TVarData(Expression(TTyp)).VUnknown
|
||
|
else
|
||
|
Result := Tmp <> Expression(TTyp)
|
||
|
end
|
||
|
else
|
||
|
Exit;
|
||
|
ttGreater:
|
||
|
if priorGreater > Prior(OpTyp) then
|
||
|
Result := PopExp > Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttLess:
|
||
|
if priorLess > Prior(OpTyp) then
|
||
|
Result := PopExp < Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttEquLess:
|
||
|
if priorEquLess > Prior(OpTyp) then
|
||
|
Result := PopExp <= Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttEquGreater:
|
||
|
if priorEquGreater > Prior(OpTyp) then
|
||
|
Result := PopExp >= Expression(TTyp)
|
||
|
else
|
||
|
Exit;
|
||
|
ttLB:
|
||
|
begin
|
||
|
Result := Expression(TTyp);
|
||
|
if FTTyp <> ttRB then
|
||
|
ErrorExpected(''')''');
|
||
|
NextToken;
|
||
|
end;
|
||
|
ttRB:
|
||
|
if (TVarData(Result).VType = varEmpty) and (PrevTTyp <> ttIdentifier) then
|
||
|
ErrorExpected(LoadStr2(irExpression))
|
||
|
else
|
||
|
Exit;
|
||
|
ttLS:
|
||
|
begin
|
||
|
NextToken;
|
||
|
Result := SetExpression1;
|
||
|
if FTTyp <> ttRS then
|
||
|
ErrorExpected(''']''');
|
||
|
NextToken;
|
||
|
end;
|
||
|
ttRS:
|
||
|
if (TVarData(Result).VType = varEmpty) and (PrevTTyp <> ttIdentifier) then
|
||
|
ErrorExpected(LoadStr2(irExpression))
|
||
|
else
|
||
|
Exit;
|
||
|
else
|
||
|
if (TVarData(Result).VType = varEmpty) and (PrevTTyp <> ttIdentifier) then
|
||
|
ErrorExpected(LoadStr2(irExpression))
|
||
|
else
|
||
|
Exit;
|
||
|
end;
|
||
|
PushExp(Result);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Result := Null;
|
||
|
try
|
||
|
OldExpStackPtr := FExpStackPtr;
|
||
|
try
|
||
|
Expression(ttUnknown);
|
||
|
JvInterpreterVarCopy(Result, PopExp);
|
||
|
finally
|
||
|
FExpStackPtr := OldExpStackPtr;
|
||
|
end;
|
||
|
except
|
||
|
on E: EVariantError do
|
||
|
JvInterpreterError(ieTypeMistmatch, CurPos);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.Expression2(const ExpType: Word): Variant;
|
||
|
var
|
||
|
ErrPos: Integer;
|
||
|
begin
|
||
|
ErrPos := PosBeg;
|
||
|
try
|
||
|
FAllowAssignment := False;
|
||
|
Result := Expression1;
|
||
|
finally
|
||
|
FAllowAssignment := True;
|
||
|
end;
|
||
|
if TVarData(Result).VType <> ExpType then
|
||
|
case ExpType of
|
||
|
varInteger:
|
||
|
JvInterpreterError(ieIntegerRequired, ErrPos);
|
||
|
varBoolean:
|
||
|
JvInterpreterError(ieBooleanRequired, ErrPos);
|
||
|
else
|
||
|
JvInterpreterError(ieUnknown, ErrPos);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ calulate set expressions, such as: [fsBold, fsItalic] }
|
||
|
|
||
|
function TJvInterpreterExpression.SetExpression1: Variant;
|
||
|
var
|
||
|
V1: Variant;
|
||
|
begin
|
||
|
Result := 0;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttIdentifier, ttInteger:
|
||
|
begin
|
||
|
if TTyp = ttInteger then
|
||
|
Result := Result or Integer(Token)
|
||
|
else
|
||
|
begin
|
||
|
FCurrArgs.Clear;
|
||
|
InternalGetValue(nil, 0, V1);
|
||
|
if not VarIsOrdinal(V1) then
|
||
|
JvInterpreterError(ieIntegerRequired, PosBeg);
|
||
|
Result := Result or 1 shl Integer(V1);
|
||
|
end;
|
||
|
NextToken; { skip ',' }
|
||
|
if TTyp = ttCol then
|
||
|
NextToken
|
||
|
else
|
||
|
if TTyp = ttRS then
|
||
|
Break
|
||
|
else
|
||
|
ErrorExpected(''']''');
|
||
|
end;
|
||
|
ttRS:
|
||
|
Break;
|
||
|
else
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
TVarData(Result).VType := varSet;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.ReadArgs;
|
||
|
|
||
|
function ReadOpenArray: Variant;
|
||
|
var
|
||
|
Values: TValueArray;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
{ open array or set constant }
|
||
|
NextToken;
|
||
|
Values[0] := Expression1;
|
||
|
I := 1;
|
||
|
while TTyp = ttCol do
|
||
|
begin
|
||
|
NextToken;
|
||
|
FCurrArgs.Clear;
|
||
|
Values[I] := Expression1;
|
||
|
Inc(I);
|
||
|
end;
|
||
|
if TTyp <> ttRS then
|
||
|
ErrorExpected(''']''');
|
||
|
Result := VarArrayCreate([0, I - 1], varVariant);
|
||
|
for I := 0 to I - 1 do
|
||
|
Result[I] := Values[I];
|
||
|
NextToken;
|
||
|
end;
|
||
|
|
||
|
var
|
||
|
LocalArgs: TJvInterpreterArgs;
|
||
|
I: Integer;
|
||
|
SK: TTokenKind;
|
||
|
begin
|
||
|
LocalArgs := FCurrArgs;
|
||
|
FCurrArgs := TJvInterpreterArgs.Create;
|
||
|
FCurrArgs.Indexed := LocalArgs.Indexed;
|
||
|
try
|
||
|
I := 0;
|
||
|
if TTyp = ttLB then
|
||
|
SK := ttRB
|
||
|
else
|
||
|
SK := ttRS;
|
||
|
|
||
|
NextToken;
|
||
|
if TTyp = ttIdentifier then
|
||
|
LocalArgs.FVarNames[I] := Token
|
||
|
else
|
||
|
LocalArgs.FVarNames[I] := '';
|
||
|
|
||
|
FCurrArgs.Clear;
|
||
|
if TTyp = ttLS then
|
||
|
LocalArgs.Values[I] := ReadOpenArray
|
||
|
//added check to recognize C style (), like "NextToken()"
|
||
|
//RWare: if token ')', skip and exit
|
||
|
else
|
||
|
if TTyp = ttRB then
|
||
|
begin
|
||
|
NextToken;
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterVarCopy(LocalArgs.Values[I], Expression1);
|
||
|
|
||
|
while TTyp = ttCol do
|
||
|
begin
|
||
|
Inc(I);
|
||
|
NextToken;
|
||
|
if TTyp = ttIdentifier then
|
||
|
LocalArgs.FVarNames[I] := Token
|
||
|
else
|
||
|
LocalArgs.FVarNames[I] := '';
|
||
|
FCurrArgs.Clear;
|
||
|
if TTyp = ttLS then
|
||
|
LocalArgs.Values[I] := ReadOpenArray
|
||
|
else
|
||
|
JvInterpreterVarCopy(LocalArgs.Values[I], Expression1);
|
||
|
end;
|
||
|
if TTyp <> SK then
|
||
|
if SK = ttRB then
|
||
|
ErrorExpected(''')''')
|
||
|
else
|
||
|
ErrorExpected(''']''');
|
||
|
NextToken;
|
||
|
LocalArgs.Count := I + 1;
|
||
|
finally
|
||
|
FCurrArgs.Free;
|
||
|
FCurrArgs := LocalArgs;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.InternalGetValue(Obj: Pointer; ObjTyp: Word;
|
||
|
var Result: Variant);
|
||
|
var
|
||
|
Identifier: string;
|
||
|
V: Variant;
|
||
|
VType: TVarType;
|
||
|
|
||
|
procedure UpdateVarParams;
|
||
|
var
|
||
|
I, C: Integer;
|
||
|
begin
|
||
|
if not FCurrArgs.FHasVars then
|
||
|
Exit;
|
||
|
C := FCurrArgs.Count;
|
||
|
FCurrArgs.Obj := nil;
|
||
|
FCurrArgs.ObjTyp := 0;
|
||
|
FCurrArgs.ObjRefHolder := Unassigned;
|
||
|
FCurrArgs.Count := 0;
|
||
|
for I := 0 to C - 1 do
|
||
|
if (FCurrArgs.FVarNames[I] <> '') and ((FCurrArgs.Types[I] and varByRef) <> 0) then
|
||
|
{ if not }SetValue(FCurrArgs.FVarNames[I], FCurrArgs.Values[I], FCurrArgs); { then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, FCurrArgs.VarNames[I])};
|
||
|
FCurrArgs.FHasVars := False;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Identifier := Token;
|
||
|
NextToken;
|
||
|
FCurrArgs.Indexed := TTyp = ttLS;
|
||
|
if TTyp in [ttLB, ttLS] then
|
||
|
ReadArgs
|
||
|
else
|
||
|
FCurrArgs.Count := 0;
|
||
|
FCurrArgs.Obj := Obj;
|
||
|
FCurrArgs.ObjTyp := ObjTyp;
|
||
|
|
||
|
if (TTyp = ttColon) and FAllowAssignment then
|
||
|
begin
|
||
|
if ObjTyp = varDispatch then
|
||
|
FCurrArgs.ObjRefHolder := IDispatch(Obj)
|
||
|
else
|
||
|
if ObjTyp = varUnknown then
|
||
|
FCurrArgs.ObjRefHolder := IUnknown(Obj);
|
||
|
|
||
|
Back;
|
||
|
FToken := Identifier; {!!!!!!!!!!!!!!}
|
||
|
{ FCurrArgs.Obj, FCurrArgs.ObjTyp, FCurrArgs.Count needed in caller }
|
||
|
Exit;
|
||
|
end;
|
||
|
|
||
|
{ need result if object field or method or assignment }
|
||
|
FCurrArgs.HasResult := (TTyp in [ttPoint, ttRB, ttCol, ttNot..ttEquLess]) or
|
||
|
FCurrArgs.Assignment;
|
||
|
FCurrArgs.ReturnIndexed := False;
|
||
|
|
||
|
JvInterpreterVarFree(Result);
|
||
|
if GetValue(Identifier, Result, FCurrArgs) then
|
||
|
begin
|
||
|
if TVarData(Result).VType = varRecord then
|
||
|
if not (FAdapter.SetRecord(Result) or
|
||
|
(FAdapter <> GlobalJvInterpreterAdapter) and
|
||
|
GlobalJvInterpreterAdapter.SetRecord(Result)) then
|
||
|
JvInterpreterErrorN(ieRecordNotDefined, -1, RsEUnknownRecordType);
|
||
|
{ Args.HasVars may be changed in previous call to GetValue }
|
||
|
if FCurrArgs.FHasVars then
|
||
|
UpdateVarParams;
|
||
|
if FCurrArgs.Indexed and not FCurrArgs.ReturnIndexed then
|
||
|
begin
|
||
|
JvInterpreterVarCopy(V, Result);
|
||
|
if not GetElement(V, Result, FCurrArgs) then
|
||
|
{ problem }
|
||
|
JvInterpreterError(ieArrayRequired, PosBeg);
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg {?}, Identifier);
|
||
|
|
||
|
FCurrArgs.Obj := nil;
|
||
|
FCurrArgs.ObjTyp := 0;
|
||
|
FCurrArgs.ObjRefHolder := Unassigned;
|
||
|
FCurrArgs.Count := 0;
|
||
|
{ FCurrArgs.Obj, FCurrArgs.ObjTyp, FCurrArgs.Count NOT needed in caller }
|
||
|
|
||
|
if TTyp = ttPoint then { object field or method }
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
VType := TVarData(Result).VType;
|
||
|
if (VType <> varObject) and (VType <> varClass) and
|
||
|
(VType <> varRecord) and (VType <> varDispatch) and (VType <> varUnknown) then
|
||
|
{if not (TVarData(Result).VType in
|
||
|
[varObject, varClass, varRecord, varDispatch, varUnknown]) then}
|
||
|
JvInterpreterError(ieROCRequired, PosBeg);
|
||
|
|
||
|
V := Null;
|
||
|
InternalGetValue(TVarData(Result).VPointer, TVarData(Result).VType, V);
|
||
|
JvInterpreterVarCopy(Result, V);
|
||
|
|
||
|
NextToken;
|
||
|
end;
|
||
|
|
||
|
Back;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.GetElement(const Variable: Variant; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
II2: Integer;
|
||
|
VV: TJvInterpreterArrayValues;
|
||
|
PP: PJvInterpreterArrayRec;
|
||
|
Bound: Integer;
|
||
|
AI: array of Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if Args.Count <> 0 then
|
||
|
begin
|
||
|
if TVarData(Variable).VType = varString then
|
||
|
begin
|
||
|
if Args.Count > 1 then
|
||
|
JvInterpreterError(ieArrayTooManyParams, -1);
|
||
|
if Length(Variable) = 0 then
|
||
|
raise ERangeError.CreateRes(@RsERangeCheckError);
|
||
|
Value := string(Variable)[Integer(Args.Values[0])];
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
if TVarData(Variable).VType = varArray then
|
||
|
begin
|
||
|
{Get array value}
|
||
|
PP := PJvInterpreterArrayRec(NativeInt(JvInterpreterVarAsType(Variable, varInteger)));
|
||
|
if Args.Count > PP.Dimension then
|
||
|
JvInterpreterError(ieArrayTooManyParams, -1)
|
||
|
else
|
||
|
if Args.Count < PP.Dimension then
|
||
|
JvInterpreterError(ieArrayNotEnoughParams, -1);
|
||
|
for II2 := 0 to Args.Count - 1 do
|
||
|
begin
|
||
|
Bound := Args.Values[II2];
|
||
|
if Bound < PP.BeginPos[II2] then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1)
|
||
|
else
|
||
|
if Bound > PP.EndPos[II2] then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
VV[II2] := Args.Values[II2];
|
||
|
end;
|
||
|
Value := JvInterpreterArrayGetElement(VV, PP);
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
if (TVarData(Variable).VType = varObject) or
|
||
|
(TVarData(Variable).VType = varClass) or (TVarData(Variable).VType = varUnknown) then
|
||
|
begin
|
||
|
Result := FAdapter.GetElement(Self, Variable, Value, Args);
|
||
|
if not Result and Assigned(FSharedAdapter) then
|
||
|
Result := FSharedAdapter.GetElement(Self, Variable, Value, Args);
|
||
|
end
|
||
|
{ for Variant Arrays }
|
||
|
else
|
||
|
if VarIsArray(Variable) then
|
||
|
begin
|
||
|
if Args.Count > VarArrayDimCount(Variable) then
|
||
|
JvInterpreterError(ieArrayTooManyParams, -1)
|
||
|
else
|
||
|
if Args.Count < VarArrayDimCount(Variable) then
|
||
|
JvInterpreterError(ieArrayNotEnoughParams, -1);
|
||
|
AI := nil;
|
||
|
SetLength(AI, Args.Count);
|
||
|
for II2 := 0 to Args.Count - 1 do
|
||
|
begin
|
||
|
Bound := Args.Values[II2];
|
||
|
if Bound > VarArrayHighBound(Variable, II2 + 1) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
if Bound < VarArrayLowBound(Variable, II2 + 1) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
AI[II2] := Bound;
|
||
|
end;
|
||
|
Value := VarArrayGet(Variable, AI);
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
{ problem }
|
||
|
JvInterpreterError(ieArrayRequired, CurPos);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.SetElement(var Variable: Variant; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
II2: Integer;
|
||
|
VV: TJvInterpreterArrayValues;
|
||
|
PP: PJvInterpreterArrayRec;
|
||
|
Bound: Integer;
|
||
|
AI: array of Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if Args.Count <> 0 then
|
||
|
begin
|
||
|
if TVarData(Variable).VType = varString then
|
||
|
begin
|
||
|
if Args.Count > 1 then
|
||
|
JvInterpreterError(ieArrayTooManyParams, -1);
|
||
|
string(TVarData(Variable).vString)[Integer(Args.Values[0])] := string(Value)[1];
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
if TVarData(Variable).VType = varArray then
|
||
|
begin
|
||
|
{ Get array value }
|
||
|
PP := PJvInterpreterArrayRec(NativeInt(JvInterpreterVarAsType(Variable, varInteger)));
|
||
|
if Args.Count > PP.Dimension then
|
||
|
JvInterpreterError(ieArrayTooManyParams, -1)
|
||
|
else
|
||
|
if Args.Count < PP.Dimension then
|
||
|
JvInterpreterError(ieArrayNotEnoughParams, -1);
|
||
|
for II2 := 0 to Args.Count - 1 do
|
||
|
begin
|
||
|
Bound := Args.Values[II2];
|
||
|
if Bound < PP.BeginPos[II2] then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1)
|
||
|
else
|
||
|
if Bound > PP.EndPos[II2] then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
VV[II2] := Args.Values[II2];
|
||
|
end;
|
||
|
JvInterpreterArraySetElement(VV, Value, PP);
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
if (TVarData(Variable).VType = varObject) or
|
||
|
(TVarData(Variable).VType = varClass) or (TVarData(Variable).VType = varUnknown) then
|
||
|
begin
|
||
|
Result := FAdapter.SetElement(Self, Variable, Value, Args);
|
||
|
if not Result and Assigned(FSharedAdapter) then
|
||
|
Result := FSharedAdapter.SetElement(Self, Variable, Value, Args);
|
||
|
end
|
||
|
{ for Variant Array }
|
||
|
else
|
||
|
if VarIsArray(Variable) then
|
||
|
begin
|
||
|
if Args.Count > VarArrayDimCount(Variable) then
|
||
|
JvInterpreterError(ieArrayTooManyParams, -1)
|
||
|
else
|
||
|
if Args.Count < VarArrayDimCount(Variable) then
|
||
|
JvInterpreterError(ieArrayNotEnoughParams, -1);
|
||
|
AI := nil;
|
||
|
SetLength(AI, Args.Count);
|
||
|
for II2 := 0 to Args.Count - 1 do
|
||
|
begin
|
||
|
Bound := Args.Values[II2];
|
||
|
if Bound > VarArrayHighBound(Variable, II2 + 1) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
if Bound < VarArrayLowBound(Variable, II2 + 1) then
|
||
|
JvInterpreterError(ieArrayIndexOutOfBounds, -1);
|
||
|
AI[II2] := Bound;
|
||
|
end;
|
||
|
VarArrayPut(Variable, Value, AI);
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
{ problem }
|
||
|
JvInterpreterError(ieArrayRequired, CurPos);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.GetValue(const Identifier: string; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
begin
|
||
|
try
|
||
|
Result := FAdapter.GetValue(Self, Identifier, Value, Args);
|
||
|
if not Result and Assigned(FSharedAdapter) then
|
||
|
Result := FSharedAdapter.GetValue(Self, Identifier, Value, Args);
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
UpdateExceptionPos(E, '');
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
if not Result and Assigned(FOnGetValue) then
|
||
|
FOnGetValue(Self, Identifier, Value, Args, Result);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterExpression.SetValue(const Identifier: string; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
begin
|
||
|
try
|
||
|
Result := FAdapter.SetValue(Self, Identifier, Value, Args);
|
||
|
if not Result and Assigned(FSharedAdapter) then
|
||
|
Result := FSharedAdapter.SetValue(Self, Identifier, Value, Args);
|
||
|
except
|
||
|
on E: EJvInterpreterError do
|
||
|
begin
|
||
|
E.FErrPos := PosBeg;
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
if not Result and Assigned(FOnSetValue) then
|
||
|
FOnSetValue(Self, Identifier, Value, Args, Result);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.Run;
|
||
|
begin
|
||
|
Init;
|
||
|
NextToken;
|
||
|
FVResult := Expression1;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterExpression.SetDisableExternalFunctions(const Value: Boolean);
|
||
|
begin
|
||
|
FDisableExternalFunctions := Value;
|
||
|
FAdapter.DisableExternalFunctions := Value;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterFunction } =============================================
|
||
|
|
||
|
constructor TJvInterpreterFunction.Create(AOwner: TComponent);
|
||
|
begin
|
||
|
inherited Create(AOwner);
|
||
|
FFunctionStack := TList.Create;
|
||
|
FSS := TStringList.Create;
|
||
|
FEventList := TList.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterFunction.Destroy;
|
||
|
begin
|
||
|
FSS.Free;
|
||
|
FFunctionStack.Free;
|
||
|
ClearList(FEventList);
|
||
|
FEventList.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.Init;
|
||
|
begin
|
||
|
inherited Init;
|
||
|
FBreak := False;
|
||
|
FContinue := False;
|
||
|
FFunctionStack.Clear;
|
||
|
FStateStackPtr := -1;
|
||
|
FCurUnitName := '';
|
||
|
FCurInstance := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.PushState;
|
||
|
begin
|
||
|
Inc(FStateStackPtr);
|
||
|
if FStateStackPtr > High(FStateStack) then
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
FStateStack[FStateStackPtr].Token := FToken;
|
||
|
FStateStack[FStateStackPtr].TTyp := FTTyp;
|
||
|
FStateStack[FStateStackPtr].PrevTTyp := FPrevTTyp;
|
||
|
FStateStack[FStateStackPtr].Backed := FBacked;
|
||
|
FStateStack[FStateStackPtr].CurPos := CurPos;
|
||
|
FStateStack[FStateStackPtr].AllowAssignment := FAllowAssignment;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.PopState;
|
||
|
begin
|
||
|
if FStateStackPtr = -1 then
|
||
|
JvInterpreterError(ieInternal, -1);
|
||
|
CurPos := FStateStack[FStateStackPtr].CurPos;
|
||
|
FToken := FStateStack[FStateStackPtr].Token;
|
||
|
FTTyp := FStateStack[FStateStackPtr].TTyp;
|
||
|
FPrevTTyp := FStateStack[FStateStackPtr].PrevTTyp;
|
||
|
FBacked := FStateStack[FStateStackPtr].Backed;
|
||
|
FAllowAssignment := FStateStack[FStateStackPtr].AllowAssignment;
|
||
|
Dec(FStateStackPtr);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.RemoveState;
|
||
|
begin
|
||
|
Dec(FStateStackPtr);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.GetLocalVars: TJvInterpreterVarList;
|
||
|
begin
|
||
|
if FFunctionContext <> nil then
|
||
|
Result := PFunctionContext(FFunctionContext).LocalVars
|
||
|
else
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InFunction(FunctionDesc: TJvInterpreterFunctionDesc);
|
||
|
const
|
||
|
cResult = 'Result';
|
||
|
var
|
||
|
FunArgs: TJvInterpreterArgs;
|
||
|
VarNames: PNameArray;
|
||
|
|
||
|
procedure EnterFunction; { TJvInterpreterFunction.InFunction local: initialization/entry of function scope }
|
||
|
var
|
||
|
FC: PFunctionContext;
|
||
|
I: Integer;
|
||
|
V: Variant;
|
||
|
begin
|
||
|
New(PFunctionContext(FC));
|
||
|
FillChar(FC^, SizeOf(FC^), 0);
|
||
|
New(VarNames);
|
||
|
PFunctionContext(FC).PrevFunContext := FFunctionContext;
|
||
|
FFunctionContext := FC;
|
||
|
PFunctionContext(FFunctionContext).LocalVars := TJvInterpreterVarList.Create;
|
||
|
FFunctionStack.Add(FFunctionContext);
|
||
|
JvInterpreterVarFree(FVResult);
|
||
|
if FunctionDesc <> nil then
|
||
|
begin
|
||
|
FCurrArgs.FHasVars := False;
|
||
|
FCurrArgs.Types := FunctionDesc.FParamTypes;
|
||
|
for I := 0 to FCurrArgs.Count - 1 do
|
||
|
begin
|
||
|
if (FunctionDesc.FParamTypes[I] and varByRef) <> 0 then
|
||
|
JvInterpreterVarCopy(V, FCurrArgs.Values[I])
|
||
|
else
|
||
|
JvInterpreterVarAssignment(V, FCurrArgs.Values[I]);
|
||
|
|
||
|
PFunctionContext(FFunctionContext).LocalVars.AddVar('', FunctionDesc.FParamNames[I], '',
|
||
|
FunctionDesc.FParamTypes[I], V,
|
||
|
TJvInterpreterSimpleDataType.Create(FunctionDesc.FParamTypes[I]));
|
||
|
VarNames^ := FunctionDesc.FParamNames;
|
||
|
FCurrArgs.FHasVars := FCurrArgs.FHasVars or ((FunctionDesc.FParamTypes[I] and varByRef) <> 0);
|
||
|
end;
|
||
|
if FunctionDesc.ResTyp > 0 then
|
||
|
begin
|
||
|
FunctionDesc.ResDataType.Init(V);
|
||
|
PFunctionContext(FFunctionContext).LocalVars.AddVar('', cResult, '',
|
||
|
FunctionDesc.ResTyp, V, FunctionDesc.ResDataType);
|
||
|
end
|
||
|
end
|
||
|
else
|
||
|
PFunctionContext(FFunctionContext).LocalVars.AddVar('', cResult, '', varVariant,
|
||
|
Null, TJvInterpreterSimpleDataType.Create(varVariant));
|
||
|
FunArgs := FCurrArgs;
|
||
|
FCurrArgs := TJvInterpreterArgs.Create;
|
||
|
end;
|
||
|
|
||
|
procedure LeaveFunction(Ok: Boolean); { TJvInterpreterFunction.InFunction local: finalization of function scope }
|
||
|
var
|
||
|
FC: PFunctionContext;
|
||
|
C: Integer;
|
||
|
|
||
|
procedure UpdateVarParams; { TJvInterpreterFunction.InFunction.LeaveFunction local. How bizarre. }
|
||
|
var
|
||
|
I, C: Integer;
|
||
|
begin
|
||
|
if not FCurrArgs.FHasVars then
|
||
|
Exit;
|
||
|
C := FCurrArgs.Count;
|
||
|
FCurrArgs.Obj := nil;
|
||
|
FCurrArgs.ObjTyp := 0;
|
||
|
FCurrArgs.ObjRefHolder := Unassigned;
|
||
|
FCurrArgs.Count := 0;
|
||
|
|
||
|
for I := 0 to C - 1 do
|
||
|
if (VarNames[I] <> '') and
|
||
|
((FCurrArgs.Types[I] and varByRef) <> 0) then
|
||
|
GetValue(VarNames[I], FCurrArgs.Values[I], FCurrArgs);
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
FCurrArgs.Free;
|
||
|
FCurrArgs := FunArgs;
|
||
|
if Ok then
|
||
|
begin
|
||
|
C := FCurrArgs.Count;
|
||
|
UpdateVarParams;
|
||
|
FCurrArgs.Count := 0;
|
||
|
if (FunctionDesc = nil) or (FunctionDesc.ResTyp > 0) then
|
||
|
begin
|
||
|
{ Return the 'result' value from the local function context to the
|
||
|
FVResult: Variant property of the component }
|
||
|
|
||
|
// PFunctionContext(FFunctionContext).LocalVars.GetValue('Result', FVResult, FCurrArgs);
|
||
|
//LEAKY: TVarData(PFunctionContext(FFunctionContext).LocalVars.FindVar('', 'Result').Value).VType := varEmpty;
|
||
|
//LEAKY: TVarData(PFunctionContext(FFunctionContext).LocalVars.FindVar('', 'Result').Value).VPointer := nil;
|
||
|
|
||
|
//VARLEAKFIX begin - Feb 2004 - Warren Postma. Fix suggested by ivan_ra att mail dott ru
|
||
|
JvInterpreterVarCopy(FVResult, LocalVars.FindVar('', cResult).Value);
|
||
|
//VARLEAKFIX end.
|
||
|
end;
|
||
|
|
||
|
FCurrArgs.Count := C;
|
||
|
end;
|
||
|
FC := PFunctionContext(FFunctionContext).PrevFunContext;
|
||
|
LocalVars.Free;
|
||
|
Dispose(PFunctionContext(FFunctionContext));
|
||
|
Dispose(VarNames);
|
||
|
FFunctionStack.Delete(FFunctionStack.Count - 1);
|
||
|
FFunctionContext := FC;
|
||
|
end;
|
||
|
|
||
|
procedure CheckNotSupportedFunctionParameters;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to FCurrArgs.Count - 1 do
|
||
|
if (TVarData(FCurrArgs.Values[I]).VType = varArray)
|
||
|
or (TVarData(FCurrArgs.Values[I]).VType = varRecord) then
|
||
|
NotImplemented(RsEInterpreter402);
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
CheckNotSupportedFunctionParameters;
|
||
|
{ allocate stack }
|
||
|
EnterFunction;
|
||
|
try
|
||
|
FExit := False;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttBegin:
|
||
|
begin
|
||
|
InterpretBegin;
|
||
|
if (TTyp <> ttSemicolon) and not FExit then
|
||
|
ErrorExpected(''';''');
|
||
|
Break;
|
||
|
end;
|
||
|
ttVar:
|
||
|
InterpretVar(PFunctionContext(FFunctionContext).LocalVars.AddVar);
|
||
|
ttConst:
|
||
|
InterpretConst(PFunctionContext(FFunctionContext).LocalVars.AddVar);
|
||
|
else
|
||
|
ErrorExpected('''' + kwBEGIN + '''');
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
LeaveFunction(True);
|
||
|
FExit := False;
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
{ if (E is EJvInterpreterError) and (Fun <> nil) and
|
||
|
((E as EJvInterpreterError).ErrUnitName = '') then }
|
||
|
if FunctionDesc <> nil then
|
||
|
UpdateExceptionPos(E, FunctionDesc.UnitName)
|
||
|
else
|
||
|
UpdateExceptionPos(E, '');
|
||
|
LeaveFunction(False);
|
||
|
FExit := False;
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.GetValue(const Identifier: string; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
{ check in local variables }
|
||
|
try
|
||
|
if FFunctionContext <> nil then
|
||
|
Result := PFunctionContext(FFunctionContext).LocalVars.GetValue(Identifier, Value, Args);
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
if Assigned(PFunctionContext(FFunctionContext).Fun) then
|
||
|
UpdateExceptionPos(E, PFunctionContext(FFunctionContext).Fun.UnitName)
|
||
|
else
|
||
|
UpdateExceptionPos(E, '');
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
if not Result then
|
||
|
Result := inherited GetValue(Identifier, Value, Args);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.SetValue(const Identifier: string; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
{ check in local variables }
|
||
|
try
|
||
|
if FFunctionContext <> nil then
|
||
|
Result := PFunctionContext(FFunctionContext).LocalVars.SetValue(Identifier, Value, Args);
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
if Assigned(PFunctionContext(FFunctionContext).Fun) then
|
||
|
UpdateExceptionPos(E, PFunctionContext(FFunctionContext).Fun.UnitName)
|
||
|
else
|
||
|
UpdateExceptionPos(E, '');
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
if not Result then
|
||
|
Result := inherited SetValue(Identifier, Value, Args);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.DoOnStatement;
|
||
|
begin
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token }
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretStatement;
|
||
|
begin
|
||
|
DoOnStatement;
|
||
|
case TTyp of
|
||
|
ttIdentifier:
|
||
|
{ assignment or function call }
|
||
|
begin
|
||
|
InterpretIdentifier;
|
||
|
if not (TTyp in [ttSemicolon, ttEnd, ttElse, ttUntil, ttFinally, ttExcept]) then
|
||
|
ErrorExpected(''';''');
|
||
|
// Back;
|
||
|
end;
|
||
|
ttSemicolon:
|
||
|
; // Back;
|
||
|
ttEnd:
|
||
|
; // Back;
|
||
|
ttBegin:
|
||
|
InterpretBegin;
|
||
|
ttIf:
|
||
|
InterpretIf;
|
||
|
ttElse:
|
||
|
Exit;
|
||
|
ttWhile:
|
||
|
InterpretWhile;
|
||
|
ttRepeat:
|
||
|
InterpretRepeat;
|
||
|
ttFor:
|
||
|
InterpretFor;
|
||
|
ttBreak:
|
||
|
FBreak := True;
|
||
|
ttContinue:
|
||
|
FContinue := True;
|
||
|
ttTry:
|
||
|
InterpretTry;
|
||
|
ttRaise:
|
||
|
InterpretRaise;
|
||
|
ttExit:
|
||
|
FExit := True;
|
||
|
ttCase:
|
||
|
InterpretCase;
|
||
|
else
|
||
|
ErrorExpected(''';''');
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token }
|
||
|
{ very simple version, many syntax errors are not found }
|
||
|
|
||
|
procedure TJvInterpreterFunction.SkipStatement;
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttIdentifier:
|
||
|
SkipIdentifier;
|
||
|
ttSemicolon:
|
||
|
NextToken;
|
||
|
ttEnd:
|
||
|
NextToken;
|
||
|
ttIf:
|
||
|
begin
|
||
|
FindToken(ttThen);
|
||
|
NextToken;
|
||
|
SkipStatement;
|
||
|
if TTyp = ttElse then
|
||
|
begin
|
||
|
NextToken;
|
||
|
SkipStatement;
|
||
|
end;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttElse:
|
||
|
Exit;
|
||
|
ttWhile, ttFor:
|
||
|
begin
|
||
|
FindToken(ttDo);
|
||
|
NextToken;
|
||
|
SkipStatement;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttRepeat:
|
||
|
begin
|
||
|
SkipToUntil;
|
||
|
SkipIdentifier;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttBreak, ttContinue:
|
||
|
NextToken;
|
||
|
ttBegin:
|
||
|
begin
|
||
|
SkipToEnd;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttTry:
|
||
|
begin
|
||
|
SkipToEnd;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttFunction, ttProcedure:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttRaise:
|
||
|
begin
|
||
|
NextToken;
|
||
|
SkipIdentifier;
|
||
|
end;
|
||
|
ttExit:
|
||
|
NextToken;
|
||
|
ttCase:
|
||
|
begin
|
||
|
SkipToEnd;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ out: current position set to token after end }
|
||
|
|
||
|
procedure TJvInterpreterFunction.SkipToEnd;
|
||
|
begin
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttEnd then
|
||
|
begin
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end
|
||
|
else
|
||
|
if TTyp in [ttBegin, ttTry, ttCase] then
|
||
|
SkipToEnd
|
||
|
else
|
||
|
if TTyp = ttEmpty then
|
||
|
ErrorExpected('''' + kwEND + '''')
|
||
|
else
|
||
|
if TTyp = ttDoubleQuote then
|
||
|
NextToken
|
||
|
else
|
||
|
SkipStatement;
|
||
|
if TTyp = ttEnd then
|
||
|
begin
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ out: current position set to token after end }
|
||
|
|
||
|
procedure TJvInterpreterFunction.SkipToUntil;
|
||
|
begin
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttUntil then
|
||
|
begin
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end
|
||
|
else
|
||
|
if TTyp = ttEmpty then
|
||
|
ErrorExpected('''' + kwUNTIL + '''')
|
||
|
else
|
||
|
SkipStatement;
|
||
|
if TTyp = ttUntil then
|
||
|
begin
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{exit: current position set to next token after assignment or function call }
|
||
|
|
||
|
procedure TJvInterpreterFunction.SkipIdentifier;
|
||
|
begin
|
||
|
while True do
|
||
|
case TTyp of
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
|
||
|
ttIdentifier..ttBoolean, ttLB, ttRB, ttCol, ttPoint, ttLS, ttRS,
|
||
|
ttNot..ttXor, // [peter schraut: replaced ttEquLess with ttXor on 2005/08/14]
|
||
|
ttDoubleQuote, ttTrue, ttFalse:
|
||
|
NextToken;
|
||
|
|
||
|
ttSemicolon, ttEnd, ttElse, ttUntil, ttFinally, ttExcept, ttDo, ttOf:
|
||
|
Break;
|
||
|
ttColon:
|
||
|
{ 'case' or assignment }
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttEqu then
|
||
|
begin
|
||
|
Back;
|
||
|
Break;
|
||
|
end;
|
||
|
end;
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irExpression));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.FindToken(ATTyp: TTokenKind);
|
||
|
begin
|
||
|
while not (TTyp in [ATTyp, ttEmpty]) do
|
||
|
NextToken;
|
||
|
if TTyp = ttEmpty then
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.NewEvent(const UnitName: string; const FunctionName,
|
||
|
EventType: string; Instance: TObject; const APropName: string): TSimpleEvent;
|
||
|
begin
|
||
|
Result := FAdapter.NewEvent(UnitName, FunctionName, EventType, Self, Instance, APropName);
|
||
|
if not Assigned(Result) then
|
||
|
Result := GlobalJvInterpreterAdapter.NewEvent(UnitName, FunctionName, EventType, Self, Instance, APropName);
|
||
|
if not Assigned(Result) then
|
||
|
JvInterpreterErrorN(ieEventNotRegistered, -1, EventType);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.FindEvent(const UnitName: string;
|
||
|
Instance: TObject; const PropName: string): TJvInterpreterEvent;
|
||
|
var
|
||
|
I: Integer;
|
||
|
Event, Event1: TJvInterpreterEvent;
|
||
|
Method: TMethod;
|
||
|
begin
|
||
|
Result := nil;
|
||
|
Method := GetPropMethod(Instance, PropName);
|
||
|
Event1 := TJvInterpreterEvent(Method.Data);
|
||
|
for I := 0 to FEventList.Count - 1 do
|
||
|
begin
|
||
|
Event := TJvInterpreterEvent(FEventList[I]);
|
||
|
if (Event1 = Event) or
|
||
|
(Cmp(Event.FUnitName, UnitName) and
|
||
|
(Event.FInstance = Instance) and
|
||
|
Cmp(Event.FPropName, PropName)) then
|
||
|
begin
|
||
|
Result := Event;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InternalSetValue(const Identifier: string);
|
||
|
var
|
||
|
FunctionDesc: TJvInterpreterFunctionDesc;
|
||
|
PropInf: PPropInfo;
|
||
|
FunctionName: string;
|
||
|
PopSt: Boolean;
|
||
|
MyArgs: TJvInterpreterArgs;
|
||
|
Variable: Variant;
|
||
|
Method: TMethod;
|
||
|
T: TObject;
|
||
|
Event: TJvInterpreterEvent;
|
||
|
begin
|
||
|
{ may be event assignment }
|
||
|
if (FCurrArgs.Obj <> nil) and (FCurrArgs.ObjTyp = varObject) then
|
||
|
begin
|
||
|
FunctionDesc := FAdapter.FindFunDesc(FCurUnitName, Token);
|
||
|
if (FunctionDesc <> nil) or ((FunctionDesc = nil) and Cmp(Token, kwNIL)) then
|
||
|
begin
|
||
|
PushState;
|
||
|
PopSt := True;
|
||
|
try
|
||
|
NextToken;
|
||
|
if not (TTyp in [ttFirstExpression..ttLastExpression] - [ttSemicolon]) then
|
||
|
begin
|
||
|
FunctionName := Token;
|
||
|
PropInf := GetPropInfo(FCurrArgs.Obj.ClassInfo, Identifier);
|
||
|
if Assigned(PropInf) and (PropInf.PropType^.Kind = tkMethod) then
|
||
|
begin
|
||
|
{ method assignment }
|
||
|
if not Cmp(Token, kwNIL) then
|
||
|
begin
|
||
|
Event := FindEvent(FCurUnitName, FCurrArgs.Obj, {$IFDEF SUPPORTS_UNICODE}UTF8ToString{$ENDIF SUPPORTS_UNICODE}(PropInf^.Name));
|
||
|
if Event <> nil then
|
||
|
begin
|
||
|
FEventList.Remove(Event);
|
||
|
Event.Free;
|
||
|
end;
|
||
|
Method := TMethod(NewEvent(FCurUnitName, FunctionName,
|
||
|
{$IFDEF SUPPORTS_UNICODE}UTF8ToString{$ENDIF SUPPORTS_UNICODE}(PropInf^.PropType^.Name),
|
||
|
FCurrArgs.Obj {FCurInstance},
|
||
|
{$IFDEF SUPPORTS_UNICODE}UTF8ToString{$ENDIF SUPPORTS_UNICODE}(PropInf^.Name)));
|
||
|
SetMethodProp(FCurrArgs.Obj, PropInf, Method);
|
||
|
FEventList.Add(Method.Data);
|
||
|
end
|
||
|
else
|
||
|
begin //Fixed Assign nil to Method property bugs - dejoy-2004-3-13
|
||
|
Method := GetMethodProp(FCurrArgs.Obj, PropInf);
|
||
|
if Method.Data <> nil then
|
||
|
begin
|
||
|
FEventList.Remove(Method.Data);
|
||
|
T := Method.Data;
|
||
|
if T is TJvInterpreterEvent then
|
||
|
T.Free;
|
||
|
end;
|
||
|
|
||
|
Method.Code := nil;
|
||
|
Method.Data := nil;
|
||
|
SetMethodProp(FCurrArgs.Obj, PropInf, Method);
|
||
|
end;
|
||
|
|
||
|
PopSt := False;
|
||
|
Exit;
|
||
|
end
|
||
|
else
|
||
|
if FAdapter.IsEvent(FCurrArgs.Obj, Identifier) then { check only local adapter }
|
||
|
begin
|
||
|
if not SetValue(Identifier, FunctionName, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, Identifier);
|
||
|
PopSt := False;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
if PopSt then
|
||
|
PopState
|
||
|
else
|
||
|
RemoveState;
|
||
|
end;
|
||
|
//Exit;
|
||
|
end;
|
||
|
end;
|
||
|
{ normal (not method) assignmnent }
|
||
|
JvInterpreterVarFree(FVResult);
|
||
|
{ push args }
|
||
|
MyArgs := FCurrArgs;
|
||
|
FCurrArgs := TJvInterpreterArgs.Create;
|
||
|
try
|
||
|
FCurrArgs.Assignment := True;
|
||
|
JvInterpreterVarCopy(FVResult, Expression1);
|
||
|
finally
|
||
|
{ pop args }
|
||
|
FCurrArgs.Free;
|
||
|
FCurrArgs := MyArgs;
|
||
|
end;
|
||
|
if FCurrArgs.Indexed then
|
||
|
begin
|
||
|
MyArgs := TJvInterpreterArgs.Create;
|
||
|
MyArgs.Obj := FCurrArgs.Obj;
|
||
|
MyArgs.ObjTyp := FCurrArgs.ObjTyp;
|
||
|
try
|
||
|
if GetValue(Identifier, Variable, MyArgs) then
|
||
|
begin
|
||
|
if not SetElement(Variable, FVResult, FCurrArgs) then
|
||
|
{ problem }
|
||
|
JvInterpreterError(ieArrayRequired, PosBeg);
|
||
|
if (TVarData(Variable).VType = varString) and
|
||
|
not SetValue(Identifier, Variable, MyArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, Identifier);
|
||
|
if VarIsArray(Variable) and
|
||
|
not SetValue(Identifier, Variable, MyArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, Identifier);
|
||
|
end
|
||
|
else
|
||
|
if not SetValue(Identifier, FVResult, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, Identifier);
|
||
|
finally
|
||
|
MyArgs.Free;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
if not SetValue(Identifier, FVResult, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, Identifier);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretIdentifier;
|
||
|
var
|
||
|
Identifier: string;
|
||
|
begin
|
||
|
Identifier := Token;
|
||
|
FCurrArgs.Clear;
|
||
|
NextToken;
|
||
|
if TTyp <> ttColon then
|
||
|
begin
|
||
|
Back;
|
||
|
FCurrArgs.Assignment := False;
|
||
|
InternalGetValue(nil, 0, FVResult);
|
||
|
Identifier := Token; { Back! }
|
||
|
NextToken;
|
||
|
end;
|
||
|
if TTyp = ttColon then { assignment }
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttEqu then
|
||
|
ErrorExpected('''=''');
|
||
|
NextToken;
|
||
|
InternalSetValue(Identifier);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{exit: current position set to next token after "end"}
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretBegin;
|
||
|
begin
|
||
|
NextToken;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttEnd:
|
||
|
begin
|
||
|
NextToken;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttElse, ttDo:
|
||
|
ErrorExpected(LoadStr2(irStatement));
|
||
|
ttSemicolon:
|
||
|
begin
|
||
|
DoOnStatement;
|
||
|
NextToken;
|
||
|
end;
|
||
|
ttIdentifier, ttBegin, ttIf, ttWhile, ttFor, ttRepeat,
|
||
|
ttBreak, ttContinue, ttTry, ttRaise, ttExit, ttCase:
|
||
|
InterpretStatement;
|
||
|
else
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
end;
|
||
|
if FBreak or FContinue or FExit then
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token after if block }
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretIf;
|
||
|
var
|
||
|
Condition: Variant;
|
||
|
begin
|
||
|
NextToken;
|
||
|
Condition := Expression2(varBoolean);
|
||
|
if TTyp <> ttThen then
|
||
|
ErrorExpected('''' + kwTHEN + '''');
|
||
|
NextToken;
|
||
|
if TVarData(Condition).VBoolean then
|
||
|
begin
|
||
|
InterpretStatement;
|
||
|
// NextToken; {!!!????}
|
||
|
if TTyp = ttElse then
|
||
|
begin
|
||
|
NextToken;
|
||
|
SkipStatement;
|
||
|
// Back; {!!!????}
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
SkipStatement;
|
||
|
if TTyp = ttElse then
|
||
|
begin
|
||
|
NextToken;
|
||
|
InterpretStatement;
|
||
|
end
|
||
|
{ else
|
||
|
if TTyp = ttSemicolon then
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttElse then
|
||
|
JvInterpreterError(ieNotAllowedBeforeElse, PosBeg)
|
||
|
end; }
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token after loop }
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretWhile;
|
||
|
var
|
||
|
WhileCurPos: Integer;
|
||
|
WhilePos: Integer;
|
||
|
Condition: Variant;
|
||
|
begin
|
||
|
PushState;
|
||
|
try
|
||
|
WhilePos := PosEnd;
|
||
|
WhileCurPos := CurPos;
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
Condition := Expression1;
|
||
|
if TVarData(Condition).VType <> varBoolean then
|
||
|
JvInterpreterError(ieBooleanRequired, WhilePos);
|
||
|
if TTyp <> ttDo then
|
||
|
ErrorExpected('''' + kwDO + '''');
|
||
|
NextToken;
|
||
|
if TVarData(Condition).VBoolean then
|
||
|
begin
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
InterpretStatement;
|
||
|
if FBreak or FExit then
|
||
|
Break;
|
||
|
end
|
||
|
else
|
||
|
Break;
|
||
|
CurPos := WhileCurPos;
|
||
|
end;
|
||
|
finally
|
||
|
PopState;
|
||
|
end;
|
||
|
SkipStatement;
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token after loop }
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretRepeat;
|
||
|
var
|
||
|
RepeatCurPos: Integer;
|
||
|
Condition: Variant;
|
||
|
begin
|
||
|
RepeatCurPos := CurPos;
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
case TTyp of
|
||
|
ttElse, ttDo:
|
||
|
ErrorExpected(LoadStr2(irStatement));
|
||
|
ttSemicolon:
|
||
|
DoOnStatement;
|
||
|
ttIdentifier, ttBegin, ttIf, ttWhile, ttFor, ttRepeat,
|
||
|
ttBreak, ttContinue, ttTry, ttRaise, ttExit, ttCase:
|
||
|
begin
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
InterpretStatement;
|
||
|
if FBreak or FExit then
|
||
|
Break;
|
||
|
end;
|
||
|
ttUntil:
|
||
|
begin
|
||
|
NextToken;
|
||
|
Condition := Expression1;
|
||
|
if TVarData(Condition).VType <> varBoolean then
|
||
|
JvInterpreterError(ieBooleanRequired, CurPos);
|
||
|
if TVarData(Condition).VBoolean then
|
||
|
Break
|
||
|
else
|
||
|
CurPos := RepeatCurPos;
|
||
|
end;
|
||
|
else
|
||
|
ErrorExpected('''' + kwUNTIL + '''');
|
||
|
end;
|
||
|
end;
|
||
|
if FBreak or FExit then
|
||
|
begin
|
||
|
SkipToUntil;
|
||
|
SkipIdentifier;
|
||
|
end;
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token after loop }
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretFor;
|
||
|
var
|
||
|
I: Integer;
|
||
|
DoCurPos: Integer;
|
||
|
iBeg, iEnd: Integer;
|
||
|
LoopVariable: string;
|
||
|
ForwardDirection: Boolean;
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
// CheckLocalIdentifier;
|
||
|
LoopVariable := Token;
|
||
|
NextToken;
|
||
|
if TTyp <> ttColon then
|
||
|
ErrorExpected(''':''');
|
||
|
NextToken;
|
||
|
if TTyp <> ttEqu then
|
||
|
ErrorExpected('''=''');
|
||
|
NextToken;
|
||
|
iBeg := Expression2(varInteger);
|
||
|
if (TTyp <> ttTo) and (TTyp <> ttDownTo) then
|
||
|
ErrorExpected('''' + kwTO + RsEXOrX + kwDOWNTO + '''');
|
||
|
ForwardDirection := TTyp = ttTo;
|
||
|
|
||
|
NextToken;
|
||
|
iEnd := Expression2(varInteger);
|
||
|
if TTyp <> ttDo then
|
||
|
ErrorExpected('''' + kwDO + '''');
|
||
|
DoCurPos := CurPos;
|
||
|
NextToken;
|
||
|
|
||
|
if ForwardDirection then
|
||
|
begin
|
||
|
for I := iBeg to iEnd do
|
||
|
begin
|
||
|
FCurrArgs.Clear;
|
||
|
if not SetValue(LoopVariable, I, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, LoopVariable);
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
InterpretStatement;
|
||
|
if FBreak or FExit then
|
||
|
begin
|
||
|
CurPos := DoCurPos;
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end;
|
||
|
CurPos := DoCurPos;
|
||
|
NextToken;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
for I := iBeg downto iEnd do
|
||
|
begin
|
||
|
FCurrArgs.Clear;
|
||
|
if not SetValue(LoopVariable, I, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, LoopVariable);
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
InterpretStatement;
|
||
|
if FBreak or FExit then
|
||
|
begin
|
||
|
CurPos := DoCurPos;
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end;
|
||
|
CurPos := DoCurPos;
|
||
|
NextToken;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
SkipStatement;
|
||
|
FContinue := False;
|
||
|
FBreak := False;
|
||
|
end;
|
||
|
|
||
|
{ exit: current position set to next token after case }
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretCase;
|
||
|
var
|
||
|
Selector, Expression, I: Integer;
|
||
|
ExpressionArray: array of array [0..1] of Integer;
|
||
|
|
||
|
function InCase(CaseSel: Integer): Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
for I := 0 to Length(ExpressionArray) - 1 do
|
||
|
if (CaseSel >= ExpressionArray[I][0]) and (CaseSel <= ExpressionArray[I][1]) then
|
||
|
begin
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
NextToken;
|
||
|
Selector := Expression2(varInteger);
|
||
|
if TTyp <> ttOf then
|
||
|
ErrorExpected('''' + kwOF + '''');
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
case TTyp of
|
||
|
ttIdentifier, ttInteger:
|
||
|
begin
|
||
|
ExpressionArray := nil;
|
||
|
SetLength(ExpressionArray, 1);
|
||
|
I := 0;
|
||
|
while True do
|
||
|
begin
|
||
|
Expression := Expression2(varInteger);
|
||
|
ExpressionArray[Length(ExpressionArray) - 1][I] := Expression;
|
||
|
if TTyp = ttDoublePoint then
|
||
|
I := 1
|
||
|
else
|
||
|
if TTyp = ttCol then
|
||
|
begin
|
||
|
if I = 0 then
|
||
|
ExpressionArray[Length(ExpressionArray) - 1][1] := Expression
|
||
|
else
|
||
|
I := 0;
|
||
|
SetLength(ExpressionArray, Length(ExpressionArray) + 1);
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if I = 0 then
|
||
|
ExpressionArray[Length(ExpressionArray) - 1][1] := Expression;
|
||
|
Break;
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
if TTyp <> ttColon then
|
||
|
ErrorExpected('''' + ':' + '''');
|
||
|
NextToken;
|
||
|
if InCase(Selector) then
|
||
|
begin
|
||
|
ExpressionArray := nil;
|
||
|
InterpretStatement;
|
||
|
SkipToEnd;
|
||
|
Break;
|
||
|
end
|
||
|
else
|
||
|
SkipStatement;
|
||
|
end;
|
||
|
ttElse:
|
||
|
begin
|
||
|
NextToken;
|
||
|
InterpretStatement;
|
||
|
SkipToEnd;
|
||
|
Break;
|
||
|
end;
|
||
|
ttEnd:
|
||
|
begin
|
||
|
NextToken;
|
||
|
Break;
|
||
|
end;
|
||
|
else
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretVar(AddVarFunc: TJvInterpreterAddVarFunc);
|
||
|
var
|
||
|
I: Integer;
|
||
|
Value: Variant;
|
||
|
TypName: string;
|
||
|
// Typ: Word;
|
||
|
DT: IJvInterpreterDataType;
|
||
|
{----olej----}
|
||
|
{Temporary for array type}
|
||
|
// ArrayType: Integer;
|
||
|
// Dimension: Integer;
|
||
|
{----olej----}
|
||
|
begin
|
||
|
repeat
|
||
|
FSS.Clear;
|
||
|
repeat
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
FSS.Add(Token);
|
||
|
NextToken;
|
||
|
until TTyp <> ttCol;
|
||
|
if TTyp <> ttColon then
|
||
|
ErrorExpected(''':''');
|
||
|
NextToken;
|
||
|
TypName := Token;
|
||
|
DT := ParseDataType;
|
||
|
for I := 0 to FSS.Count - 1 do
|
||
|
begin
|
||
|
DT.Init(Value);
|
||
|
AddVarFunc(FCurUnitName, FSS[I], TypName, DT.GetTyp, Value, DT);
|
||
|
end;
|
||
|
FSS.Clear;
|
||
|
NextToken;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
NextToken;
|
||
|
Back;
|
||
|
until TTyp <> ttIdentifier;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretConst(AddVarFunc: TJvInterpreterAddVarFunc);
|
||
|
var
|
||
|
Identifier: string;
|
||
|
Value: Variant;
|
||
|
begin
|
||
|
repeat
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
Identifier := Token;
|
||
|
NextToken;
|
||
|
if TTyp <> ttEqu then
|
||
|
ErrorExpected('=');
|
||
|
NextToken;
|
||
|
Value := Expression1;
|
||
|
|
||
|
AddVarFunc(FCurUnitName, Identifier, '', varEmpty, Value,
|
||
|
TJvInterpreterSimpleDataType.Create(VarType(Value)));
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
NextToken;
|
||
|
Back;
|
||
|
until TTyp <> ttIdentifier;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretTry;
|
||
|
var
|
||
|
ReRaiseException: Boolean;
|
||
|
|
||
|
procedure FindFinallyExcept;
|
||
|
begin
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttSemicolon:
|
||
|
;
|
||
|
ttFinally, ttExcept:
|
||
|
Exit;
|
||
|
else
|
||
|
SkipStatement;
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure InterpretExcept(E: Exception);
|
||
|
var
|
||
|
ExceptionClassName, ExceptionVarName: string;
|
||
|
ExceptionClass: TClass;
|
||
|
V: Variant;
|
||
|
|
||
|
function On1: Boolean;
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
ExceptionClassName := Token;
|
||
|
NextToken;
|
||
|
if TTyp = ttColon then
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
ExceptionVarName := ExceptionClassName;
|
||
|
ExceptionClassName := Token;
|
||
|
NextToken;
|
||
|
end;
|
||
|
FCurrArgs.Clear;
|
||
|
if not GetValue(ExceptionClassName, V, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg {?}, ExceptionClassName);
|
||
|
if VarType(V) <> varClass then
|
||
|
JvInterpreterError(ieClassRequired, PosBeg {?});
|
||
|
ExceptionClass := V2C(V);
|
||
|
if TTyp <> ttDo then
|
||
|
ErrorExpected('''' + kwDO + '''');
|
||
|
Result := E is ExceptionClass;
|
||
|
if Result then
|
||
|
{ do this 'on' section }
|
||
|
begin
|
||
|
NextToken;
|
||
|
PFunctionContext(FFunctionContext).LocalVars.AddVar('', ExceptionVarName,
|
||
|
ExceptionClassName, varObject, O2V(E),
|
||
|
TJvInterpreterSimpleDataType.Create(varObject));
|
||
|
try
|
||
|
InterpretStatement;
|
||
|
finally
|
||
|
PFunctionContext(FFunctionContext).LocalVars.DeleteVar('', ExceptionVarName);
|
||
|
end;
|
||
|
SkipToEnd;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
NextToken;
|
||
|
SkipStatement;
|
||
|
{ if TTyp = ttSemicolon then
|
||
|
NextToken; }
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttOn then
|
||
|
begin
|
||
|
if On1 then
|
||
|
begin
|
||
|
ReRaiseException := False;
|
||
|
Exit;
|
||
|
end;
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
case TTyp of
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttOn:
|
||
|
if On1 then
|
||
|
begin
|
||
|
ReRaiseException := False;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttEnd:
|
||
|
begin
|
||
|
ReRaiseException := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
ttElse:
|
||
|
begin
|
||
|
NextToken;
|
||
|
InterpretStatement;
|
||
|
NextToken;
|
||
|
if TTyp = ttSemicolon then
|
||
|
NextToken;
|
||
|
if TTyp <> ttEnd then
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
Exit;
|
||
|
end;
|
||
|
else
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
end;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
Back;
|
||
|
InterpretBegin;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure DoFinallyExcept(E: Exception);
|
||
|
var
|
||
|
OldExit: Boolean;
|
||
|
begin
|
||
|
OldExit := FExit;
|
||
|
try
|
||
|
FExit := False;
|
||
|
case TTyp of
|
||
|
ttFinally:
|
||
|
{ do statements up to 'end' }
|
||
|
begin
|
||
|
InterpretBegin;
|
||
|
if E <> nil then
|
||
|
ReRaiseException := True;
|
||
|
end;
|
||
|
ttExcept:
|
||
|
begin
|
||
|
if E = nil then
|
||
|
{ skip except section }
|
||
|
SkipToEnd
|
||
|
else
|
||
|
{ except section }
|
||
|
begin
|
||
|
try
|
||
|
InterpretExcept(E);
|
||
|
FLastError.Clear;
|
||
|
except
|
||
|
on E1: EJvInterpreterError do
|
||
|
begin
|
||
|
if E1.ErrCode = ieRaise then
|
||
|
ReRaiseException := True;
|
||
|
end
|
||
|
else
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
FExit := FExit or OldExit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
NextToken;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttFinally:
|
||
|
begin
|
||
|
DoFinallyExcept(nil);
|
||
|
Exit;
|
||
|
end;
|
||
|
ttExcept:
|
||
|
begin
|
||
|
DoFinallyExcept(nil);
|
||
|
Exit;
|
||
|
end;
|
||
|
ttSemicolon:
|
||
|
begin
|
||
|
DoOnStatement;
|
||
|
NextToken;
|
||
|
end;
|
||
|
ttIdentifier, ttBegin, ttIf, ttWhile, ttFor, ttRepeat,
|
||
|
ttBreak, ttContinue, ttTry, ttRaise, ttExit, ttCase:
|
||
|
begin
|
||
|
try
|
||
|
InterpretStatement;
|
||
|
if FBreak or FContinue or FExit then
|
||
|
begin
|
||
|
FindFinallyExcept;
|
||
|
DoFinallyExcept(nil);
|
||
|
Exit;
|
||
|
end;
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
FindFinallyExcept;
|
||
|
|
||
|
ReRaiseException := False;
|
||
|
DoFinallyExcept(E);
|
||
|
|
||
|
if ReRaiseException then
|
||
|
raise
|
||
|
else
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
else
|
||
|
ErrorExpected('''' + kwFINALLY + '''');
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.InterpretRaise;
|
||
|
var
|
||
|
V: Variant;
|
||
|
begin
|
||
|
NextToken;
|
||
|
case TTyp of
|
||
|
ttEmpty, ttSemicolon, ttEnd, ttBegin, ttElse, ttFinally, ttExcept:
|
||
|
{ re-raising exception }
|
||
|
raise EJvInterpreterError.Create(ieRaise, PosBeg, '', '');
|
||
|
ttIdentifier:
|
||
|
begin
|
||
|
InternalGetValue(nil, 0, V);
|
||
|
if VarType(V) <> varObject then
|
||
|
JvInterpreterError(ieClassRequired, PosBeg {?});
|
||
|
UpdateExceptionPos(Exception(V2O(V)), '');
|
||
|
raise V2O(V);
|
||
|
end;
|
||
|
else
|
||
|
JvInterpreterError(ieClassRequired, PosBeg {?});
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterFunction.Run;
|
||
|
begin
|
||
|
Init;
|
||
|
NextToken;
|
||
|
InFunction(nil);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.GetFunStackCount: Integer;
|
||
|
begin
|
||
|
Result := FFunctionStack.Count;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.ParseDataType: IJvInterpreterDataType;
|
||
|
var
|
||
|
TypName: string;
|
||
|
Typ: Word;
|
||
|
ArrayBegin, ArrayEnd: TJvInterpreterArrayValues;
|
||
|
TempBegin, TempEnd: Integer;
|
||
|
ArrayType: Integer;
|
||
|
Dimension: Integer;
|
||
|
Minus1, Minus2: Boolean;
|
||
|
//
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
ArrayDT: IJvInterpreterDataType;
|
||
|
begin
|
||
|
//NextToken;
|
||
|
TypName := Token;
|
||
|
Dimension := 0;
|
||
|
if TTyp = ttIdentifier then
|
||
|
begin
|
||
|
Typ := TypeName2VarTyp(TypName);
|
||
|
JvInterpreterRecord := TJvInterpreterRecord(FAdapter.GetRec(TypName));
|
||
|
if JvInterpreterRecord = nil then
|
||
|
JvInterpreterRecord := TJvInterpreterRecord(GlobalJvInterpreterAdapter.GetRec(TypName));
|
||
|
if JvInterpreterRecord <> nil then
|
||
|
Result := TJvInterpreterRecordDataType.Create(JvInterpreterRecord)
|
||
|
else
|
||
|
Result := TJvInterpreterSimpleDataType.Create(Typ);
|
||
|
end
|
||
|
else
|
||
|
if TTyp = ttArray then
|
||
|
begin
|
||
|
{ Get Array variables params }
|
||
|
{ This code is not very clear }
|
||
|
// Typ := varArray;
|
||
|
NextToken;
|
||
|
if (TTyp <> ttLS) and (TTyp <> ttOf) then
|
||
|
ErrorExpected('''[' + RsEXOrX + kwOF + '''');
|
||
|
{ Parse Array Range }
|
||
|
if TTyp = ttLS then
|
||
|
begin
|
||
|
Dimension := 0;
|
||
|
repeat
|
||
|
NextToken;
|
||
|
Minus1 := False;
|
||
|
if (Trim(FTokenStr) = '-') then
|
||
|
begin
|
||
|
Minus1 := True;
|
||
|
NextToken;
|
||
|
end;
|
||
|
TempBegin := StrToInt(FTokenStr);
|
||
|
try
|
||
|
ArrayBegin[Dimension] := TempBegin;
|
||
|
if Minus1 then
|
||
|
ArrayBegin[Dimension] := ArrayBegin[Dimension] * (-1);
|
||
|
except
|
||
|
ErrorExpected(LoadStr2(irIntegerValue));
|
||
|
end;
|
||
|
|
||
|
NextToken;
|
||
|
if TTyp <> ttDoublePoint then
|
||
|
ErrorExpected('''..''');
|
||
|
|
||
|
NextToken;
|
||
|
Minus2 := False;
|
||
|
if (Trim(FTokenStr) = '-') then
|
||
|
begin
|
||
|
Minus2 := True;
|
||
|
NextToken;
|
||
|
end;
|
||
|
TempEnd := StrToInt(FTokenStr);
|
||
|
try
|
||
|
ArrayEnd[Dimension] := TempEnd;
|
||
|
except
|
||
|
if Minus2 then
|
||
|
ArrayEnd[Dimension] := ArrayEnd[Dimension] * (-1);
|
||
|
ErrorExpected(LoadStr2(irIntegerValue));
|
||
|
end;
|
||
|
|
||
|
if (Dimension < 0) or (Dimension > cJvInterpreterMaxArgs) then
|
||
|
JvInterpreterError(ieArrayBadDimension, CurPos);
|
||
|
if not (ArrayBegin[Dimension] <= ArrayEnd[Dimension]) then
|
||
|
JvInterpreterError(ieArrayBadRange, CurPos);
|
||
|
{End Array Range}
|
||
|
NextToken;
|
||
|
Inc(Dimension);
|
||
|
until TTyp <> ttCol; { , }
|
||
|
|
||
|
if TTyp <> ttRS then
|
||
|
ErrorExpected(''']''');
|
||
|
NextToken;
|
||
|
if TTyp <> ttOf then
|
||
|
ErrorExpected('''' + kwOF + '''');
|
||
|
end
|
||
|
else
|
||
|
if TTyp = ttOf then
|
||
|
begin
|
||
|
Dimension := 1;
|
||
|
ArrayBegin[0] := 0;
|
||
|
ArrayEnd[0] := -1;
|
||
|
end;
|
||
|
NextToken;
|
||
|
ArrayType := TypeName2VarTyp(Token);
|
||
|
// recursion for arrays
|
||
|
ArrayDT := ParseDataType;
|
||
|
|
||
|
Result := TJvInterpreterArrayDataType.Create(ArrayBegin, ArrayEnd, Dimension, ArrayType, ArrayDT);
|
||
|
{ end: var A: array [1..200] of Integer, parsing }
|
||
|
end
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterUnit } =================================================
|
||
|
|
||
|
constructor TJvInterpreterUnit.Create(AOwner: TComponent);
|
||
|
begin
|
||
|
inherited Create(AOwner);
|
||
|
FClearUnits := True;
|
||
|
FEventHandlerList := TList.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterUnit.Destroy;
|
||
|
begin
|
||
|
ClearList(FEventHandlerList);
|
||
|
FEventHandlerList.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.Init;
|
||
|
begin
|
||
|
inherited Init;
|
||
|
if FClearUnits then
|
||
|
begin
|
||
|
FAdapter.ClearSource;
|
||
|
FUnitSection := usUnknown;
|
||
|
ClearList(FEventHandlerList);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.ReadFunctionHeader(FunctionDesc: TJvInterpreterFunctionDesc);
|
||
|
var
|
||
|
TypName: string;
|
||
|
Fun: Boolean;
|
||
|
|
||
|
procedure ReadParams;
|
||
|
var
|
||
|
VarParam, VarConst: Boolean;
|
||
|
ParamType: string;
|
||
|
iBeg: Integer;
|
||
|
begin
|
||
|
while True do
|
||
|
begin
|
||
|
VarParam := False;
|
||
|
VarConst := False;
|
||
|
NextToken;
|
||
|
FunctionDesc.FParamNames[FunctionDesc.ParamCount] := Token;
|
||
|
if TTyp = ttRB then
|
||
|
Break;
|
||
|
if TTyp = ttVar then
|
||
|
begin
|
||
|
VarParam := True;
|
||
|
NextToken;
|
||
|
end;
|
||
|
if TTyp = ttConst then
|
||
|
begin
|
||
|
VarConst := True;
|
||
|
// NextToken;
|
||
|
end;
|
||
|
iBeg := FunctionDesc.ParamCount;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttIdentifier:
|
||
|
FunctionDesc.FParamNames[FunctionDesc.ParamCount] := Token;
|
||
|
ttSemicolon: Break;
|
||
|
ttRB: Exit;
|
||
|
ttColon:
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
ParamType := Token;
|
||
|
while True do
|
||
|
begin
|
||
|
if TTyp = ttRB then
|
||
|
Back;
|
||
|
if TTyp in [ttRB, ttSemicolon] then
|
||
|
Break;
|
||
|
NextToken;
|
||
|
end;
|
||
|
FunctionDesc.FParamTypeNames[FunctionDesc.FParamCount] := ParamType; // for ParamTypeNames
|
||
|
Inc(FunctionDesc.FParamCount);
|
||
|
while iBeg < FunctionDesc.FParamCount do
|
||
|
begin
|
||
|
FunctionDesc.FParamTypeNames[iBeg] := ParamType; // for ParamTypeNames
|
||
|
FunctionDesc.FParamTypes[iBeg] := TypeName2VarTyp(ParamType);
|
||
|
if VarParam then
|
||
|
FunctionDesc.FParamTypes[iBeg] := FunctionDesc.FParamTypes[iBeg] or
|
||
|
varByRef;
|
||
|
if VarConst then
|
||
|
FunctionDesc.FParamTypes[iBeg] := FunctionDesc.FParamTypes[iBeg] or
|
||
|
varByConst;
|
||
|
|
||
|
Inc(iBeg);
|
||
|
end;
|
||
|
Break;
|
||
|
end;
|
||
|
ttCol:
|
||
|
Inc(FunctionDesc.FParamCount);
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
Fun := TTyp = ttFunction;
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
FunctionDesc.FIdentifier := Token;
|
||
|
NextToken;
|
||
|
if TTyp = ttPoint then
|
||
|
begin
|
||
|
FunctionDesc.FClassIdentifier := FunctionDesc.FIdentifier;
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
FunctionDesc.FIdentifier := Token;
|
||
|
NextToken;
|
||
|
end;
|
||
|
FunctionDesc.FResTyp := varEmpty;
|
||
|
FunctionDesc.FParamCount := 0;
|
||
|
if TTyp = ttLB then
|
||
|
begin
|
||
|
// NextToken;
|
||
|
ReadParams;
|
||
|
NextToken;
|
||
|
end;
|
||
|
if Fun then
|
||
|
if (TTyp = ttColon) then
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
TypName := Token;
|
||
|
FunctionDesc.FResDataType := ParseDataType;
|
||
|
FunctionDesc.FResTyp := FunctionDesc.FResDataType.GetTyp;
|
||
|
FunctionDesc.FResTypName := TypName;
|
||
|
|
||
|
if FunctionDesc.FResTyp = 0 then
|
||
|
FunctionDesc.FResTyp := varVariant;
|
||
|
NextToken;
|
||
|
end
|
||
|
else
|
||
|
ErrorExpected(''':''');
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.InterpretFunction;
|
||
|
var
|
||
|
FunctionDesc: TJvInterpreterFunctionDesc;
|
||
|
FunctionName: string;
|
||
|
FunctionIndex: Integer;
|
||
|
DllName: string;
|
||
|
LastTTyp: TTokenKind;
|
||
|
begin
|
||
|
FunctionDesc := TJvInterpreterFunctionDesc.Create;
|
||
|
try
|
||
|
ReadFunctionHeader(FunctionDesc);
|
||
|
FunctionDesc.FPosBeg := CurPos;
|
||
|
LastTTyp := TTyp;
|
||
|
NextToken;
|
||
|
if TTyp = ttExternal then
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttString then
|
||
|
DllName := Token
|
||
|
else
|
||
|
if TTyp = ttIdentifier then
|
||
|
begin
|
||
|
FCurrArgs.Clear;
|
||
|
if not GetValue(Token, FVResult, FCurrArgs) then
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, PosBeg, Token);
|
||
|
DllName := VResult;
|
||
|
end
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irStringConstant)); {DEBUG!!!}
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected('''' + drNAME + RsEXOrX + drINDEX + '''');
|
||
|
FunctionIndex := -1;
|
||
|
FunctionName := '';
|
||
|
if Cmp(Token, drNAME) then
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttString then
|
||
|
FunctionName := Token
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irStringConstant)); {DEBUG!!!}
|
||
|
end
|
||
|
else
|
||
|
if Cmp(Token, drINDEX) then
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttInteger then
|
||
|
FunctionIndex := Token
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irIntegerConstant)); {DEBUG!!!}
|
||
|
end
|
||
|
else
|
||
|
ErrorExpected('''' + drNAME + RsEXOrX + drINDEX + '''');
|
||
|
with FunctionDesc do
|
||
|
FAdapter.AddExtFun(FCurUnitName {??!!}, FIdentifier, noInstance, DllName,
|
||
|
FunctionName, FunctionIndex, FParamCount, FParamTypes, FResTyp);
|
||
|
NextToken;
|
||
|
end
|
||
|
else
|
||
|
if FUnitSection = usInterface then
|
||
|
begin
|
||
|
CurPos := FunctionDesc.FPosBeg;
|
||
|
FTTyp := LastTTyp;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
FindToken(ttBegin);
|
||
|
SkipToEnd;
|
||
|
with FunctionDesc do
|
||
|
FAdapter.AddSrcFun(FCurUnitName {??!!}, FIdentifier, FClassIdentifier, FPosBeg, CurPos,
|
||
|
FParamCount, FParamTypes, FParamTypeNames, FParamNames, FResTyp, FResTypName, FResDataType,
|
||
|
nil);
|
||
|
end;
|
||
|
finally
|
||
|
FunctionDesc.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.ReadUnit(const UnitName: string);
|
||
|
var
|
||
|
OldUnitName: string;
|
||
|
OldSource: string;
|
||
|
S: string;
|
||
|
begin
|
||
|
if FAdapter.UnitExists(UnitName) then
|
||
|
Exit;
|
||
|
FAdapter.AddSrcUnit(FCurUnitName, '', '');
|
||
|
OldUnitName := FCurUnitName;
|
||
|
OldSource := Source;
|
||
|
PushState;
|
||
|
try
|
||
|
try
|
||
|
if not GetUnitSource(UnitName, S) then
|
||
|
JvInterpreterErrorN(ieUnitNotFound, PosBeg, UnitName);
|
||
|
FCurUnitName := UnitName;
|
||
|
Source := S;
|
||
|
NextToken;
|
||
|
if TTyp <> ttUnit then
|
||
|
ErrorExpected('''' + kwUNIT + '''');
|
||
|
InterpretUnit;
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
UpdateExceptionPos(E, FCurUnitName);
|
||
|
raise;
|
||
|
end;
|
||
|
end
|
||
|
finally
|
||
|
FCurUnitName := OldUnitName;
|
||
|
Source := OldSource;
|
||
|
PopState;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.InterpretUses(var UsesList: string);
|
||
|
begin
|
||
|
NextToken;
|
||
|
if not (TTyp in [ttIdentifier, ttString]) then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
UsesList := Token;
|
||
|
ReadUnit(Token);
|
||
|
while True do
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp = ttIn then
|
||
|
begin
|
||
|
{ ignore }
|
||
|
NextToken;
|
||
|
NextToken;
|
||
|
end;
|
||
|
if TTyp = ttSemicolon then
|
||
|
Exit;
|
||
|
if TTyp <> ttCol then
|
||
|
ErrorExpected(''',''');
|
||
|
NextToken;
|
||
|
if not (TTyp in [ttIdentifier, ttString]) then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
UsesList := UsesList + ',';
|
||
|
ReadUnit(Token);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.InterpretUnit;
|
||
|
var
|
||
|
UsesList: string;
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
FCurUnitName := Token;
|
||
|
NextToken;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
UsesList := '';
|
||
|
NextToken;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttFunction, ttProcedure:
|
||
|
begin
|
||
|
InterpretFunction;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
end;
|
||
|
ttEnd:
|
||
|
Break;
|
||
|
ttUses:
|
||
|
InterpretUses(UsesList);
|
||
|
ttVar:
|
||
|
InterpretVar(FAdapter.AddSrcVar);
|
||
|
ttConst:
|
||
|
InterpretConst(FAdapter.AddSrcVar);
|
||
|
ttInterface:
|
||
|
FUnitSection := usInterface;
|
||
|
ttImplementation:
|
||
|
FUnitSection := usImplementation;
|
||
|
ttType:
|
||
|
InterpretType;
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irDeclaration));
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
if TTyp <> ttEnd then
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
NextToken;
|
||
|
if TTyp <> ttPoint then
|
||
|
ErrorExpected('''.''');
|
||
|
FAdapter.AddSrcUnit(FCurUnitName, Source, UsesList);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.InterpretType;
|
||
|
var
|
||
|
Identifier: string;
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
Identifier := Token;
|
||
|
NextToken;
|
||
|
if TTyp <> ttEqu then
|
||
|
ErrorExpected('''=''');
|
||
|
NextToken;
|
||
|
case TTyp of
|
||
|
ttClass:
|
||
|
InterpretClass(Identifier);
|
||
|
ttRecord:
|
||
|
InterpretRecord(Identifier);
|
||
|
else
|
||
|
{ only class declaration for form is supported }
|
||
|
ErrorExpected(LoadStr2(irClass));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.InterpretClass(const Identifier: string);
|
||
|
var
|
||
|
JvInterpreterSrcClass: TJvInterpreterIdentifier;
|
||
|
FunDesc: TJvInterpreterFunctionDesc; // Class Fields support
|
||
|
begin
|
||
|
NextToken;
|
||
|
if TTyp <> ttLB then
|
||
|
ErrorExpected('''(''');
|
||
|
NextToken;
|
||
|
if TTyp <> ttIdentifier then
|
||
|
ErrorExpected(LoadStr2(irIdentifier));
|
||
|
NextToken;
|
||
|
if TTyp <> ttRB then
|
||
|
ErrorExpected(''')''');
|
||
|
|
||
|
JvInterpreterSrcClass := TJvInterpreterClass.Create;
|
||
|
try
|
||
|
JvInterpreterSrcClass.UnitName := FCurUnitName;
|
||
|
JvInterpreterSrcClass.Identifier := Identifier;
|
||
|
NextToken;
|
||
|
if TTyp = ttIdentifier then
|
||
|
begin // First fields can follow class declaration
|
||
|
Back;
|
||
|
InterpretVar(TJvInterpreterClass(JvInterpreterSrcClass).ClassFields.AddVar);
|
||
|
NextToken;
|
||
|
end;
|
||
|
while True do
|
||
|
begin // try to interpret other fields
|
||
|
case TTyp of { } // property declaration not supported!!
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttFunction, ttProcedure: // from InterpetFunction
|
||
|
begin
|
||
|
FunDesc := TJvInterpreterFunctionDesc.Create;
|
||
|
try // empty reading
|
||
|
ReadFunctionHeader(FunDesc);
|
||
|
finally
|
||
|
FunDesc.Free;
|
||
|
end;
|
||
|
end;
|
||
|
ttEnd:
|
||
|
Break;
|
||
|
ttPrivate,ttProtected,ttPublic,ttPublished:
|
||
|
begin // Add more fields
|
||
|
NextToken;
|
||
|
Back;
|
||
|
if TTyp = ttIdentifier then
|
||
|
InterpretVar(TJvInterpreterClass(JvInterpreterSrcClass).ClassFields.AddVar);
|
||
|
end;
|
||
|
else
|
||
|
ErrorExpected(LoadStr2(irDeclaration));
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
NextToken;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
|
||
|
FAdapter.AddSrcClass(JvInterpreterSrcClass);
|
||
|
except
|
||
|
JvInterpreterSrcClass.Free;
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.InterpretRecord(const Identifier: string);
|
||
|
var
|
||
|
// JvInterpreterSrcRecord: TJvInterpreterIdentifier;
|
||
|
// Fields: array of TJvInterpreterRecField;
|
||
|
// TempField: TJvInterpreterRecField;
|
||
|
// TempCount: Integer;
|
||
|
// TempTyp: Word;
|
||
|
JvInterpreterRecord: TJvInterpreterRecord;
|
||
|
begin
|
||
|
JvInterpreterRecord := TJvInterpreterRecord.Create;
|
||
|
JvInterpreterRecord.RecordSize := 0;
|
||
|
JvInterpreterRecord.Identifier := Identifier;
|
||
|
JvInterpreterRecord.FieldCount := 0;
|
||
|
InterpretVar(JvInterpreterRecord.AddField);
|
||
|
NextToken;
|
||
|
if TTyp <> ttEnd then
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
NextToken;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
// ����� �������
|
||
|
|
||
|
FAdapter.FRecordList.Add(JvInterpreterRecord);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.Run;
|
||
|
var
|
||
|
FunctionDesc: TJvInterpreterFunctionDesc;
|
||
|
begin
|
||
|
Init;
|
||
|
NextToken;
|
||
|
case TTyp of
|
||
|
ttVar, ttBegin:
|
||
|
InFunction(nil);
|
||
|
ttFunction, ttProcedure:
|
||
|
InterpretFunction;
|
||
|
ttUnit:
|
||
|
begin
|
||
|
try
|
||
|
InterpretUnit;
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
UpdateExceptionPos(E, FCurUnitName);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
FCompiled := True;
|
||
|
{ execute main function }
|
||
|
FunctionDesc := FAdapter.FindFunDesc(FCurUnitName, 'main');
|
||
|
if FunctionDesc = nil then
|
||
|
JvInterpreterError(ieMainUndefined, -1);
|
||
|
CurPos := FunctionDesc.PosBeg;
|
||
|
NextToken;
|
||
|
InFunction(FunctionDesc);
|
||
|
end;
|
||
|
else
|
||
|
FVResult := Expression1;
|
||
|
end;
|
||
|
FCompiled := True;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.Compile;
|
||
|
begin
|
||
|
Init;
|
||
|
try
|
||
|
NextToken;
|
||
|
if TTyp <> ttUnit then
|
||
|
ErrorExpected('''' + kwUNIT + '''');
|
||
|
InterpretUnit;
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
UpdateExceptionPos(E, FCurUnitName);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
FCompiled := True;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.SourceChanged;
|
||
|
begin
|
||
|
inherited SourceChanged;
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TJvInterpreterFormAccessProtected = class(TJvInterpreterForm);
|
||
|
|
||
|
function TJvInterpreterUnit.GetValue(const Identifier: string; var Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
var
|
||
|
FunctionDesc: TJvInterpreterFunctionDesc;
|
||
|
OldArgs: TJvInterpreterArgs;
|
||
|
OldInstance: TObject; // class method support
|
||
|
begin
|
||
|
Result := inherited GetValue(Identifier, Value, Args);
|
||
|
if Result then
|
||
|
Exit;
|
||
|
FunctionDesc := nil;
|
||
|
|
||
|
if Args.Obj = nil then
|
||
|
FunctionDesc := FAdapter.FindFunDesc(FCurUnitName, Identifier)
|
||
|
else
|
||
|
if Args.ObjTyp = varObject then
|
||
|
begin
|
||
|
if Args.Obj is TJvInterpreterSrcUnit then
|
||
|
FunctionDesc := FAdapter.FindFunDesc((Args.Obj as TJvInterpreterSrcUnit).Identifier,
|
||
|
Identifier)
|
||
|
else
|
||
|
if (Args.Obj is TJvInterpreterForm) then
|
||
|
with TJvInterpreterFormAccessProtected(Args.Obj) do
|
||
|
FunctionDesc := FAdapter.FindFunDesc(UnitName, Identifier, ClassIdentifier);
|
||
|
end;
|
||
|
|
||
|
Result := FunctionDesc <> nil;
|
||
|
if Result then
|
||
|
begin
|
||
|
FAdapter.CheckArgs(Args, FunctionDesc.FParamCount, FunctionDesc.FParamTypes); {not tested !}
|
||
|
OldArgs := FCurrArgs;
|
||
|
OldInstance := FCurInstance;
|
||
|
if (Args.Obj is TJvInterpreterForm) then
|
||
|
begin
|
||
|
FCurInstance:=Args.Obj; // class method support
|
||
|
end; //
|
||
|
try
|
||
|
FCurrArgs := Args;
|
||
|
ExecFunction(FunctionDesc);
|
||
|
finally
|
||
|
FCurrArgs := OldArgs;
|
||
|
if Args.Obj is TJvInterpreterForm then
|
||
|
FCurInstance := OldInstance; // class method support
|
||
|
end;
|
||
|
Value := FVResult;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterUnit.SetValue(const Identifier: string; const Value: Variant;
|
||
|
var Args: TJvInterpreterArgs): Boolean;
|
||
|
begin
|
||
|
Result := inherited SetValue(Identifier, Value, Args);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterUnit.GetUnitSource(const UnitName: string; var Source: string): Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
if Assigned(FOnGetUnitSource) then
|
||
|
FOnGetUnitSource(UnitName, Source, Result);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.DeclareExternalFunction(const Declaration: string);
|
||
|
var
|
||
|
OldSource: string;
|
||
|
OldPos: Integer;
|
||
|
begin
|
||
|
Source := Declaration;
|
||
|
OldSource := Source;
|
||
|
OldPos := FParser.Pos;
|
||
|
try
|
||
|
NextToken;
|
||
|
if not (TTyp in [ttFunction, ttProcedure]) then
|
||
|
ErrorExpected('''' + kwFUNCTION + RsEXOrX + kwPROCEDURE + '''');
|
||
|
InterpretFunction;
|
||
|
finally
|
||
|
Source := OldSource;
|
||
|
FParser.Pos := OldPos;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterUnit.ExecFunction(Fun: TJvInterpreterFunctionDesc);
|
||
|
var
|
||
|
OldUnitName: string;
|
||
|
S: string;
|
||
|
begin
|
||
|
PushState;
|
||
|
FAllowAssignment := True;
|
||
|
OldUnitName := FCurUnitName;
|
||
|
try
|
||
|
if not Cmp(FCurUnitName, Fun.UnitName) then
|
||
|
begin
|
||
|
FCurUnitName := Fun.UnitName;
|
||
|
FAdapter.CurUnitChanged(FCurUnitName, S);
|
||
|
Source := S;
|
||
|
end;
|
||
|
CurPos := Fun.PosBeg;
|
||
|
NextToken;
|
||
|
try
|
||
|
InFunction(Fun);
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
UpdateExceptionPos(E, FCurUnitName);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
if not Cmp(FCurUnitName, OldUnitName) then
|
||
|
begin
|
||
|
FCurUnitName := OldUnitName;
|
||
|
FAdapter.CurUnitChanged(FCurUnitName, S);
|
||
|
Source := S;
|
||
|
end;
|
||
|
PopState;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterUnit.CallFunction(const FunctionName: string; Args: TJvInterpreterArgs;
|
||
|
Params: array of Variant): Variant;
|
||
|
begin
|
||
|
Result := CallFunctionEx(nil, '', FunctionName, Args, Params);
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterUnit.CallFunctionEx(Instance: TObject; const UnitName: string;
|
||
|
const FunctionName: string; Args: TJvInterpreterArgs; Params: array of Variant): Variant;
|
||
|
var
|
||
|
FunctionDesc: TJvInterpreterFunctionDesc;
|
||
|
I: Integer;
|
||
|
OldArgs: TJvInterpreterArgs;
|
||
|
OldInstance: TObject;
|
||
|
begin
|
||
|
if not Compiled then
|
||
|
Compile;
|
||
|
OldInstance := FCurInstance;
|
||
|
try
|
||
|
FCurInstance := Instance;
|
||
|
FunctionDesc := FAdapter.FindFunDesc(UnitName, FunctionName);
|
||
|
if FunctionDesc <> nil then
|
||
|
begin
|
||
|
OldArgs := FCurrArgs;
|
||
|
if Args = nil then
|
||
|
begin
|
||
|
FCurrArgs.Clear;
|
||
|
for I := Low(Params) to High(Params) do
|
||
|
begin
|
||
|
FCurrArgs.Values[FCurrArgs.Count] := Params[I];
|
||
|
Inc(FCurrArgs.Count);
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
FCurrArgs := Args;
|
||
|
try
|
||
|
{ simple init }
|
||
|
FBreak := False;
|
||
|
FContinue := False;
|
||
|
FLastError.Clear;
|
||
|
|
||
|
ExecFunction(FunctionDesc);
|
||
|
|
||
|
Result := FVResult;
|
||
|
finally
|
||
|
FCurrArgs := OldArgs;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
JvInterpreterErrorN(ieUnknownIdentifier, -1, FunctionName);
|
||
|
finally
|
||
|
FCurInstance := OldInstance;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterUnit.FunctionExists(const UnitName: string;
|
||
|
const FunctionName: string): Boolean;
|
||
|
begin
|
||
|
Result := FAdapter.FindFunDesc(UnitName, FunctionName) <> nil;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterProgramStrings } =======================================
|
||
|
|
||
|
type
|
||
|
TJvInterpreterProgramStrings = class(TStringList)
|
||
|
private
|
||
|
FJvInterpreterProgram: TJvInterpreterProgram;
|
||
|
protected
|
||
|
procedure Changed; override;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterProgramStrings.Changed;
|
||
|
begin
|
||
|
FJvInterpreterProgram.Source := Text;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterProgram } ==============================================
|
||
|
|
||
|
constructor TJvInterpreterProgram.Create(AOwner: TComponent);
|
||
|
begin
|
||
|
inherited Create(AOwner);
|
||
|
FPas := TJvInterpreterProgramStrings.Create;
|
||
|
(FPas as TJvInterpreterProgramStrings).FJvInterpreterProgram := Self;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterProgram.Destroy;
|
||
|
begin
|
||
|
FPas.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterProgram.GetPas: TStrings;
|
||
|
begin
|
||
|
Result := FPas;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterProgram.SetPas(Value: TStrings);
|
||
|
begin
|
||
|
FPas.Assign(Value);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterProgram.DoOnStatement;
|
||
|
begin
|
||
|
if Assigned(FOnStatement) then
|
||
|
FOnStatement(Self);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterProgram.Run;
|
||
|
var
|
||
|
UsesList: string;
|
||
|
begin
|
||
|
// (rom) Does this always work? After "program" a line end or tab is allowed.
|
||
|
if AnsiStrLIComp(PChar(FParser.Source), 'program ', Length('program ')) <> 0 then
|
||
|
begin
|
||
|
inherited Run;
|
||
|
Exit;
|
||
|
end;
|
||
|
Init;
|
||
|
NextToken;
|
||
|
while True do
|
||
|
begin
|
||
|
case TTyp of
|
||
|
ttEmpty:
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
ttFunction, ttProcedure:
|
||
|
begin
|
||
|
InterpretFunction;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
end;
|
||
|
ttEnd:
|
||
|
Break;
|
||
|
ttUses:
|
||
|
InterpretUses(UsesList);
|
||
|
ttVar:
|
||
|
InterpretVar(FAdapter.AddSrcVar);
|
||
|
ttConst:
|
||
|
InterpretConst(FAdapter.AddSrcVar);
|
||
|
ttInterface:
|
||
|
FUnitSection := usInterface;
|
||
|
ttImplementation:
|
||
|
FUnitSection := usImplementation;
|
||
|
ttType:
|
||
|
InterpretType;
|
||
|
ttProgram:
|
||
|
begin
|
||
|
NextToken;
|
||
|
FCurUnitName := Token;
|
||
|
NextToken;
|
||
|
if TTyp <> ttSemicolon then
|
||
|
ErrorExpected(''';''');
|
||
|
end;
|
||
|
ttBegin:
|
||
|
Break;
|
||
|
else
|
||
|
ErrorExpected('''' + kwEND + '''');
|
||
|
end;
|
||
|
NextToken;
|
||
|
end;
|
||
|
FCompiled := True;
|
||
|
FAdapter.AddSrcUnit(FCurUnitName, Source, UsesList);
|
||
|
{ execute program function }
|
||
|
{ FunctionDesc := FAdapter.FindFunDesc(FCurUnitName, 'program');
|
||
|
if FunctionDesc <> nil then
|
||
|
begin
|
||
|
CurPos := FunctionDesc.PosBeg;
|
||
|
NextToken;
|
||
|
InFunction(FunctionDesc);
|
||
|
end; }
|
||
|
try
|
||
|
InterpretBegin;
|
||
|
if (TTyp <> ttPoint) then
|
||
|
ErrorExpected('''.''');
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
UpdateExceptionPos(E, FCurUnitName);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.GetDebugPointerToGlobalVars: TJvInterpreterVarList;
|
||
|
begin
|
||
|
Result := Adapter.FSrcVarList;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterFunction.GetDebugPointerToFunStack: Pointer;
|
||
|
begin
|
||
|
Result := FFunctionStack;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterMethodList } ===========================================
|
||
|
|
||
|
function SortMethodIdentifier(Item1, Item2: Pointer): Integer;
|
||
|
begin
|
||
|
{ function AnsiStrIComp about 30% faster than AnsiCompareText }
|
||
|
{ Result := AnsiCompareText(TJvInterpreterIdentifier(Item1).Identifier,
|
||
|
TJvInterpreterIdentifier(Item2).Identifier); }
|
||
|
Result := AnsiStrIComp(PChar(TJvInterpreterIdentifier(Item1).Identifier),
|
||
|
PChar(TJvInterpreterIdentifier(Item2).Identifier));
|
||
|
|
||
|
if (Result = 0) and (Item1 <> Item2) then
|
||
|
begin
|
||
|
if TJvInterpreterMethod(Item1).FClassType.InheritsFrom(TJvInterpreterMethod(Item2).FClassType) then
|
||
|
Result := -1
|
||
|
else if TJvInterpreterMethod(Item1).FClassType = TJvInterpreterMethod(Item2).FClassType then
|
||
|
Result := 0
|
||
|
else
|
||
|
Result := 1;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterMethodList.Sort(Compare: TListSortCompare);
|
||
|
begin
|
||
|
inherited Sort(SortMethodIdentifier);
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterRecord } ===============================================
|
||
|
|
||
|
procedure TJvInterpreterRecord.AddField(const UnitName, Identifier, Typ: string;
|
||
|
VTyp: Word; const Value: Variant; DataType: IJvInterpreterDataType);
|
||
|
begin
|
||
|
Fields[FieldCount].Identifier := Identifier;
|
||
|
Fields[FieldCount].Typ := varEmpty;
|
||
|
Fields[FieldCount].Offset := RecordSize;
|
||
|
Fields[FieldCount].DataType := DataType;
|
||
|
|
||
|
Inc(RecordSize, SizeOf(TVarData));
|
||
|
Inc(FieldCount);
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterRecord.NewRecord(var Value: Variant);
|
||
|
const
|
||
|
EmptyStr: string = '';
|
||
|
var
|
||
|
I: Integer;
|
||
|
Rec: PAnsiChar;
|
||
|
// Res: Boolean;
|
||
|
RecHolder: TJvInterpreterRecHolder;
|
||
|
begin
|
||
|
if Assigned(CreateFunc) then
|
||
|
CreateFunc(Pointer(Rec))
|
||
|
else
|
||
|
begin
|
||
|
GetMem(Rec, RecordSize);
|
||
|
for I := 0 to FieldCount - 1 do
|
||
|
begin
|
||
|
if Fields[I].Typ = varString then
|
||
|
PString(PString(Rec + Fields[I].Offset)^) := @EmptyStr
|
||
|
else
|
||
|
if Fields[I].Typ = varEmpty then
|
||
|
begin
|
||
|
PVarData(Rec + Fields[I].Offset)^.VType := varNull;
|
||
|
if Fields[I].DataType <> nil then
|
||
|
Fields[I].DataType.Init(Variant(PVarData(Rec + Fields[I].Offset)^));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
JvInterpreterVarCopy(Value, R2V(Identifier, Rec));
|
||
|
RecHolder := TJvInterpreterRecHolder(TVarData(Value).VPointer);
|
||
|
RecHolder.JvInterpreterRecord := Self;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterRecordDataType } =======================================
|
||
|
|
||
|
constructor TJvInterpreterRecordDataType.Create(ARecordDesc: TJvInterpreterRecord);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FRecordDesc := ARecordDesc;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterRecordDataType.GetTyp: Word;
|
||
|
begin
|
||
|
Result := varEmpty;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterRecordDataType.Init(var V: Variant);
|
||
|
begin
|
||
|
FRecordDesc.NewRecord(V);
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterArrayDataType } ========================================
|
||
|
|
||
|
constructor TJvInterpreterArrayDataType.Create(AArrayBegin, AArrayEnd: TJvInterpreterArrayValues;
|
||
|
ADimension: Integer; AArrayType: Integer; ADT: IJvInterpreterDataType);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FArrayBegin := AArrayBegin;
|
||
|
FArrayEnd := AArrayEnd;
|
||
|
FDimension := ADimension;
|
||
|
FArrayType := AArrayType;
|
||
|
FDT := ADT;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterArrayDataType.GetTyp: Word;
|
||
|
begin
|
||
|
Result := varArray;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterArrayDataType.Init(var V: Variant);
|
||
|
begin
|
||
|
V := NativeInt(JvInterpreterArrayInit(FDimension, FArrayBegin, FArrayEnd, FArrayType, FDT));
|
||
|
TVarData(V).VType := varArray;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterSimpleDataType } =======================================
|
||
|
|
||
|
constructor TJvInterpreterSimpleDataType.Create(ATyp: TVarType);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FTyp := ATyp;
|
||
|
end;
|
||
|
|
||
|
function TJvInterpreterSimpleDataType.GetTyp: Word;
|
||
|
begin
|
||
|
Result := FTyp;
|
||
|
end;
|
||
|
|
||
|
procedure TJvInterpreterSimpleDataType.Init(var V: Variant);
|
||
|
begin
|
||
|
V := Null;
|
||
|
TVarData(V).VType := varEmpty;
|
||
|
if (FTyp <> 0) and (FTyp <> varObject) then //dejoy fixed: can't define TObject up d6
|
||
|
V := Var2Type(V, FTyp);
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterSrcUnit } ==============================================
|
||
|
|
||
|
function TJvInterpreterSrcUnit.UsesList: TNameArray;
|
||
|
begin
|
||
|
Result := FUsesList;
|
||
|
end;
|
||
|
|
||
|
//=== { TJvInterpreterClass } ================================================
|
||
|
|
||
|
constructor TJvInterpreterClass.Create;
|
||
|
begin
|
||
|
FClassFields:=TJvInterpreterVarList.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TJvInterpreterClass.Destroy;
|
||
|
begin
|
||
|
FClassFields.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
var
|
||
|
OleInitialized: Boolean;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
procedure Finit;
|
||
|
begin
|
||
|
FreeAndNil(FieldGlobalJvInterpreterAdapter);
|
||
|
FreeAndNil(GlobalVariantObjectInstance);
|
||
|
FreeAndNil(GlobalVariantRecordInstance);
|
||
|
FreeAndNil(GlobalVariantClassInstance);
|
||
|
FreeAndNil(GlobalVariantPointerInstance);
|
||
|
FreeAndNil(GlobalVariantSetInstance);
|
||
|
FreeAndNil(GlobalVariantArrayInstance);
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
if OleInitialized then
|
||
|
OleUnInitialize;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
{$IFDEF JvInterpreter_DEBUG}
|
||
|
if ObjCount <> 0 then
|
||
|
Windows.MessageBox(0, PChar('Memory leak in JvInterpreter.pas'#10 +
|
||
|
'ObjCount = ' + IntToStr(ObjCount)),
|
||
|
'JvInterpreter Internal Error', MB_ICONERROR);
|
||
|
{$ENDIF JvInterpreter_DEBUG}
|
||
|
end;
|
||
|
|
||
|
initialization
|
||
|
{$IFDEF JvInterpreter_OLEAUTO}
|
||
|
OleInitialized := OleInitialize(nil) = S_OK;
|
||
|
{$ENDIF JvInterpreter_OLEAUTO}
|
||
|
|
||
|
finalization
|
||
|
Finit;
|
||
|
|
||
|
end.
|