AST Identities
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -27,7 +27,8 @@ uses
|
||||
Myc.Ast.Compiler.Specializer in '..\Src\AST\Myc.Ast.Compiler.Specializer.pas',
|
||||
Myc.Ast.Environment in '..\Src\AST\Myc.Ast.Environment.pas',
|
||||
Myc.Ast.Debugger in '..\Src\AST\Myc.Ast.Debugger.pas',
|
||||
Myc.Ast.Analysis.Purity in '..\Src\AST\Myc.Ast.Analysis.Purity.pas';
|
||||
Myc.Ast.Analysis.Purity in '..\Src\AST\Myc.Ast.Analysis.Purity.pas',
|
||||
Myc.Ast.Identities in '..\Src\AST\Myc.Ast.Identities.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Environment.pas"/>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Debugger.pas"/>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Analysis.Purity.pas"/>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Identities.pas"/>
|
||||
<BuildConfiguration Include="Base">
|
||||
<Key>Base</Key>
|
||||
</BuildConfiguration>
|
||||
|
||||
@@ -0,0 +1,395 @@
|
||||
unit Myc.Ast.Identities;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
Myc.Data.Value,
|
||||
Myc.Data.Keyword;
|
||||
|
||||
type
|
||||
// Forward declarations
|
||||
INamedIdentity = interface;
|
||||
IConstantIdentity = interface;
|
||||
IKeywordIdentity = interface;
|
||||
IDefinitionIdentity = interface;
|
||||
|
||||
// Represents a position in the source code.
|
||||
ISourceLocation = interface
|
||||
function GetLine: Integer;
|
||||
function GetCol: Integer;
|
||||
function ToString: string;
|
||||
property Line: Integer read GetLine;
|
||||
property Col: Integer read GetCol;
|
||||
end;
|
||||
|
||||
// Discriminator enum for identity types.
|
||||
TAstIdentityKind = (
|
||||
ikStructural, // Pure location, no extra data (e.g. If, Block)
|
||||
ikNamed, // Identifier, MacroDef (Name + Location)
|
||||
ikConstant, // Literals (Value + Location)
|
||||
ikKeyword, // Keywords (Keyword + Location)
|
||||
ikDefinition // Complex definitions (DefString + Location)
|
||||
);
|
||||
|
||||
// Base interface for the "Green Tree" nodes.
|
||||
// Holds the raw syntax data and optional source location.
|
||||
IAstIdentity = interface
|
||||
{$region 'private'}
|
||||
function GetKind: TAstIdentityKind;
|
||||
function GetLocation: ISourceLocation;
|
||||
{$endregion}
|
||||
|
||||
function ToString: string;
|
||||
|
||||
// Explicit casting methods (Fail-Fast)
|
||||
function AsNamed: INamedIdentity;
|
||||
function AsConstant: IConstantIdentity;
|
||||
function AsKeyword: IKeywordIdentity;
|
||||
function AsDefinition: IDefinitionIdentity;
|
||||
|
||||
property Kind: TAstIdentityKind read GetKind;
|
||||
|
||||
// Optional: Returns nil if the node has no source mapping (e.g. generated code)
|
||||
property Location: ISourceLocation read GetLocation;
|
||||
end;
|
||||
|
||||
INamedIdentity = interface(IAstIdentity)
|
||||
{$region 'private'}
|
||||
function GetName: string;
|
||||
{$endregion}
|
||||
property Name: string read GetName;
|
||||
end;
|
||||
|
||||
IConstantIdentity = interface(IAstIdentity)
|
||||
{$region 'private'}
|
||||
function GetValue: TDataValue;
|
||||
{$endregion}
|
||||
property Value: TDataValue read GetValue;
|
||||
end;
|
||||
|
||||
IKeywordIdentity = interface(IAstIdentity)
|
||||
{$region 'private'}
|
||||
function GetValue: IKeyword;
|
||||
{$endregion}
|
||||
property Value: IKeyword read GetValue;
|
||||
end;
|
||||
|
||||
IDefinitionIdentity = interface(IAstIdentity)
|
||||
{$region 'private'}
|
||||
function GetDefinition: string;
|
||||
{$endregion}
|
||||
property Definition: string read GetDefinition;
|
||||
end;
|
||||
|
||||
// Factory and static access.
|
||||
TIdentities = record
|
||||
public
|
||||
class function Location(ALine, ACol: Integer): ISourceLocation; static;
|
||||
|
||||
class function Structural(const ALoc: ISourceLocation = nil): IAstIdentity; static;
|
||||
class function Identifier(const AName: string; const ALoc: ISourceLocation = nil): INamedIdentity; static;
|
||||
class function Constant(const AValue: TDataValue; const ALoc: ISourceLocation = nil): IConstantIdentity; static;
|
||||
class function Keyword(const AValue: IKeyword; const ALoc: ISourceLocation = nil): IKeywordIdentity; static;
|
||||
class function Definition(const ADef: string; const ALoc: ISourceLocation = nil): IDefinitionIdentity; static;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
TSourceLocation = class(TInterfacedObject, ISourceLocation)
|
||||
private
|
||||
FLine, FCol: Integer;
|
||||
function GetLine: Integer;
|
||||
function GetCol: Integer;
|
||||
public
|
||||
constructor Create(ALine, ACol: Integer);
|
||||
function ToString: string; override;
|
||||
end;
|
||||
|
||||
// Abstract base implementation providing the casting logic
|
||||
TAbstractIdentity = class(TInterfacedObject, IAstIdentity)
|
||||
private
|
||||
FLocation: ISourceLocation;
|
||||
function GetKind: TAstIdentityKind; virtual; abstract;
|
||||
function GetLocation: ISourceLocation;
|
||||
public
|
||||
constructor Create(const ALoc: ISourceLocation);
|
||||
function ToString: string; override;
|
||||
|
||||
function AsNamed: INamedIdentity; virtual;
|
||||
function AsConstant: IConstantIdentity; virtual;
|
||||
function AsKeyword: IKeywordIdentity; virtual;
|
||||
function AsDefinition: IDefinitionIdentity; virtual;
|
||||
end;
|
||||
|
||||
TStructuralIdentity = class(TAbstractIdentity)
|
||||
protected
|
||||
function GetKind: TAstIdentityKind; override;
|
||||
end;
|
||||
|
||||
TNamedIdentity = class(TAbstractIdentity, INamedIdentity)
|
||||
private
|
||||
FName: string;
|
||||
function GetName: string;
|
||||
protected
|
||||
function GetKind: TAstIdentityKind; override;
|
||||
public
|
||||
constructor Create(const AName: string; const ALoc: ISourceLocation);
|
||||
function ToString: string; override;
|
||||
function AsNamed: INamedIdentity; override;
|
||||
end;
|
||||
|
||||
TConstantIdentity = class(TAbstractIdentity, IConstantIdentity)
|
||||
private
|
||||
FValue: TDataValue;
|
||||
function GetValue: TDataValue;
|
||||
protected
|
||||
function GetKind: TAstIdentityKind; override;
|
||||
public
|
||||
constructor Create(const AValue: TDataValue; const ALoc: ISourceLocation);
|
||||
function ToString: string; override;
|
||||
function AsConstant: IConstantIdentity; override;
|
||||
end;
|
||||
|
||||
TKeywordIdentity = class(TAbstractIdentity, IKeywordIdentity)
|
||||
private
|
||||
FValue: IKeyword;
|
||||
function GetValue: IKeyword;
|
||||
protected
|
||||
function GetKind: TAstIdentityKind; override;
|
||||
public
|
||||
constructor Create(const AValue: IKeyword; const ALoc: ISourceLocation);
|
||||
function ToString: string; override;
|
||||
function AsKeyword: IKeywordIdentity; override;
|
||||
end;
|
||||
|
||||
TDefinitionIdentity = class(TAbstractIdentity, IDefinitionIdentity)
|
||||
private
|
||||
FDefinition: string;
|
||||
function GetDefinition: string;
|
||||
protected
|
||||
function GetKind: TAstIdentityKind; override;
|
||||
public
|
||||
constructor Create(const ADef: string; const ALoc: ISourceLocation);
|
||||
function ToString: string; override;
|
||||
function AsDefinition: IDefinitionIdentity; override;
|
||||
end;
|
||||
|
||||
{ TSourceLocation }
|
||||
|
||||
constructor TSourceLocation.Create(ALine, ACol: Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
FLine := ALine;
|
||||
FCol := ACol;
|
||||
end;
|
||||
|
||||
function TSourceLocation.GetCol: Integer;
|
||||
begin
|
||||
Result := FCol;
|
||||
end;
|
||||
|
||||
function TSourceLocation.GetLine: Integer;
|
||||
begin
|
||||
Result := FLine;
|
||||
end;
|
||||
|
||||
function TSourceLocation.ToString: string;
|
||||
begin
|
||||
Result := Format('Line %d, Col %d', [FLine, FCol]);
|
||||
end;
|
||||
|
||||
{ TAbstractIdentity }
|
||||
|
||||
constructor TAbstractIdentity.Create(const ALoc: ISourceLocation);
|
||||
begin
|
||||
inherited Create;
|
||||
FLocation := ALoc;
|
||||
end;
|
||||
|
||||
function TAbstractIdentity.GetLocation: ISourceLocation;
|
||||
begin
|
||||
Result := FLocation;
|
||||
end;
|
||||
|
||||
function TAbstractIdentity.ToString: string;
|
||||
begin
|
||||
if Assigned(FLocation) then
|
||||
Result := FLocation.ToString
|
||||
else
|
||||
Result := '<unknown location>';
|
||||
end;
|
||||
|
||||
function TAbstractIdentity.AsNamed: INamedIdentity;
|
||||
begin
|
||||
raise EInvalidCast.Create('Identity is not a Named Identity');
|
||||
end;
|
||||
|
||||
function TAbstractIdentity.AsConstant: IConstantIdentity;
|
||||
begin
|
||||
raise EInvalidCast.Create('Identity is not a Constant Identity');
|
||||
end;
|
||||
|
||||
function TAbstractIdentity.AsKeyword: IKeywordIdentity;
|
||||
begin
|
||||
raise EInvalidCast.Create('Identity is not a Keyword Identity');
|
||||
end;
|
||||
|
||||
function TAbstractIdentity.AsDefinition: IDefinitionIdentity;
|
||||
begin
|
||||
raise EInvalidCast.Create('Identity is not a Definition Identity');
|
||||
end;
|
||||
|
||||
{ TStructuralIdentity }
|
||||
|
||||
function TStructuralIdentity.GetKind: TAstIdentityKind;
|
||||
begin
|
||||
Result := ikStructural;
|
||||
end;
|
||||
|
||||
{ TNamedIdentity }
|
||||
|
||||
constructor TNamedIdentity.Create(const AName: string; const ALoc: ISourceLocation);
|
||||
begin
|
||||
inherited Create(ALoc);
|
||||
FName := AName;
|
||||
end;
|
||||
|
||||
function TNamedIdentity.GetKind: TAstIdentityKind;
|
||||
begin
|
||||
Result := ikNamed;
|
||||
end;
|
||||
|
||||
function TNamedIdentity.GetName: string;
|
||||
begin
|
||||
Result := FName;
|
||||
end;
|
||||
|
||||
function TNamedIdentity.AsNamed: INamedIdentity;
|
||||
begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TNamedIdentity.ToString: string;
|
||||
begin
|
||||
Result := Format('Name: "%s" (%s)', [FName, inherited ToString]);
|
||||
end;
|
||||
|
||||
{ TConstantIdentity }
|
||||
|
||||
constructor TConstantIdentity.Create(const AValue: TDataValue; const ALoc: ISourceLocation);
|
||||
begin
|
||||
inherited Create(ALoc);
|
||||
FValue := AValue;
|
||||
end;
|
||||
|
||||
function TConstantIdentity.GetKind: TAstIdentityKind;
|
||||
begin
|
||||
Result := ikConstant;
|
||||
end;
|
||||
|
||||
function TConstantIdentity.GetValue: TDataValue;
|
||||
begin
|
||||
Result := FValue;
|
||||
end;
|
||||
|
||||
function TConstantIdentity.AsConstant: IConstantIdentity;
|
||||
begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TConstantIdentity.ToString: string;
|
||||
begin
|
||||
Result := Format('Const: %s (%s)', [FValue.ToString, inherited ToString]);
|
||||
end;
|
||||
|
||||
{ TKeywordIdentity }
|
||||
|
||||
constructor TKeywordIdentity.Create(const AValue: IKeyword; const ALoc: ISourceLocation);
|
||||
begin
|
||||
inherited Create(ALoc);
|
||||
FValue := AValue;
|
||||
end;
|
||||
|
||||
function TKeywordIdentity.GetKind: TAstIdentityKind;
|
||||
begin
|
||||
Result := ikKeyword;
|
||||
end;
|
||||
|
||||
function TKeywordIdentity.GetValue: IKeyword;
|
||||
begin
|
||||
Result := FValue;
|
||||
end;
|
||||
|
||||
function TKeywordIdentity.AsKeyword: IKeywordIdentity;
|
||||
begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TKeywordIdentity.ToString: string;
|
||||
begin
|
||||
Result := Format('Keyword: :%s (%s)', [FValue.Name, inherited ToString]);
|
||||
end;
|
||||
|
||||
{ TDefinitionIdentity }
|
||||
|
||||
constructor TDefinitionIdentity.Create(const ADef: string; const ALoc: ISourceLocation);
|
||||
begin
|
||||
inherited Create(ALoc);
|
||||
FDefinition := ADef;
|
||||
end;
|
||||
|
||||
function TDefinitionIdentity.GetKind: TAstIdentityKind;
|
||||
begin
|
||||
Result := ikDefinition;
|
||||
end;
|
||||
|
||||
function TDefinitionIdentity.GetDefinition: string;
|
||||
begin
|
||||
Result := FDefinition;
|
||||
end;
|
||||
|
||||
function TDefinitionIdentity.AsDefinition: IDefinitionIdentity;
|
||||
begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TDefinitionIdentity.ToString: string;
|
||||
begin
|
||||
Result := Format('Def: "%s" (%s)', [FDefinition, inherited ToString]);
|
||||
end;
|
||||
|
||||
{ TIdentities }
|
||||
|
||||
class function TIdentities.Location(ALine, ACol: Integer): ISourceLocation;
|
||||
begin
|
||||
Result := TSourceLocation.Create(ALine, ACol);
|
||||
end;
|
||||
|
||||
class function TIdentities.Structural(const ALoc: ISourceLocation): IAstIdentity;
|
||||
begin
|
||||
Result := TStructuralIdentity.Create(ALoc);
|
||||
end;
|
||||
|
||||
class function TIdentities.Identifier(const AName: string; const ALoc: ISourceLocation): INamedIdentity;
|
||||
begin
|
||||
Result := TNamedIdentity.Create(AName, ALoc);
|
||||
end;
|
||||
|
||||
class function TIdentities.Constant(const AValue: TDataValue; const ALoc: ISourceLocation): IConstantIdentity;
|
||||
begin
|
||||
Result := TConstantIdentity.Create(AValue, ALoc);
|
||||
end;
|
||||
|
||||
class function TIdentities.Keyword(const AValue: IKeyword; const ALoc: ISourceLocation): IKeywordIdentity;
|
||||
begin
|
||||
Result := TKeywordIdentity.Create(AValue, ALoc);
|
||||
end;
|
||||
|
||||
class function TIdentities.Definition(const ADef: string; const ALoc: ISourceLocation): IDefinitionIdentity;
|
||||
begin
|
||||
Result := TDefinitionIdentity.Create(ADef, ALoc);
|
||||
end;
|
||||
|
||||
end.
|
||||
+41
-34
@@ -15,6 +15,25 @@ type
|
||||
// --- Forward Declarations ---
|
||||
IAstNode = interface;
|
||||
|
||||
// --- Identity & Provenance ---
|
||||
|
||||
/// Represents the immutable identity or provenance of an AST node.
|
||||
/// This allows tracking where a node came from (Parser, Generator, Macro, etc.)
|
||||
/// without coupling the AST to specific source formats.
|
||||
IAstIdentity = interface
|
||||
['{5C496755-721D-4793-9526-7E2E63357719}']
|
||||
function ToString: string;
|
||||
end;
|
||||
|
||||
/// Specific identity for nodes originating from source code text.
|
||||
ISourceLocation = interface(IAstIdentity)
|
||||
['{98226687-F323-49B0-8D38-61803B225973}']
|
||||
function GetLine: Integer;
|
||||
function GetCol: Integer;
|
||||
property Line: Integer read GetLine;
|
||||
property Col: Integer read GetCol;
|
||||
end;
|
||||
|
||||
// --- Error Handling Infrastructure ---
|
||||
|
||||
TCompilerErrorLevel = (elHint, elWarning, elError);
|
||||
@@ -28,6 +47,7 @@ type
|
||||
end;
|
||||
|
||||
ICompilerLog = interface
|
||||
['{8E5F2C10-4B3A-49F1-9C2D-7A8B5E6F4D3C}']
|
||||
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);
|
||||
@@ -54,12 +74,10 @@ type
|
||||
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.
|
||||
// Base class for all Compiler related exceptions.
|
||||
EAstException = class(Exception);
|
||||
|
||||
// 2. The concrete exception thrown at the END of a compilation pass if errors occurred.
|
||||
// It wraps the accumulated log.
|
||||
// The concrete exception thrown at the END of a compilation pass if errors occurred.
|
||||
ECompilationFailed = class(EAstException)
|
||||
private
|
||||
FErrors: TArray<TCompilerError>;
|
||||
@@ -69,10 +87,6 @@ type
|
||||
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;
|
||||
@@ -129,7 +143,6 @@ type
|
||||
akNop
|
||||
);
|
||||
|
||||
// Helper for TAstNodeKind providing a string representation
|
||||
TAstNodeKindHelper = record helper for TAstNodeKind
|
||||
public
|
||||
function ToString: string;
|
||||
@@ -137,7 +150,6 @@ type
|
||||
|
||||
// --- Concrete Type Definitions ---
|
||||
|
||||
// A single field in a record literal
|
||||
TRecordFieldLiteral = record
|
||||
Key: IKeywordNode;
|
||||
Value: IAstNode;
|
||||
@@ -174,6 +186,7 @@ type
|
||||
{$region 'private'}
|
||||
function GetKind: TAstNodeKind;
|
||||
function GetIsTyped: Boolean;
|
||||
function GetIdentity: IAstIdentity;
|
||||
{$endregion}
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue;
|
||||
|
||||
@@ -205,6 +218,7 @@ type
|
||||
|
||||
property IsTyped: Boolean read GetIsTyped;
|
||||
property Kind: TAstNodeKind read GetKind;
|
||||
property Identity: IAstIdentity read GetIdentity;
|
||||
end;
|
||||
|
||||
IAstTypedNode = interface(IAstNode)
|
||||
@@ -214,7 +228,6 @@ type
|
||||
property StaticType: IStaticType read GetStaticType;
|
||||
end;
|
||||
|
||||
// The abstract definition of a callable function body
|
||||
IFunctionDefinition = interface(IAstTypedNode)
|
||||
{$region 'private'}
|
||||
function GetBody: IAstNode;
|
||||
@@ -227,7 +240,6 @@ type
|
||||
end;
|
||||
|
||||
INopNode = interface(IAstTypedNode)
|
||||
// A placeholder node for the UI (e.g., drag target).
|
||||
end;
|
||||
|
||||
IConstantNode = interface(IAstTypedNode)
|
||||
@@ -246,12 +258,10 @@ type
|
||||
property Name: string read GetName;
|
||||
end;
|
||||
|
||||
// Represents a keyword literal in the AST (e.g., :foo)
|
||||
IKeywordNode = interface(IAstTypedNode)
|
||||
{$region 'private'}
|
||||
function GetValue: IKeyword;
|
||||
{$endregion}
|
||||
// The interned keyword object
|
||||
property Value: IKeyword read GetValue;
|
||||
end;
|
||||
|
||||
@@ -281,27 +291,17 @@ type
|
||||
{$region 'private'}
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetBody: IAstNode;
|
||||
|
||||
// The structural layout. Always present after binding.
|
||||
function GetLayout: IScopeLayout;
|
||||
|
||||
// The runtime descriptor. Can be nil during early compilation phases.
|
||||
function GetDescriptor: IScopeDescriptor;
|
||||
|
||||
function GetUpvalues: TArray<TResolvedAddress>;
|
||||
function GetHasNestedLambdas: Boolean;
|
||||
// GetIsPure is inherited from IFunctionDefinition
|
||||
{$endregion}
|
||||
|
||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
||||
property Body: IAstNode read GetBody;
|
||||
|
||||
property Layout: IScopeLayout read GetLayout;
|
||||
property Descriptor: IScopeDescriptor read GetDescriptor;
|
||||
|
||||
property Upvalues: TArray<TResolvedAddress> read GetUpvalues;
|
||||
property HasNestedLambdas: Boolean read GetHasNestedLambdas;
|
||||
// IsPure is inherited
|
||||
end;
|
||||
|
||||
IFunctionCallNode = interface(IAstTypedNode)
|
||||
@@ -319,18 +319,15 @@ type
|
||||
property IsTargetPure: Boolean read GetIsTargetPure;
|
||||
end;
|
||||
|
||||
// A node representing a macro call.
|
||||
IMacroExpansionNode = interface(IAstTypedNode)
|
||||
{$region 'private'}
|
||||
function GetCallNode: IFunctionCallNode;
|
||||
function GetExpandedBody: IAstNode;
|
||||
{$endregion}
|
||||
// The AST fragment that resulted from the macro expansion.
|
||||
property CallNode: IFunctionCallNode read GetCallNode;
|
||||
property ExpandedBody: IAstNode read GetExpandedBody;
|
||||
end;
|
||||
|
||||
// A node representing a tail-recursive call.
|
||||
IRecurNode = interface(IAstTypedNode)
|
||||
{$region 'private'}
|
||||
function GetArguments: TArray<IAstNode>;
|
||||
@@ -376,7 +373,6 @@ type
|
||||
property Body: IAstNode read GetBody;
|
||||
end;
|
||||
|
||||
// Represents a quasiquoted expression, e.g., `(a b)
|
||||
IQuasiquoteNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetExpression: IAstNode;
|
||||
@@ -384,7 +380,6 @@ type
|
||||
property Expression: IAstNode read GetExpression;
|
||||
end;
|
||||
|
||||
// Represents an unquoted expression, e.g., ~x
|
||||
IUnquoteNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetExpression: IAstNode;
|
||||
@@ -392,7 +387,6 @@ type
|
||||
property Expression: IAstNode read GetExpression;
|
||||
end;
|
||||
|
||||
// Represents an unquote-splicing expression, e.g., ~@y
|
||||
IUnquoteSplicingNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetExpression: IQuasiquoteNode;
|
||||
@@ -418,7 +412,6 @@ type
|
||||
property Member: IKeywordNode read GetMember;
|
||||
end;
|
||||
|
||||
// Represents a record literal, e.g., {:a 1 :b 2}
|
||||
IRecordLiteralNode = interface(IAstTypedNode)
|
||||
{$region 'private'}
|
||||
function GetFields: TArray<TRecordFieldLiteral>;
|
||||
@@ -459,7 +452,6 @@ type
|
||||
function Execute(const RootNode: IAstNode): TDataValue;
|
||||
end;
|
||||
|
||||
// A factory for creating visitors
|
||||
TEvaluatorFactory = reference to function(const Scope: IExecutionScope): IEvaluatorVisitor;
|
||||
|
||||
implementation
|
||||
@@ -496,14 +488,29 @@ begin
|
||||
end;
|
||||
|
||||
function TCompilerError.ToString: string;
|
||||
var
|
||||
location: string;
|
||||
loc: ISourceLocation;
|
||||
begin
|
||||
// Simplified string representation for quick debugging
|
||||
// 1. Try to extract location from Node Identity
|
||||
location := '';
|
||||
if Assigned(Node) and Assigned(Node.Identity) then
|
||||
begin
|
||||
if Supports(Node.Identity, ISourceLocation, loc) then
|
||||
location := Format('[Line %d, Col %d] ', [loc.Line, loc.Col])
|
||||
else
|
||||
location := Format('[%s] ', [Node.Identity.ToString]);
|
||||
end;
|
||||
|
||||
// 2. Prefix with Level
|
||||
case Level of
|
||||
elHint: Result := '[Hint] ';
|
||||
elWarning: Result := '[Warning] ';
|
||||
elError: Result := '[Error] ';
|
||||
end;
|
||||
Result := Result + Message;
|
||||
|
||||
// 3. Assemble
|
||||
Result := Result + location + Message;
|
||||
end;
|
||||
|
||||
{ TCompilerLog }
|
||||
|
||||
+364
-154
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user