From edd3e83377f7d545c4428f4f4495dfe2f400bfa2 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Wed, 5 Nov 2025 10:03:27 +0100 Subject: [PATCH] Fixed macro expansion --- Src/AST/Myc.Ast.Compiler.TCO.pas | 5 -- Src/AST/Myc.Ast.TypeChecker.pas | 7 --- Src/AST/Myc.Ast.Visitor.pas | 12 +++-- Src/Data/Myc.Data.Value.pas | 88 -------------------------------- 4 files changed, 7 insertions(+), 105 deletions(-) diff --git a/Src/AST/Myc.Ast.Compiler.TCO.pas b/Src/AST/Myc.Ast.Compiler.TCO.pas index 85f62b5..80b249b 100644 --- a/Src/AST/Myc.Ast.Compiler.TCO.pas +++ b/Src/AST/Myc.Ast.Compiler.TCO.pas @@ -212,11 +212,6 @@ begin FNextIsTail := FIsTailStack.Peek; N.ExpandedBody := Accept(N.ExpandedBody); - // Also visit the original call nodes, though they are not in tail pos - FNextIsTail := False; - N.Callee := Accept(N.Callee); - N.Arguments := AcceptNodes(N.Arguments); - Result := N; end; diff --git a/Src/AST/Myc.Ast.TypeChecker.pas b/Src/AST/Myc.Ast.TypeChecker.pas index 6f025d3..0e82542 100644 --- a/Src/AST/Myc.Ast.TypeChecker.pas +++ b/Src/AST/Myc.Ast.TypeChecker.pas @@ -51,7 +51,6 @@ type function VisitKeyword(const Node: IKeywordNode): IAstNode; override; // Compile-time nodes (should not be present) - function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override; function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override; public constructor Create(const ADescriptor: IScopeDescriptor); @@ -148,12 +147,6 @@ begin raise Exception.Create('TTypeChecker: MacroDefinition node encountered.'); end; -function TTypeChecker.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; -begin - // TypeChecker runs *after* expansion, so we just visit the body. - Result := Accept(Node.ExpandedBody); -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 35126f9..fae6576 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -503,12 +503,14 @@ var N: TMacroExpansionNode; begin N := (Node as TMacroExpansionNode); - // Visit original call parts - N.Callee := Accept(N.Callee); - N.Arguments := AcceptNodes(N.Arguments); - // Visit expanded body + + // ONLY visit the expanded body, as this is the "real" AST node. N.ExpandedBody := Accept(N.ExpandedBody); - Result := Node; + + // Callee and Arguments are metadata for the visualizer and must NOT be visited + // by subsequent phases (Binder, TypeChecker, etc.). + + Result := Node; // Return the (mutated) wrapper end; function TAstTransformer.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; diff --git a/Src/Data/Myc.Data.Value.pas b/Src/Data/Myc.Data.Value.pas index 845b400..96e2fc7 100644 --- a/Src/Data/Myc.Data.Value.pas +++ b/Src/Data/Myc.Data.Value.pas @@ -63,10 +63,6 @@ type class operator Implicit(const AValue: String): TDataValue; overload; inline; class operator Implicit(const AValue: TDataValue.TFunc): TDataValue; overload; inline; - // atomic operations - function CompareAndSet(const Expected, NewValue: TDataValue): Boolean; - function Reset(const NewValue: TDataValue): TDataValue; - class function FromIntf(const AValue: T): TDataValue; static; function AsIntf: T; inline; @@ -229,53 +225,6 @@ begin Result := (FInterface as TVal).Value; end; -function TDataValue.CompareAndSet(const Expected, NewValue: TDataValue): Boolean; - - function IntfCompareExchange(var VTarget: IInterface; const AValue, Compare: IInterface): IInterface; inline; - begin - if AValue <> nil then - AValue._AddRef; - - Result := IInterface(TInterlocked.CompareExchange(Pointer(VTarget), Pointer(AValue), Pointer(Compare))); - - if (AValue <> nil) and (Pointer(Result) <> Pointer(Compare)) then - AValue._Release; - end; - -begin - Result := false; - if FKind <> Expected.Kind then - exit; - if FKind <> NewValue.Kind then - raise EArgumentException.Create('Value kinds have to match'); - - if FKind = vkVoid then - raise EArgumentException.Create('Value is void'); - - case FKind of - vkScalar: - case FScalar.Kind of - TScalar.TKind.Ordinal, TScalar.TKind.Keyword: - Result := - TInterlocked - .CompareExchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64, Expected.AsScalar.Value.AsInt64) - = Expected.AsScalar.Value.AsInt64; - TScalar.TKind.Float: - Result := - TInterlocked - .CompareExchange(FScalar.Value.AsDouble, NewValue.AsScalar.Value.AsDouble, Expected.AsScalar.Value.AsDouble) - = Expected.AsScalar.Value.AsDouble; - end; - vkPointer: - Result := - TInterlocked.CompareExchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64, Expected.AsScalar.Value.AsInt64) - = Expected.AsScalar.Value.AsInt64; - - vkText, vkSeries, vkRecordSeries, vkRecord, vkGenericRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric: - Result := IntfCompareExchange(FInterface, NewValue.FInterface, Expected.FInterface) = Expected.FInterface; - end; -end; - class function TDataValue.FromIntf(const AValue: T): TDataValue; begin Result.FKind := vkInterface; @@ -345,43 +294,6 @@ begin Result := TMapSeries.Create(SourceSeries, MapperFunc); end; -function TDataValue.Reset(const NewValue: TDataValue): TDataValue; - - function IntfExchange(var VTarget: IInterface; const AValue: IInterface): IInterface; inline; - begin - if AValue <> nil then - AValue._AddRef; - - Result := IInterface(TInterlocked.Exchange(Pointer(VTarget), Pointer(AValue))); - - if AValue <> nil then - AValue._Release; - end; - -begin - if FKind <> NewValue.Kind then - raise EArgumentException.Create('Value kinds have to match'); - - if FKind = vkVoid then - raise EArgumentException.Create('Value is void'); - - case FKind of - vkScalar: - case FScalar.Kind of - TScalar.TKind.Ordinal, TScalar.TKind.Keyword: - Result := TInterlocked.Exchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64); - TScalar.TKind.Float: Result := TInterlocked.Exchange(FScalar.Value.AsDouble, NewValue.AsScalar.Value.AsDouble); - end; - vkPointer: Result := TInterlocked.Exchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64); - - vkText, vkSeries, vkRecordSeries, vkRecord, vkGenericRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric: - begin - Result.FKind := FKind; - Result.FInterface := IntfExchange(FInterface, NewValue.FInterface); - end; - end; -end; - function TDataValue.ToString: String; var sb: TStringBuilder;