Macro expander integrated in binder

This commit is contained in:
Michael Schimmel
2025-10-05 02:45:13 +02:00
parent 54bf350c70
commit 0d73a13051
6 changed files with 373 additions and 218 deletions
+166 -6
View File
@@ -10,12 +10,41 @@ uses
type
// Contains the "pure" native implementations.
// These functions work with Delphi-native types (like TScalar) instead of TDataValue,
// making them type-safe and easier to test.
// The registration mechanism below will automatically create the required high-performance
// wrappers to make them available to the script interpreter.
TRtlFunctions = record
public
[TRtlFunction('+')]
class function Add(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('-')]
class function Subtract(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('*')]
class function Multiply(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('/')]
class function Divide(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('=')]
class function Equal(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('<>')]
class function NotEqual(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('<')]
class function LessThan(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('<=')]
class function LessThanOrEqual(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('>')]
class function GreaterThan(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('>=')]
class function GreaterThanOrEqual(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('not')]
class function LogicalNot(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlFunction('Abs')]
class function Abs(const Arg: TScalar): TScalar; static;
@@ -31,8 +60,6 @@ type
[TRtlFunction('Sign')]
class function Sign(const Arg: TScalar): TScalar; static;
// NOTE: Higher-order and complex functions can keep the TDataValue signature for now.
// The registry is smart enough to handle both native types and the TDataValue signature directly.
[TRtlFunction('Memoize')]
class function Memoize(const Args: TArray<TDataValue>): TDataValue; static;
@@ -57,6 +84,139 @@ uses
System.Math,
Myc.Data.Decimal;
{ TRtlFunctions - Operator Implementations }
class function TRtlFunctions.Add(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator + requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Add, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator +.');
Result := res;
end;
class function TRtlFunctions.Subtract(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) = 1 then // Unary negation
begin
if not TScalar.TryUnaryOperation(TScalar.TUnaryOp.Negate, Args[0], res) then
raise EArgumentException.Create('Invalid argument for unary operator -.');
end
else if Length(Args) = 2 then // Binary subtraction
begin
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Subtract, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for binary operator -.');
end
else
raise EArgumentException.Create('Operator - requires 1 or 2 arguments.');
Result := res;
end;
class function TRtlFunctions.Multiply(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator * requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Multiply, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator *.');
Result := res;
end;
class function TRtlFunctions.Divide(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator / requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Divide, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator /.');
Result := res;
end;
class function TRtlFunctions.Equal(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator = requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Equal, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator =.');
Result := res;
end;
class function TRtlFunctions.NotEqual(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator <> requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.NotEqual, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator <>.');
Result := res;
end;
class function TRtlFunctions.LessThan(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator < requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Less, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator <.');
Result := res;
end;
class function TRtlFunctions.LessThanOrEqual(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator <= requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.LessOrEqual, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator <=.');
Result := res;
end;
class function TRtlFunctions.GreaterThan(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator > requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.Greater, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator >.');
Result := res;
end;
class function TRtlFunctions.GreaterThanOrEqual(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator >= requires 2 arguments.');
if not TScalar.TryBinaryOperation(TScalar.TBinaryOp.GreaterOrEqual, Args[0], Args[1], res) then
raise EArgumentException.Create('Invalid arguments for operator >=.');
Result := res;
end;
class function TRtlFunctions.LogicalNot(const Args: TArray<TDataValue>): TDataValue;
var
res: TScalar;
begin
if Length(Args) <> 1 then
raise EArgumentException.Create('Operator not requires 1 argument.');
if not TScalar.TryUnaryOperation(TScalar.TUnaryOp.Not, Args[0], res) then
raise EArgumentException.Create('Invalid argument for operator not.');
Result := res;
end;
{ TRtlFunctions - Standard Functions }
class function TRtlFunctions.Abs(const Arg: TScalar): TScalar;
begin
case Arg.Kind of