unit testunit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,
uSE2Compiler,
// für den Compiler
uSE2UnitCacheMngr,
// für den Unit-Cache-Manager
uSE2Errors,
// für TSE2ErrorType
uSE2Reader,
// wird zum Lesen der Daten benutzt
uSE2PEData,
// die ByteCode-Daten
uSE2RunTime;
// für die RunTime
type
TForm1 =
class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
procedure CompilerError(Sender: TObject; ErrorType: TSE2ErrorType; ErrorUnit, ErrorText:
string; ErrorPos, ErrorLine: integer; UserData: TObject);
procedure CompilerNeedUnit(Sender: TObject;
const Name:
string;
const Readers: TList);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Compiler : TSE2Compiler;
RunTime : TSE2RunTime;
PEData : TSE2PE;
begin
Compiler := TSE2Compiler.Create;
// den Compiler erstellen
try // hier wird der Quelltext des Scripts compiliert
Compiler.OnGetFile := CompilerNeedUnit;
Compiler.OnCompilerError := CompilerError;
PEData := Compiler.Compile(
'
program MyScript;'
+#13#10+ '
uses MyUnit;'
+#13#10+ '
var i: integer;'
+#13#10+ '
begin'+#13#10+ '
i := Add(2, 4);'
+#13#10+ '
Console.WriteLine(i);'
+#13#10+ '
end.'+#13#10);
// falls das compilieren erfolgreich war, ist PEData ungleich nil
if PEData <>
nil then
begin
try // hier wird die RunTime erstellt, die das kompilierte
// Script ausführt
RunTime := TSE2RunTime.Create;
try
// zuerst muss das kompilierte Script übergeben werden
RunTime.AppCode := PEData;
// nun muss die RunTime initialisiert werden
RunTime.Initialize;
// hier wird das Script ausgeführt
RunTime.Run;
// nun noch die RunTime stoppen
RunTime.Finalize;
// wenn wir folgende Zeile nicht einfügen
// RunTime.AppCode := nil
// wird das Objekt PEData automatisch von der RunTime
// freigegeben.
// Da wir das aber selbst machen, fügen wir die Zeile ein RunTime.AppCode := nil;
finally
// die RunTime freigeben
RunTime.Free;
end;
finally
// das kompilierte Skript freigeben
PEData.Free;
end;
end;
finally // den Compiler freigeben
Compiler.Free;
end;
end;
procedure TForm1.CompilerError(Sender: TObject; ErrorType: TSE2ErrorType; ErrorUnit, ErrorText:
string; ErrorPos, ErrorLine: integer; UserData: TObject);
begin
// nur Fehler anzeigen
if ErrorType = petError
then // Fehlernachricht anzeigen
ShowMessage('
Compiler error: '+#13#10+ Format('
[%s] [Zeile %d]: %s', [ErrorUnit, ErrorLine, ErrorText] ) );
end;
procedure TForm1.CompilerNeedUnit(Sender: TObject;
const Name:
string;
const Readers: TList);
begin
// falls der Compiler die Unit "MyUnit" haben will
if SameText(
Name, '
MyUnit')
then
begin
// dann wird er Quelltext der Unit hinzugefügt
// dazu muss in der Liste "Readers" ein Objekt vom
// Typ "TSE2Reader" hinzufügen. Jedoch ist "TSE2Reader"
// eine abstrakte Klasse. Vom Reader sind zwei Versionen
// bei der Script-Engine mit dabei:
// - ein StringReader, mit dem man direkt den Quelltext als
// string übergeben kann
// - ein StreamReader, mit dem man den Stream mit dem Quelltext
// auslesen kann
// da hier direkt ein String benutzt wird, wird der TStringReader
// benutzt
Readers.Add( TSE2StringReader.Create(
// nun übergibt man im Constructor direkt den Quelltext
// der Unit "MyUnit"
'
unit MyUnit;'+#13#10+
'
interface'+#13#10+
'
function Add(const i1, i2: integer): integer;'+#13#10+
'
implementation'+#13#10+
'
function Add(const i1, i2: integer): integer;'+#13#10+
'
begin result := i1 + i2;end;'+#13#10+
'
end.' ) );
end;
end;
end.