Files
MycLib/Src/AST/Myc.Ast.Compiler.Lowering.pas
Michael Schimmel 4e508d90a5 Compiler exceptions
2025-11-25 15:27:57 +01:00

103 lines
3.0 KiB
ObjectPascal

unit Myc.Ast.Compiler.Lowering;
interface
uses
System.SysUtils,
System.Classes,
System.Generics.Collections,
Myc.Data.Scalar,
Myc.Data.Value,
Myc.Ast.Nodes, // Provides EAstException
Myc.Ast.Visitor,
Myc.Ast.Scope,
Myc.Ast.Types,
Myc.Ast;
type
// Exception specific to AST lowering/rewriting errors
ELoweringException = class(EAstException);
IAstLowerer = interface(IAstVisitor)
function Execute(const RootNode: IAstNode): IAstNode;
end;
// This transformer runs *after* TypeChecker (Phase 3).
// It "lowers" the AST by rewriting complex nodes into simpler ones
// that the evaluator can understand (e.g., operator folding).
TAstLowerer = class(TAstTransformer, IAstLowerer)
private
FBinaryOperators: TDictionary<string, TScalar.TBinaryOp>;
FUnaryOperators: TDictionary<string, TScalar.TUnaryOp>;
protected
// Implement Visit methods here when specific lowering logic is added
// (e.g. converting operator function calls to specific node types if added in future)
public
constructor Create;
destructor Destroy; override;
function Execute(const RootNode: IAstNode): IAstNode;
class function Lower(const RootNode: IAstNode): IAstNode; static;
end;
implementation
uses
System.Generics.Defaults,
Myc.Data.Keyword;
{ TAstLowerer }
constructor TAstLowerer.Create;
begin
inherited Create;
// Operator folding maps (Reserved for future static optimization)
FBinaryOperators := TDictionary<string, TScalar.TBinaryOp>.Create;
FBinaryOperators.Add('+', TScalar.TBinaryOp.Add);
FBinaryOperators.Add('-', TScalar.TBinaryOp.Subtract);
FBinaryOperators.Add('*', TScalar.TBinaryOp.Multiply);
FBinaryOperators.Add('/', TScalar.TBinaryOp.Divide);
FBinaryOperators.Add('=', TScalar.TBinaryOp.Equal);
FBinaryOperators.Add('<>', TScalar.TBinaryOp.NotEqual);
FBinaryOperators.Add('<', TScalar.TBinaryOp.Less);
FBinaryOperators.Add('<=', TScalar.TBinaryOp.LessOrEqual);
FBinaryOperators.Add('>', TScalar.TBinaryOp.Greater);
FBinaryOperators.Add('>=', TScalar.TBinaryOp.GreaterOrEqual);
FUnaryOperators := TDictionary<string, TScalar.TUnaryOp>.Create;
FUnaryOperators.Add('not', TScalar.TUnaryOp.Not);
end;
destructor TAstLowerer.Destroy;
begin
FUnaryOperators.Free;
FBinaryOperators.Free;
inherited;
end;
class function TAstLowerer.Lower(const RootNode: IAstNode): IAstNode;
begin
var lowerer := TAstLowerer.Create as IAstLowerer;
try
Result := lowerer.Execute(RootNode);
except
on E: Exception do
raise ELoweringException.Create('Internal Error during AST Lowering: ' + E.Message);
end;
end;
function TAstLowerer.Execute(const RootNode: IAstNode): IAstNode;
begin
if not Assigned(RootNode) then
exit(nil);
Result := Accept(RootNode);
if not Assigned(Result) then
Result := TAst.Block([]);
end;
end.