AST type infer SoC
This commit is contained in:
@@ -219,34 +219,19 @@ end;
|
||||
|
||||
function TAstBinder.VisitConstant(const Node: IConstantNode): IAstNode;
|
||||
begin
|
||||
// Set type (Phase 3)
|
||||
case Node.Value.Kind of
|
||||
TDataValueKind.vkScalar: (Node as TAstNode).StaticType := TTypes.FromScalarKind(Node.Value.AsScalar.Kind);
|
||||
TDataValueKind.vkText: (Node as TAstNode).StaticType := TTypes.Text;
|
||||
TDataValueKind.vkVoid: (Node as TAstNode).StaticType := TTypes.Void;
|
||||
else
|
||||
(Node as TAstNode).StaticType := TTypes.Unknown;
|
||||
end;
|
||||
// Binding pass does not assign types.
|
||||
Result := Node;
|
||||
end;
|
||||
|
||||
function TAstBinder.VisitKeyword(const Node: IKeywordNode): IAstNode;
|
||||
begin
|
||||
(Node as TAstNode).StaticType := TTypes.Keyword;
|
||||
// Binding pass does not assign types.
|
||||
Result := Node;
|
||||
end;
|
||||
|
||||
function TAstBinder.VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode;
|
||||
var
|
||||
elemType: IStaticType;
|
||||
begin
|
||||
try
|
||||
elemType := TTypes.FromScalarKind(TScalar.StringToKind(Node.Definition));
|
||||
except
|
||||
on E: Exception do
|
||||
elemType := TTypes.Unknown;
|
||||
end;
|
||||
(Node as TAstNode).StaticType := TTypes.CreateSeries(elemType);
|
||||
// Binding pass does not assign types.
|
||||
Result := Node;
|
||||
end;
|
||||
|
||||
@@ -254,14 +239,14 @@ function TAstBinder.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode
|
||||
begin
|
||||
// Visit children
|
||||
Result := inherited VisitAddSeriesItem(Node);
|
||||
(Node as TAstNode).StaticType := TTypes.Void;
|
||||
// Binding pass does not assign types.
|
||||
end;
|
||||
|
||||
function TAstBinder.VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode;
|
||||
begin
|
||||
// Visit children
|
||||
Result := inherited VisitSeriesLength(Node);
|
||||
(Node as TAstNode).StaticType := TTypes.Ordinal;
|
||||
// Binding pass does not assign types.
|
||||
end;
|
||||
|
||||
function TAstBinder.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||
@@ -291,8 +276,6 @@ begin
|
||||
// --- Replace Node ---
|
||||
// Create a new TBoundIdentifierNode (implementation is in Myc.Ast)
|
||||
var boundParamNode := TBoundIdentifierNode.Create(paramNode.Name, adr);
|
||||
// Set its type
|
||||
(boundParamNode as TAstNode).StaticType := TTypes.Unknown;
|
||||
// Replace it in the parameter array
|
||||
N.Parameters[i] := boundParamNode;
|
||||
end;
|
||||
@@ -338,7 +321,7 @@ function TAstBinder.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
||||
begin
|
||||
// Visit children
|
||||
Result := inherited VisitRecurNode(Node);
|
||||
(Node as TAstNode).StaticType := TTypes.Void; // Recur never returns a value
|
||||
// Binding pass does not assign types.
|
||||
end;
|
||||
|
||||
function TAstBinder.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
|
||||
@@ -382,8 +365,7 @@ begin
|
||||
// --- Replace Node ---
|
||||
// Create the new TBoundIdentifierNode (implementation is in Myc.Ast)
|
||||
Result := TBoundIdentifierNode.Create(Node.Name, adr);
|
||||
// Copy static type from scope to the new node
|
||||
(Result as TAstNode).StaticType := symbol.StaticType;
|
||||
// StaticType remains TTypes.Unknown (default)
|
||||
end
|
||||
else
|
||||
begin
|
||||
@@ -414,8 +396,7 @@ begin
|
||||
// 3. --- Replace Node ---
|
||||
// Replace the TIdentifierNode with a new TBoundIdentifierNode
|
||||
N.Identifier := TBoundIdentifierNode.Create(N.Identifier.Name, address);
|
||||
// Set static type (Unknown) on the *new* node
|
||||
(N.Identifier as TAstNode).StaticType := TTypes.Unknown; // TypeChecker will set this
|
||||
// StaticType remains TTypes.Unknown (default)
|
||||
|
||||
// 4. Mutate this declaration node
|
||||
N.IsBoxed := (FBoxedDeclarations <> nil) and FBoxedDeclarations.Contains(Node);
|
||||
|
||||
@@ -47,7 +47,7 @@ type
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode; override;
|
||||
function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
|
||||
|
||||
// Base cases (types are already set by Binder)
|
||||
// Base cases (types are now set here)
|
||||
function VisitConstant(const Node: IConstantNode): IAstNode; override;
|
||||
function VisitKeyword(const Node: IKeywordNode): IAstNode; override;
|
||||
|
||||
@@ -100,27 +100,49 @@ begin
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitConstant(const Node: IConstantNode): IAstNode;
|
||||
var
|
||||
constType: IStaticType;
|
||||
begin
|
||||
// Type was set by Binder, just propagate it up.
|
||||
// This is a leaf node, call inherited (does nothing)
|
||||
Result := inherited VisitConstant(Node);
|
||||
|
||||
// Assign the type based on the literal value
|
||||
case Node.Value.Kind of
|
||||
TDataValueKind.vkScalar: constType := TTypes.FromScalarKind(Node.Value.AsScalar.Kind);
|
||||
TDataValueKind.vkText: constType := TTypes.Text;
|
||||
TDataValueKind.vkVoid: constType := TTypes.Void;
|
||||
else
|
||||
constType := TTypes.Unknown;
|
||||
end;
|
||||
|
||||
Result := SetType(Result, constType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitKeyword(const Node: IKeywordNode): IAstNode;
|
||||
begin
|
||||
// Type was set by Binder, just propagate it up.
|
||||
// This is a leaf node
|
||||
Result := inherited VisitKeyword(Node);
|
||||
Result := SetType(Result, TTypes.Keyword);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
|
||||
var
|
||||
symbol: TResolvedSymbol;
|
||||
begin
|
||||
// Type was set by Binder (read from scope), just propagate it up.
|
||||
// This is a leaf node (guaranteed to be IBoundIdentifierNode)
|
||||
Result := inherited VisitIdentifier(Node);
|
||||
|
||||
// Get the type from the descriptor (which was populated by Binder/RTL)
|
||||
symbol := FCurrentDescriptor.FindSymbol(Node.Name);
|
||||
Result := SetType(Result, symbol.StaticType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
||||
begin
|
||||
// Type was set by Binder (TTypes.Void), just propagate it up.
|
||||
// Visit children first
|
||||
Result := inherited VisitRecurNode(Node);
|
||||
// Recur always results in Void (it never returns)
|
||||
Result := SetType(Result, TTypes.Void);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
|
||||
@@ -147,14 +169,16 @@ begin
|
||||
if Assigned(Node.Initializer) then
|
||||
initType := (Node.Initializer as TAstNode).StaticType
|
||||
else
|
||||
initType := TTypes.Void;
|
||||
initType := TTypes.Unknown; // <-- This was TTypes.Void
|
||||
|
||||
// 3. Get the address from the bound identifier (SAFE CAST)
|
||||
boundIdent := Node.Identifier;
|
||||
adr := boundIdent.AsBoundIdentifierNode.Address;
|
||||
|
||||
// 4. Update the type in the scope descriptor (which was set to Unknown by the binder).
|
||||
FCurrentDescriptor.UpdateType(adr.SlotIndex, initType);
|
||||
// Only update if we have a concrete type (not the default Unknown).
|
||||
if initType.Kind <> stUnknown then
|
||||
FCurrentDescriptor.UpdateType(adr.SlotIndex, initType);
|
||||
|
||||
// 5. Update the static types of the nodes themselves.
|
||||
(boundIdent as TAstNode).StaticType := initType;
|
||||
@@ -164,6 +188,7 @@ end;
|
||||
function TTypeChecker.VisitAssignment(const Node: IAssignmentNode): IAstNode;
|
||||
var
|
||||
targetType, sourceType: IStaticType;
|
||||
adr: TResolvedAddress;
|
||||
begin
|
||||
// 1. Visit children first (Identifier, Value)
|
||||
inherited;
|
||||
@@ -176,6 +201,17 @@ begin
|
||||
if not TTypeRules.CanAssign(targetType, sourceType) then
|
||||
raise ETypeException.CreateFmt('Cannot assign type %s to %s', [sourceType.ToString, targetType.ToString]);
|
||||
|
||||
// 4. If the target was 'Unknown' (from 'def'), update the descriptor
|
||||
// with the new, inferred type. This enables recursion.
|
||||
if (targetType.Kind = stUnknown) and (sourceType.Kind <> stUnknown) then
|
||||
begin
|
||||
adr := Node.Identifier.AsBoundIdentifierNode.Address;
|
||||
FCurrentDescriptor.UpdateType(adr.SlotIndex, sourceType);
|
||||
// Re-set the identifier's node type (it was visited *before* this)
|
||||
(Node.Identifier as TAstNode).StaticType := sourceType;
|
||||
targetType := sourceType;
|
||||
end;
|
||||
|
||||
Result := SetType(Node, targetType);
|
||||
end;
|
||||
|
||||
@@ -489,9 +525,20 @@ begin
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode;
|
||||
var
|
||||
elemType: IStaticType;
|
||||
begin
|
||||
// Type was set by Binder, just propagate it up.
|
||||
// This is a leaf node
|
||||
Result := inherited VisitCreateSeries(Node);
|
||||
|
||||
// Assign the type
|
||||
try
|
||||
elemType := TTypes.FromScalarKind(TScalar.StringToKind(Node.Definition));
|
||||
except
|
||||
on E: Exception do
|
||||
elemType := TTypes.Unknown;
|
||||
end;
|
||||
Result := SetType(Result, TTypes.CreateSeries(elemType));
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode;
|
||||
|
||||
+11
-12
@@ -324,18 +324,6 @@ type
|
||||
property IsTailCall: Boolean read FIsTailCall write FIsTailCall;
|
||||
end;
|
||||
|
||||
TMacroExpansionNode = class(TFunctionCallNode, IMacroExpansionNode)
|
||||
private
|
||||
FExpandedBody: IAstNode;
|
||||
function GetExpandedBody: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMacroExpansion: IMacroExpansionNode; override;
|
||||
property ExpandedBody: IAstNode read FExpandedBody write FExpandedBody; // Writeable
|
||||
end;
|
||||
|
||||
TRecurNode = class(TAstNode, IRecurNode)
|
||||
private
|
||||
FArguments: TArray<IAstNode>;
|
||||
@@ -348,6 +336,17 @@ type
|
||||
property Arguments: TArray<IAstNode> read FArguments write FArguments; // Writeable
|
||||
end;
|
||||
|
||||
TMacroExpansionNode = class(TFunctionCallNode, IMacroExpansionNode)
|
||||
private
|
||||
FExpandedBody: IAstNode;
|
||||
function GetExpandedBody: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMacroExpansion: IMacroExpansionNode; override;
|
||||
property ExpandedBody: IAstNode read FExpandedBody write FExpandedBody; // Writeable
|
||||
end;
|
||||
TBlockExpressionNode = class(TAstNode, IBlockExpressionNode)
|
||||
private
|
||||
FExpressions: TArray<IAstNode>;
|
||||
|
||||
Reference in New Issue
Block a user