diff --git a/ASTPlayground/MainForm.fmx b/ASTPlayground/MainForm.fmx index 2b14982..7e88d5b 100644 --- a/ASTPlayground/MainForm.fmx +++ b/ASTPlayground/MainForm.fmx @@ -236,23 +236,9 @@ object Form1: TForm1 DataDetectorTypes = [] Lines.Strings = ( '(do' - '(defmacro repeat [n body]' - ' `(do' - ' (def loop (fn [counter]' - ' (if (> counter 0)' - ' (do' - ' ~body' - ' (recur (- counter 1))' - ' )' - ' (do' - ' )' - ' )' - ' ))' - ' (loop ~n)' - ' )' - ')' - '' - '(repeat 5 "hi")' + '(defmacro test [body] `(fn [] ~body ))' + '(defmacro test2 [body] `(fn [] ~body ))' + '(test2 "hi")' ')') StyledSettings = [Size, Style, FontColor] TextSettings.Font.Family = 'Consolas' diff --git a/Src/AST/Myc.Ast.Binding.pas b/Src/AST/Myc.Ast.Binding.pas index 66d9865..ed9ddee 100644 --- a/Src/AST/Myc.Ast.Binding.pas +++ b/Src/AST/Myc.Ast.Binding.pas @@ -46,8 +46,6 @@ type // --- Standard Traversal (Use inherited) --- function VisitKeyword(const Node: IKeywordNode): IAstNode; override; - function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override; - function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override; function VisitRecurNode(const Node: IRecurNode): IAstNode; override; function VisitConstant(const Node: IConstantNode): IAstNode; override; function VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode; override; @@ -171,21 +169,6 @@ begin end; end; -function TAstBinder.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; -begin - // Macros are compile-time only. The Binder (Phase 2) should not see them. - raise Exception.Create('TMyAstBinder: MacroDefinition node encountered.'); -end; - -function TAstBinder.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; -begin - // The MacroExpander (Phase 1) created this node. - // We must bind the ExpandedBody, but keep the MacroExpansionNode wrapper. - // The base TAstTransformer implementation already does exactly this - // by visiting Callee, Arguments, and ExpandedBody. - Result := inherited VisitMacroExpansionNode(Node); -end; - function TAstBinder.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; begin // --- Transformation: Keyword-as-Function --- diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas index 281c043..47226ed 100644 --- a/Src/AST/Myc.Ast.Evaluator.pas +++ b/Src/AST/Myc.Ast.Evaluator.pas @@ -249,10 +249,10 @@ end; function TEvaluatorVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; begin - // Macro definitions are compile-time constructs and should have been - // processed and removed from the AST by the TMacroExpander. - // If we encounter one here, it's a compiler pipeline error. - raise Exception.Create('Macro definitions cannot be evaluated at runtime.'); + // Macro definitions are compile-time constructs. + // The MacroExpander leaves them in the AST for the Visualizer. + // The Evaluator must simply ignore them. + Result := TDataValue.Void; end; function TEvaluatorVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; diff --git a/Src/AST/Myc.Ast.MacroExpander.pas b/Src/AST/Myc.Ast.MacroExpander.pas index 94c455e..3bd90bb 100644 --- a/Src/AST/Myc.Ast.MacroExpander.pas +++ b/Src/AST/Myc.Ast.MacroExpander.pas @@ -259,8 +259,9 @@ function TMacroExpander.VisitMacroDefinition(const Node: IMacroDefinitionNode): begin // Register the macro in the current descriptor FCurrentDescriptor.DefineMacro(Node.Name.Name, Node); - // Remove the (defmacro ...) node from the AST; it's compile-time only. - Result := nil; + + // Keep the node in the AST (for the visualizer). + Result := Node; end; function TMacroExpander.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; diff --git a/Src/AST/Myc.Ast.TypeChecker.pas b/Src/AST/Myc.Ast.TypeChecker.pas index 0e82542..d66066a 100644 --- a/Src/AST/Myc.Ast.TypeChecker.pas +++ b/Src/AST/Myc.Ast.TypeChecker.pas @@ -50,8 +50,6 @@ type function VisitConstant(const Node: IConstantNode): IAstNode; override; function VisitKeyword(const Node: IKeywordNode): IAstNode; override; - // Compile-time nodes (should not be present) - function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override; public constructor Create(const ADescriptor: IScopeDescriptor); function Execute(const RootNode: IAstNode; const ADescriptor: IScopeDescriptor): IAstNode; @@ -142,11 +140,6 @@ begin Result := TRecurNode.Create(newArgs, TTypes.Void); end; -function TTypeChecker.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; -begin - raise Exception.Create('TTypeChecker: MacroDefinition node encountered.'); -end; - function TTypeChecker.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; var initType: IStaticType; diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas index fae6576..2eb038b 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -543,13 +543,8 @@ begin end; function TAstTransformer.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; -var - N: TMacroDefinitionNode; begin - N := (Node as TMacroDefinitionNode); - N.Name := Accept(N.Name).AsIdentifier; - N.Parameters := AcceptParameters(N.Parameters); - N.Body := Accept(N.Body); + // Do nothing, just pass the node through Result := Node; end;