Compiler errors
This commit is contained in:
+167
-8
@@ -12,9 +12,70 @@ uses
|
||||
Myc.Ast.Types;
|
||||
|
||||
type
|
||||
// --- Forward Declarations to break cycles ---
|
||||
IAstVisitor = interface;
|
||||
// --- Forward Declarations ---
|
||||
IAstNode = interface;
|
||||
|
||||
// --- Error Handling Infrastructure ---
|
||||
|
||||
TCompilerErrorLevel = (elHint, elWarning, elError);
|
||||
|
||||
TCompilerError = record
|
||||
Level: TCompilerErrorLevel;
|
||||
Message: string;
|
||||
Node: IAstNode; // Context node where the error occurred
|
||||
constructor Create(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode = nil);
|
||||
function ToString: string;
|
||||
end;
|
||||
|
||||
ICompilerLog = interface
|
||||
procedure Add(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode = nil);
|
||||
procedure AddError(const AMessage: string; const ANode: IAstNode = nil);
|
||||
procedure AddWarning(const AMessage: string; const ANode: IAstNode = nil);
|
||||
|
||||
function HasErrors: Boolean;
|
||||
function GetEntryCount: Integer;
|
||||
function GetEntries: TArray<TCompilerError>;
|
||||
|
||||
property Entries: TArray<TCompilerError> read GetEntries;
|
||||
end;
|
||||
|
||||
// Standard implementation of the log
|
||||
TCompilerLog = class(TInterfacedObject, ICompilerLog)
|
||||
private
|
||||
FEntries: TList<TCompilerError>;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Add(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode = nil);
|
||||
procedure AddError(const AMessage: string; const ANode: IAstNode = nil);
|
||||
procedure AddWarning(const AMessage: string; const ANode: IAstNode = nil);
|
||||
function HasErrors: Boolean;
|
||||
function GetEntryCount: Integer;
|
||||
function GetEntries: TArray<TCompilerError>;
|
||||
end;
|
||||
|
||||
// 1. The abstract base class for all Compiler related exceptions.
|
||||
// Catching this will catch compilation failures AND internal logic errors.
|
||||
EAstException = class(Exception);
|
||||
|
||||
// 2. The concrete exception thrown at the END of a compilation pass if errors occurred.
|
||||
// It wraps the accumulated log.
|
||||
ECompilationFailed = class(EAstException)
|
||||
private
|
||||
FErrors: TArray<TCompilerError>;
|
||||
public
|
||||
constructor Create(const AErrors: TArray<TCompilerError>);
|
||||
function ToString: string; override;
|
||||
property Errors: TArray<TCompilerError> read FErrors;
|
||||
end;
|
||||
|
||||
// 3. (Optional) Exception for critical internal bugs (e.g. implementation defects).
|
||||
// This should ideally never happen in production.
|
||||
EInternalCompilerError = class(EAstException);
|
||||
|
||||
// --- AST Interfaces ---
|
||||
|
||||
IAstVisitor = interface;
|
||||
IFunctionDefinition = interface;
|
||||
IIdentifierNode = interface;
|
||||
IConstantNode = interface;
|
||||
@@ -158,7 +219,7 @@ type
|
||||
{$region 'private'}
|
||||
function GetBody: IAstNode;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetIsPure: Boolean; // (* ADDED *)
|
||||
function GetIsPure: Boolean;
|
||||
{$endregion}
|
||||
property Body: IAstNode read GetBody;
|
||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
||||
@@ -249,7 +310,7 @@ type
|
||||
function GetArguments: TArray<IAstNode>;
|
||||
function GetIsTailCall: Boolean;
|
||||
function GetStaticTarget: TDataValue.TFunc;
|
||||
function GetIsTargetPure: Boolean; // (* ADDED *)
|
||||
function GetIsTargetPure: Boolean;
|
||||
{$endregion}
|
||||
property Callee: IAstNode read GetCallee;
|
||||
property Arguments: TArray<IAstNode> read GetArguments;
|
||||
@@ -401,10 +462,6 @@ type
|
||||
// A factory for creating visitors
|
||||
TEvaluatorFactory = reference to function(const Scope: IExecutionScope): IEvaluatorVisitor;
|
||||
|
||||
// Base class for ALL compiler exceptions.
|
||||
// Renamed from IAstException to EAstException to follow standard Delphi naming convention.
|
||||
EAstException = class(Exception);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@@ -429,4 +486,106 @@ begin
|
||||
Value := AValue;
|
||||
end;
|
||||
|
||||
{ TCompilerError }
|
||||
|
||||
constructor TCompilerError.Create(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode);
|
||||
begin
|
||||
Level := ALevel;
|
||||
Message := AMessage;
|
||||
Node := ANode;
|
||||
end;
|
||||
|
||||
function TCompilerError.ToString: string;
|
||||
begin
|
||||
// Simplified string representation for quick debugging
|
||||
case Level of
|
||||
elHint: Result := '[Hint] ';
|
||||
elWarning: Result := '[Warning] ';
|
||||
elError: Result := '[Error] ';
|
||||
end;
|
||||
Result := Result + Message;
|
||||
end;
|
||||
|
||||
{ TCompilerLog }
|
||||
|
||||
constructor TCompilerLog.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FEntries := TList<TCompilerError>.Create;
|
||||
end;
|
||||
|
||||
destructor TCompilerLog.Destroy;
|
||||
begin
|
||||
FEntries.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TCompilerLog.Add(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode);
|
||||
begin
|
||||
FEntries.Add(TCompilerError.Create(ALevel, AMessage, ANode));
|
||||
end;
|
||||
|
||||
procedure TCompilerLog.AddError(const AMessage: string; const ANode: IAstNode);
|
||||
begin
|
||||
Add(elError, AMessage, ANode);
|
||||
end;
|
||||
|
||||
procedure TCompilerLog.AddWarning(const AMessage: string; const ANode: IAstNode);
|
||||
begin
|
||||
Add(elWarning, AMessage, ANode);
|
||||
end;
|
||||
|
||||
function TCompilerLog.HasErrors: Boolean;
|
||||
var
|
||||
entry: TCompilerError;
|
||||
begin
|
||||
Result := False;
|
||||
for entry in FEntries do
|
||||
if entry.Level = elError then
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
function TCompilerLog.GetEntryCount: Integer;
|
||||
begin
|
||||
Result := FEntries.Count;
|
||||
end;
|
||||
|
||||
function TCompilerLog.GetEntries: TArray<TCompilerError>;
|
||||
begin
|
||||
Result := FEntries.ToArray;
|
||||
end;
|
||||
|
||||
{ ECompilationFailed }
|
||||
|
||||
constructor ECompilationFailed.Create(const AErrors: TArray<TCompilerError>);
|
||||
var
|
||||
msg: string;
|
||||
begin
|
||||
if Length(AErrors) > 0 then
|
||||
msg := Format('Compilation failed with %d error(s). First: %s', [Length(AErrors), AErrors[0].Message])
|
||||
else
|
||||
msg := 'Compilation failed with unspecified errors.';
|
||||
inherited Create(msg);
|
||||
FErrors := AErrors;
|
||||
end;
|
||||
|
||||
function ECompilationFailed.ToString: string;
|
||||
var
|
||||
sb: TStringBuilder;
|
||||
err: TCompilerError;
|
||||
begin
|
||||
sb := TStringBuilder.Create;
|
||||
try
|
||||
sb.AppendLine(Message);
|
||||
for err in FErrors do
|
||||
begin
|
||||
sb.Append(' - ');
|
||||
sb.AppendLine(err.ToString);
|
||||
end;
|
||||
Result := sb.ToString;
|
||||
finally
|
||||
sb.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user