Manual de referencia de PascalScript

Éste es el manual de referencia de PascalScript, el lenguaje utilizado en el generador de informes y en el proceso de importación de datos.

Sintaxis de PascalScript

Program -> [PROGRAM Ident ';']
[UsesClause]
Block '.'

UsesClause -> USES (String/,)... ';'

Block -> [DeclSection]...
CompoundStmt

DeclSection -> ConstSection
-> VarSection
-> ProcedureDeclSection

ConstSection -> CONST (ConstantDecl)...

ConstantDecl -> Ident '=' Expression ';'

VarSection -> VAR (VarList ';')...

VarList -> Ident/','... ':' TypeIdent
[InitValue]

TypeIdent -> Ident
-> Array

Array -> ARRAY '[' ArrayDim/','... ']' OF
Ident

ArrayDim -> Expression..Expression
-> Expression

InitValue -> '=' Expression

Expression -> SimpleExpression [RelOp SimpleExpression]...

SimpleExpression -> ['-'] Term [AddOp Term]...

Term -> Factor [MulOp Factor]...

Factor -> Designator
-> UnsignedNumber
-> String
-> '(' Expression ')'
-> NOT Factor
-> '[' SetConstructor ']'

SetConstructor -> SetNode/','...

SetNode -> Expression ['..' Expression]

RelOp -> '>'
-> '<'
-> '<='
-> '>='
-> '<>'
-> '='
-> IN
-> IS

AddOp -> '+'
-> '-'
-> OR
-> XOR

MulOp -> '*'
-> '/'
-> DIV
-> MOD
-> AND
-> SHL
-> SHR

Designator -> ['@'] Ident ['.' Ident | '[' ExprList ']' | '(' ExprList ')']...

ExprList -> Expression/','...

Statement -> [SimpleStatement | StructStmt]

StmtList -> Statement/';'...

SimpleStatement -> Designator
-> Designator ':=' Expression
-> BREAK | CONTINUE | EXIT

StructStmt -> CompoundStmt
-> ConditionalStmt
-> LoopStmt
-> TryStmt
-> WithStmt

CompoundStmt -> BEGIN StmtList END

ConditionalStmt -> IfStmt
-> CaseStmt

IfStmt -> IF Expression THEN Statement [ELSE Statement]

CaseStmt -> CASE Expression OF CaseSelector/';'... [ELSE Statement][';'] END

CaseSelector -> SetConstructor ':' Statement

LoopStmt -> RepeatStmt
-> WhileStmt
-> ForStmt

RepeatStmt -> REPEAT StmtList UNTIL Expression

WhileStmt -> WHILE Expression DO Statement

ForStmt -> FOR Ident ':=' Expression ToDownto Expression DO Statement

ToDownto -> (TO | DOWNTO)

TryStmt -> TRY StmtList (FINALLY | EXCEPT) StmtList END

WithStmt -> WITH (Designator/,..) DO Statement

ProcedureDeclSection -> ProcedureDecl
-> FunctionDecl

ProcedureDecl -> ProcedureHeading ';' Block ';'

ProcedureHeading -> PROCEDURE Ident [FormalParameters]

FunctionDecl -> FunctionHeading ';' Block ';'

FunctionHeading -> FUNCTION Ident [FormalParameters] ':' Ident

FormalParameters -> '(' FormalParam/';'... ')'

FormalParm -> [VAR | CONST] VarList

Estructura del Script

La estructura es la misma que la del lenguaje Object Pascal :

#language PascalScript // esto es opcional
program MyProgram; // esto es opcional

uses 'unit1.pas', 'unit2.pas';

// la sección uses – debe estar antes de
cualquier otra sección

var // sección var
i, j: Integer;

const // sección const
pi = 3.14159;

procedure p1; // procedimientos y funciones
var
i: Integer;

procedure p2; // procedimiento anidado
begin
end;

begin
end;

begin // procedimiento principal que será ejecutado.
end.

Tipos de datos

Internamente siempre se opera con el tipo Variant. Sin embargo se pueden utilizar los siguientes tipos predeterminados en los scripts:

Byte | Igual que el tipo Integer 
Word |
Integer |
Longint |
Cardinal |
TColor |
Boolean
Real | Igual que Extended
Single |
Double |
Extended |
TDate |
TTime |
TDateTime |
Char |
String |
Variant |
Pointer |
Array |

No todos los tipos son compatibles en asignación. Como en Object Pascal no se puede asignar Extended a String o a un Integer. Solo un tipo -Variant- puede ser asignado a todos los demás tipos y puede obtener el valor de cualquier otro tipo.

Clases

No se puede definir una clase dentro del Script, pero se pueden utilizar clases externas predefinidas. Por ejemplo :

var
f: TForm;
b: TButton;

procedure ButtonClick(Sender: TButton);
begin
ShowMessage(Sender.Name);
f.ModalResult := mrOk;
end;

// no es necesario utilizar todos los parámetros en los manejadores de eventos
// porque aquí no se realiza la comprobación de tipos

procedure ButtonMouseMove(Sender: TButton);
begin
b.Caption := 'sacado';
end;

begin
f := TForm.Create(nil);
f.Caption := 'Test it!';
f.BorderStyle := bsDialog;
f.Position := poScreenCenter;
b := TButton.Create(f);
b.Name := 'Button1';
b.Parent := f;
b.SetBounds(10, 10, 75, 25);
b.Caption := 'Test';
b.OnClick := @ButtonClick; { o lo que es lo mismo b.OnClick := 'ButtonClick' }
b.OnMouseMove := @ButtonMouseMove;
f.ShowModal;
f.Free;
end.

Se puede acceder a cualquier propiedad (simple, indexada o por defecto) o método. Todas las propiedades publicadas (published) de los objetos son accesibles desde el Script por defecto. Las propiedades y métodos públicos (public) necesitan el código de implementación -por ese motivo solo se puede acceder a ellos parcialmente (por ejemplo no se puede acceder a los métodos TForm.Print o TForm.Canvas porque no están implementados). También se pueden crear clases nuevas.

Funciones

Estas son las funciones predefinidas que pueden usarse en el Script :

function IntToStr(i: Integer): String
function FloatToStr(e: Extended): String
function DateToStr(e: Extended): String
function TimeToStr(e: Extended): String
function DateTimeToStr(e: Extended): String
function VarToStr(v: Variant): String
function StrToInt(s: String): Integer
function StrToFloat(s: String): Extended
function StrToDate(s: String): Extended
function StrToTime(s: String): Extended
function StrToDateTime(s: String): Extended
function Format(Fmt: String; Args: array):String
function FormatFloat(Fmt: String; Value: Extended): String
function FormatDateTime(Fmt: String; DateTime: TDateTime): String
function FormatMaskText(EditMask: string; Value: string): string
function EncodeDate(Year, Month, Day: Word): TDateTime
procedure DecodeDate(Date: TDateTime; var Year, Month, Day: Word)
function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime
procedure DecodeTime(Time: TDateTime; var Hour, Min, Sec, MSec: Word)
function Date: TDateTime
function Time: TDateTime
function Now: TDateTime
function DayOfWeek(aDate: DateTime): Integer
function IsLeapYear(Year: Word): Boolean
function DaysInMonth(nYear, nMonth: Integer): Integer
function Length(s: String): Integer
function Copy(s: String; from, count: Integer): String
function Pos(substr, s: String): Integer
procedure Delete(var s: String; from, count: Integer): String
procedure Insert(s: String; var s2: String; pos: Integer): String
function Uppercase(s: String): String
function Lowercase(s: String): String
function Trim(s: String): String
function NameCase(s: String): String
function CompareText(s, s1: String): Integer
function Chr(i: Integer): Char
function Ord(ch: Char): Integer
procedure SetLength(var S: String; L: Integer)
function Round(e: Extended): Integer
function Trunc(e: Extended): Integer
function Int(e: Extended): Integer
function Frac(X: Extended): Extended
function Sqrt(e: Extended): Extended
function Abs(e: Extended): Extended
function Sin(e: Extended): Extended
function Cos(e: Extended): Extended
function ArcTan(X: Extended): Extended
function Tan(X: Extended): Extended
function Exp(X: Extended): Extended
function Ln(X: Extended): Extended
function Pi: Extended
procedure Inc(var i: Integer; incr: Integer = 1)
procedure Dec(var i: Integer; decr: Integer = 1)
procedure RaiseException(Param: String)
procedure ShowMessage(Msg: Variant)
procedure Randomize
function Random: Extended
function ValidInt(cInt: String): Boolean
function ValidFloat(cFlt: String): Boolean
function ValidDate(cDate: String): Boolean
function CreateOleObject(ClassName: String): Variant
function VarArrayCreate(Bounds: Array; Typ: Integer): Variant

Algunas funciones tienen parámetros por defecto. Se utilizan del mismo modo que en Delphi :

Inc(a);
Inc(b, 2);

Eventos

Se pueden usar eventos. El siguiente ejemplo muestra como conectar un manejador de eventos al evento TButton.OnClick :

var
b: TButton;
Form1: Tform;

procedure ButtonClick(Sender: TButton);
begin
ShowMessage(Sender.Name);
end;

begin
b := TButton.Create(Form1);
b.Parent := Form1;
b.OnClick := @ButtonClick; // lo mismo que b.OnClick := 'ButtonClick'
b.OnClick := nil; // limpia el evento
end.

Hay algunos eventos predefinidos disponibles en la unidad FS_iEvents:

TfsNotifyEvent
TfsMouseEvent
TfsMouseMoveEvent
TfsKeyEvent
TfsKeyPressEvent
TfsCloseEvent
TfsCloseQueryEvent
TfsCanResizeEvent

Conjuntos y enumeraciones

Las enumeraciones están soportadas. Se puede escribir en el Script :

Form1.BorderStyle := bsDialog;

Los conjuntos no están soportados, sin embargo se pueden utilizar constantes de la siguiente forma :

Font.Style := fsBold; // Font.Style :=  [fsBold] en Delphi
Font.Style := fsBold + fsItalic; // Font.Style := [fsBold, fsItalic]
Font.Style := 0; // Font.Style := []

Arrays

Se soportan todos los tipos de array : estático (mono o multi-dimensional), dinámico y arrays de Variant. Éste es un ejemplo de uso de todos los tipos :

var
ar1: array[0..2] of Integer;
ar2: array of Integer;
ar3: Variant;
SetLength(ar2, 3);
ar3 := VarArrayCreate([0, 2], varInteger);
ar1[0] := 1;
ar2[0] := 1;
ar3[0] := 1;