{*******************************************************} { } { 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', 'À'..'ß', '_']; IdentBackChars: TCharSet = ['A'..'Z', '_', '0'..'9', 'À'..'ß']; 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 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.