103 lines
2.8 KiB
ObjectPascal
103 lines
2.8 KiB
ObjectPascal
unit TestAst;
|
|
|
|
interface
|
|
|
|
uses
|
|
Myc.Ast,
|
|
DUnitX.TestFramework;
|
|
|
|
type
|
|
[TestFixture]
|
|
TTestAst = class
|
|
private
|
|
FScope: TExecutionScope;
|
|
FVisitor: IAstVisitor;
|
|
public
|
|
[Setup]
|
|
procedure Setup;
|
|
[TearDown]
|
|
procedure TearDown;
|
|
|
|
[Test]
|
|
procedure TestHelloWorld;
|
|
[Test]
|
|
procedure TestVariableDeclarationAndUsage;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.Generics.Collections,
|
|
Myc.Data.Types;
|
|
|
|
{ TTestAst }
|
|
|
|
procedure TTestAst.Setup;
|
|
begin
|
|
// Create scope and visitor once for each test
|
|
FScope := TExecutionScope.Create;
|
|
FVisitor := TEvaluatorVisitor.Create(FScope);
|
|
end;
|
|
|
|
procedure TTestAst.TearDown;
|
|
begin
|
|
FVisitor := nil;
|
|
FScope.Free;
|
|
end;
|
|
|
|
procedure TTestAst.TestHelloWorld;
|
|
var
|
|
ast: IExpressionNode;
|
|
resultValue: IDataValue;
|
|
textValue: IDataTextValue;
|
|
begin
|
|
// 1. Build the AST for the expression: "hello " + "world"
|
|
ast := TAst.BinaryExpr(TAst.Constant(TDataType.Text.CreateValue('hello ')), boAdd, TAst.Constant(TDataType.Text.CreateValue('world')));
|
|
|
|
// 2. Execute (evaluate) the AST
|
|
resultValue := ast.Accept(FVisitor);
|
|
|
|
// 3. Assert the result
|
|
Assert.IsNotNull(resultValue, 'The evaluation must return a value.');
|
|
Assert.AreEqual(dkText, resultValue.DataType.Kind, 'The result must be of text kind.');
|
|
|
|
textValue := TDataType.TValue(resultValue).AsText;
|
|
Assert.AreEqual('hello world', textValue.Value, 'The string concatenation result is wrong.');
|
|
end;
|
|
|
|
procedure TTestAst.TestVariableDeclarationAndUsage;
|
|
var
|
|
varDeclStmt: IStatementNode;
|
|
blockStmt: IStatementNode;
|
|
identifierExpr: IExpressionNode;
|
|
resultValue: IDataValue;
|
|
ordinalValue: IDataOrdinalValue;
|
|
begin
|
|
// 1. Build the AST for the statement: let myVar = 42;
|
|
varDeclStmt := TAst.VarDecl(TAst.Identifier('myVar'), TAst.Constant(TDataType.Ordinal.CreateValue(42)));
|
|
|
|
// It's good practice to wrap statements in a block
|
|
blockStmt := TAst.Block([varDeclStmt]);
|
|
|
|
// 2. Build the AST for the expression that uses the variable: myVar
|
|
identifierExpr := TAst.Identifier('myVar');
|
|
|
|
// 3. Execute the statement to declare and assign the variable
|
|
blockStmt.Accept(FVisitor);
|
|
|
|
// 4. Execute the expression to retrieve the variable's value
|
|
resultValue := identifierExpr.Accept(FVisitor);
|
|
|
|
// 5. Assert the result
|
|
Assert.IsNotNull(resultValue, 'The evaluation must return a value.');
|
|
Assert.AreEqual(dkOrdinal, resultValue.DataType.Kind, 'The result must be of ordinal kind.');
|
|
|
|
ordinalValue := TDataType.TValue(resultValue).AsOrdinal;
|
|
Assert.AreEqual(Int64(42), ordinalValue.Value, 'The variable value is wrong.');
|
|
end;
|
|
|
|
initialization
|
|
TDUnitX.RegisterTestFixture(TTestAst);
|
|
|
|
end.
|