mirror of
http://gitlab.expertsoft.com.ua/git/expertcad
synced 2026-01-12 00:45:40 +02:00
5776 lines
140 KiB
ObjectPascal
5776 lines
140 KiB
ObjectPascal
{*******************************************************}
|
||
{ }
|
||
{ Delphi Interpreter }
|
||
{ Copyright (c) 1996-1998 S.Kurinny & S.Kostinsky }
|
||
{ }
|
||
{*******************************************************}
|
||
|
||
Unit delphin;
|
||
|
||
Interface
|
||
Uses
|
||
classes, sysutils, forms, windows, dialogs, typinfo, controls,
|
||
Variants,
|
||
// {$ifdef DELPHI7}
|
||
// Variants,
|
||
// {$endif}
|
||
stdctrls;
|
||
|
||
{-------------------------------------------------------------------------}
|
||
|
||
Const
|
||
{ maximal number of procedure parameters allowed in the interpreter}
|
||
maxparams = 100;
|
||
|
||
SErrFunDefined='Function %s is already defined';
|
||
eofincom_ERR = 'Unexpected EOF in comment block';
|
||
delimeter_expected = 'Operator delimeter expected';
|
||
eofinstring_ERR ='Unexpected EOF in string constant declaration';
|
||
need_opbr ='( expected';
|
||
comma_expected= 'Comma expected';
|
||
need_clbr= ') expected';
|
||
begin_expected= 'BEGIN expected';
|
||
unk_macrotype= 'Unknown macro type %S';
|
||
par_notfound= 'Parameter %S not found';
|
||
unkn_id= 'Unknown identifier: %s';
|
||
unexp_writer= 'Unknown variable type during writing program';
|
||
do_exp= 'DO expected';
|
||
down_to_exp= 'TO or DOWNTO expected';
|
||
unit_declared= 'Unit %s already defined';
|
||
bad_unit= 'Unit declaration error';
|
||
fun_notfound= 'Function %s not found';
|
||
until_exp= 'UNTIL Expected';
|
||
linker_error= 'Link Error';
|
||
labname_exp= 'Label name expected';
|
||
label_already= 'Label <%s> already defined';
|
||
delim_or_coma= 'Comma or delimeter expected';
|
||
err_declpart= 'Error in declaration block';
|
||
lab_notdef= 'Label <%s> not defined';
|
||
progname_exp= 'Program name expected';
|
||
varname_exp= 'Variable name expected';
|
||
var_already= 'Variable <%s> already defined';
|
||
bad_varblock= 'Error in variable declaration block';
|
||
var_NotDef= 'Variable <%s> not defined';
|
||
else_exp= 'ELSE expected';
|
||
then_exp= 'THEN expected';
|
||
id_expected= 'Identifier expected';
|
||
meth_decerr= 'Method declaration error';
|
||
bad_methparam= 'Method parameters declaration error';
|
||
no_props= 'Properties not implemented';
|
||
need_par= 'Parent name expected';
|
||
clbr_exp= ') Expected';
|
||
only_class= 'Only class declarations allowed';
|
||
err_decl= '%s declaration error';
|
||
p2_exp= 'Colon expected';
|
||
synt_err='Syntax error in (%s): %s.';
|
||
bad_idName= 'Bad identifier name <%s>';
|
||
bad_id= 'Bad identifier <%s>';
|
||
opsq_exp= '[ expected but %s found';
|
||
clsq_exp= '] expected but %s found';
|
||
in_funuse= 'Invalid function usage';
|
||
in_procuse= 'Invalid procedure usage';
|
||
bad_hex= 'Hex constant declaration error';
|
||
file_not_found= 'File %S not found';
|
||
compile_before= 'Compile before run';
|
||
bad_realconst= 'Real constant declaration error';
|
||
bad_charconst= 'String constant declaration error';
|
||
unsup_partype= 'Unsupported parameter type';
|
||
no_resvar= 'Variable Result not found for %s';
|
||
proc_notfound= 'Procedure %s not found';
|
||
eq_exp= '= expected';
|
||
end_expected= 'END expected';
|
||
SErrCircularVarRef='Circular variable %S reference';
|
||
SErrUnknReaderType='Unknown reader type';
|
||
|
||
type
|
||
// tproctype = Function(slf: tobject; Var s: Array of variant): variant; register;
|
||
TProcType = Function(slf: tobject; var APropName: String; Var s: Array of variant): variant; register;
|
||
|
||
tbytearray = Array[0..maxparams] of byte;
|
||
|
||
TFunListItem = Class
|
||
PropName: String;
|
||
ProcAddr: tproctype;
|
||
ParCount: integer;
|
||
Fun: boolean;
|
||
Params: tbytearray; {0-stack param 1-var param 2-no param
|
||
3-open array param}
|
||
IsProp: Boolean;
|
||
IsPropSet: Boolean;
|
||
End;
|
||
|
||
TFunList = Class(TStringList)
|
||
Public
|
||
Constructor Create;
|
||
|
||
Procedure AddItem(Const Aname,APropName: String; ProcAddr: TProcType;
|
||
Fun, IsProp, IsPropSet: Boolean; Const Params: Array of byte);
|
||
Destructor Destroy; override;
|
||
End;
|
||
|
||
Var
|
||
Funs: TFunList;
|
||
|
||
{-------------------------------------------------------------------------}
|
||
|
||
{Converts object to variant. Used when writing interface functions
|
||
for importing Delphi objects and functions to interpreter.}
|
||
Function ObjToVar(S: TObject): Variant;
|
||
|
||
{Converts variant to object. Used when writing interface functions
|
||
for importing Delphi objects and functions to interpreter.}
|
||
Function VarToObj(S: Variant): TObject;
|
||
|
||
{@see ObjToVar}
|
||
Function OV(S: TObject): Variant;
|
||
|
||
{@see VarToObj}
|
||
Function VO(S: Variant): TObject;
|
||
|
||
{ Use this function to call previously registered in interpreter procedure or function.
|
||
|
||
@param ProcName function name
|
||
@param SLF pointer to object instance if called function is object method
|
||
@param S parameters
|
||
@return return value (for functions)}
|
||
{Function CallHalProc(Const procName: String; slf: tobject;
|
||
Var s: Array of variant): variant;}
|
||
|
||
{ Returns address of registered in interpreter function or procedure
|
||
Returns nil if item not found
|
||
}
|
||
//Function GetHalProcAddr(Const FunName: String): tproctype;
|
||
|
||
{ Calls interpreter procedure or function without parameters
|
||
If procedure or function with ProcName not found does nothing
|
||
}
|
||
//function SimpleCallHalProc(Const ProcName:String):Variant;
|
||
|
||
{Registers Delphi's procedure in interpreter
|
||
@param AName Procedure name. For registration object method use qualified name
|
||
('TOBJECT.FREE')
|
||
@param ProcAddr Import function address. @see TProcType
|
||
@param Params Array of parameters definitions.
|
||
If =[2] - no parameters, otherwise type of each parameter should be specified.
|
||
Parameter types: 0 - stack parameter, 1 - var parameter, 3 - open array.
|
||
Open array is passed to import function in variant with array type.
|
||
V[0] - array size. V[1]..V[V[0]] - array items. Use convert functions
|
||
for converting to array of const of to other array types
|
||
}
|
||
Procedure AddProc(Const Aname: String; ProcAddr: TProcType; Const Params: Array of byte);
|
||
|
||
{ Same as AddProc, but for registering functions
|
||
@see AddProc
|
||
}
|
||
Procedure AddFun(Const Aname: String; ProcAddr: TProcType; Const Params: Array of byte);
|
||
|
||
{ Registers object properties. Interface functions for reading and
|
||
writing property value should be specified.
|
||
If Property is read-only then pass SETPROCADDR=nil}
|
||
Procedure AddProp(Const Aname: String; ProcAddr, SetProcAddr: TProcType);
|
||
|
||
{ Registers array properties.
|
||
ADIM- array dimension. ( 3 ---> A[1,2,2] 1 --> A[6])}
|
||
Procedure AddArrayProp(Const Aname: String; ADim: Integer; ProcAddr, SetProcAddr: TProcType);
|
||
|
||
{ Deletes previously registered in the interpreter procedure or function
|
||
If item with ProcName not found does nothing
|
||
}
|
||
procedure DelProc(Const ProcName:String);
|
||
|
||
{----------------------------------------------}
|
||
|
||
Const
|
||
conotifyevent = 'TNotifyEvent'; // don't resource
|
||
cocloseevent = 'TCloseEvent'; // don't resource
|
||
coprocResult = '.Result'; // don't resource
|
||
StackSize=1000;
|
||
Type
|
||
|
||
// Functions of this type are used for converting external variable
|
||
// names to ids
|
||
TDynaVarNameTOId = Function(Const S: String): Integer of Object;
|
||
|
||
// Procedures of this type are called to set value to external variable by id.
|
||
TDynaSetVar = Procedure(ID: Integer; Value: Variant) of Object;
|
||
|
||
// Functions of this type are used to get values of external variables
|
||
TDynaGetVar = Function(ID: Integer): Variant of Object;
|
||
|
||
Type
|
||
ECompilerError = Class(Exception);
|
||
|
||
{-------------------}
|
||
|
||
Type
|
||
TToken = Record
|
||
ID: Integer;
|
||
Data: Variant;
|
||
End;
|
||
|
||
Type TCharSet = Set of char;
|
||
|
||
Const
|
||
WhiteSpaces: TCharSet = ['+', '-', '/', '*', '(', ')', ':', '=', ',', ';', '>', '<',
|
||
'$', '.', '#', '[', ']', '^', '@', '&', '~', '|', '%'];
|
||
BlackSpaces: TCharSet = [#1..#32];
|
||
StopChars: TCharSet = [#0..#32, '+', '-', '/', '*', '(', ')', ':', '=', ',', '''',
|
||
'{', '}', ';', '>', '<', '$', '.', '#', '[', ']', '"', '^', '@', '&', '~', '|', '%'];
|
||
FirstIdentChar: TCharSet = ['A'..'Z', '<27>'..'<27>', '_'];
|
||
IdentBackChars: TCharSet = ['A'..'Z', '_', '0'..'9', '<27>'..'<27>'];
|
||
Digit: TCharSet = ['0'..'9'];
|
||
HexDigit: TCharSet = ['0'..'9', 'A'..'F'];
|
||
|
||
{----------------------------------------------}
|
||
|
||
{ Writer types }
|
||
Const
|
||
wInteger = 1;
|
||
wDouble = 2;
|
||
wString = 3;
|
||
WBoolean = 4;
|
||
|
||
{----------------------------------------------}
|
||
Const
|
||
ocAdd = 0;
|
||
ocSub = 1;
|
||
ocMul = 2;
|
||
ocDiv = 3;
|
||
ocMod = 4;
|
||
ocSlash = 5;
|
||
ocShl = 6;
|
||
ocShr = 7;
|
||
ocNot = 8;
|
||
ocOr = 9;
|
||
ocXor = 10;
|
||
ocAnd = 11;
|
||
ocGreaterEqual = 12;
|
||
ocEqual = 13;
|
||
ocLessEqual = 14;
|
||
ocNotEqual = 15;
|
||
ocGreater = 16;
|
||
ocLess = 17;
|
||
ocNeg = 18;
|
||
ocGoto = 19;
|
||
ocIF = 20;
|
||
ocloadconst = 23;
|
||
ochalt = 26;
|
||
ocincvar = 29;
|
||
ocdecvar = 30;
|
||
ocbackcode = 34;
|
||
ocextfun = 42;
|
||
ocextproc = 43;
|
||
ocsetself = 44;
|
||
ocloadextvar = 45;
|
||
ocstoreextvar = 46;
|
||
ocselffromvar = 47;
|
||
ocmov = 48;
|
||
occall = 49;
|
||
ocreturn = 50;
|
||
ocvarraycreate = 51;
|
||
ocsetvarray = 52;
|
||
|
||
|
||
{ Character IDs}
|
||
|
||
idEndOfFile = 0;
|
||
idNewLine = $0a;
|
||
idpower = Integer('^');
|
||
idPoint = Integer('.');
|
||
idDelimeter = Integer(';');
|
||
idgreater = Integer('>');
|
||
idless = Integer('<');
|
||
idComma = Integer(',');
|
||
idPlus = Integer('+');
|
||
idMinus = Integer('-');
|
||
idSlash = Integer('/');
|
||
idStar = Integer('*');
|
||
idOpenBracket = Integer('(');
|
||
idCloseBracket = Integer(')');
|
||
idOpenComment = Integer('{');
|
||
idCloseComment = Integer('}');
|
||
idEqual = Integer('=');
|
||
idnotequal = integer('#');
|
||
id2Points = Integer(':');
|
||
idStringChar = Integer('''');
|
||
id2StringChar = Integer('"');
|
||
idsqopenbracket = integer('[');
|
||
idsqclosebracket = integer(']');
|
||
|
||
{ ID Bases and ID ends }
|
||
idBase = 256;
|
||
idReservedBase = 1000;
|
||
idReservedEnd = 1999;
|
||
|
||
{ Other IDs }
|
||
idIdentifier = idBase + 0;
|
||
idStringConst = idBase + 1;
|
||
idNumberConst = idBase + 2;
|
||
idresconst = idbase + 5;
|
||
idhexConst = idbase + 6;
|
||
|
||
{ Reserverd Words [idReservedBase,idReservedEnd] }
|
||
id_Program = idReservedBase + 0;
|
||
id_Label = idReservedBase + 1;
|
||
id_Goto = idReservedBase + 2;
|
||
id_Var = idReservedBase + 3;
|
||
id_begin = idReservedBase + 4;
|
||
id_end = idReservedBase + 5;
|
||
id_and = idReservedBase + 6;
|
||
id_or = idReservedBase + 7;
|
||
id_xor = idReservedBase + 8;
|
||
id_not = idReservedBase + 9;
|
||
id_shl = idReservedBase + 10;
|
||
id_shr = idReservedBase + 11;
|
||
id_div = idReservedBase + 12;
|
||
id_mod = idReservedBase + 13;
|
||
id_true = idReservedBase + 14;
|
||
id_false = idReservedBase + 15;
|
||
id_if = idReservedBase + 16;
|
||
id_then = idReservedBase + 17;
|
||
Id_else = idReservedBase + 18;
|
||
id_while = idReservedBase + 19;
|
||
id_repeat = idReservedBase + 20;
|
||
id_until = idReservedBase + 21;
|
||
id_for = idReservedBase + 22;
|
||
id_to = idReservedBase + 23;
|
||
id_downto = idReservedBase + 24;
|
||
id_do = idReservedBase + 25;
|
||
id_nil = idReservedBase + 27;
|
||
id_unitinit = idReservedBase + 31;
|
||
id_unitfinal = idReservedBase + 32;
|
||
id_class = idReservedBase + 33;
|
||
id_type = idReservedBase + 34;
|
||
id_constr = idReservedBase + 35;
|
||
id_destr = idReservedBase + 36;
|
||
id_uses = idReservedBase + 37;
|
||
id_unit = idReservedBase + 38;
|
||
id_interface = idReservedBase + 39;
|
||
id_implement = idReservedBase + 40;
|
||
id_procedure = idReservedBase + 41;
|
||
id_private = idReservedBase + 42;
|
||
id_public = idReservedBase + 43;
|
||
id_protected = idReservedBase + 44;
|
||
id_published = idReservedBase + 45;
|
||
id_function = idReservedBase + 46;
|
||
id_const = idReservedBase + 47;
|
||
id_property = idReservedBase + 48;
|
||
id_virtual = idReservedBase + 49;
|
||
id_override = idReservedBase + 50;
|
||
id_dynamic = idReservedBase + 51;
|
||
id_record = idReservedBase + 52;
|
||
id_forward = idReservedBase + 53;
|
||
id_index = idReservedBase + 54;
|
||
id_read = idReservedBase + 55;
|
||
id_write = idReservedBase + 56;
|
||
id_stored = idReservedBase + 57;
|
||
id_default = idReservedBase + 58;
|
||
id_abstract = idReservedBase + 59;
|
||
id_stdcall=idReservedBase + 69;
|
||
|
||
{------------------------------}
|
||
|
||
Type
|
||
|
||
TResConstListItem = Class
|
||
public
|
||
Value: Variant;
|
||
End;
|
||
|
||
TResConstList = Class(TStringList)
|
||
Public
|
||
Constructor Create;
|
||
Procedure AddConst(Const AName: String; Var V: Variant);
|
||
Destructor Destroy; override;
|
||
End;
|
||
|
||
TDynaVarItem = Class
|
||
public
|
||
VarNameTOID: TDynaVarNameToID;
|
||
SetVar: TDYnaSetVar;
|
||
GetVar: TDynaGetVar;
|
||
LocalVar: Boolean;
|
||
OwnerSelf: TObject;
|
||
End;
|
||
|
||
TDynaVars = Class(TStringlist)
|
||
Public
|
||
Function GetDynaObject(Const vname: String; AOwnerSelf: TObject;
|
||
Var varid, funid: integer): boolean;
|
||
Procedure AddDyna(Const name: String;
|
||
Avarnametoid: TDynaVarNameTOID;
|
||
ASetVar: TDYnaSetVar;
|
||
AGetVar: TDynaGetVar; LocalVars: Boolean; AOwnerSelf: TObject);
|
||
Procedure DelDyna(Const name: String);
|
||
Destructor Destroy; override;
|
||
End;
|
||
|
||
TObjectListItem = Class
|
||
public
|
||
Pearent: String;
|
||
End;
|
||
|
||
tobjitem = Class
|
||
public
|
||
objtype: String;
|
||
tobj: tobject;
|
||
End;
|
||
|
||
tobjcollect = Class(tstringlist)
|
||
Public
|
||
Constructor Create;
|
||
Destructor Destroy; override;
|
||
Function ObjbyName(Const aname: String; Var tob: tobjitem): boolean;
|
||
End;
|
||
|
||
pvariantarray = ^tvariantarray;
|
||
tvariantarray = Array[0..StackSize] of variant;
|
||
|
||
Const
|
||
tifunction = 2;
|
||
tivariable = 0;
|
||
tiprocedure = 1;
|
||
|
||
Type
|
||
TIdentListItem = Class
|
||
Public
|
||
ID: Integer;
|
||
VType: String;
|
||
IdentType: Integer; {0-Variable 1-procedure 2-function}
|
||
ParCount: Integer;
|
||
Params: tbytearray;
|
||
ParamNames: TStringList;
|
||
Constructor Create;
|
||
Destructor Destroy; override;
|
||
Procedure Assign(Source: TIdentlistItem);
|
||
End;
|
||
|
||
tbinprogitem = Record
|
||
a, b, opcode: integer;
|
||
End;
|
||
|
||
tprogarray = Array[0..1000] of tbinprogitem;
|
||
pprogarray = ^tprogarray;
|
||
pintarray = ^tintarray;
|
||
tintarray = Array[0..1000] of integer;
|
||
|
||
TIdentList = Class(TStringList)
|
||
private
|
||
Function AddItem(Const Aname: String; ID: Integer): Integer;
|
||
Function IDByName(Const AName: String; Var AID: integer): boolean;
|
||
Function ItemByName(Const Aname: String; Var Ident: TIdentListItem): boolean;
|
||
Public
|
||
Constructor Create;
|
||
Destructor Destroy; override;
|
||
Procedure Assign(Source: TPersistent); override;
|
||
End;
|
||
|
||
TConstItem = Class(TCollectionItem)
|
||
Public
|
||
Data: Variant;
|
||
End;
|
||
|
||
TConstList = Class(TCollection)
|
||
Public
|
||
Function newitem(adata: variant): integer;
|
||
End;
|
||
|
||
TIDLabelItem = Class(TCollectionItem)
|
||
Public
|
||
referenced: boolean;
|
||
exist: boolean;
|
||
Place: integer;
|
||
End;
|
||
|
||
TIDLabelList = Class(TCollection)
|
||
Public
|
||
Function newitem: integer;
|
||
Procedure SetPlace(index, aplace: integer);
|
||
Procedure SetReference(index: integer);
|
||
Function existlabels: boolean;
|
||
End;
|
||
|
||
TProgItem = Class(TCollectionItem)
|
||
Public
|
||
OpCode: integer;
|
||
A: integer;
|
||
B: integer;
|
||
End;
|
||
|
||
TProgCollect = Class(TCollection)
|
||
Public
|
||
Procedure putop(ID, AA, AB: integer);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Var
|
||
ResWords: TIdentList;
|
||
DynaVars: TDynaVars;
|
||
ResConsts: TResConstList;
|
||
|
||
{------------------------------}
|
||
|
||
Function GetClassParent(C:TClass):String;
|
||
Function GetPearent(Const objname: String): String;
|
||
|
||
// Releases memory occupied by array of constants, converted using
|
||
// function VARTOCONSTS.
|
||
Procedure disposeconsts(Var c: Array of tvarrec; size: integer);
|
||
|
||
Procedure setnotifyevent(ControlLink: TObject; Const eventlink: String; fmynotifyevent: TNotifyEvent);
|
||
Function SetToken(ID: integer; V: Variant): TToken;
|
||
Function Hex2Dec(Const S: String): Longint;
|
||
|
||
{ Same as AddDynaVar, but variables will be visible only in script
|
||
of HalComp=AOwnerSelf}
|
||
Procedure AddLocalVar(Const name: String;
|
||
Avarnametoid: TDynaVarNameTOID;
|
||
ASetVar: TDYnaSetVar;
|
||
AGetVar: TDynaGetVar; AOwnerSelf: TObject);
|
||
|
||
|
||
{ Registers external variables (your Delphi programs variables) in interpreter.
|
||
These variables will be visible in all scripts.
|
||
Name - Name of the DYNA definition. This name can be used
|
||
later for deleting DYNA definitions.
|
||
AVARNAMETOID
|
||
- function for converting variable names to ids
|
||
TDYNAVARNAMETOID= FUNCTION(CONST S:STRING):INTEGER OF OBJECT;
|
||
Interpreter calls functions AVARNAMETOID of all DYNA definitions.
|
||
If S is yours variable return its ID (it's up to you to decide what ID,
|
||
variables of different DYNA definitions could have same IDs).
|
||
If S is not your's variable return -1
|
||
|
||
ASETVAR
|
||
- procedure for writing value to DYNA variable.
|
||
TDYNASETVAR=PROCEDURE (ID: INTEGER; VALUE: VARIANT) OF OBJECT;
|
||
|
||
AGETVAR - procedure for reading DYNA variable value
|
||
TDYNAGETVAR=FUNCTION (ID: INTEGER): VARIANT OF OBJECT;
|
||
}
|
||
Procedure AddDynaVar(Const name: String;
|
||
Avarnametoid: TDynaVarNameTOID;
|
||
ASetVar: TDYnaSetVar;
|
||
AGetVar: TDynaGetVar);
|
||
|
||
// Deletes DYNA definition with Name
|
||
Procedure deldynavar(Const name: String);
|
||
|
||
{ Converts variant to array of constants. Returns Maxp - high bound of array.
|
||
Use only in interface functions.}
|
||
Procedure VarToConsts(Var V: Variant; Var P: Array of tvarrec; Var MaxP: Integer);
|
||
|
||
{ Registers constant with name ANAME and with value V
|
||
Example: AddConst('Pi',pi);}
|
||
Procedure AddConst(Const AName: String; V: Variant);
|
||
|
||
{ Converts variant to array of string. Returns Maxp - high bound of array.
|
||
Use only in interface functions.}
|
||
Procedure VarToStringS(Var V: Variant; Var P: Array of String; Var MaxP: Integer);
|
||
|
||
{ Clears array of HAL parameters}
|
||
Procedure ClearHalParams;
|
||
|
||
{ Returns value of HAL parameter with name PARAMNAME.
|
||
HAL parameters are "virtual" variables accessible from any place
|
||
in program}
|
||
Function GetHalParam(Const ParamName: String): Variant;
|
||
|
||
// Write value to HAL parameter with name PARAMNAME.
|
||
// HAL parameters are "virtual" variables accessible from any place
|
||
// in program
|
||
Procedure SetHalParam(Const ParamName: String; Value: Variant);
|
||
|
||
{------------------------------}
|
||
|
||
Type
|
||
TInternalVarItem = Class
|
||
public
|
||
Value: Variant;
|
||
End;
|
||
|
||
TInternalVar = Class(TStringList)
|
||
Private
|
||
MyResult: Variant;
|
||
Function DynaGetVar(ID: Integer): Variant;
|
||
Procedure DynaSetVar(ID: Integer; Value: Variant);
|
||
Function DynaVarNameTOId(Const S: String): Integer;
|
||
Public
|
||
Constructor Create;
|
||
Destructor Destroy; override;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Const
|
||
stintvar = '__InternalVar';
|
||
|
||
Var
|
||
InternalVariables: TInternalVar;
|
||
|
||
{----------------------------------------------}
|
||
Type
|
||
tbuf = Array[1..12000] of char;
|
||
pbuf = ^tbuf;
|
||
|
||
THalCompiler = Class
|
||
Private
|
||
DolEnabled: Boolean;
|
||
HalOwner: TObject;
|
||
IdentPrefix: String;
|
||
spoint: integer;
|
||
fout: tstream;
|
||
Labels, Variables: TIdentList;
|
||
Consts: TConstList;
|
||
IDLabels: TIDLabelList;
|
||
Prog: TProgCollect;
|
||
lastvar: TIdentListItem;
|
||
lastobject: TObject;
|
||
mobjects: tobjcollect;
|
||
notfromobj: boolean;
|
||
FLastClassType: String;
|
||
nextstate: boolean;
|
||
Function NextByte: byte;
|
||
Function getinternalfun(Const sname: String; ident: tidentlistitem): integer;
|
||
Function VarIDByName(Const AName: String; Var Id: Integer): boolean;
|
||
Procedure getprocbody(i: integer);
|
||
Procedure getvartype;
|
||
Function getprocdef(askip: boolean): Integer;
|
||
Procedure getclassdefblock(b: boolean);
|
||
Procedure getmyvariables(b: boolean);
|
||
Function ReadByte: byte;
|
||
Procedure findobject(Var s: String);
|
||
Procedure gettypeidentifier;
|
||
Procedure BackBytes(a: integer);
|
||
Function getvar: integer;
|
||
Procedure putcode(aid, a, b: integer);
|
||
Function iexpression: integer;
|
||
Function isimpleexpression: integer;
|
||
Function GetOpenArray(NeedSq: boolean): Integer;
|
||
Procedure getuserfunction(Const name: String; scope, fik: boolean);
|
||
Procedure getcoma;
|
||
Procedure getidentifier;
|
||
Function iterm: integer;
|
||
Function ifactor: integer;
|
||
Function VarByName(Const AName: String; Var Ident: TIdentListItem): boolean;
|
||
Function AddVars(Const Aname: String; ID: Integer): Integer;
|
||
Function myexpress: integer;
|
||
Procedure equaldispath(Const VarName: String);
|
||
Procedure labeldispatch(Const labelname: String);
|
||
Procedure getprogramname;
|
||
Procedure getclassdef(Const cname: String);
|
||
Procedure getdeclarations;
|
||
Procedure myinit;
|
||
Procedure mydone;
|
||
Procedure getoperatorcoma;
|
||
Procedure getwhileoperator;
|
||
Procedure getrepeatoperator;
|
||
Procedure getforoperator;
|
||
Procedure getifoperator;
|
||
Procedure getoperator;
|
||
Procedure getoperatorblock;
|
||
Procedure compileprogram;
|
||
Procedure writeprogram;
|
||
public
|
||
inbuf: ^tbuf;
|
||
curread, numread: integer;
|
||
Token: TToken;
|
||
// Converts curent stream position into Line number and char position in line
|
||
// (1 based)
|
||
procedure ConvertCurPos(Var ALine,AChar:Integer);
|
||
Constructor Create(afin: TMemoryStream; afout: TStream);
|
||
Procedure compile; virtual;
|
||
Destructor Destroy; override;
|
||
Procedure getclosebracket;
|
||
Procedure getafterproc;
|
||
Procedure getopenbracket;
|
||
Procedure getdelimeter;
|
||
function GetLineNumber:Integer;
|
||
Function ReadToken: TToken;
|
||
Procedure error(Const s: String);
|
||
Function NextToken: TToken;
|
||
End;
|
||
{------------------------------}
|
||
Type
|
||
TBinProg = Class
|
||
Private
|
||
TempVars: Array[0..maxparams] of variant;
|
||
curpos: integer;
|
||
CallStack: Array[0..1000] of integer;
|
||
CallMax: Integer;
|
||
ConstSize: integer;
|
||
ProgSize: integer;
|
||
LabelSize: integer;
|
||
c: pvariantarray;
|
||
prog: pprogarray;
|
||
lastobject: tobject;
|
||
l: pintarray;
|
||
s: tvariantarray;
|
||
Procedure _ocstoreextvar(b, a: integer; Var V: Variant);
|
||
Procedure _ocsetself(A: TObject); register;
|
||
Procedure _ocselffromvar(Var A: Variant); register;
|
||
Procedure _ocloadextvar(Var V: Variant; b, a: integer); register;
|
||
Procedure _CallExtFun(Var V: Variant; var PropName:String; ProcAddr: TProcType); register;
|
||
Function _dispatch(opcode, a, b: integer): boolean;
|
||
Procedure Error(Const s: String);
|
||
Public
|
||
Procedure RunFrom(Acurpos: Integer);
|
||
Constructor Create(Fin: TStream);
|
||
Procedure Run;
|
||
Destructor Destroy; override;
|
||
End;
|
||
|
||
THalRuner = Class
|
||
Private
|
||
instream: tmemorystream;
|
||
Compiled: boolean;
|
||
mymem: TMemoryStream;
|
||
HalOwner: TObject;
|
||
myobjects: tobjcollect;
|
||
FBinProg: TBinProg;
|
||
loadtemp: boolean; { set true to copy Variables to TempVarList}
|
||
dontrun: boolean; { set true if you need to compile only}
|
||
TempVarList: TIdentList;
|
||
FLastClassType: String;
|
||
Procedure AddObject(Const objname, objtype: String; tobj: tobject);
|
||
Procedure AddObjectbyRef(Const objname: String; tobj: tobject);
|
||
Public
|
||
Constructor Create(T: TMemoryStream);
|
||
Procedure Run;
|
||
Destructor Destroy; override;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Var
|
||
OutMemo: TMemo = Nil;
|
||
ErrorMemo: TMemo = Nil;
|
||
ErrorPrinted: Boolean = false;
|
||
OutLabel: TLabel = Nil;
|
||
|
||
Type
|
||
// Main component for visual work with interpreter. Specify script in
|
||
// property SCRIPT and use property Result for executing script and
|
||
// obtaining result. Script will be compiled only once or if you set
|
||
// property FSCRIPTCHANGED to true.
|
||
// You can "hook" event with name EventLink of component ControlLink
|
||
// and script will be executed instead of previously set event.
|
||
// (only TnotifyEvent supported for now + variably Sender can be used
|
||
// in the script).
|
||
|
||
THalComp = Class(TComponent)
|
||
Private
|
||
FVarNameTOID: TDynaVarNameTOID;
|
||
FGetVar: TDynaGetVar;
|
||
FSetVar: TDYnaSetVar;
|
||
FExpression, fobname: String;
|
||
fob: tobject;
|
||
FMyStream: TMemoryStream;
|
||
FControl: TComponent;
|
||
FEventLink: String;
|
||
FScript: TStrings;
|
||
Procedure SetExpression(Const S: String);
|
||
Procedure MyOnCHange(Sender: TObject);
|
||
Procedure SetScript(Value: TStrings);
|
||
Protected
|
||
DelOnFree: Boolean;
|
||
Procedure Notification(AComponent: TComponent;
|
||
Operation: TOperation); override;
|
||
Function getresult: variant;
|
||
Public
|
||
EventDispatcher:boolean; // true if this instance of halcomp is event dispatcher
|
||
FScriptChanged: boolean;
|
||
FHalRuner: THalRuner;
|
||
FLastClassType: String;
|
||
|
||
|
||
// This form components will be accessible from script body.
|
||
// Set only if THALCOMP has no owner (if there is owner then it's
|
||
// components accessible).
|
||
Friend: TForm;
|
||
|
||
Procedure Loaded; override;
|
||
Procedure FMyNotifyEvent(Sender: TObject);
|
||
Procedure FOnFOrmClose(Sender: TObject; Var Action: TCloseAction);
|
||
Constructor Create(AOwner: TComponent); override;
|
||
Destructor Destroy; override;
|
||
Procedure Run;
|
||
Procedure Compile(Const obname: String; ob: tobject);
|
||
|
||
// Use for execuiting script and for obtaining result
|
||
// (Script will be compiled if neccessary)
|
||
// (main property)
|
||
Property Result: Variant Read getResult;
|
||
|
||
Published
|
||
Property Script: TStrings Read FScript Write SetScript;
|
||
|
||
// Formula can be specified here (Use EXPRESSION or SCRIPT but not both)
|
||
Property Expression: String Read FExpression Write SetExpression;
|
||
|
||
// Component which will be hooked
|
||
Property ControlLink: TComponent Read FControl Write FControl;
|
||
|
||
// Event name
|
||
Property EventLink: String Read FEventLink Write FEventLink;
|
||
|
||
|
||
// Events for specifying external variables.
|
||
// These variables will be accessible only in this macros
|
||
// Read in the TDynaVarNameTOID type declaration about these events
|
||
Property VarNameTOID: TDynaVarNameTOID Read FVarNameTOID Write FVarNameTOID;
|
||
Property GetVar: TDynaGetVar Read FGetVar Write FGetVar;
|
||
Property SetVar: TDYnaSetVar Read FSetVar Write FSetVar;
|
||
End;
|
||
{------------------------------}
|
||
|
||
// Object for calculation of connected formulas. Example: A=B+C B=C-5 C=4
|
||
(*
|
||
TFormulaListItem = Class
|
||
public
|
||
Formula: String;
|
||
Value: Variant;
|
||
NeedCalc: Boolean;
|
||
End;
|
||
*)
|
||
(*
|
||
TFormulaList = Class(TStringList)
|
||
Private
|
||
IntStack: TIntStack;
|
||
Function HVarNameTOId(Const S: String): Integer;
|
||
Procedure HSetVar(ID: Integer; Value: Variant);
|
||
Function HGetVar(ID: Integer): Variant;
|
||
Public
|
||
// Calculate formula. Previously defined constants and calculatable
|
||
// variables could be used in the formula body.
|
||
Function CalcFormula(Const AFormula: String): Variant;
|
||
|
||
// Define constant
|
||
Procedure AddValue(Const VarName: String; AValue: Variant);
|
||
|
||
// Define variable
|
||
// (A=B+4 ---> ADDFORMULA('A','B+4');
|
||
Procedure AddFormula(Const VarName, AFormula: String);
|
||
|
||
Procedure AddVF(Const VarName, AFormula: String; AValue: Variant;
|
||
ACalc: Boolean);
|
||
|
||
// Get variable value.Formulas will be recalculated only once.
|
||
Function GetValue(Const VarName: String): Variant;
|
||
|
||
Constructor Create;
|
||
Destructor Destroy; override;
|
||
End;
|
||
*)
|
||
{------------------------------}
|
||
TQRNotifyOperation = (qrMasterDataAdvance, qrBandPrinted, qrBandSizeChange);
|
||
|
||
TMethodNameHolder = Class
|
||
Public
|
||
MethodName: String;
|
||
End;
|
||
|
||
PVarDataList = ^TVarDataList;
|
||
TVarDataList = array[0..65535] of TVarData;
|
||
|
||
THalEvent = Class(TComponent)
|
||
Protected
|
||
it: tidentlistitem;
|
||
PrName, ProcName: String;
|
||
HR: THalRuner;
|
||
Function GetParam(Const ParName: String): Variant;
|
||
Function GetProcItem: TIdentListItem;
|
||
Procedure SetParam(Const ParName: String; Value: Variant);
|
||
Public
|
||
Procedure ExecProc(F:TObject;ParCount:Integer;Params:PVarDataList);
|
||
Procedure MCloseEvent(Sender: TObject; Var Action: TCloseAction);
|
||
Procedure MNotifyEvent(Sender: TObject);
|
||
Procedure MDragDropEvent(Sender, Source: TObject; X, Y: Integer);
|
||
Procedure MDragOverEvent(Sender, Source: TObject; X, Y: Integer; State: TDragState; Var Accept: Boolean);
|
||
Procedure MEndDragEvent(Sender, Target: TObject; X, Y: Integer);
|
||
Procedure MStartDragEvent(Sender: TObject; Var DragObject: TDragObject);
|
||
Procedure MKeyPressEvent(Sender: TObject; Var Key: Char);
|
||
|
||
procedure mQROnNeedDataEvent(Sender : TObject; var MoreData : Boolean);
|
||
procedure mQRNotifyOperationEvent(Sender : TObject; Operation : TQRNotifyOperation);
|
||
procedure mQRBandBeforePrintEvent(Sender : TObject; var PrintBand : Boolean);
|
||
procedure mQRBandAfterPrintEvent(Sender : TObject; BandPrinted : Boolean);
|
||
procedure mQRReportBeforePrintEvent(Sender : TObject; var PrintReport : Boolean);
|
||
procedure mQRFilterEvent(var PrintRecord : boolean);
|
||
function MHelpEvent(Command: Word; Data: Longint;var CallHelp: Boolean): Boolean;
|
||
procedure MCloseQueryEvent(Sender: TObject;var CanClose: Boolean);
|
||
procedure mQRLabelOnPrintEvent(sender : TObject; var Value : string);
|
||
procedure mQRProgressUpdateEvent(Sender : TObject; Progress : integer);
|
||
procedure mQRPageAvailableEvent(Sender : TObject; PageNum : integer);
|
||
|
||
procedure MMouseEvent(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure MMouseMoveEvent(Sender: TObject; Shift: TShiftState;X, Y: Integer);
|
||
procedure MKeyEvent(Sender: TObject; var Key: Word;Shift: TShiftState);
|
||
End;
|
||
|
||
THalEventClass = Class of THalEvent;
|
||
|
||
TMyReader = Class(TReader)
|
||
Public
|
||
Constructor Create(Stream: TStream; BufSize: Integer);
|
||
Function FindMethod(Root: TComponent;
|
||
Const MethodName: String): Pointer; Override;
|
||
End;
|
||
|
||
TMyStream = Class(TFileStream)
|
||
Public
|
||
Function ReadComponent(Instance: TComponent): TComponent;
|
||
Function ReadComponentRes(Instance: TComponent): TComponent;
|
||
End;
|
||
{------------------------------}
|
||
TEventListItem = Class
|
||
Address: Pointer;
|
||
EventClass: THalEventClass;
|
||
End;
|
||
|
||
TEventList = Class(TStringList)
|
||
Public
|
||
Constructor Create;
|
||
Function ItemByName(Const AEventType: String): TEventListItem;
|
||
Procedure AddItem(Const AEventType: String; AAddress: Pointer;
|
||
AEventClass: THalEventClass);
|
||
Destructor Destroy; override;
|
||
End;
|
||
{------------------------------------------------------------------}
|
||
|
||
Type
|
||
TPosListItem=Class(TCollectionItem)
|
||
public
|
||
LinePos:Integer;
|
||
CharPos:Integer;
|
||
end;
|
||
|
||
TPosList=class(TCollection)
|
||
public
|
||
constructor Create;
|
||
Function AddPos(ALine,AChar:Integer):TPosListItem;
|
||
end;
|
||
|
||
{------------------------------}
|
||
|
||
// Register event if interpreter. Example in HALINIT.PAS
|
||
Procedure RegisterEvent(Const AEventType: String; AAddress: Pointer;
|
||
AEventClass: THalEventClass);
|
||
|
||
// Call this function to check is event with particular type registered in interpreter
|
||
// or not
|
||
Function RegisteredEvent(Const EventType: String): Boolean;
|
||
|
||
// Run script from file MACRONAME
|
||
Function RunMacro(Const MacroName: String): Variant;
|
||
|
||
// Run script from file MACRONAME Additionally you will be able to use
|
||
// all form AFORM components in the script body
|
||
Function RunMacroFriend(Const MacroName: String; AForm: TForm): Variant;
|
||
|
||
// Run form with name FORMPATH
|
||
function RunForm(Const FormPath: String):TForm;
|
||
|
||
// Run DFM+PAS. Form will be showed modal.
|
||
Function RunFormModal(Const FormPath: String): Integer;
|
||
|
||
|
||
// Run script or form (depends from extension)
|
||
// Mpath -path to script or form
|
||
// Modal - true if show form modal
|
||
Function RunFormMacro(Const MPath: String; Modal: Boolean): Variant;
|
||
|
||
Function MyReadComponentResFile(Const FileName: String; Instance: TComponent): TComponent;
|
||
|
||
// --------------------- code designer procedures -----------------
|
||
|
||
Function FindFormInVarDecl(S:TMemoryStream;Const FormName:String;
|
||
Var BegLine,BegPos,EndLine,EndPos:Integer):Boolean;
|
||
|
||
// Searches for "implementation" and return True if was found
|
||
// ALine,Apos contain line and char positions (1 based)
|
||
Function ImplFound(M:TMemoryStream;Var ALine,APos:Integer):Boolean;
|
||
|
||
procedure FindFormInEventNames(S:TMemoryStream;Const FormName:String;PosList:TPosList);
|
||
Function FindFormInTypeDecl(S:TMemoryStream;Const FormName:String;
|
||
Var ALine,APos:Integer):Boolean;
|
||
|
||
|
||
{ Searches for the event with EventName in codegen section and returns True if
|
||
event was found and position of the event name in the code
|
||
}
|
||
function FindEventInCodeGen(S:TMemoryStream;Const EventName:String;
|
||
Var ALine,AChar:Integer):Boolean;
|
||
|
||
{ Searches for code designer "special section"
|
||
(before "private" clause in class definition)
|
||
Returns True if found and false otherwise
|
||
FormClassName - class name of the form (= TForm1 or smth )
|
||
}
|
||
Function GetCodegenSection(S:TMemoryStream; Const FormClassName:String;
|
||
Var BegLine,BegPos,EndLine,EndPos:Integer):Boolean;
|
||
|
||
{ Searches for the position of the unit name
|
||
Returns true if such position was found
|
||
ALine - line number where unit name was found
|
||
APos - position of unit name
|
||
}
|
||
Function GetUnitNamePos(S:TMemoryStream; Var ALine,APos,Aleng:Integer):Boolean;
|
||
|
||
{ Searches for 'uses' clause. Returns true if found and false otherwise
|
||
Example:
|
||
Uses*
|
||
Classes,Forms,Dialogs,
|
||
chUtils**;
|
||
* - BegLine,BegPos (all 1 based)
|
||
|
||
** - EndLine,EndPos (all 1 based)
|
||
If there is no extra space between ; and last unit name then returns coma position
|
||
(so Endpos should be decremented in any case)
|
||
}
|
||
Function GetUsesPos(S:TMemoryStream;Var BegLine,BegPos,EndLine,EndPos:Integer;
|
||
AfterImpl:Boolean):Boolean;
|
||
|
||
{ Searches stream for method name occurence and returns true if method name
|
||
was found and false if not found
|
||
}
|
||
Function GetMethodLine(S:TMemoryStream;Const AMethodName:String;
|
||
Var BegLine,BegPos,EndLine,EndPos:Integer):boolean;
|
||
|
||
{ Searches stream for 'end.' occurence (or 'initialization') returns True if found
|
||
and False otherwise
|
||
Aline - line where something before 'end.' can be inserted (1 based)
|
||
AChar - char position in Aline where smth. can be inserted
|
||
}
|
||
Function FindProgramEnd(S:TMemoryStream; Var ALine,AChar:Integer):Boolean;
|
||
|
||
Procedure DelphinRegister;
|
||
|
||
|
||
function GetEventDispatcher(F:TComponent):THalComp;
|
||
procedure CallEvent(F:TComponent;Const EventName:String;ParamCount:Integer;Params:Pointer);
|
||
function IsDelphinForm(F:TComponent):boolean;
|
||
|
||
{----------------------------------------------}
|
||
Implementation
|
||
{------------------------------------------------------------------}
|
||
|
||
constructor TPosList.Create;
|
||
begin
|
||
Inherited Create(TPosListitem);
|
||
end;
|
||
|
||
{------------------------------------------------------------------}
|
||
|
||
function TPosList.AddPos(ALine,AChar:Integer):TPosListItem;
|
||
begin
|
||
Result:=TPoslistItem(Add);
|
||
Result.LinePos:=ALine;
|
||
Result.Charpos:=AChar;
|
||
end;
|
||
|
||
{-------------------------------}
|
||
|
||
Procedure outdouble(s: TStream; c: double);
|
||
Begin
|
||
s.Writebuffer(c, sizeof(double));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure outint(s: TStream; c: integer);
|
||
Begin
|
||
s.Writebuffer(c, sizeof(integer));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure outbyte(s: TStream; c: byte);
|
||
Begin
|
||
s.Writebuffer(c, sizeof(byte));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure outstring(s: TStream; Const mys: String);
|
||
Var
|
||
b: byte;
|
||
Begin
|
||
b := length(mys);
|
||
outbyte(s, b);
|
||
s.WriteBuffer(mys[1], b);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure outboolean(s: TStream; b: boolean);
|
||
Begin
|
||
s.Writebuffer(b, sizeof(boolean));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function getbyte(S: Tstream): byte;
|
||
Begin
|
||
s.ReadBuffer(Result, sizeof(byte));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function getstring(S: Tstream): String;
|
||
Var
|
||
b: byte;
|
||
t: String[255];
|
||
Begin
|
||
b := getbyte(s);
|
||
SetLength(t, b);
|
||
s.ReadBuffer(t[1], b);
|
||
Result := t;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function getboolean(S: Tstream): boolean;
|
||
Begin
|
||
s.ReadBuffer(Result, sizeof(boolean));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function getdouble(S: Tstream): double;
|
||
Begin
|
||
s.ReadBuffer(Result, sizeof(double));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function getint(S: Tstream): integer;
|
||
Begin
|
||
s.ReadBuffer(Result, sizeof(integer));
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Procedure setnotifyevent(ControlLink: TObject; Const eventlink: String; fmynotifyevent: TNotifyEvent);
|
||
Var
|
||
oldpropinfo: PPropInfo;
|
||
// tm: tmethod;
|
||
tn: tnotifyevent;
|
||
Begin
|
||
If (ControlLink = Nil) or (EventLink = '') then exit;
|
||
oldpropinfo := GetPropInfo(ControlLink.Classinfo, EventLink);
|
||
If CompareText(oldpropinfo^.proptype^.name, coNotifyEvent) = 0 then
|
||
Begin
|
||
tn := fMyNotifyEvent;
|
||
SetMethodProp(ControlLink, oldpropinfo, tmethod(tn));
|
||
End;
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Function Hex2Dec(Const S: String): Longint;
|
||
Var
|
||
HexStr: String;
|
||
Begin
|
||
If Pos('$', S) = 0
|
||
then
|
||
HexStr := '$' + S
|
||
Else
|
||
HexStr := S;
|
||
Result := StrToIntDef(HexStr, 0);
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocsetvarray(Var V, V1: Variant; a: Integer);
|
||
Begin
|
||
V[a] := V1;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocmov(Var A, B: Variant); register;
|
||
Begin
|
||
a := b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocvarraycreate(Var A: Variant; B: Integer); register;
|
||
Begin
|
||
a := VarArrayCreate([0, b], varVariant);
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocincvar(Var A: Variant); register;
|
||
Begin
|
||
a := a + 1;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocdecvar(Var A: Variant); register;
|
||
Begin
|
||
a := a - 1;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocAdd(Var A, B: Variant); register;
|
||
Begin
|
||
A := a + b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocSub(Var A, B: Variant); register;
|
||
Begin
|
||
a := a - b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocMul(Var A, B: Variant); register;
|
||
Begin
|
||
a := a * b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocDiv(Var A, B: Variant); register;
|
||
Begin
|
||
a := a div b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocMod(Var A, B: Variant); register;
|
||
Begin
|
||
a := a mod b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocSlash(Var A, B: Variant); register;
|
||
Begin
|
||
a := a / b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocShl(Var A, B: Variant); register;
|
||
Begin
|
||
a := a shl b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocShr(Var A, B: Variant); register;
|
||
Begin
|
||
a := a shr b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocNot(Var A: Variant); register;
|
||
Begin
|
||
a := not a;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocOr(Var A, B: Variant); register;
|
||
Begin
|
||
a := a or b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocXor(Var A, B: Variant); register;
|
||
Begin
|
||
a := a xor b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocAnd(Var A, B: Variant); register;
|
||
Begin
|
||
a := a and b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocGreaterEqual(Var A, B: Variant); register;
|
||
Begin
|
||
a := a >= b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocEqual(Var A, B: Variant); register;
|
||
Begin
|
||
a := (vartype(a) = vartype(b)) and (a = b);
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocLessEqual(Var A, B: Variant); register;
|
||
Begin
|
||
a := a <= b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocNotEqual(Var A, B: Variant); register;
|
||
Begin
|
||
a := (vartype(a) <> vartype(b)) or (a <> b);
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocGreater(Var A, B: Variant); register;
|
||
Begin
|
||
a := a > b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocLess(Var A, B: Variant); register;
|
||
Begin
|
||
a := a < b;
|
||
End;
|
||
|
||
{---------------------------------------------------}
|
||
|
||
Procedure _ocNeg(Var A: Variant); register;
|
||
Begin
|
||
a := -a;
|
||
End;
|
||
|
||
{----------------------------------------------}
|
||
|
||
Procedure THalCompiler.myinit;
|
||
Begin
|
||
Labels := TIdentList.Create;
|
||
variables := TIdentList.Create;
|
||
consts := TConstList.Create(tconstitem);
|
||
IDLabels := TIDLabelList.Create(tidlabelitem);
|
||
Prog := TProgCollect.Create(tprogitem);
|
||
End;
|
||
|
||
{----------------------------------------------}
|
||
|
||
Procedure THalCompiler.mydone;
|
||
Begin
|
||
Variables.Free;
|
||
Consts.Free;
|
||
Labels.Free;
|
||
IDLabels.Free;
|
||
Prog.Free;
|
||
End;
|
||
|
||
{----------------------------------------}
|
||
|
||
procedure THalCompiler.ConvertCurPos(Var ALine,AChar:Integer);
|
||
begin
|
||
ALine:=GetLineNumber;
|
||
AChar:=CurRead;
|
||
While (AChar>0) and (not (inbuf[AChar] in [#13,#10])) do dec(AChar);
|
||
AChar:=CurRead-AChar+1;
|
||
end;
|
||
|
||
{----------------------------------------}
|
||
|
||
function THalCompiler.GetLineNumber:Integer;
|
||
Var
|
||
i:integer;
|
||
begin
|
||
Result:=1;
|
||
For i := 1 to curread do
|
||
If inbuf[i] = char(idnewline)
|
||
then
|
||
inc(Result);
|
||
end;
|
||
|
||
{----------------------------------------}
|
||
|
||
Procedure THalCompiler.Error(Const s: String);
|
||
Var
|
||
linenumber: integer;
|
||
sa: String;
|
||
Begin
|
||
linenumber := GetLineNumber;
|
||
sa := Format(synt_err, [InttoStr(linenumber), #13#10 + s]);
|
||
{ If AllowPrint then
|
||
myerrorout(sa);}
|
||
Raise ECompilerError.Create(sa);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.ReadByte: byte;
|
||
Begin
|
||
inc(curread);
|
||
If curread > numread then
|
||
Begin
|
||
Result := idEndOfFile;
|
||
exit;
|
||
End;
|
||
Result := byte(Inbuf[curread]);
|
||
End;
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.NextByte: byte;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
i := curread;
|
||
Result := ReadByte;
|
||
curread := i;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.BackBytes(a: integer);
|
||
Begin
|
||
If curread - a >= 0 then dec(curread, a);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.ReadToken: TToken;
|
||
Var
|
||
b, begst, a: byte;
|
||
s: String;
|
||
i: integer;
|
||
|
||
Label
|
||
label2, label1, l9, l8, l10, l11;
|
||
|
||
Begin
|
||
Application.ProcessMessages;
|
||
label1:
|
||
a := ReadByte;
|
||
If char(a) in BlackSpaces then Goto label1;
|
||
{--}
|
||
If a = idslash then
|
||
Begin
|
||
If ReadByte <> idslash then
|
||
Begin
|
||
backbytes(1);
|
||
a := idslash;
|
||
Goto l9;
|
||
End;
|
||
l8: a := readbyte;
|
||
If a = idEndOFFile then
|
||
Goto l9;
|
||
If not (a < 32) then
|
||
Goto l8;
|
||
Goto label1;
|
||
End;
|
||
l9:
|
||
|
||
{-----}
|
||
If a = idminus then
|
||
Begin
|
||
If ReadByte <> idminus then
|
||
Begin
|
||
backbytes(1);
|
||
a := idminus;
|
||
Goto l11;
|
||
End;
|
||
s := '';
|
||
l10: a := readbyte;
|
||
If a = idEndOFFile then
|
||
Goto l11;
|
||
If not (a < 32) then
|
||
Begin
|
||
s := s + Char(a);
|
||
Goto l10;
|
||
End {else
|
||
If (length(S) > 0) and (nextstate = false) and (AllowPrint)
|
||
then
|
||
MyStdOut(s)};
|
||
Goto label1;
|
||
End;
|
||
l11:
|
||
{-----}
|
||
If ((a = idopenbracket) or (a = idslash)) and (nextbyte = idstar) then
|
||
Begin
|
||
b := a;
|
||
Repeat
|
||
a := ReadByte;
|
||
Case a of
|
||
idstar:
|
||
If nextbyte = b then
|
||
Begin
|
||
readbyte;
|
||
Goto label1;
|
||
End;
|
||
idEndOfFile:
|
||
Error(eofincom_ERR);
|
||
End;
|
||
Until false;
|
||
End;
|
||
{----}
|
||
If char(a) in WhiteSpaces then
|
||
Begin
|
||
DolEnabled := (a = Integer('$'));
|
||
Result := SetToken(a, 0);
|
||
exit;
|
||
End;
|
||
Case a of
|
||
idOpenComment:
|
||
Begin
|
||
Repeat
|
||
a := ReadByte;
|
||
Case a of
|
||
idCloseComment: Goto label1;
|
||
idEndOfFile: Error(eofincom_ERR);
|
||
End;
|
||
Until false;
|
||
End;
|
||
IdStringChar, Id2StringChar:
|
||
Begin
|
||
s := ''; begst := a;
|
||
Repeat
|
||
a := ReadByte;
|
||
If a = begst then
|
||
Begin
|
||
Result := SetToken(idStringConst, s);
|
||
exit;
|
||
End
|
||
Else
|
||
If a = idEndOfFile
|
||
then
|
||
Error(eofinstring_ERR)
|
||
Else
|
||
s := s + char(a);
|
||
Until false;
|
||
End;
|
||
idEndOFFile:
|
||
Begin
|
||
Result := SetToken(idEndOFFile, 0);
|
||
exit;
|
||
End;
|
||
End;
|
||
S := '';
|
||
label2:
|
||
S := S + char(a);
|
||
a := ReadByte;
|
||
If not (char(a) in StopChars) then
|
||
Goto label2;
|
||
BackBytes(1);
|
||
s := AnsiUpperCase(s);
|
||
If s[1] in FirstIdentChar then
|
||
Begin
|
||
If length(s) > 1 then
|
||
For i := 2 to length(s) do
|
||
If not (s[i] in identbackchars) then Error(Format(bad_idName, [s]));
|
||
If ResWords.IDByName(s, i)
|
||
then
|
||
Result := SetToken(i, s)
|
||
Else
|
||
If ResConsts.Find(s, i)
|
||
then
|
||
Result := SetToken(idresconst, i)
|
||
else
|
||
Result := SetToken(idIdentifier, s);
|
||
End else
|
||
Begin
|
||
If s[2] = 'X' then
|
||
Begin
|
||
Result := SetToken(idHexConst, copy(s, 3, length(s)));
|
||
End else
|
||
Begin
|
||
For i := 1 to length(s) do
|
||
If not ((s[i] in Digit) or ((DolEnabled) and (S[i] in HExDIgit)))
|
||
Then Error(Format(bad_id, [s]));
|
||
Result := SetToken(idNumberConst, s);
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.NextToken: TToken;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
nextstate := true;
|
||
i := curread;
|
||
Result := ReadToken;
|
||
curread := i;
|
||
nextstate := false;
|
||
End;
|
||
|
||
{----------------------------------------}
|
||
|
||
Procedure THalCompiler.putcode(aid, a, b: integer);
|
||
Begin
|
||
prog.putop(aid, a, b);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getdelimeter;
|
||
Var
|
||
Token: TToken;
|
||
Begin Token := ReadToken;
|
||
If (Token.id <> iddelimeter)
|
||
then
|
||
Error(delimeter_expected);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.iexpression: integer;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := isimpleexpression;
|
||
Case nexttoken.id of
|
||
{ = }
|
||
idequal:
|
||
Begin
|
||
token := readtoken;
|
||
i := isimpleexpression;
|
||
putcode(ocequal, Result, i);
|
||
End;
|
||
{ > >= }
|
||
idgreater:
|
||
Begin
|
||
token := readtoken;
|
||
If nexttoken.id = idequal then
|
||
Begin
|
||
token := readtoken;
|
||
i := isimpleexpression;
|
||
putcode(ocgreaterequal, Result, i);
|
||
End else
|
||
Begin
|
||
i := isimpleexpression;
|
||
putcode(ocgreater, Result, i);
|
||
End;
|
||
End;
|
||
{ < <= <> }
|
||
idless:
|
||
Begin
|
||
token := readtoken;
|
||
Case nexttoken.id of
|
||
idequal:
|
||
Begin
|
||
token := readtoken;
|
||
i := isimpleexpression;
|
||
putcode(oclessequal, Result, i);
|
||
End;
|
||
idgreater:
|
||
Begin
|
||
token := readtoken;
|
||
i := isimpleexpression;
|
||
putcode(ocnotequal, Result, i);
|
||
End;
|
||
Else
|
||
Begin
|
||
i := isimpleexpression;
|
||
putcode(ocless, Result, i);
|
||
End;
|
||
End;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.isimpleexpression: integer;
|
||
Label
|
||
l1;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := iterm;
|
||
l1:
|
||
Case nexttoken.id of
|
||
idPlus:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := iterm;
|
||
putcode(ocadd, Result, i);
|
||
Goto l1;
|
||
End;
|
||
idMinus:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := iterm;
|
||
putcode(ocsub, Result, i);
|
||
Goto l1;
|
||
End;
|
||
id_Or:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := iterm;
|
||
putcode(ocor, Result, i);
|
||
Goto l1;
|
||
End;
|
||
id_Xor:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := iterm;
|
||
putcode(ocxor, Result, i);
|
||
Goto l1;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.iterm: integer;
|
||
Var
|
||
i: integer;
|
||
Label
|
||
l1;
|
||
Begin
|
||
Result := ifactor;
|
||
l1:
|
||
Case nexttoken.id of
|
||
id_shl:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocshl, Result, i);
|
||
Goto l1;
|
||
End;
|
||
id_shr:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocshr, Result, i);
|
||
Goto l1;
|
||
End;
|
||
id_And:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocand, Result, i);
|
||
Goto l1;
|
||
End;
|
||
idStar:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocmul, Result, i);
|
||
Goto l1;
|
||
End;
|
||
idSlash:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocslash, Result, i);
|
||
Goto l1;
|
||
End;
|
||
id_div:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocdiv, Result, i);
|
||
Goto l1;
|
||
End;
|
||
id_mod:
|
||
Begin
|
||
Token := ReadToken;
|
||
i := ifactor;
|
||
putcode(ocmod, Result, i);
|
||
Goto l1;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getopenbracket;
|
||
Begin
|
||
token := ReadToken;
|
||
If (token.id <> idOpenBracket) and (token.id <> idsqOpenBracket)
|
||
Then Error(need_opbr);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getclosebracket;
|
||
Begin
|
||
token := ReadToken;
|
||
If (token.id <> idcloseBracket) and (token.id <> idsqcloseBracket)
|
||
Then Error(need_clbr);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getcoma;
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> idcomma then Error(comma_expected);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.GetOpenArray(NeedSq: boolean): Integer;
|
||
Var
|
||
ints: Array[0..200] of integer;
|
||
i, maxints: integer;
|
||
ospoint: integer;
|
||
|
||
Begin
|
||
If (NeedSq) or (nexttoken.id = idsqopenbracket) then
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> idsqopenbracket then Error(Format(opsq_exp, [token.data]));
|
||
End;
|
||
{----}
|
||
maxints := 0;
|
||
ospoint := spoint;
|
||
inc(spoint);
|
||
While (nexttoken.id <> idsqclosebracket) and
|
||
(nexttoken.id <> idclosebracket) do
|
||
Begin
|
||
If maxints > 0 then getcoma;
|
||
ints[maxints] := iexpression;
|
||
inc(maxints);
|
||
End;
|
||
putcode(ocvarraycreate, ospoint, maxints);
|
||
|
||
putcode(ocloadconst, spoint, Consts.newitem(maxints));
|
||
|
||
putcode(ocsetvarray, 0, spoint);
|
||
inc(spoint);
|
||
|
||
putcode(0, ospoint, 0);
|
||
For i := 0 to maxints - 1 do
|
||
Begin
|
||
putcode(ocsetvarray, i + 1, ints[i]);
|
||
putcode(0, ospoint, 0);
|
||
End;
|
||
Result := ospoint;
|
||
{----}
|
||
If (NeedSq) or (nexttoken.id = idsqclosebracket) then
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> idsqclosebracket then
|
||
Error(Format(clsq_exp, [token.data]));
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getuserfunction(Const name: String; scope, fik: boolean);
|
||
Var
|
||
oldstack, i, index: integer;
|
||
f: TFunListItem;
|
||
ia: Array[0..maxparams] of integer;
|
||
sname, sname1: String;
|
||
ident: tidentlistitem;
|
||
olastobj: TObject;
|
||
onotfromobj: boolean;
|
||
Label lt, lr, lr1;
|
||
|
||
Begin
|
||
|
||
olastobj := lastobject; onotfromobj := notfromobj;
|
||
If varbyname(name, ident) then
|
||
Begin
|
||
i := getinternalfun(name, ident);
|
||
putcode(ocmov, spoint, i);
|
||
exit;
|
||
End;
|
||
|
||
// If (Not assigned(Funs)) then Error(Format(unkn_id, [name]));
|
||
|
||
|
||
If Fik then
|
||
Begin
|
||
sname := name + '_VET';
|
||
While (Funs.Find(sname, index) = false) Do
|
||
Begin
|
||
i := pos('.', sname);
|
||
If i = 0 then Goto lr1;
|
||
sname1 := GetPearent(copy(sname, 1, i - 1));
|
||
If sname1 = '' then Goto lr1;
|
||
delete(sname, 1, i - 1);
|
||
sname := sname1 + sname;
|
||
End;
|
||
Goto lr;
|
||
End;
|
||
lr1: sname := name;
|
||
While (Funs.Find(sname, index) = false) Do
|
||
Begin
|
||
i := pos('.', sname);
|
||
If i = 0 then Error(Format(unkn_id, [name]));
|
||
sname1 := GetPearent(copy(sname, 1, i - 1));
|
||
If sname1 = '' then Error(Format(unkn_id, [name]));
|
||
delete(sname, 1, i - 1);
|
||
sname := sname1 + sname;
|
||
End;
|
||
lr:
|
||
f := TFunListItem(Funs.Objects[index]);
|
||
If f.parcount > 0 then getopenbracket;
|
||
If (f.fun <> scope) and (f.fun) then
|
||
Begin
|
||
If scope then Error(in_funuse) else Error(in_procuse);
|
||
End;
|
||
If f.parcount > 0 then
|
||
Begin
|
||
oldstack := spoint;
|
||
For i := 0 to F.Parcount - 1 do
|
||
Begin
|
||
Case f.Params[i] of
|
||
0: ia[i] := iexpression;
|
||
1: ia[i] := getvar;
|
||
3: ia[i] := getopenarray(F.ParCount <> 1);
|
||
4: Begin
|
||
getclosebracket;
|
||
token := readtoken;
|
||
If token.id <> id2points then Error(p2_exp);
|
||
token := readtoken;
|
||
If token.id <> idequal then Error(eq_exp);
|
||
ia[i] := iexpression;
|
||
Goto lt;
|
||
End;
|
||
Else Error(unsup_partype);
|
||
End;
|
||
If (i < f.parcount - 1) and (f.params[i + 1] <> 4) then getcoma;
|
||
End;
|
||
lt:
|
||
spoint := oldstack;
|
||
End;
|
||
If (olastobj <> Nil) or (onotfromobj) then
|
||
Begin
|
||
If oNotFromObj
|
||
then
|
||
putcode(ocselffromvar, Integer(olastobj), 0)
|
||
else
|
||
putcode(ocsetself, integer(olastobj), 0);
|
||
End;
|
||
putcode(ocextfun, spoint, index);
|
||
If f.parcount > 0 then
|
||
Begin
|
||
i := 0;
|
||
While i <= f.parcount - 1 do
|
||
Begin
|
||
putcode(ia[i], ia[i + 1], ia[i + 2]);
|
||
inc(i, 3);
|
||
End;
|
||
End;
|
||
If (f.parcount > 0) and (F.Params[f.parcount - 1] <> 4) then
|
||
getclosebracket;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.AddVars(Const Aname: String; ID: Integer): Integer;
|
||
Begin
|
||
Result := Variables.additem(IdentPrefix + Aname, ID);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.VarIDByName(Const AName: String; Var Id: Integer): boolean;
|
||
Var
|
||
S: String;
|
||
i: integer;
|
||
Label l1;
|
||
Begin
|
||
S := IdentPrefix;
|
||
l1:
|
||
Result := Variables.Find(s + Aname, id);
|
||
If (result) or (s = '') then
|
||
exit;
|
||
i := length(s);
|
||
If S[i] = '.' then dec(i);
|
||
While (S[i] <> '.') and (i > 0) do
|
||
dec(i);
|
||
setlength(s, i);
|
||
Goto l1;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.VarByName(Const AName: String; Var Ident: TIdentListItem): boolean;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := VarIDByName(aname, i);
|
||
If result then ident := (Variables.Objects[i] as tidentlistitem)
|
||
Else ident := Nil;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.findobject(Var s: String);
|
||
Var
|
||
tob: tobjitem;
|
||
ident: tIdentListItem;
|
||
Begin
|
||
notfromobj := false;
|
||
If mobjects.objbyname(s, tob) then
|
||
Begin
|
||
lastobject := tob.tobj; s := tob.objtype;
|
||
End
|
||
Else
|
||
If (varbyname(s, ident)) and (GetClass(ident.vtype)<>nil)
|
||
Then
|
||
Begin
|
||
notfromobj := true; lastobject := TObject(ident.id);
|
||
s := ident.vtype;
|
||
End
|
||
Else lastobject := Nil;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.getinternalfun(
|
||
Const sname: String; ident: tidentlistitem): integer;
|
||
Var
|
||
i: integer;
|
||
pind: Array[0..100] of integer;
|
||
im: tidentlistitem;
|
||
temp: String;
|
||
Begin
|
||
Result:=0;
|
||
With ident do
|
||
Begin
|
||
If parcount > 0 then
|
||
Begin
|
||
getopenbracket;
|
||
For i := 0 to parcount - 1 do
|
||
Begin
|
||
If params[i] = 0 then
|
||
pind[i] := iexpression
|
||
Else
|
||
pind[i] := getvar;
|
||
|
||
temp := sname + '.' + paramnames.strings[i];
|
||
If varbyname(temp, im) = false then
|
||
Error(Format(proc_notfound, [temp]));
|
||
|
||
putcode(ocmov, im.id, pind[i]);
|
||
If i < parcount - 1 then
|
||
getcoma;
|
||
End;
|
||
getclosebracket;
|
||
End;
|
||
|
||
If varbyname(sname + coprocresult, im)
|
||
then
|
||
Result := im.id
|
||
Else
|
||
Error(Format(no_resvar, [sname]));
|
||
If varbyname(sname, im)
|
||
then
|
||
putcode(occall, im.id, 0)
|
||
Else
|
||
error(Format(proc_notfound, [sname]));
|
||
|
||
For i := 0 to parcount - 1 do If params[i] <> 0 then
|
||
Begin
|
||
varbyname(sname + '.' + paramnames.strings[i], im);
|
||
putcode(ocmov, pind[i], im.id);
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.ifactor: integer;
|
||
Var
|
||
v, code, l: integer;
|
||
s: String;
|
||
funid, varid: integer;
|
||
ident: TIdentListItem;
|
||
mextended: extended;
|
||
tob: tobjitem;
|
||
Label
|
||
label1, lab1, lop;
|
||
Begin
|
||
Result:=0;
|
||
Token := ReadToken; l := token.id;
|
||
Case l of
|
||
idsqopenbracket:
|
||
Begin
|
||
Result := GetOpenArray(false);
|
||
token := readtoken;
|
||
If token.id <> idsqclosebracket then
|
||
Error(Format(clsq_exp, [token.data]));
|
||
End;
|
||
ididentifier:
|
||
Begin
|
||
s := token.data;
|
||
If nexttoken.id = idpoint then
|
||
Begin
|
||
findobject(s);
|
||
End;
|
||
While nexttoken.id = idpoint do
|
||
Begin
|
||
token := readtoken;
|
||
token := readtoken;
|
||
If token.id <> ididentifier then Error(id_expected);
|
||
s := s + '.' + token.data;
|
||
End;
|
||
If (nexttoken.id = idopenbracket) or (nexttoken.id = idsqopenbracket) Then
|
||
Begin
|
||
lab1:
|
||
getuserfunction(s, false, false);
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End else
|
||
Begin
|
||
If Mobjects.ObjbyName(s, tob) then
|
||
Begin
|
||
putcode(ocloadconst, spoint, Consts.newitem(Integer(tob.tobj)));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End else
|
||
If DynaVars.GetDynaObject(s, HalOwner, varid, funid) then
|
||
Begin
|
||
putcode(ocloadextvar, varid, funid);
|
||
putcode(ocbackcode, spoint, 0);
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End else
|
||
Begin
|
||
If varbyname(s, ident) then
|
||
Begin
|
||
Case ident.identtype of
|
||
tivariable:
|
||
Begin
|
||
putcode(ocmov, spoint, ident.id);
|
||
Result := spoint;
|
||
inc(Spoint);
|
||
End;
|
||
Else
|
||
Error(in_procuse);
|
||
End;
|
||
End
|
||
else Goto lab1;
|
||
End;
|
||
End;
|
||
End;
|
||
idresconst:
|
||
Begin
|
||
putcode(ocloadconst, spoint, Consts.newitem(
|
||
TResConstListItem(ResConsts.Objects[token.data]).Value));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
id_false:
|
||
Begin
|
||
putcode(ocloadconst, spoint, Consts.newitem(FALSE));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
id_true:
|
||
Begin
|
||
putcode(ocloadconst, spoint, Consts.newitem(TRUE));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
id_nil:
|
||
Begin
|
||
putcode(ocloadconst, spoint, Consts.newitem(0));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
Integer('$'):
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> idnumberconst
|
||
then
|
||
Error(bad_hex);
|
||
lop:
|
||
v := Hex2Dec(token.data);
|
||
putcode(ocloadconst, spoint, Consts.newitem(v));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
idhexconst:
|
||
Begin
|
||
Goto lop;
|
||
End;
|
||
idnumberconst:
|
||
Begin
|
||
If nexttoken.id = idpoint then
|
||
Begin
|
||
s := token.data;
|
||
token := readtoken;
|
||
token := readtoken;
|
||
If token.id <> idnumberconst then
|
||
Error(bad_realconst);
|
||
s := s + '.' + token.data;
|
||
val(s, mextended, code);
|
||
putcode(ocloadconst, spoint, Consts.newitem(mextended));
|
||
End else
|
||
Begin
|
||
val(token.data, v, code);
|
||
putcode(ocloadconst, spoint, Consts.newitem(v));
|
||
End;
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
idnotequal:
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> idnumberconst then
|
||
Error(bad_charconst);
|
||
val(token.data, v, code);
|
||
putcode(ocloadconst, spoint, Consts.newitem(Char(v)));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
idstringconst:
|
||
Begin
|
||
S := token.data;
|
||
label1:
|
||
Case nexttoken.id of
|
||
idnotequal:
|
||
Begin
|
||
token := readtoken;
|
||
token := readtoken;
|
||
If token.id <> idnumberconst then
|
||
Error(bad_charconst);
|
||
val(token.data, v, code);
|
||
s := s + char(v);
|
||
Goto label1;
|
||
End;
|
||
idstringconst:
|
||
Begin
|
||
token := readtoken; S := S + token.data;
|
||
Goto label1;
|
||
End;
|
||
End;
|
||
putcode(ocloadconst, spoint, Consts.newitem(s));
|
||
Result := spoint;
|
||
inc(spoint);
|
||
End;
|
||
idopenbracket:
|
||
Begin
|
||
Result := iexpression;
|
||
getclosebracket;
|
||
End;
|
||
idplus:
|
||
Begin
|
||
Result := ifactor;
|
||
End;
|
||
idminus:
|
||
Begin
|
||
Result := ifactor;
|
||
putcode(ocneg, Result, 0);
|
||
End;
|
||
id_not:
|
||
Begin
|
||
Result := ifactor;
|
||
putcode(ocnot, Result, 0);
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.myexpress: integer;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
i := spoint;
|
||
Result := iexpression;
|
||
spoint := i;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.equaldispath(Const VarName: String);
|
||
Var
|
||
i, j: integer;
|
||
index: integer;
|
||
vname: String;
|
||
|
||
{-----------------------------}
|
||
|
||
Function getobjfuns(Var idx: integer): boolean;
|
||
Var
|
||
i: integer;
|
||
sname1: String;
|
||
|
||
Begin
|
||
Result := false;
|
||
While Funs.Find(vname + '_SET', idx) = false do
|
||
Begin
|
||
i := pos('.', vname); If i = 0 then exit;
|
||
sname1 := GetPearent(copy(vname, 1, i - 1)); If sname1 = '' then exit;
|
||
delete(vname, 1, i - 1);
|
||
vname := sname1 + vname;
|
||
End;
|
||
Result := True;
|
||
End;
|
||
Function getDefObjFuns(Var idx: integer): boolean;
|
||
Var
|
||
i: integer;
|
||
sname1: String;
|
||
Begin
|
||
Result := false;
|
||
result := Funs.Find(vname + '_SET', idx);
|
||
End;
|
||
{-----------------------------}
|
||
Var
|
||
varid, funid: integer;
|
||
Ident: TIdentListItem;
|
||
olastobj: tobject;
|
||
onotfromobj: boolean;
|
||
|
||
Begin
|
||
vname := varname;
|
||
If (varbyname(vname, ident)) and (ident.identtype = 0) then
|
||
Begin
|
||
i := myexpress;
|
||
j := ident.id;
|
||
putcode(ocmov, j, i);
|
||
End
|
||
Else
|
||
If DynaVars.GetDynaObject(vname, HalOwner, varid, funid) then
|
||
Begin
|
||
i := myexpress;
|
||
putcode(ocstoreextvar, varid, funid);
|
||
putcode(ocbackcode, i, 0);
|
||
End
|
||
Else
|
||
If (assigned(Funs)) and (pos('.', vname) <> 0) and (getobjfuns(index)) then
|
||
Begin
|
||
olastobj := lastobject; onotfromobj := notfromobj;
|
||
i := myexpress;
|
||
If (olastobj <> Nil) or (onotfromobj) then
|
||
Begin
|
||
If oNotFromObj then putcode(ocselffromvar, Integer(olastobj), 0) else
|
||
putcode(ocsetself, integer(olastobj), 0);
|
||
End;
|
||
|
||
putcode(ocextfun, spoint, index);
|
||
putcode(i, 0, 0);
|
||
End
|
||
Else
|
||
If (assigned(Funs)) and (pos('.', vname) = 0) and (getdefobjfuns(index)) then
|
||
begin
|
||
i := myexpress;
|
||
putcode(ocextfun, spoint, index);
|
||
putcode(i, 0, 0);
|
||
End
|
||
else
|
||
Error(Format(var_NotDef, [varname]));
|
||
End;
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.labeldispatch(Const labelname: String);
|
||
Var
|
||
pl, i: integer;
|
||
Begin
|
||
If Labels.IDByName(labelname, i) = false then
|
||
Error(Format(lab_notdef, [labelname]));
|
||
|
||
pl := prog.count;
|
||
IDLabels.setplace(i, pl);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getprogramname;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
i := nexttoken.id;
|
||
If (i = id_Program) or (i = id_unit) then
|
||
Begin
|
||
Token := ReadToken;
|
||
Token := ReadToken;
|
||
If Token.Id <> idIdentifier then
|
||
Error(progname_exp);
|
||
getdelimeter;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getidentifier;
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> ididentifier then Error(id_expected);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.getprocdef(askip: boolean): Integer;
|
||
Var
|
||
ProcName: String;
|
||
k, AParamCount: Integer;
|
||
AParams: tbytearray;
|
||
MAdd: Boolean;
|
||
ident: integer;
|
||
EResult: TIdentListItem;
|
||
|
||
{--}
|
||
|
||
Procedure getprocparams;
|
||
Label
|
||
l1, l2;
|
||
Var
|
||
k, curtp, st: integer;
|
||
il: Array[1..100] of integer;
|
||
sname: String;
|
||
Begin
|
||
l1: curtp := 0; st := 0;
|
||
Case nexttoken.id of
|
||
ididentifier:
|
||
Begin
|
||
l2:
|
||
getidentifier;
|
||
If madd = false then
|
||
Begin
|
||
inc(st);
|
||
sname := ProcName + '.' + Token.Data;
|
||
il[st] := AddVars(sname, spoint);
|
||
EResult.ParamNames.Add(Token.Data);
|
||
inc(spoint);
|
||
AParams[AParamCount] := curtp;
|
||
inc(AParamCount);
|
||
End;
|
||
Case nexttoken.id of
|
||
idcomma:
|
||
Begin
|
||
token := readtoken;
|
||
Goto l2;
|
||
End;
|
||
id2points:
|
||
Begin
|
||
token := readtoken;
|
||
token := Readtoken;
|
||
If madd = false then
|
||
For k := 1 to st do
|
||
Tidentlistitem(Variables.Objects[il[k]]).VType := token.data;
|
||
If nexttoken.id <> idclosebracket then
|
||
getdelimeter;
|
||
End;
|
||
Else
|
||
error(meth_decerr);
|
||
End;
|
||
End;
|
||
idclosebracket:
|
||
exit;
|
||
id_var:
|
||
Begin
|
||
token := readtoken;
|
||
curtp := 1;
|
||
Goto l2;
|
||
End;
|
||
id_const:
|
||
Begin
|
||
token := readtoken;
|
||
Goto l2;
|
||
End;
|
||
Else
|
||
Error(bad_methparam);
|
||
End;
|
||
Goto l1;
|
||
End;
|
||
{--}
|
||
Begin
|
||
|
||
getidentifier; ProcName := token.data;
|
||
While nexttoken.id = idpoint do
|
||
Begin
|
||
token := readtoken;
|
||
getidentifier;
|
||
ProcName := ProcName + '.' + token.data;
|
||
End;
|
||
Madd := varidbyname(ProcName, ident);
|
||
AParamCount := 0;
|
||
If madd = false then
|
||
Begin
|
||
k := IDLabels.newitem;
|
||
Result := AddVars(ProcName, k);
|
||
EResult := tidentlistitem(Variables.Objects[Result]);
|
||
End;
|
||
If nexttoken.id = idopenbracket then
|
||
Begin
|
||
getopenbracket;
|
||
getprocparams;
|
||
getclosebracket;
|
||
End;
|
||
If Madd = false then
|
||
Begin
|
||
With EResult do
|
||
Begin
|
||
Params := AParams;
|
||
ParCount := AParamCount;
|
||
IdentType := 1;
|
||
End;
|
||
If nexttoken.id = id2points then
|
||
Begin
|
||
Token := ReadToken;
|
||
getvartype;
|
||
EResult.VType := token.data;
|
||
End;
|
||
AddVars(ProcName + coProcResult, spoint);
|
||
inc(spoint);
|
||
End;
|
||
varidbyname(ProcName, Result);
|
||
getdelimeter;
|
||
getafterproc;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getafterproc;
|
||
Var
|
||
i: integer;
|
||
s: boolean;
|
||
Label
|
||
l1;
|
||
Begin
|
||
s := true;
|
||
l1:
|
||
i := Nexttoken.id;
|
||
If (i = id_virtual) or (i = id_override) or (i = id_dynamic) or (i = id_abstract) or
|
||
(i=id_stdcall)
|
||
Then
|
||
Begin
|
||
Token := Readtoken;
|
||
getdelimeter;
|
||
If s then
|
||
Begin
|
||
s := false;
|
||
Goto l1;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getclassdefblock(b: boolean);
|
||
Label
|
||
l1;
|
||
Begin
|
||
l1:
|
||
Case nexttoken.id of
|
||
ididentifier:
|
||
Begin
|
||
getmyvariables(b);
|
||
End;
|
||
id_property:
|
||
Begin
|
||
Error(no_props);
|
||
End;
|
||
id_procedure, id_function:
|
||
Begin
|
||
Token := ReadToken;
|
||
getprocdef(false);
|
||
End;
|
||
Else exit;
|
||
End;
|
||
Goto l1;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getclassdef(Const cname: String);
|
||
Var
|
||
ParName: String;
|
||
Label
|
||
l1;
|
||
Begin
|
||
ParName := '';
|
||
IdentPrefix := cname + '.';
|
||
If NextToken.ID = idopenbracket then
|
||
Begin
|
||
Token := ReadToken;
|
||
Token := ReadToken;
|
||
If Token.ID <> ididentifier then
|
||
Error(need_par);
|
||
ParName := Token.Data;
|
||
Token := ReadToken;
|
||
If Token.ID <> idclosebracket then
|
||
Error(clbr_exp);
|
||
End;
|
||
FLastClassType := ParName;
|
||
l1:
|
||
Case NextToken.id of
|
||
iddelimeter:
|
||
Begin
|
||
Token := Readtoken;
|
||
IdentPrefix := '';
|
||
exit;
|
||
End;
|
||
id_private, id_public, id_published, id_protected:
|
||
Begin
|
||
Token := ReadToken;
|
||
getclassdefblock(true);
|
||
End;
|
||
id_end:
|
||
Begin
|
||
Token := ReadToken;
|
||
getdelimeter;
|
||
IdentPrefix := '';
|
||
exit;
|
||
End;
|
||
Else
|
||
getclassdefblock(true);
|
||
End;
|
||
Goto l1;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.gettypeidentifier;
|
||
Var
|
||
s: String;
|
||
Begin
|
||
Token := ReadToken;
|
||
S := Token.Data;
|
||
Token := ReadToken;
|
||
If Token.ID <> idequal then
|
||
Error(Format(err_decl, [s]));
|
||
Token := ReadToken;
|
||
Case Token.ID of
|
||
id_record, id_class: getclassdef(s);
|
||
Else
|
||
Error(only_class);
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getvartype;
|
||
Begin
|
||
Token := ReadToken;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getmyvariables(b: boolean);
|
||
Label
|
||
l6, l5;
|
||
Var
|
||
vcurent, ad, mid: integer;
|
||
vc: Array[0..200] of tidentlistitem;
|
||
s: String;
|
||
ident: tidentlistitem;
|
||
tob: tobjitem;
|
||
ob: boolean;
|
||
Begin
|
||
ob := b;
|
||
l6:
|
||
vcurent := 0;
|
||
l5: b := ob;
|
||
Token := ReadToken;
|
||
If Token.ID <> idIdentifier then
|
||
Error(varname_exp);
|
||
s := Token.Data;
|
||
If varbyname(s, ident) then
|
||
Error(Format(var_already, [s]));
|
||
If b then
|
||
Begin
|
||
If mobjects.objbyname(s, tob) then b := false;
|
||
If B then
|
||
Begin
|
||
mid := AddVars(s, spoint);
|
||
vc[vcurent] := tidentlistitem(Variables.Objects[mid]);
|
||
inc(vcurent);
|
||
inc(spoint);
|
||
End;
|
||
End;
|
||
Token := ReadToken;
|
||
Case Token.ID of
|
||
idcomma: Goto l5;
|
||
id2points:
|
||
Begin
|
||
getvartype;
|
||
If b then
|
||
For ad := 0 to vcurent - 1 do vc[ad].VType := token.data;
|
||
getdelimeter;
|
||
If (NextToken.ID <= idReservedEnd) and
|
||
(NextToken.ID >= idReservedBase)
|
||
Then exit
|
||
Else Goto l6;
|
||
End;
|
||
Else Error(bad_varblock);
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getprocbody(i: integer);
|
||
Var
|
||
oidentpref: String;
|
||
l1: integer;
|
||
Begin
|
||
If nexttoken.id = id_forward then
|
||
Begin
|
||
token := readtoken;
|
||
getdelimeter;
|
||
exit;
|
||
End;
|
||
oidentpref := identprefix;
|
||
identprefix := variables.strings[i] + '.';
|
||
getdeclarations;
|
||
l1 := (variables.objects[i] as tidentlistitem).id;
|
||
IDLabels.setplace(l1, prog.count);
|
||
IDLabels.SetReference(l1);
|
||
getoperatorblock;
|
||
getdelimeter;
|
||
identprefix := oidentpref;
|
||
putcode(ocreturn, 0, 0);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getdeclarations;
|
||
Label l8, l3, l6;
|
||
Var
|
||
s: String;
|
||
i, k: integer;
|
||
Begin
|
||
l8:
|
||
Case nexttoken.id of
|
||
id_uses:
|
||
Begin
|
||
Token := ReadToken;
|
||
l6:
|
||
getidentifier;
|
||
Token := ReadToken;
|
||
If token.id = idcomma
|
||
then
|
||
Goto l6
|
||
else
|
||
Goto l8;
|
||
End;
|
||
id_interface, id_implement:
|
||
Begin
|
||
Token := ReadToken;
|
||
Goto l8;
|
||
End;
|
||
id_begin, id_end:
|
||
Begin end;
|
||
id_procedure, id_function:
|
||
Begin
|
||
Token := ReadToken;
|
||
getprocbody(getprocdef(true));
|
||
Goto l8;
|
||
End;
|
||
id_label:
|
||
Begin
|
||
Token := ReadToken;
|
||
l3:
|
||
Token := ReadToken;
|
||
If Token.ID <> idIdentifier then
|
||
Error(labname_exp);
|
||
S := Token.Data;
|
||
If labels.idbyname(s, i) then
|
||
Error(Format(label_already, [s]));
|
||
k := IDLabels.newitem;
|
||
labels.additem(s, k);
|
||
Token := ReadToken;
|
||
Case Token.Id of
|
||
idDelimeter: Goto l8;
|
||
idComma: Goto l3;
|
||
Else
|
||
Error(delim_or_coma);
|
||
End;
|
||
End;
|
||
id_type:
|
||
Begin
|
||
Token := ReadToken;
|
||
While NextToken.ID = ididentifier do
|
||
gettypeidentifier;
|
||
Goto l8;
|
||
End;
|
||
id_var:
|
||
Begin
|
||
token := readtoken;
|
||
getmyvariables(true);
|
||
Goto l8;
|
||
End;
|
||
Else
|
||
Error(err_declpart);
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getoperatorcoma;
|
||
Begin
|
||
getoperator;
|
||
If (nexttoken.id = iddelimeter) or
|
||
((token.id <> id2points) and (nexttoken.id <> id_end) and (nexttoken.id <> id_until))
|
||
Then getdelimeter;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getwhileoperator;
|
||
Var
|
||
a, i, l2, l1: integer;
|
||
Begin
|
||
Token := ReadToken;
|
||
l1 := IDLabels.newitem;
|
||
IDLabels.SetReference(l1);
|
||
IDLabels.setplace(l1, prog.count);
|
||
l2 := IDLabels.newitem;
|
||
IDLabels.SetReference(l2);
|
||
i := spoint;
|
||
a := iexpression;
|
||
spoint := i;
|
||
putcode(ocif, a, l2);
|
||
token := readtoken;
|
||
If Token.id <> id_do then
|
||
Error(do_exp);
|
||
getoperator;
|
||
putcode(ocgoto, l1, 0);
|
||
IDLabels.setplace(l2, prog.count);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getrepeatoperator;
|
||
Var
|
||
i, a, l1: integer;
|
||
Begin
|
||
token := readtoken;
|
||
l1 := IDLabels.newitem;
|
||
IDLabels.SetReference(l1);
|
||
IDLabels.setplace(l1, prog.count);
|
||
While (nexttoken.id <> id_until) and (nexttoken.id <> idendoffile) do
|
||
getoperatorcoma;
|
||
token := readtoken;
|
||
If token.id <> id_until then
|
||
Error(until_exp);
|
||
i := spoint;
|
||
a := iexpression;
|
||
spoint := i;
|
||
putcode(ocif, a, l1);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getforoperator;
|
||
Var
|
||
mi, a, l, l2, l1, vid, i: integer;
|
||
ident: tidentlistitem;
|
||
Begin
|
||
token := ReadToken;
|
||
token := readtoken;
|
||
If token.id <> ididentifier then
|
||
Error(varname_exp);
|
||
If varbyname(token.data, ident) = false then
|
||
Error(Format(var_NotDef, [token.data]));
|
||
vid := ident.id;
|
||
token := readtoken;
|
||
If token.id <> id2points then
|
||
Error(p2_exp);
|
||
token := readtoken;
|
||
If token.id <> idequal then
|
||
Error(eq_exp);
|
||
i := myexpress;
|
||
putcode(ocmov, vid, i);
|
||
token := readtoken;
|
||
l1 := IDLabels.newitem;
|
||
IDLabels.SetReference(l1);
|
||
l2 := IDLabels.newitem;
|
||
IDLabels.SetReference(l2);
|
||
IDLabels.setplace(l1, prog.count);
|
||
l := token.id;
|
||
mi := spoint;
|
||
a := iexpression;
|
||
putcode(ocmov, spoint, vid);
|
||
token := readtoken; If token.id <> id_do then Error(do_exp);
|
||
Case l of
|
||
id_to:
|
||
Begin
|
||
putcode(oclessequal, spoint, a);
|
||
putcode(ocif, spoint, l2);
|
||
spoint := mi;
|
||
getoperator;
|
||
putcode(ocincvar, vid, 0);
|
||
End;
|
||
id_downto:
|
||
Begin
|
||
putcode(ocgreaterequal, spoint, a);
|
||
putcode(ocif, spoint, l2);
|
||
spoint := mi;
|
||
getoperator;
|
||
putcode(ocdecvar, vid, 0);
|
||
End;
|
||
Else
|
||
Error(down_to_exp);
|
||
End;
|
||
putcode(ocgoto, l1, 0);
|
||
IDLabels.setplace(l2, prog.count);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getifoperator;
|
||
Var
|
||
i, a: integer;
|
||
l1, l2: integer;
|
||
NToken:TToken;
|
||
Begin
|
||
Token := ReadToken;
|
||
i := spoint;
|
||
a := iexpression;
|
||
spoint := i;
|
||
l1 := IDLabels.newitem;
|
||
IDLabels.SetReference(l1);
|
||
putcode(ocif, a, l1);
|
||
token := readtoken;
|
||
If token.id <> id_then then
|
||
Error(then_exp);
|
||
getoperator;
|
||
|
||
NToken:=NextToken;
|
||
If (NToken.id = iddelimeter) or (Ntoken.id=id_End) then
|
||
Begin
|
||
IDLabels.setplace(l1, prog.count);
|
||
exit;
|
||
End;
|
||
|
||
token := readtoken;
|
||
If token.id <> id_else then
|
||
Error(else_exp);
|
||
l2 := IDLabels.newitem;
|
||
IDLabels.SetReference(l2);
|
||
putcode(ocgoto, l2, 0);
|
||
IDLabels.setplace(l1, prog.count);
|
||
getoperator;
|
||
IDLabels.setplace(l2, prog.count);
|
||
End;
|
||
{------------------------------}
|
||
|
||
Function THalCompiler.getvar: integer;
|
||
Var
|
||
t: tidentlistitem;
|
||
Begin
|
||
token := readtoken;
|
||
If token.id <> ididentifier then Error(varname_exp);
|
||
If varbyname(token.data, t) = false then
|
||
Error(Format(var_NotDef, [token.data]));
|
||
result := t.id;
|
||
Lastvar := t;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getoperator;
|
||
Var
|
||
l, i: integer;
|
||
s: String;
|
||
Label l23;
|
||
Begin
|
||
l := NextToken.Id;
|
||
Case l of
|
||
id_begin:
|
||
getoperatorblock;
|
||
id_if:
|
||
getifoperator;
|
||
id_while:
|
||
getwhileoperator;
|
||
id_repeat:
|
||
getrepeatoperator;
|
||
id_for:
|
||
getforoperator;
|
||
id_Goto:
|
||
Begin
|
||
Token := ReadToken;
|
||
Token := ReadToken;
|
||
If Token.ID <> idIdentifier then Error(labname_exp);
|
||
S := Token.Data;
|
||
If Labels.IDByName(s, i) = false
|
||
Then Error(Format(lab_notdef, [s]));
|
||
IDLabels.SetReference(i);
|
||
putcode(ocgoto, i, 0);
|
||
End;
|
||
idIdentifier:
|
||
Begin
|
||
Token := ReadToken;
|
||
s := Token.Data;
|
||
If nexttoken.id = idpoint then
|
||
Begin
|
||
findobject(s);
|
||
End;
|
||
While nexttoken.id = idpoint do
|
||
Begin
|
||
token := readtoken;
|
||
token := readtoken;
|
||
If token.id <> ididentifier then
|
||
Error(id_expected);
|
||
s := s + '.' + token.data;
|
||
End;
|
||
Case nexttoken.id of
|
||
idopenbracket, idsqopenbracket: l23: getuserfunction(s, true, true);
|
||
id2points:
|
||
Begin
|
||
Token := ReadToken;
|
||
Case nexttoken.id of
|
||
idequal:
|
||
Begin
|
||
Token := ReadToken;
|
||
equaldispath(s);
|
||
End;
|
||
Else
|
||
labeldispatch(s);
|
||
End;
|
||
End;
|
||
Else
|
||
Goto l23;
|
||
End;
|
||
End;
|
||
Else
|
||
Error(Format(unkn_id, [nexttoken.data]));
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.getoperatorblock;
|
||
Begin
|
||
Token := ReadToken;
|
||
If token.id = id_end then exit;
|
||
If token.id <> id_begin then Error(begin_expected);
|
||
While (nexttoken.id <> idEndOFFile) and (nexttoken.id <> id_end) do
|
||
getoperatorcoma;
|
||
token := ReadToken;
|
||
If token.id <> id_end
|
||
then
|
||
Error(end_expected);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.compileprogram;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
i := IDLabels.newitem;
|
||
IDLabels.SetReference(i);
|
||
putcode(ocgoto, i, 0);
|
||
getprogramname;
|
||
getdeclarations;
|
||
IDLabels.setplace(i, prog.count);
|
||
getoperatorblock;
|
||
Token := ReadToken;
|
||
putcode(ochalt, 0, 0);
|
||
End;
|
||
|
||
{-----------------------------------------------------------------------}
|
||
|
||
Procedure THalCompiler.writeprogram;
|
||
|
||
{-----------}
|
||
Procedure writeconsts;
|
||
Var
|
||
i: integer;
|
||
v: variant;
|
||
Begin
|
||
outint(fout, consts.count);
|
||
For i := 0 to consts.count - 1 do
|
||
Begin
|
||
v := tconstitem(consts.items[i]).data;
|
||
Case Vartype(v) of
|
||
varBoolean:
|
||
Begin
|
||
outbyte(fout, wboolean);
|
||
outboolean(fout, v);
|
||
End;
|
||
varSingle, varDouble:
|
||
Begin
|
||
outbyte(fout, wdouble);
|
||
outdouble(fout, v);
|
||
End;
|
||
varSmallint, varbyte, varinteger:
|
||
Begin
|
||
outbyte(fout, winteger); outint(fout, v);
|
||
End;
|
||
varstring:
|
||
Begin
|
||
outbyte(fout, wstring);
|
||
outstring(fout, v);
|
||
End;
|
||
Else
|
||
Error(unexp_writer);
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{-----------}
|
||
|
||
Procedure writelabels;
|
||
Var
|
||
i, c: integer;
|
||
Begin
|
||
outint(fout, idlabels.count);
|
||
For i := 0 to idlabels.count - 1 do
|
||
Begin
|
||
c := tidlabelitem(idlabels.items[i]).Place;
|
||
outint(fout, c);
|
||
End;
|
||
End;
|
||
|
||
{-----------}
|
||
|
||
Procedure writeprog;
|
||
Var
|
||
i: integer;
|
||
v: tprogitem;
|
||
Begin
|
||
outint(fout, prog.count);
|
||
For i := 0 to prog.count - 1 do
|
||
Begin
|
||
v := tprogitem(prog.items[i]);
|
||
outint(fout, v.a);
|
||
outint(fout, v.b);
|
||
outint(fout, v.opcode);
|
||
End;
|
||
End;
|
||
|
||
{-----------}
|
||
Begin
|
||
writeconsts;
|
||
writelabels;
|
||
writeprog;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Constructor THalCompiler.Create(afin: TMemoryStream; afout: TStream);
|
||
Begin
|
||
Inherited create;
|
||
myinit;
|
||
fout := afout;
|
||
inbuf := afin.memory;
|
||
numread := afin.size;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Destructor THalCompiler.Destroy;
|
||
Begin
|
||
mydone;
|
||
Inherited;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCompiler.compile;
|
||
Begin
|
||
compileprogram;
|
||
If idlabels.existlabels = false then
|
||
Error(linker_error);
|
||
WriteProgram;
|
||
End;
|
||
|
||
{=======================================================}
|
||
|
||
Procedure TBinProg.Error(Const s: String);
|
||
Begin
|
||
Raise ECompilerError.Create(s);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Destructor TBinProg.Destroy;
|
||
Begin
|
||
If assigned(prog) then
|
||
freemem(prog, progsize * sizeof(tbinprogitem));
|
||
If assigned(c) then
|
||
freemem(c, constsize * sizeof(variant));
|
||
If assigned(l) then
|
||
freemem(l, labelsize * sizeof(integer));
|
||
Inherited destroy;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Constructor TBinProg.Create(Fin: TStream);
|
||
{--}
|
||
Procedure readconsts;
|
||
Var
|
||
i: integer;
|
||
b: byte;
|
||
v: variant;
|
||
Begin
|
||
constsize := getint(fin);
|
||
getmem(c, constsize * sizeof(variant));
|
||
fillchar(c^, constsize * sizeof(variant), 0);
|
||
For i := 0 to constsize - 1 do
|
||
Begin
|
||
b := getbyte(fin);
|
||
Case b of
|
||
wInteger: v := getint(fin);
|
||
wDouble: v := getdouble(fin);
|
||
wString: v := getstring(fin);
|
||
WBoolean: v := getboolean(fin);
|
||
Else Error(SErrUnknReaderType);
|
||
End;
|
||
c^[i] := v;
|
||
End;
|
||
End;
|
||
{--}
|
||
|
||
Procedure readprogram;
|
||
Begin
|
||
progsize := getint(fin);
|
||
getmem(prog, progsize * sizeof(tbinprogitem));
|
||
Fin.ReadBuffer(Prog^, progsize * sizeof(tbinprogitem));
|
||
End;
|
||
|
||
{--}
|
||
|
||
Procedure readlabels;
|
||
Begin
|
||
labelsize := getint(fin);
|
||
getmem(l, labelsize * sizeof(integer));
|
||
Fin.ReadBuffer(L^, LabelSize * sizeof(integer));
|
||
End;
|
||
|
||
{--}
|
||
Var
|
||
i: integer;
|
||
|
||
Begin
|
||
Inherited create;
|
||
{ getmem(s, stacksize * sizeof(variant));
|
||
fillchar(s^, stacksize * sizeof(variant), 0);}
|
||
For i:=0 to StackSize do
|
||
With TVarData(S[i]) do
|
||
vType:=varInteger;
|
||
|
||
readconsts;
|
||
readlabels;
|
||
readprogram;
|
||
End;
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg._ocloadextvar(Var V: Variant; b, a: integer); register;
|
||
Begin
|
||
V := (DynaVars.Objects[b] as TDynaVarItem).GetVar(a);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg._ocsetself(A: TObject); register;
|
||
Begin
|
||
lastobject := a;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg._CallExtFun(Var V: Variant; var PropName:String; ProcAddr: TProcType); register;
|
||
Begin
|
||
V := ProcAddr(lastobject, PropName,TempVars);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg._ocselffromvar(Var A: Variant); register;
|
||
Begin
|
||
lastobject := tobject(VarToObj(a));
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg._ocstoreextvar(b, a: integer; Var V: Variant);
|
||
Begin
|
||
(DynaVars.Objects[b] as TDynaVarItem).SetVar(a, V);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TBinProg._dispatch(opcode, a, b: integer): boolean;
|
||
Var
|
||
PCount, ik, a1: integer;
|
||
mint: Array[0..maxparams] of integer;
|
||
myfun: TFunListItem;
|
||
Begin
|
||
inc(curpos); Result := true;
|
||
Case opcode of
|
||
{------------------------------}
|
||
{general functions}
|
||
ocincvar: _ocincvar(S[a]);
|
||
ocdecvar: _ocdecvar(S[a]);
|
||
ocAdd: _ocAdd(S[a], s[b]);
|
||
ocSub: _ocSub(S[a], s[b]);
|
||
ocMul: _ocMul(S[a], s[b]);
|
||
ocDiv: _ocDiv(S[a], s[b]);
|
||
ocMod: _ocMod(S[a], s[b]);
|
||
ocSlash: _ocSlash(S[a], s[b]);
|
||
ocShl: _ocShl(S[a], s[b]);
|
||
ocShr: _ocShr(S[a], s[b]);
|
||
ocNot: _ocNot(S[a]);
|
||
ocOr: _ocOr(S[a], s[b]);
|
||
ocXor: _ocXor(S[a], s[b]);
|
||
ocAnd: _ocAnd(S[a], s[b]);
|
||
ocGreaterEqual: _ocGreaterEqual(S[a], s[b]);
|
||
ocEqual: _ocEqual(S[a], s[b]);
|
||
ocLessEqual: _ocLessEqual(S[a], s[b]);
|
||
ocNotEqual: _ocNotEqual(S[a], s[b]);
|
||
ocGreater: _ocGreater(S[a], s[b]);
|
||
ocLess: _ocLess(S[a], s[b]);
|
||
ocNeg: _ocNeg(S[a]);
|
||
ocmov: _ocmov(S[a], S[b]);
|
||
ocloadconst: _ocmov(S[a], c[b]);
|
||
ocvarraycreate: _ocvarraycreate(S[a], b);
|
||
ocsetvarray:
|
||
Begin
|
||
a1 := prog^[curpos].a;
|
||
inc(curpos);
|
||
_ocsetvarray(S[a1], S[b], a);
|
||
End;
|
||
{---------------------------------------}
|
||
ocsetself:
|
||
_ocsetself(TOBject(a));
|
||
ocselffromvar:
|
||
_ocselffromvar(s[a]);
|
||
|
||
ocloadextvar:
|
||
Begin
|
||
a1 := prog^[curpos].a;
|
||
inc(curpos);
|
||
_ocloadextvar(S[a1], b, a);
|
||
End;
|
||
ocstoreextvar:
|
||
Begin
|
||
a1 := prog^[curpos].a;
|
||
inc(curpos);
|
||
_ocstoreextvar(b, a, S[a1]);
|
||
End;
|
||
{---------------------------------------}
|
||
occall:
|
||
Begin
|
||
CallStack[CallMax] := curpos;
|
||
inc(CallMax);
|
||
Curpos := L^[a];
|
||
exit;
|
||
End;
|
||
ocGoto:
|
||
curpos := L^[a];
|
||
ocIF:
|
||
If s[a] = false
|
||
then
|
||
curpos := L^[B];
|
||
ochalt:
|
||
Begin
|
||
Result := false;
|
||
exit;
|
||
End;
|
||
ocreturn:
|
||
Begin
|
||
If CallMax = 0 then
|
||
Begin
|
||
Result := false;
|
||
exit;
|
||
End;
|
||
dec(callmax);
|
||
Curpos := CallStack[callmax];
|
||
exit;
|
||
End;
|
||
|
||
{---------------------------------------}
|
||
ocextfun:
|
||
Begin
|
||
myfun := tfunlistitem(Funs.Objects[b]);
|
||
PCount := myfun.parcount;
|
||
If PCount = 0 then
|
||
S[a] := myfun.ProcAddr(lastobject, myFun.PropName, TempVars)
|
||
Else
|
||
Begin
|
||
Dec(PCount);
|
||
ik := 0;
|
||
While ik <= PCount do
|
||
Begin
|
||
mint[ik] := prog[curpos].opcode;
|
||
mint[ik + 1] := prog[curpos].a;
|
||
mint[ik + 2] := prog[curpos].b;
|
||
inc(curpos);
|
||
inc(ik, 3);
|
||
End;
|
||
For ik := 0 to PCount do
|
||
TempVars[ik] := S[mint[ik]];
|
||
_CallExtFun(S[a], MyFun.PropName, MyFun.ProcAddr);
|
||
For ik := 0 to PCount do
|
||
If myfun.params[ik] = 1 then S[mint[ik]] := TempVars[ik];
|
||
End;
|
||
End;
|
||
Else Error('Invalid opcode');
|
||
End; End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg.Run;
|
||
Begin
|
||
RunFrom(0);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TBinProg.RunFrom(Acurpos: Integer);
|
||
Begin
|
||
curpos := ACurPos;
|
||
While
|
||
_dispatch(prog^[curpos].opcode, prog^[curpos].a, prog^[curpos].b)
|
||
Do Begin end;
|
||
End;
|
||
|
||
{============================================================}
|
||
|
||
Procedure thalRuner.AddObjectbyRef(Const objname: String; tobj: tobject);
|
||
Begin
|
||
AddObject(ObjName, tobj.ClassName, tobj);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure thalRuner.AddObject(Const objname, objtype: String; tobj: tobject);
|
||
Var
|
||
t: tobjitem;
|
||
Begin
|
||
t := tobjitem.create;
|
||
t.objtype := ansiuppercase(objtype);
|
||
t.tobj := tobj;
|
||
myobjects.addobject(ansiuppercase(objname), t);
|
||
End;
|
||
|
||
{-------------------}
|
||
|
||
Constructor THalRuner.Create(T: TMemoryStream);
|
||
Begin
|
||
Inherited Create;
|
||
instream := t;
|
||
myobjects := Tobjcollect.create;
|
||
TempVarList := TIdentList.Create;
|
||
End;
|
||
|
||
{-------------------}
|
||
|
||
Procedure THalRuner.Run;
|
||
Var
|
||
FHalCompiler: THalCompiler;
|
||
Begin
|
||
If compiled = false then
|
||
Begin
|
||
mymem := TmemoryStream.create;
|
||
FHalCompiler := THalCompiler.Create(instream, mymem);
|
||
Try
|
||
FHalCOmpiler.HALOWNER := HalOwner;
|
||
FHalCompiler.mobjects := myobjects;
|
||
FHalCompiler.compile;
|
||
Finally
|
||
FLastClassType := FHalCompiler.FLastClassType;
|
||
If loadtemp then TempVarList.Assign(FHalCompiler.Variables);
|
||
FHalCompiler.free;
|
||
End;
|
||
mymem.seek(0, 0);
|
||
FBinProg := TBinProg.Create(mymem);
|
||
compiled := true;
|
||
End;
|
||
If dontrun then exit;
|
||
FBinProg.Run;
|
||
End;
|
||
|
||
{-------------------}
|
||
|
||
Destructor THalRuner.Destroy;
|
||
Begin
|
||
If compiled then
|
||
Begin
|
||
mymem.free;
|
||
FBinProg.Free;
|
||
myobjects.free;
|
||
End;
|
||
TempVarList.Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function UnUniqName(Const Name: String): String;
|
||
Var
|
||
i, Code, k: integer;
|
||
Begin
|
||
i := length(Name);
|
||
While (I > 0) and (Name[i] <> '_') do dec(i);
|
||
If (i = 0) then Result := Name else
|
||
Begin
|
||
Val(Copy(Name, i + 1, MaxInt), k, Code);
|
||
If Code <> 0 then Result := Name else Result := Copy(Name, 1, i - 1);
|
||
If k>0 then begin end;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure disposeconsts(Var c: Array of tvarrec; size: integer);
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to size do
|
||
If C[i].Vtype = VTVariant
|
||
then
|
||
FreeMem(C[i].VVariant, SizeOf(Variant));
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure ClearHalParams;
|
||
Begin
|
||
InternalVariables.Clear;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Function GetHalParam(Const ParamName: String): Variant;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := 0;
|
||
With InternalVariables do
|
||
Begin
|
||
If Find(AnsiUpperCase(ParamName), i) = false then exit;
|
||
Result := (Objects[i] as TInternalVarItem).Value;
|
||
End;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure SetHalParam(Const ParamName: String; Value: Variant);
|
||
Var
|
||
R: TInternalVarItem;
|
||
S: String;
|
||
i: integer;
|
||
Begin
|
||
S := AnsiUpperCase(ParamName);
|
||
With InternalVariables do
|
||
Begin
|
||
If Find(S, i) then (Objects[i] as TInternalVarItem).Value := Value
|
||
Else
|
||
Begin
|
||
R := TInternalVarItem.Create;
|
||
R.Value := Value;
|
||
AddObject(S, R);
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure AddConst(Const AName: String; V: Variant);
|
||
Begin
|
||
ResConsts.AddConst(AName, V);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Constructor TResConstList.Create;
|
||
Begin
|
||
Inherited;
|
||
sorted := true;
|
||
duplicates := dupignore;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure TResConstList.AddConst(Const AName: String; Var V: Variant);
|
||
Var
|
||
t: tresconstlistitem;
|
||
Begin
|
||
t := tresconstlistitem.Create;
|
||
t.Value := V;
|
||
AddObject(AnsiUpperCase(AName), t);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Destructor TResConstList.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do
|
||
Objects[i].Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure VarToStringS(Var V: Variant; Var P: Array of String; Var MaxP: Integer);
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
MaxP := V[0];
|
||
For i := 1 to V[0] do P[i - 1] := V[i];
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure VarToConsts(Var V: Variant; Var P: Array of tvarrec; Var MaxP: Integer);
|
||
Var
|
||
i: integer;
|
||
PV: PVariant;
|
||
Begin
|
||
MaxP := V[0];
|
||
For i := 1 to MaxP do
|
||
Begin
|
||
GetMem(PV, Sizeof(Variant));
|
||
PV^ := V[i];
|
||
P[i - 1].VVariant := PV;
|
||
p[i - 1].Vtype := VtVariant;
|
||
End;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure TIdentList.Assign(Source: TPersistent);
|
||
Var
|
||
i: integer;
|
||
P1: TIdentListItem;
|
||
Begin
|
||
Inherited;
|
||
For i := 0 to Count - 1 do
|
||
Begin
|
||
P1 := tidentlistitem(Objects[i]);
|
||
Objects[i] := TObject(TIdentListitem.Create);
|
||
(Objects[i] as tidentlistitem).Assign(P1);
|
||
End;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure TIdentListItem.Assign(Source: TIdentlistItem);
|
||
Begin
|
||
ID := Source.ID;
|
||
VType := Source.Vtype;
|
||
IdentType := Source.IdentType;
|
||
ParCount := Source.ParCount;
|
||
Params := Source.Params;
|
||
ParamNames.Assign(Source.ParamNames);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Constructor TIdentListItem.Create;
|
||
Begin
|
||
Inherited;
|
||
ParamNames := TStringList.Create;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Destructor TIdentListItem.Destroy;
|
||
Begin
|
||
ParamNames.Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Constructor TInternalVar.Create;
|
||
Begin
|
||
Inherited;
|
||
AddDynaVar(stintvar, DynaVarNameToID, DynaSetVAR, dynagetvar);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Destructor TInternalVar.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
DelDynaVar(stintvar);
|
||
For i := 0 to Count - 1 do
|
||
Objects[i].Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Function TInternalVar.DynaVarNameTOId(Const S: String): Integer;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
If CompareText(s, 'Result') = 0
|
||
then
|
||
Result := 0
|
||
Else
|
||
If Find(s, i)
|
||
then
|
||
Result := i + 1
|
||
Else
|
||
Result := -1;
|
||
End;
|
||
{--------------------------------}
|
||
|
||
Procedure TInternalVar.DynaSetVar(ID: Integer; Value: Variant);
|
||
Begin
|
||
If ID = 0
|
||
then
|
||
MyResult := Value
|
||
else
|
||
If ID - 1 <= Count then
|
||
(Objects[ID - 1] as TInternalVarItem).Value := Value;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Function TInternalVar.DynaGetVar(ID: Integer): Variant;
|
||
Begin
|
||
If ID = 0 then Result := MyResult else
|
||
Begin
|
||
If ID - 1 <= Count then Result := (Objects[ID - 1] as TInternalVarItem).Value
|
||
Else Result := 0;
|
||
End;
|
||
End;
|
||
{------------------------------}
|
||
|
||
Procedure AddLocalVar(Const name: String;
|
||
Avarnametoid: TDynaVarNameTOID;
|
||
ASetVar: TDYnaSetVar;
|
||
AGetVar: TDynaGetVar; AOwnerSelf: TObject);
|
||
Begin
|
||
DynaVars.AddDyna(name, Avarnametoid, ASetVar, AGetVar, true, AOwnerSelf);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure AddDynaVar(Const name: String;
|
||
Avarnametoid: TDynaVarNameTOID;
|
||
ASetVar: TDYnaSetVar;
|
||
AGetVar: TDynaGetVar);
|
||
Begin
|
||
DynaVars.AddDyna(name, Avarnametoid, ASetVar, AGetVar, false, DynaVars);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure deldynavar(Const name: String);
|
||
Begin
|
||
Dynavars.DelDyna(name);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TDynaVars.AddDyna(Const name: String;
|
||
Avarnametoid: TDynaVarNameTOID;
|
||
ASetVar: TDYnaSetVar;
|
||
AGetVar: TDynaGetVar; LocalVars: Boolean; AOwnerSelf: TObject);
|
||
Var
|
||
t: tdynavaritem;
|
||
Begin
|
||
t := tdynavaritem.create;
|
||
With t do
|
||
Begin
|
||
varnametoid := Avarnametoid;
|
||
SetVar := ASetVar;
|
||
GetVar := AGetVar;
|
||
LocalVar := LocalVars;
|
||
OwnerSelf := AOwnerSelf;
|
||
End;
|
||
AddObject(AnsiUpperCase(name), t);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TDynaVars.GetDynaObject(Const vname: String; AOwnerSelf: TObject;
|
||
Var varid, funid: integer): boolean;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := false;
|
||
For i := count - 1 downto 0 do
|
||
If ((Objects[i] as TDynaVarItem).LocalVar = false)
|
||
Or
|
||
(AOwnerSelf = (Objects[i] as TDynaVarItem).OwnerSelf) then
|
||
Begin
|
||
varid := (Objects[i] as TDynaVarItem).VarNameToID(vname);
|
||
If (varid <> -1) then
|
||
Begin
|
||
funid := i;
|
||
Result := true;
|
||
exit;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TDynaVars.DelDyna(Const name: String);
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
i := IndexOF(AnsiUpperCase(name));
|
||
If i <> -1 then
|
||
Delete(i);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Destructor TDynaVars.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do
|
||
Objects[i].Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function GetClassParent(C:TClass):String;
|
||
begin
|
||
C:=C.ClassParent;
|
||
If C=nil
|
||
then
|
||
Result:=''
|
||
else
|
||
Result:=C.ClassName;
|
||
end;
|
||
|
||
{------------------------------}
|
||
|
||
Function GetPearent(Const objname: String): String;
|
||
Var
|
||
C:TClass;
|
||
Begin
|
||
C:=GetClass(ObjName);
|
||
If (C=nil)
|
||
then
|
||
Result:=''
|
||
else
|
||
Result:=GetClassParent(C);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Constructor TObjCollect.Create;
|
||
Begin
|
||
Inherited;
|
||
sorted := true;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Destructor TObjCollect.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do If assigned(Objects[i]) then Objects[i].Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TObjCollect.ObjbyName(Const aname: String; Var tob: tobjitem): boolean;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
tob := Nil;
|
||
Result := Find(aname, i);
|
||
If result then tob := Tobjitem(Objects[i]);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TProgCollect.putop(ID, AA, AB: integer);
|
||
Var
|
||
s: tprogitem;
|
||
Begin
|
||
s := tprogitem(add);
|
||
s.opcode := id;
|
||
s.a := aa;
|
||
s.b := ab;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TIDLabelList.newitem: integer;
|
||
Begin
|
||
Result := TIDLabelItem(Add).Index;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TIdLabelList.existlabels: boolean;
|
||
Var
|
||
i: integer;
|
||
s: tidlabelitem;
|
||
Begin
|
||
Result := false;
|
||
For i := 0 to count - 1 do
|
||
Begin
|
||
s := tidlabelitem(items[i]);
|
||
If s.exist <> s.referenced then exit;
|
||
End;
|
||
Result := true;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TIdLabelList.SetReference(index: integer);
|
||
Begin
|
||
tidlabelitem(items[index]).referenced := true;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TIdLabelList.SetPlace(index, aplace: integer);
|
||
Var
|
||
s: tidlabelitem;
|
||
Begin
|
||
s := tidlabelitem(items[index]);
|
||
s.place := aplace;
|
||
s.exist := true;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function tconstlist.newitem(adata: variant): integer;
|
||
Var
|
||
t: tconstitem;
|
||
Begin
|
||
t := tconstitem(Add);
|
||
t.data := adata;
|
||
Result := t.index;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TIdentList.IDByName(Const AName: String; Var AID: integer): boolean;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := Find(aname, i);
|
||
If result then AID := TIdentListItem(Objects[i]).ID;
|
||
End;
|
||
|
||
{-------------------}
|
||
|
||
Constructor TIdentList.Create;
|
||
Begin
|
||
Inherited Create;
|
||
Sorted := true;
|
||
End;
|
||
|
||
{-------------------}
|
||
|
||
Function TIdentList.AddItem(Const Aname: String; ID: Integer): Integer;
|
||
Var
|
||
t: TIdentListItem;
|
||
Begin
|
||
t := TIdentListItem.Create;
|
||
t.Id := id;
|
||
Result := addobject(AnsiUpperCase(aname), t);
|
||
End;
|
||
|
||
{-------------------}
|
||
|
||
Destructor TIdentList.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do If assigned(Objects[i]) then Objects[i].Free;
|
||
Inherited destroy;
|
||
End;
|
||
|
||
{----------------------------------------------}
|
||
|
||
Procedure NewR(Const AName: String; AID: Integer);
|
||
Begin
|
||
ResWords.AddItem(AName, AID);
|
||
End;
|
||
|
||
{----------------------------------------------}
|
||
|
||
Procedure InitReservedWords;
|
||
Begin
|
||
NewR('Program', id_Program);
|
||
NewR('Label', id_Label);
|
||
NewR('Goto', id_Goto);
|
||
NewR('Var', id_Var);
|
||
NewR('Begin', id_begin);
|
||
NewR('End', id_end);
|
||
|
||
Newr('And', id_and);
|
||
Newr('Or', id_or);
|
||
Newr('Xor', id_xor);
|
||
Newr('Not', id_not);
|
||
Newr('Shl', id_shl);
|
||
Newr('Shr', id_shr);
|
||
|
||
Newr('Div', id_div);
|
||
Newr('Mod', id_mod);
|
||
|
||
Newr('True', id_true);
|
||
Newr('False', id_false);
|
||
Newr('Nil', id_nil);
|
||
|
||
Newr('If', id_if);
|
||
Newr('then', id_then);
|
||
Newr('else', id_else);
|
||
|
||
Newr('While', id_while);
|
||
Newr('Repeat', id_repeat);
|
||
Newr('Until', id_until);
|
||
Newr('For', id_for);
|
||
Newr('To', id_to);
|
||
Newr('DownTo', id_downto);
|
||
Newr('Do', id_do);
|
||
|
||
{------}
|
||
Newr('initialization', id_unitinit);
|
||
Newr('finalization', id_unitfinal);
|
||
Newr('class', id_class);
|
||
Newr('type', id_type);
|
||
Newr('constructor', id_constr);
|
||
Newr('destructor', id_destr);
|
||
Newr('uses', id_uses);
|
||
Newr('unit', id_unit);
|
||
Newr('interface', id_interface);
|
||
Newr('implementation', id_implement);
|
||
Newr('procedure', id_procedure);
|
||
Newr('private', id_private);
|
||
Newr('public', id_public);
|
||
Newr('protected', id_protected);
|
||
Newr('published', id_published);
|
||
Newr('function', id_function);
|
||
Newr('const', id_const);
|
||
|
||
Newr('property', id_property);
|
||
Newr('virtual', id_virtual);
|
||
Newr('override', id_override);
|
||
Newr('dynamic', id_dynamic);
|
||
Newr('record', id_record);
|
||
Newr('forward', id_forward);
|
||
|
||
Newr('index', id_index);
|
||
Newr('read', id_read);
|
||
Newr('write', id_write);
|
||
Newr('stored', id_stored);
|
||
Newr('default', id_default);
|
||
Newr('abstract', id_abstract);
|
||
|
||
Newr('stdcall', id_stdcall);
|
||
|
||
{------}
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function SetToken(ID: integer; V: Variant): TToken;
|
||
Begin
|
||
Result.ID := ID; Result.Data := V;
|
||
End;
|
||
|
||
{------------------------------}
|
||
Var
|
||
FLMethods: TList;
|
||
EventList: TEventList;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Constructor TEventList.Create;
|
||
Begin
|
||
Inherited;
|
||
Sorted := True;
|
||
Duplicates := dupIgnore;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function TEventList.ItemByName(Const AEventType: String): TEventListItem;
|
||
Var
|
||
i: Integer;
|
||
Begin
|
||
Result := Nil;
|
||
If Find(AnsiUpperCase(AEventType), i)
|
||
then
|
||
Result := TEventListItem(Objects[i]);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure RegisterEvent(Const AEventType: String; AAddress: Pointer;
|
||
AEventClass: THalEventClass);
|
||
Begin
|
||
EventList.AddItem(AEventType, AAddress, AEventClass);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure TEventList.AddItem(Const AEventType: String; AAddress: Pointer;
|
||
AEventClass: THalEventClass);
|
||
Var
|
||
F: TEventListItem;
|
||
Begin
|
||
F := TEventListItem.Create;
|
||
F.Address := AAddress;
|
||
F.EventClass := AEventClass;
|
||
AddObject(AnsiUpperCase(AEventType), F);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Destructor TEventList.Destroy;
|
||
Var
|
||
i: Integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do
|
||
Objects[i].Free;
|
||
Inherited;
|
||
End;
|
||
{-------------------------------------------}
|
||
|
||
Function RegisteredEvent(Const EventType: String): Boolean;
|
||
Begin
|
||
Result := (EventList.ItemByName(Eventtype)) <> Nil;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function RunFormMacro(Const MPath: String; Modal: Boolean): Variant;
|
||
Var
|
||
s: String;
|
||
Begin
|
||
Result := NULL;
|
||
s := AnsiUpperCase(ExtractFileExt(MPath));
|
||
If S = '.DFM' then Begin
|
||
If modal
|
||
then
|
||
Result := RunFormModal(MPath)
|
||
else
|
||
RunForm(MPath);
|
||
End else
|
||
If (S = '.PAS') or (S = '.HAL')
|
||
then
|
||
Result := RunMacro(MPath)
|
||
else
|
||
Raise Exception.Create(Format(unk_macrotype, [AnsiUpperCase(MPath)]));
|
||
End;
|
||
|
||
{---------------------------------}
|
||
|
||
function IsDelphinForm(F:TComponent):boolean;
|
||
begin
|
||
Result:=GetEventDispatcher(F)<>nil;
|
||
end;
|
||
|
||
{---------------------------------}
|
||
|
||
function GetEventDispatcher(F:TComponent):THalComp;
|
||
Var
|
||
i:Integer;
|
||
begin
|
||
Result:=nil;
|
||
With F do
|
||
for I:=0 to ComponentCount-1 do
|
||
if (Components[i] is THalComp) and (THalComp(Components[i]).EventDispatcher) then
|
||
begin
|
||
Result:=THalComp(Components[i]);
|
||
exit;
|
||
end;
|
||
end;
|
||
|
||
{---------------------------------}
|
||
|
||
procedure CallEvent(F:TComponent;Const EventName:String;ParamCount:Integer;Params:Pointer);
|
||
Var
|
||
H:THalEvent;
|
||
HCo:THalComp;
|
||
begin
|
||
HCo:=GetEventDispatcher(F.Owner);
|
||
If HCo=nil then
|
||
exit;
|
||
H:=THalEvent.Create(F.Owner);
|
||
try
|
||
H.HR := HCo.FHalRuner;
|
||
H.ProcName := EventName;
|
||
H.ExecProc(F,ParamCount,Params);
|
||
finally
|
||
H.Free;
|
||
end;
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function THalEvent.GetProcItem: TIdentListItem;
|
||
Var
|
||
OName:String;
|
||
Begin
|
||
Result:=nil;
|
||
OName:=UnUniqName(Owner.Name);
|
||
PrName := AnsiUpperCase('T' + OName + '.' + ProcName);
|
||
If HR.TempVarList.ItemByname(prname, Result) then
|
||
exit;
|
||
If OName=Owner.Name then
|
||
raise Exception.CreateFmt(proc_notfound, [prname]);
|
||
|
||
PrName := AnsiUpperCase('T' + Owner.Name + '.' + ProcName);
|
||
if HR.TempVarList.ItemByname(prname, Result) = false then
|
||
raise Exception.CreateFmt(proc_notfound, [prname]);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.SetParam(Const ParName: String; Value: Variant);
|
||
Var
|
||
iw: TIdentListItem;
|
||
Begin
|
||
If HR.TempVarList.ItemByname(ParName, iw) = false
|
||
Then
|
||
showmessage(Format(par_notfound, [ParName]))
|
||
Else
|
||
HR.FBinProg.S[iw.id] := Value;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function THalEvent.GetParam(Const ParName: String): Variant;
|
||
Var
|
||
iw: TIdentListItem;
|
||
Begin
|
||
Result := 0;
|
||
If HR.TempVarList.ItemByname(ParName, iw) = false
|
||
Then
|
||
showmessage(Format(par_notfound, [ParName]))
|
||
Else
|
||
Result := HR.FBinProg.S[iw.id];
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.ExecProc(F:TObject;ParCount:Integer;Params:PVarDataList);
|
||
Var
|
||
k,I: Integer;
|
||
Begin
|
||
If not assigned(it) then
|
||
it := GetProcItem;
|
||
|
||
If it=nil then
|
||
exit;
|
||
|
||
If F<>nil then
|
||
SetParam(PrName + '.Sender' , OV(F));
|
||
|
||
K:=1;
|
||
|
||
For i := ParCount-1 downto 0 do
|
||
begin
|
||
SetParam(PrName + '.' + it.Paramnames[K], Variant(Params[i]));
|
||
inc(k);
|
||
end;
|
||
|
||
HR.FBinProg.RunFrom(HR.FBinProg.L^[it.id]);
|
||
|
||
K:=1;
|
||
For i :=ParCount-1 downto 0 do
|
||
begin
|
||
Variant(Params[i]) := GetParam(PrName + '.' + it.Paramnames[k]);
|
||
inc(k);
|
||
end;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MDragDropEvent(Sender, Source: TObject; X, Y: Integer);
|
||
Var
|
||
V: Array[0..2] of Variant;
|
||
Begin
|
||
V[2] := OV(Source);
|
||
V[1] := X;
|
||
V[0] := Y;
|
||
ExecProc(Sender,3,@V);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
function SetToInt(const aSet;const Size:integer):Integer;
|
||
begin
|
||
Result := 0;
|
||
Move(aSet, Result, Size);
|
||
end;
|
||
|
||
procedure IntToSet(const Value:integer; var aSet;const Size:integer);
|
||
begin
|
||
Move(Value, aSet, Size);
|
||
end;
|
||
|
||
procedure THalEvent.MMouseEvent(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
Var
|
||
V:Array[0..3] of variant;
|
||
|
||
begin
|
||
V[3]:= Button;
|
||
V[2]:= Byte(SetToInt(Shift, SizeOf(TShiftState)));
|
||
V[1]:= X;
|
||
V[0]:= Y;
|
||
ExecProc(Sender,4,@V);
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.MMouseMoveEvent(Sender: TObject; Shift: TShiftState;X, Y: Integer);
|
||
Var
|
||
V:Array[0..2] of Variant;
|
||
begin
|
||
V[2]:=Byte(SetToInt(Shift, SizeOf(TShiftState)));
|
||
V[1]:=X;
|
||
V[0]:=Y;
|
||
ExecProc(Sender,3,@V);
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.MKeyEvent(Sender: TObject; var Key: Word;Shift: TShiftState);
|
||
Var
|
||
V:Array[0..1] of variant;
|
||
begin
|
||
V[1]:=Key;
|
||
V[0]:=Byte(SetToInt(Shift, SizeOf(TShiftState)));
|
||
ExecProc(Sender,2,@V);
|
||
Key:=V[1];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MDragOverEvent(Sender, Source: TObject; X, Y: Integer; State: TDragState; Var Accept: Boolean);
|
||
Var
|
||
V: Array[0..4] of Variant;
|
||
Begin
|
||
V[4] := OV(Source);
|
||
V[3] := X;
|
||
V[2] := Y;
|
||
V[1] := Ord(State);
|
||
V[0] := Accept;
|
||
ExecProc(Sender,5,@V);
|
||
Accept := V[4];
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MEndDragEvent(Sender, Target: TObject; X, Y: Integer);
|
||
Var
|
||
V: Array[0..2] of Variant;
|
||
Begin
|
||
V[2] := OV(target);
|
||
V[1] := X;
|
||
V[0] := Y;
|
||
ExecProc(Sender,3,@V);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MStartDragEvent(Sender: TObject; Var DragObject: TDragObject);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
Begin
|
||
V[0] := OV(DragObject);
|
||
ExecProc(Sender,1,@V);
|
||
DragObject := TDragObject(VO(V[0]));
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQROnNeedDataEvent(Sender : TObject; var MoreData : Boolean);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=MoreData;
|
||
ExecProc(Sender,1,@V);
|
||
MoreData:=v[0];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRNotifyOperationEvent(Sender : TObject; Operation : TQRNotifyOperation);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=Integer(Operation);
|
||
ExecProc(Sender,1,@V);
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRBandBeforePrintEvent(Sender : TObject; var PrintBand : Boolean);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=PrintBand;
|
||
ExecProc(Sender,1,@V);
|
||
PrintBand:=v[0];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRBandAfterPrintEvent(Sender : TObject; BandPrinted : Boolean);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=BandPrinted;
|
||
ExecProc(Sender,1,@V);
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRReportBeforePrintEvent(Sender : TObject; var PrintReport : Boolean);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=PrintReport;
|
||
ExecProc(Sender,1,@V);
|
||
PrintReport:=v[0];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRFilterEvent(var PrintRecord : boolean);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=PrintRecord;
|
||
ExecProc(nil,1,@V);
|
||
PrintRecord:=v[0];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
// this event return results
|
||
// it's probably not implemented yet
|
||
function THalEvent.MHelpEvent(Command: Word; Data: Longint;var CallHelp: Boolean): Boolean;
|
||
Var
|
||
V: Array[0..2] of Variant;
|
||
begin
|
||
v[2]:=Command;
|
||
v[1]:=Data;
|
||
v[0]:=CallHelp;
|
||
ExecProc(nil,3,@V);
|
||
CallHelp:=v[2];
|
||
Result:=True;
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.MCloseQueryEvent(Sender: TObject;var CanClose: Boolean);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0]:=CanClose;
|
||
ExecProc(Sender,1,@V);
|
||
CanClose:=v[0];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRLabelOnPrintEvent(sender : TObject; var Value : string);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
v[0] := Value;
|
||
ExecProc(Sender,1,@V);
|
||
Value:=v[0];
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRProgressUpdateEvent(Sender : TObject; Progress : integer);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
V[0]:=Progress;
|
||
ExecProc(Sender,1,@V);
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
procedure THalEvent.mQRPageAvailableEvent(Sender : TObject; PageNum : integer);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
begin
|
||
V[0]:=PageNum;
|
||
ExecProc(Sender,1,@V);
|
||
end;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MKeyPressEvent(Sender: TObject; Var Key: Char);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
S: String;
|
||
Begin
|
||
V[0] := Key;
|
||
ExecProc(Sender,1,@V);
|
||
S := V[0];
|
||
Key := S[1];
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MCloseEvent(Sender: TObject; Var Action: TCloseAction);
|
||
Var
|
||
V: Array[0..0] of Variant;
|
||
Begin
|
||
V[0] := Action;
|
||
ExecProc(Sender,1,@V);
|
||
Action := V[0];
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Procedure THalEvent.MNotifyEvent(Sender: TObject);
|
||
Begin
|
||
ExecProc(Sender,0,nil);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Constructor TMyReader.Create(Stream: TStream; BufSize: Integer);
|
||
Begin
|
||
Inherited;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function TMyReader.FindMethod(Root: TComponent;
|
||
Const MethodName: String): Pointer;
|
||
Var
|
||
A: TMethodNameHolder;
|
||
Begin
|
||
a := TMethodNameHolder.Create;
|
||
FLMethods.Add(a);
|
||
a.MethodName := MethodName;
|
||
Result := Pointer(FlMethods.Count);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function TMyStream.ReadComponent(Instance: TComponent): TComponent;
|
||
Var
|
||
Reader: TMyReader;
|
||
Begin
|
||
Reader := TMyReader.Create(Self, 4096);
|
||
Try
|
||
Result := Reader.ReadRootComponent(Instance);
|
||
Finally
|
||
Reader.Free;
|
||
End;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function TMyStream.ReadComponentRes(Instance: TComponent): TComponent;
|
||
Begin
|
||
ReadResHeader;
|
||
Result := ReadComponent(Instance);
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
function RunForm(Const FormPath: String):TForm;
|
||
Begin
|
||
Result := TForm.Create(Application);
|
||
MyReadComponentResFile(FormPath, Result);
|
||
Result.Show;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function RunFormModal(Const FormPath: String): Integer;
|
||
Var
|
||
Form: TForm;
|
||
Begin
|
||
Form := TForm.Create(Application);
|
||
try
|
||
MyReadComponentResFile(FormPath, Form);
|
||
Form.Hide;
|
||
Result := Form.ShowModal;
|
||
finally
|
||
Form.Free;
|
||
end;
|
||
End;
|
||
|
||
{-------------------------------------------}
|
||
|
||
Function MyReadComponentResFile(Const FileName: String;
|
||
Instance: TComponent): TComponent;
|
||
Label
|
||
lexit;
|
||
Var
|
||
Stream: TMyStream;
|
||
j: integer;
|
||
HCo: THalComp;
|
||
PasFileName: String;
|
||
{---}
|
||
Procedure updateprops(Instan, MyOwner: TComponent);
|
||
Var
|
||
maxp, i: integer;
|
||
proplist: Array[0..1000] of PPropInfo;
|
||
s: TMethodNameHolder;
|
||
p: TMethod;
|
||
si: TEventListItem;
|
||
TempObj: THalEvent;
|
||
Begin
|
||
maxp := GetPropList(Instan.classinfo, tkmethods, @PropList);
|
||
For i := 0 to maxp - 1 do
|
||
Begin
|
||
P := getmethodprop(Instan, proplist[i]);
|
||
If (Integer(P.Code)>0) and (Integer(P.Code)<=FLMethods.Count) then
|
||
Begin
|
||
S := TMethodNameHolder(FLMethods.Items[Integer(P.Code)-1]);
|
||
si := EventList.ItemByName(proplist[i]^.PropType^.Name);
|
||
If Assigned(si) then
|
||
Begin
|
||
TempObj := Si.EventClass.Create(Nil);
|
||
MyOwner.InsertComponent(TempObj);
|
||
P.Data := TempObj;
|
||
P.Code := Si.Address;
|
||
TempObj.HR := HCo.FHalRuner;
|
||
TempObj.ProcName := S.MethodName;
|
||
End else
|
||
P.Code := Nil;
|
||
S.Free;
|
||
SetMethodProp(Instan, proplist[i], p);
|
||
End;
|
||
End;
|
||
End;
|
||
{---}
|
||
|
||
Begin
|
||
FLMethods.Clear;
|
||
|
||
Stream := TMyStream.Create(FileName, fmOpenRead);
|
||
Try
|
||
Result := Stream.ReadComponentRes(Instance);
|
||
If Result is TForm then
|
||
TForm(Result).Visible:=False;
|
||
Finally
|
||
Stream.Free;
|
||
End;
|
||
|
||
PasFileName := ChangeFIleExt(Filename, '.PAS');
|
||
|
||
If Fileexists(PasFileName) then
|
||
begin
|
||
HCo := THalComp.Create(Result);
|
||
HCo.EventDispatcher:=True;
|
||
HCo.Script.LoadFromFile(PasFileName);
|
||
HCo.Compile('', Nil);
|
||
HCo.FHalRuner.LoadTemp := true;
|
||
HCo.FHalRuner.dontrun := true;
|
||
HCo.Run;
|
||
|
||
UpdateProps(Result, Result);
|
||
j := 0;
|
||
While j <= Instance.ComponentCount - 1 do
|
||
Begin
|
||
UpdateProps(Result.Components[j], Result);
|
||
inc(j);
|
||
End;
|
||
end;
|
||
{------------}
|
||
lexit:
|
||
If (Result is TForm) then
|
||
Begin
|
||
If (Assigned(TForm(Result).OnCreate)) then
|
||
TForm(Result).OnCreate(Result);
|
||
If (Not Assigned(TForm(Result).OnClose)) then
|
||
TForm(Result).OnClose := HCo.FOnFormClose;
|
||
End;
|
||
End;
|
||
{------------------------------}
|
||
(*
|
||
Procedure TFormulaList.AddValue(Const VarName: String; AValue: Variant);
|
||
Begin
|
||
AddVF(VarName, '', AValue, false);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TFormulaList.AddFormula(Const VarName, AFormula: String);
|
||
Begin
|
||
AddVF(VarName, AFormula, NULL, true);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TFormulaList.AddVF(Const VarName, AFormula: String;
|
||
AValue: Variant; ACalc: Boolean);
|
||
Var
|
||
F: TFormulaListItem;
|
||
Begin
|
||
F := TFormulaListItem.Create;
|
||
F.Formula := AFormula;
|
||
F.Value := AValue;
|
||
F.NeedCalc := ACalc;
|
||
AddObject(AnsiUpperCase(VarName), F);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TFormulaList.HVarNameTOId(Const S: String): Integer;
|
||
Begin
|
||
If Find(AnsiUpperCase(S), Result) = false then Result := -1;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TFormulaList.HSetVar(ID: Integer; Value: Variant);
|
||
Begin
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TFormulaList.HGetVar(ID: Integer): Variant;
|
||
Begin
|
||
If IntStack.IndexOf(Pointer(ID)) <> -1
|
||
then
|
||
Raise Exception.CreateFMT(SErrCircularVarRef, [Strings[ID]]);
|
||
Result := GetValue(Strings[ID]);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TFormulaList.CalcFormula(Const AFormula: String): Variant;
|
||
Var
|
||
H: THalComp;
|
||
Begin
|
||
H := THalComp.Create(Nil);
|
||
With H do
|
||
Begin
|
||
VarNameTOID := HVarNameTOID;
|
||
GetVar := HGetVar;
|
||
SetVar := HSetVar;
|
||
Loaded;
|
||
Expression := AFormula;
|
||
End;
|
||
Try
|
||
Result := H.Result;
|
||
Finally
|
||
H.Free;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function TFormulaList.GetValue(Const VarName: String): Variant;
|
||
Var
|
||
i: integer;
|
||
F: TFormulaListItem;
|
||
Begin
|
||
Result := NULL;
|
||
If Find(AnsiUpperCase(VarName), i) = false
|
||
then
|
||
Raise Exception.CreateFMT('Variable %S not found', [VARName]);
|
||
F := Objects[i] as TFormulaListItem;
|
||
With f do
|
||
Begin
|
||
If NeedCalc = false
|
||
then
|
||
Result := Value
|
||
else
|
||
Begin
|
||
Try
|
||
IntStack.Push(i);
|
||
Value := CalcFormula(Formula);
|
||
NeedCalc := False;
|
||
Result := Value;
|
||
Finally
|
||
IntStack.Pop;
|
||
End;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Constructor TFormulaList.Create;
|
||
Begin
|
||
Inherited;
|
||
Sorted := True;
|
||
Duplicates := dupError;
|
||
IntStack := TIntStack.Create;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Destructor TFormulaList.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do
|
||
Objects[i].Free;
|
||
IntStack.Free;
|
||
Inherited;
|
||
End;
|
||
*)
|
||
{------------------------------}
|
||
|
||
Function RunMacro(Const MacroName: String): Variant;
|
||
Begin
|
||
Result := RunMacroFriend(MacroName, Nil);
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function RunMacroFriend(Const MacroName: String; AForm: TForm): Variant;
|
||
Var
|
||
HC: THalComp;
|
||
Begin
|
||
If not FileExists(MacroName) then
|
||
Begin
|
||
ShowMessage(Format(file_not_found, [MacroName])); exit;
|
||
End;
|
||
HC := THalComp.Create(AForm);
|
||
Try
|
||
HC.Script.LoadFromFile(MacroName);
|
||
HC.FScriptChanged := true;
|
||
Result := NULL;
|
||
Result := HC.Result;
|
||
Finally
|
||
HC.Free;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCOmp.FOnFOrmClose(Sender: TObject; Var Action: TCloseAction);
|
||
Begin
|
||
Action := caFree;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalCOmp.Loaded;
|
||
Begin
|
||
Inherited;
|
||
If assigned(FVarNameTOID) and assigned(FGetVar) and assigned(FSetVar)
|
||
Then
|
||
Begin
|
||
AddLocalVar(Name, Fvarnametoid, FSetVar, FGetVar, Self);
|
||
DelOnFree := true;
|
||
End;
|
||
If componentstate = [csdesigning] then exit;
|
||
SetNotifyEvent(ControlLink, EventLink, fmyNotifyEvent);
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Destructor THalComp.Destroy;
|
||
Begin
|
||
If assigned(fhalruner) then FHalRuner.Free;
|
||
If assigned(Fmystream) then FMyStream.Free;
|
||
If delonfree then DelDynaVar(Name);
|
||
FScript.Free;
|
||
Inherited;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Function THalCOmp.getresult: variant;
|
||
Begin
|
||
Compile('', Nil);
|
||
Run;
|
||
getresult := InternalVariables.MyResult;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure THalComp.FMyNotifyEvent(Sender: TObject);
|
||
Begin
|
||
Compile('Sender', sender);
|
||
Run;
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Procedure THalComp.Compile(Const obname: String; ob: tobject);
|
||
Var
|
||
Temp: TStringList;
|
||
Begin
|
||
If FScriptChanged then
|
||
Begin
|
||
FScriptChanged := false;
|
||
If assigned(fhalruner) then FHalRuner.Free;
|
||
If assigned(fMyStream) then FMyStream.Free;
|
||
FHalRuner := Nil;
|
||
End;
|
||
|
||
If not assigned(fhalruner) then
|
||
Begin
|
||
FMyStream := TMemoryStream.Create;
|
||
Temp := TStringList.Create;
|
||
Temp.Assign(FScript);
|
||
Temp.SaveToStream(FMyStream);
|
||
Temp.Free;
|
||
FHalRuner := THalRuner.Create(FMyStream);
|
||
FhalRuner.HALOwner := Self;
|
||
End;
|
||
FOB := ob; Fobname := obname;
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Procedure THalComp.Run;
|
||
{----------------}
|
||
|
||
Procedure addobj(V: TObject);
|
||
Var j: integer;
|
||
Begin
|
||
With V as TForm do
|
||
For j := 0 to ComponentCount - 1 do
|
||
FhalRuner.AddObjectBYRef(Components[j].Name, Components[j]);
|
||
FhalRuner.AddObjectBYRef('Self', TForm(V));
|
||
End;
|
||
|
||
{----------------}
|
||
Begin
|
||
If not assigned(fhalruner) then
|
||
Raise Exception.Create(compile_before);
|
||
FhalRuner.MyObjects.Clear;
|
||
If Friend <> Nil
|
||
then
|
||
AddObj(Friend)
|
||
else
|
||
If Owner <> Nil
|
||
then
|
||
AddObj(Owner);
|
||
FhalRuner.AddObjectBYRef('Screen', Screen);
|
||
FhalRuner.AddObjectBYRef('Application', Application);
|
||
If fob <> Nil then
|
||
FhalRuner.AddObjectbyRef(fobname, fob);
|
||
FMyStream.Seek(0, 0);
|
||
Try
|
||
FHalRuner.Run;
|
||
Finally
|
||
FLastClassType := FHalRuner.FLastClassType;
|
||
End;
|
||
End;
|
||
{------------------------------------}
|
||
|
||
Procedure THalComp.Notification(AComponent: TComponent;
|
||
Operation: TOperation);
|
||
Begin
|
||
Inherited;
|
||
If (Operation = opRemove) and (AComponent = FControl) then
|
||
Begin
|
||
FControl := Nil;
|
||
EventLink := '';
|
||
End;
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Constructor THalComp.Create(AOwner: TComponent);
|
||
Begin
|
||
Inherited;
|
||
FScript := TStringList.Create;
|
||
TStringList(FScript).OnCHange := MyOnChange;
|
||
FScript.Add('begin');
|
||
FScript.Add('end.');
|
||
End;
|
||
|
||
{-------------------------------}
|
||
|
||
Procedure THalComp.SetExpression(Const S: String);
|
||
Var
|
||
t: String;
|
||
Begin
|
||
FExpression := S;
|
||
If S = '' then exit;
|
||
t := s;
|
||
FScriptChanged := true;
|
||
FScript.Clear;
|
||
FSCript.Add('begin');
|
||
If t[length(t)] <> ';'
|
||
then
|
||
t := t + ';';
|
||
FSCript.Add('Result:=' + t);
|
||
FSCript.Add('end.');
|
||
End;
|
||
|
||
{--------------------------------------}
|
||
|
||
Procedure THalComp.SetScript(Value: TStrings);
|
||
Begin
|
||
FScript.Assign(Value);
|
||
FScriptChanged := true;
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Procedure THalComp.MyOnCHange(Sender: TObject);
|
||
Begin
|
||
FScriptCHanged := True;
|
||
End;
|
||
|
||
{--------------------}
|
||
|
||
Procedure InitHalUnit;
|
||
Begin
|
||
AddConst('qrMasterDataAdvance',qrMasterDataAdvance);
|
||
AddConst('qrBandPrinted',qrBandPrinted);
|
||
AddConst('qrBandSizeChange',qrBandSizeChange);
|
||
AddConst('mbLeft',mbLeft);
|
||
AddConst('mbRight',mbRight);
|
||
AddConst('mbMiddle',mbMiddle);
|
||
|
||
AddConst('ssShift',ssShift);
|
||
AddConst('ssAlt',ssAlt);
|
||
AddConst('ssCtrl',ssCtrl);
|
||
AddConst('ssLeft',ssLeft);
|
||
AddConst('ssRight',ssRight);
|
||
AddConst('ssMiddle',ssMiddle);
|
||
AddConst('ssDouble',ssDouble);
|
||
End;
|
||
|
||
{-----------------------------}
|
||
|
||
Procedure RegisterEvents;
|
||
Begin
|
||
RegisterEvent('TQRAfterPrintEvent', @THalEvent.MNotifyEvent, THalEvent);
|
||
RegisterEvent('TQRAfterPreviewEvent', @THalEvent.MNotifyEvent, THalEvent);
|
||
RegisterEvent('TQRNotifyEvent', @THalEvent.MNotifyEvent, THalEvent);
|
||
|
||
RegisterEvent(coNotifyEvent, @THalEvent.MNotifyEvent, THalEvent);
|
||
RegisterEvent(coCloseEvent, @THalEvent.MCloseEvent, THalEvent);
|
||
RegisterEvent('TDragDropEvent', @THalEvent.MDragDropEvent, THalEvent);
|
||
RegisterEvent('TDragOverEvent', @THalEvent.MDragOverEvent, THalEvent);
|
||
RegisterEvent('TEndDragEvent', @THalEvent.MEndDragEvent, THalEvent);
|
||
RegisterEvent('TStartDragEvent', @THalEvent.MStartDragEvent, THalEvent);
|
||
RegisterEvent('TKeyPressEvent', @THalEvent.MKeyPressEvent, THalEvent);
|
||
|
||
RegisterEvent('TQROnNeedDataEvent', @THalEvent.mQROnNeedDataEvent, THalEvent);
|
||
RegisterEvent('TQRNotifyOperationEvent', @THalEvent.mQRNotifyOperationEvent, THalEvent);
|
||
RegisterEvent('TQRBandBeforePrintEvent', @THalEvent.mQRBandBeforePrintEvent, THalEvent);
|
||
RegisterEvent('TQRBandAfterPrintEvent', @THalEvent.mQRBandAfterPrintEvent, THalEvent);
|
||
RegisterEvent('TQRReportBeforePrintEvent', @THalEvent.mQRReportBeforePrintEvent, THalEvent);
|
||
RegisterEvent('TQRFilterEvent', @THalEvent.mQRFilterEvent, THalEvent);
|
||
RegisterEvent('THelpEvent', @THalEvent.MHelpEvent, THalEvent);
|
||
RegisterEvent('TCloseQueryEvent', @THalEvent.MCloseQueryEvent, THalEvent);
|
||
RegisterEvent('TQRLabelOnPrintEvent', @THalEvent.mQRLabelOnPrintEvent, THalEvent);
|
||
RegisterEvent('TQRProgressUpdateEvent', @THalEvent.mQRProgressUpdateEvent, THalEvent);
|
||
RegisterEvent('TQRPageAvailableEvent', @THalEvent.mQRPageAvailableEvent, THalEvent);
|
||
|
||
RegisterEvent('TMouseEvent', @THalEvent.MMouseEvent, THalEvent);
|
||
RegisterEvent('TMouseMoveEvent', @THalEvent.MMouseMoveEvent, THalEvent);
|
||
RegisterEvent('TKeyEvent', @THalEvent.MKeyEvent, THalEvent);
|
||
|
||
End;
|
||
|
||
{---------------------------------}
|
||
(*
|
||
Type
|
||
TMethodsProperty = Class(TStringProperty)
|
||
Public
|
||
Function GetAttributes: TPropertyAttributes; override;
|
||
Procedure GetValueList(List: TStrings); virtual;
|
||
Procedure GetValues(Proc: TGetStrProc); override;
|
||
Function Getvname: String; virtual;
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Function TMethodsProperty.Getvname: String;
|
||
Begin
|
||
Result := 'ControlLink';
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Procedure TMethodsProperty.GetValueList(List: TStrings);
|
||
Var
|
||
Instance: TComponent;
|
||
PropInfo: PPropInfo;
|
||
mc: tcomponent;
|
||
maxp, i: integer;
|
||
proplist: Array[0..1000] of PPropInfo;
|
||
Begin
|
||
List.BeginUpdate;
|
||
List.Clear;
|
||
Instance := TComponent(GetComponent(0));
|
||
PropInfo := TypInfo.GetPropInfo(Instance.ClassInfo, getvname);
|
||
|
||
If (PropInfo <> Nil) and (PropInfo^.PropType^.Kind = tkClass) then
|
||
Begin
|
||
mc := TObject(GetOrdProp(Instance, PropInfo)) as TComponent;
|
||
If (mc = Nil) then mc := Instance.Owner;
|
||
If (mc <> Nil) then
|
||
Begin
|
||
maxp := GetPropList(mc.classinfo, tkmethods, @PropList);
|
||
For i := 0 to maxp - 1 do
|
||
If CompareText(proplist[i]^.proptype^.name, 'TNotifyEvent') = 0 then
|
||
List.Add(proplist[i]^.name);
|
||
End;
|
||
End;
|
||
List.EndUpdate;
|
||
End;
|
||
|
||
{------------------------------}
|
||
*)
|
||
Function TIdentList.ItemByName(Const Aname: String; Var Ident: TIdentListItem): boolean;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
ident := Nil;
|
||
Result := Find(aname, i);
|
||
If result then Ident := TIdentListItem(Objects[i]);
|
||
End;
|
||
(*
|
||
{------------------------------------}
|
||
|
||
Function TMethodsProperty.GetAttributes: TPropertyAttributes;
|
||
Begin
|
||
Result := [paValueList, paSortList, paMultiSelect];
|
||
End;
|
||
|
||
{------------------------------------}
|
||
|
||
Procedure TMethodsProperty.GetValues(Proc: TGetStrProc);
|
||
Var
|
||
I: Integer;
|
||
Values: TStringList;
|
||
Begin
|
||
Values := TStringList.Create;
|
||
Try
|
||
GetValueList(Values);
|
||
For I := 0 to Values.Count - 1 do
|
||
Proc(Values[I]);
|
||
Finally
|
||
Values.Free;
|
||
End;
|
||
End;
|
||
|
||
{------------------------------------------------------------------}
|
||
*)
|
||
Function FindFormInVarDecl(S:TMemoryStream;Const FormName:String;
|
||
Var BegLine,BegPos,EndLine,EndPos:Integer):Boolean;
|
||
Var
|
||
HAL:THALCompiler;
|
||
A:Integer;
|
||
begin
|
||
Result:=False;
|
||
HAL:=THALCompiler.Create(S,nil);
|
||
With HAL do
|
||
try
|
||
While true do
|
||
begin
|
||
Token:=ReadToken;
|
||
If (Token.ID=idEndOfFile) or (Token.ID=id_implement) then break;
|
||
If Token.ID=id_var then
|
||
begin
|
||
Token:=ReadToken;
|
||
If (Token.ID=ididentifier) and (CompareText(Token.Data,FormName)=0) then
|
||
begin
|
||
A:=CurRead-Length(FormName);
|
||
Token:=ReadToken;
|
||
If Token.ID<>id2points then continue;
|
||
Token:=ReadToken;
|
||
If (Token.id<>ididentifier) or (CompareText(Token.Data,'T'+FormName)<>0) then continue;
|
||
ConvertCurPos(EndLine,EndPos);
|
||
CurRead:=A;
|
||
ConvertCurPos(BegLine,BegPos);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------}
|
||
|
||
Function FindFormInTypeDecl(S:TMemoryStream;Const FormName:String;
|
||
Var ALine,APos:Integer):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
FName:String;
|
||
begin
|
||
HAL:=THalCompiler.Create(S,nil);
|
||
Fname:='T'+FormName;
|
||
Result:=False;
|
||
With HAL do
|
||
Try
|
||
While true do
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.ID=idendoffile then break;
|
||
If Token.ID=id_type then
|
||
begin
|
||
Token:=ReadToken;
|
||
If (Token.ID=ididentifier) and (CompareText(Token.Data,FName)=0) then
|
||
begin
|
||
Result:=True;
|
||
CurRead:=CurRead-Length(FName);
|
||
ConvertCurPos(ALine,APos);
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------}
|
||
|
||
procedure FindFormInEventNames(S:TMemoryStream;Const FormName:String;PosList:TPosList);
|
||
Var
|
||
HAL:THalCompiler;
|
||
Skip:Boolean;
|
||
ALine,AChar:Integer;
|
||
FName:String;
|
||
begin
|
||
HAL:=THalCompiler.Create(s,nil);
|
||
Skip:=True;
|
||
FName:='T'+FormName;
|
||
With HAL do
|
||
Try
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.ID=idEndOfFile then break;
|
||
If (Token.id=id_implement) then
|
||
begin
|
||
Skip:=False;
|
||
continue;
|
||
end;
|
||
If Skip then continue;
|
||
If (Token.ID=ididentifier) and (CompareText(FName,Token.Data)=0)
|
||
and (NextToken.ID=idpoint) then
|
||
begin
|
||
Dec(CurRead,Length(FName));
|
||
ConvertCurPos(ALine,AChar);
|
||
Inc(CurRead,Length(FName));
|
||
PosList.AddPos(ALine,AChar);
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------}
|
||
|
||
Function ImplFound(M:TMemoryStream;Var ALine,APos:Integer):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
begin
|
||
Result:=False;
|
||
HAl:=THalCompiler.Create(M,nil);
|
||
With HAL do
|
||
Try
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.id=idEndOfFile then break;
|
||
If Token.id=id_Implement then
|
||
begin
|
||
ConvertCurPos(ALine,APos);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------}
|
||
|
||
function FindEventInCodeGen(S:TMemoryStream;Const EventName:String;
|
||
Var ALine,AChar:Integer):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
begin
|
||
Result:=False;
|
||
HAL:=THalCompiler.Create(S,nil);
|
||
Try
|
||
With HAL do
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.ID=idendoffile then break;
|
||
IF (Token.id =id_procedure) or (Token.ID=id_function) then
|
||
begin
|
||
Token:=ReadToken;
|
||
If (Token.id=ididentifier) and (CompareText(Token.Data,EventName)=0)
|
||
and (NextToken.ID=idOpenBracket) then
|
||
begin
|
||
CurRead:=CurRead-Length(EventName);
|
||
ConvertCurPos(ALine,AChar);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{-----------------------------------------------------------}
|
||
|
||
Function GetCodegenSection(S:TMemoryStream; Const FormClassName:String;
|
||
Var BegLine,BegPos,EndLine,EndPos:Integer):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
sPos:Integer;
|
||
//----------
|
||
function CheckToken(ID:Integer):Boolean;
|
||
begin
|
||
With HAL do
|
||
begin
|
||
Token:=ReadToken;
|
||
Result:=Token.ID=ID;
|
||
end;
|
||
end;
|
||
//----------
|
||
begin
|
||
Result:=False;
|
||
HAL:=THalCompiler.Create(s,nil);
|
||
try
|
||
With Hal do
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.ID=idendoffile then break;
|
||
If (Token.id=ididentifier) and (CompareText(FormClassName,Token.Data)=0) then
|
||
begin
|
||
if CheckToken(idequal)=False then continue;
|
||
if CheckToken(id_class)=False then continue;
|
||
if CheckToken(idopenbracket)=False then continue;
|
||
if CheckToken(ididentifier)=False then continue;
|
||
if CheckToken(idclosebracket)=False then continue;
|
||
ConvertCurPos(BegLine,BegPos);
|
||
While True do
|
||
begin
|
||
sPos:=CurRead;
|
||
Token:=ReadToken;
|
||
If Token.ID=idendoffile then break;
|
||
if Token.id=id_private then
|
||
begin
|
||
CurRead:=sPos;
|
||
ConvertCurPos(EndLine,EndPos);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
break;
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{-----------------------------------------------------------}
|
||
|
||
Function GetUnitNamePos(S:TMemoryStream; Var ALine,APos,Aleng:Integer):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
OCurread:Integer;
|
||
begin
|
||
Result:=False;
|
||
HAL:=THalCompiler.Create(s,nil);
|
||
Try
|
||
With HAl do
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
if token.id=idendoffile then break;
|
||
if token.id=id_unit then
|
||
begin
|
||
Token:=ReadToken;
|
||
OCurRead:=CurRead;
|
||
While InBuf[CurRead]<>' ' do dec(CurRead);
|
||
ALeng:=OCurRead-CurRead;
|
||
ConvertCurPos(ALine,APos);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
finally
|
||
HAl.Free;
|
||
end;
|
||
end;
|
||
|
||
{-----------------------------------------------------------}
|
||
|
||
Function GetUsesPos(S:TMemoryStream;Var BegLine,BegPos,EndLine,EndPos:Integer;
|
||
AfterImpl:Boolean):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
sPos:Integer;
|
||
label
|
||
l1;
|
||
begin
|
||
Result:=False;
|
||
HAL:=THalCompiler.Create(S,nil);
|
||
Try
|
||
With HAL do
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
if Token.ID=idendoffile then break;
|
||
If (Token.ID=id_implement) and (AfterImpl) then
|
||
begin
|
||
AfterImpl:=False;
|
||
continue;
|
||
end;
|
||
IF AfterImpl then continue;
|
||
if Token.ID=id_uses then
|
||
begin
|
||
ConvertCurPos(BegLine,BegPos);
|
||
While True do
|
||
begin
|
||
sPos:=CurRead;
|
||
Token:=ReadToken;
|
||
If Token.ID=idendoffile then goto l1;
|
||
if token.id=idDelimeter then
|
||
begin
|
||
CurRead:=sPos;
|
||
Result:=True;
|
||
ConvertCurPos(EndLine,EndPos);
|
||
Goto L1;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
l1:
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{-----------------------------------------------------------}
|
||
|
||
Function GetMethodLine(S:TMemoryStream;Const AMethodName:String;
|
||
Var BegLine,BegPos,EndLine,EndPos:Integer):boolean;
|
||
Var
|
||
TypeName,FMethodName:String;
|
||
i:integer;
|
||
HAL:THalCompiler;
|
||
//----------------
|
||
procedure FindMethod;
|
||
Var
|
||
BPos:Integer;
|
||
begin
|
||
With HAL do
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
BPos:=CurRead;
|
||
if Token.id=idEndOfFile then break;
|
||
if (Token.id=idIdentifier) and (CompareText(Token.Data,TypeName)=0) then
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.id=idpoint then
|
||
begin
|
||
Token:=ReadToken;
|
||
If (Token.id=idIdentifier) and (CompareText(Token.Data,FMethodName)=0) then
|
||
begin
|
||
ConvertCurPos(EndLine,EndPos);
|
||
CurRead:=BPos-Length(TypeName);
|
||
ConvertCurPos(BegLine,BegPos);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
//----------------
|
||
begin
|
||
Result:=False;
|
||
i:=Pos('.',AMethodName);
|
||
TypeName:=Copy(AMethodName,1,i-1);
|
||
FMethodName:=Copy(AMethodName,i+1,MaxInt);
|
||
try
|
||
HAL:=THalCompiler.Create(S,nil);
|
||
FindMethod;
|
||
finally
|
||
HAl.Free;
|
||
end;
|
||
end;
|
||
|
||
{-----------------------------------------------------------}
|
||
|
||
Function FindProgramEnd(S:TMemoryStream; Var ALine,AChar:Integer):Boolean;
|
||
Var
|
||
HAL:THalCompiler;
|
||
sPos:Integer;
|
||
begin
|
||
Result:=False;
|
||
HAL:=THalCompiler.Create(S,nil);
|
||
Try
|
||
With HAL do
|
||
While True do
|
||
begin
|
||
Token:=ReadToken;
|
||
If Token.ID=idendoffile then break;
|
||
If Token.ID=id_unitinit then
|
||
begin
|
||
CurRead:=CurRead-Length('initialization');
|
||
ConvertCurPos(ALine,AChar);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
IF Token.ID=id_end then
|
||
begin
|
||
sPos:=CurRead;
|
||
Token:=ReadToken;
|
||
If Token.ID=idpoint then
|
||
begin
|
||
CurRead:=sPos-3;
|
||
ConvertCurPos(ALine,AChar);
|
||
Result:=True;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
finally
|
||
HAL.Free;
|
||
end;
|
||
end;
|
||
|
||
{---------------------------------}
|
||
|
||
Procedure DelphinRegister;
|
||
Begin
|
||
RegisterComponents('Dream Controls', [THalComp]);
|
||
//RegisterPropertyEditor(typeinfo(String), thalcomp, 'EventLink', TMethodsProperty);
|
||
End;
|
||
|
||
{---------------------------------}
|
||
|
||
Procedure AddProc(Const Aname: String; ProcAddr: TProcType; Const Params: Array of byte);
|
||
var
|
||
APropName : String;
|
||
Begin
|
||
APropName := copy(AName,pos('.',AName)+1,length(AName));
|
||
Funs.AddItem(Aname, APropName, ProcAddr, true, false, false, Params);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure AddFun(Const Aname: String; ProcAddr: TProcType;
|
||
Const Params: Array of byte);
|
||
var
|
||
APropName : String;
|
||
Begin
|
||
APropName := copy(AName,pos('.',AName)+1,length(AName));
|
||
Funs.AddItem(Aname, APropName, ProcAddr, false, false, false, Params);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure AddArrayProp(Const Aname: String; ADim: Integer; ProcAddr, SetProcAddr: TProcType);
|
||
Var
|
||
A: Array[0..100] of byte;
|
||
i: integer;
|
||
APropName : String;
|
||
Begin
|
||
For i := 0 to ADim - 1 do
|
||
A[i] := 0; A[ADim] := 4;
|
||
|
||
APropName := copy(AName,pos('.',AName)+1,length(AName));
|
||
|
||
Funs.AddItem(Aname, APropName, ProcAddr, false, true, false, Slice(A, ADim));
|
||
If Assigned(SetProcAddr) then
|
||
Funs.AddItem(Aname + '_VET', APropName, SetProcAddr, false, true, true, Slice(A, ADim + 1));
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Procedure AddProp(Const Aname: String; ProcAddr, SetProcAddr: TProcType);
|
||
var
|
||
APropName : String;
|
||
Begin
|
||
APropName := copy(AName,pos('.',AName)+1,length(AName));
|
||
Funs.AddItem(Aname, APropName, ProcAddr, false, true, false, [2]);
|
||
If Assigned(SetProcAddr) then
|
||
Funs.AddItem(Aname + '_SET', APropName, SetProcAddr, false, true, true, [0]);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
{function SimpleCallHalProc(Const ProcName:String):Variant;
|
||
Var
|
||
s: Array[0..1] of variant;
|
||
begin
|
||
Result:=CallHalProc(ProcName,nil,S);
|
||
end;}
|
||
|
||
{--------------------------------}
|
||
(*
|
||
Function CallHalProc(Const procName: String;
|
||
slf: tobject; Var s: Array of variant): variant;
|
||
Var
|
||
R: TProcType;
|
||
Begin
|
||
Result := NULL;
|
||
R := GetHalProcAddr(procname);
|
||
If Assigned(R) then
|
||
Result := R(slf, s)
|
||
{ Else Raise
|
||
Exception.CreateFmt(fun_notfound, [AnsiUpperCase(procname)]);}
|
||
End;
|
||
*)
|
||
{------------------------------}
|
||
|
||
Constructor TFunList.Create;
|
||
Begin
|
||
Inherited Create;
|
||
Sorted := true;
|
||
Duplicates := dupIgnore;
|
||
End;
|
||
|
||
{-----------------------------------------------------------}
|
||
|
||
function Min(A,B:Integer):Integer;
|
||
begin
|
||
If A<B
|
||
then
|
||
Result:=A
|
||
else
|
||
Result:=B;
|
||
|
||
end;
|
||
|
||
{------------------------------}
|
||
|
||
Destructor TFunList.Destroy;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
For i := 0 to Count - 1 do
|
||
Objects[i].Free;
|
||
Inherited destroy;
|
||
End;
|
||
|
||
{------------------------------}
|
||
|
||
Procedure TFunList.AddItem(Const Aname,APropName: String; ProcAddr: TProcType;
|
||
Fun, IsProp, IsPropSet: Boolean; Const Params: Array of byte);
|
||
Var
|
||
t: TFunListItem;
|
||
i: integer;
|
||
Begin
|
||
Try
|
||
t := TFunListItem.Create;
|
||
If params[0] = 2 then
|
||
t.parcount := 0
|
||
else
|
||
t.ParCount := min(maxparams, high(Params) + 1);
|
||
t.Fun := Fun;
|
||
t.PropName := APropName;
|
||
t.IsProp := IsProp;
|
||
t.IsPropSet := IsPropSet;
|
||
t.procaddr := procaddr;
|
||
If params[0] <> 2 then
|
||
For i := 0 to min(high(Params), maxparams) do t.Params[i] := Params[i];
|
||
addobject(AnsiUpperCase(aname), t)
|
||
Except
|
||
Raise Exception.CreateFmt(SErrFunDefined, [ANAme]);
|
||
End;
|
||
End;
|
||
|
||
{------------------------------------------------------------------}
|
||
|
||
procedure DelProc(Const ProcName:String);
|
||
Var
|
||
i:Integer;
|
||
begin
|
||
With Funs do
|
||
If Find(AnsiUpperCase(ProcName),i) then
|
||
begin
|
||
Objects[i].Free;
|
||
Delete(i);
|
||
end{ else
|
||
Raise Exception.CreateFmt('Procedure %s not found',[ProcName])};
|
||
end;
|
||
|
||
{--------------------------------}
|
||
|
||
Function OV(S: TObject): Variant;
|
||
Begin
|
||
Result := ObjToVar(S);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Function VO(S: Variant): TObject;
|
||
Begin
|
||
Result := VarToObj(S);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Function ObjToVar(S: TObject): Variant;
|
||
Begin
|
||
TVarData(Result).VPointer := Pointer(s);
|
||
TVarData(Result).VType := vtinteger;
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
Function VarToObj(S: Variant): TObject;
|
||
Begin
|
||
Result := TObject(TVarData(S).VPointer);
|
||
End;
|
||
|
||
{--------------------------------}
|
||
|
||
{Function GetHalProcAddr(Const FunName: String): tproctype;
|
||
Var
|
||
i: integer;
|
||
Begin
|
||
Result := Nil;
|
||
If Funs.Find(AnsiUpperCase(FunName), i) then
|
||
Result := TFunListItem(Funs.Objects[i]).ProcAddr;
|
||
End;}
|
||
|
||
{----------------------------------------------}
|
||
|
||
|
||
|
||
Initialization
|
||
// addconst('pp',ssDouble);
|
||
Funs := TFunList.Create;
|
||
|
||
ResWords := TIdentList.Create;
|
||
InitReservedWords;
|
||
Dynavars := TDynaVars.Create;
|
||
InternalVariables := TInternalVar.Create;
|
||
ResConsts := TResConstList.Create;
|
||
|
||
RegisterClasses([THAlComp]);
|
||
InitHalUnit;
|
||
FLMethods := TList.Create;
|
||
EventList := TEventList.Create;
|
||
RegisterEvents;
|
||
// EventDispatcher:=CallEvent;
|
||
// ExecuteProgram:=RunFormModal;
|
||
Finalization
|
||
|
||
FLMethods.Free;
|
||
EventList.Free;
|
||
|
||
InternalVariables.Free;
|
||
ResWords.Free;
|
||
DynaVars.Free;
|
||
ResConsts.Free;
|
||
Funs.Free;
|
||
|
||
End.
|