Ast development

This commit is contained in:
Michael Schimmel
2025-09-02 17:49:30 +02:00
parent a83bbf4f54
commit eb7902d9e8
7 changed files with 257 additions and 83 deletions
+36 -37
View File
@@ -399,9 +399,8 @@ var
series: TScalarRecordSeries;
recordValue: TScalarRecord;
visitor: IAstVisitor;
ast: IAstNode;
ast: IExpressionNode;
resultValue: TAstValue;
resultRecord: TScalarRecord;
i: Integer;
begin
Memo1.Lines.Clear;
@@ -409,17 +408,13 @@ begin
// --- 1. Arrange (in Delphi) ---
Memo1.Lines.Add('1. Arranging test data in Delphi...');
// Clear and prepare the global scope for the script.
FGScope.Clear;
RegisterNativeFunctions(FGScope);
// Generate JSON definition from our test record type.
jsonDef := TRttiAstHelper.RecordDefinitionToJson(TypeInfo(TOHLCV));
FGScope.SetValue('ohlcvDef', TAstValue.FromText(jsonDef));
Memo1.Lines.Add(' - Generated and injected JSON definition for TOHLCV.');
// Create a TScalarRecordSeries and populate it with some data.
recordDef := TRttiAstHelper.JsonToRecordDefinition(jsonDef);
series := TScalarRecordSeries.Create(recordDef);
for i := 0 to 4 do
@@ -439,7 +434,6 @@ begin
series.Add(recordValue);
end;
// Inject the pre-populated series into the script's scope.
FGScope.SetValue('ohlcvSeries', TAstValue.FromRecordSeries(series));
Memo1.Lines.Add(Format(' - Created and injected a series with %d records.', [series.TotalCount]));
Memo1.Lines.Add('');
@@ -447,24 +441,32 @@ begin
// --- 2. Act (in Script) ---
Memo1.Lines.Add('2. Executing script...');
// Create an AST that:
// a) Creates a new, empty series to test the native function.
// b) Accesses the 3rd element (index 2) of the pre-populated series.
// c) Returns the accessed record as the final result.
// This script now tests member access and indexing the resulting member series.
// let closeColumn = ohlcvSeries.Close;
// let secondClose = closeColumn[1];
// secondClose
ast :=
TAst.Block(
[
TAst.VarDecl(
TAst.Identifier('newSeries'),
TAst.FunctionCall(TAst.Identifier('CreateRecordSeries'), [TAst.Identifier('ohlcvDef')])
),
TAst.Indexer(TAst.Identifier('ohlcvSeries'), TAst.Constant(TScalar.FromInt64(2)))
]
TAst.LambdaExpr(
[],
TAst.Block(
[
TAst.VarDecl(
TAst.Identifier('closeColumn'),
TAst.MemberAccess(TAst.Identifier('ohlcvSeries'), TAst.Identifier('Close'))
),
TAst.VarDecl(
TAst.Identifier('secondClose'),
TAst.Indexer(TAst.Identifier('closeColumn'), TAst.Constant(TScalar.FromInt64(1)))
),
TAst.AssignResult(TAst.Identifier('secondClose'))
]
)
);
FLastAst := ast;
visitor := TEvaluatorVisitor.Create(FGScope);
resultValue := ast.Accept(visitor);
resultValue := TAst.FunctionCall(ast, []).Accept(visitor);
Memo1.Lines.Add(' - Script finished.');
Memo1.Lines.Add(Format(' - Script returned value of type: %s', [GetEnumName(TypeInfo(TAstValueKind), Ord(resultValue.Kind))]));
Memo1.Lines.Add('');
@@ -472,34 +474,31 @@ begin
// --- 3. Assert (in Delphi) ---
Memo1.Lines.Add('3. Asserting results in Delphi...');
if (resultValue.Kind <> avkRecord) then
if (resultValue.Kind <> avkScalar) then
begin
Memo1.Lines.Add('TEST FAILED: Script did not return a record.');
Memo1.Lines.Add('TEST FAILED: Script did not return a scalar value.');
exit;
end;
Memo1.Lines.Add(' - Result is a scalar, as expected.');
resultRecord := resultValue.AsRecord;
Memo1.Lines.Add(' - Result is a record, as expected.');
var resultScalar := resultValue.AsScalar;
if (resultScalar.Kind <> skDouble) then
begin
Memo1.Lines.Add('TEST FAILED: Returned scalar is not a Double.');
exit;
end;
Memo1.Lines.Add(' - Returned scalar is a Double, as expected.');
// Verify the 'Close' price of the 3rd record (index 2)
var closeValue := resultRecord.Items['Close'].Value.AsDouble;
var expectedClose := 102.0 + 2; // from the data generation loop for i=2
var closeValue := resultScalar.Value.AsDouble;
// The script asks for index [1], which is the second-to-last element.
// The data was generated for i in 0..4, so the second-to-last is i=3.
var expectedClose := 102.0 + 3;
if (abs(closeValue - expectedClose) > 0.001) then
begin
Memo1.Lines.Add(Format('TEST FAILED: Expected Close price %f, but got %f.', [expectedClose, closeValue]));
exit;
end;
Memo1.Lines.Add(Format(' - Verified Close price: %f.', [closeValue]));
// Verify the 'Volume' of the 3rd record (index 2)
var volumeValue := resultRecord.Items['Volume'].Value.AsInt64;
var expectedVolume := 10000 * (2 + 1); // for i=2
if (volumeValue <> expectedVolume) then
begin
Memo1.Lines.Add(Format('TEST FAILED: Expected Volume %d, but got %d.', [expectedVolume, volumeValue]));
exit;
end;
Memo1.Lines.Add(Format(' - Verified Volume: %d.', [volumeValue]));
Memo1.Lines.Add('');
Memo1.Lines.Add('--- TEST PASSED ---');
end;