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.