Binder refactoring
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
unit Myc.Ast.Binding.Nodes;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Classes,
|
||||
System.Generics.Collections,
|
||||
Myc.Data.Scalar,
|
||||
Myc.Data.Value,
|
||||
Myc.Ast.Nodes,
|
||||
Myc.Ast.Visitor,
|
||||
Myc.Ast.Scope,
|
||||
Myc.Ast.Types,
|
||||
Myc.Ast;
|
||||
|
||||
type
|
||||
TBoundIdentifierNode = class(TIdentifierNode)
|
||||
private
|
||||
FAddress: TResolvedAddress;
|
||||
public
|
||||
constructor Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
|
||||
property Address: TResolvedAddress read FAddress;
|
||||
end;
|
||||
|
||||
TBoundVariableDeclarationNode = class(TVariableDeclarationNode)
|
||||
private
|
||||
FIsBoxed: Boolean;
|
||||
public
|
||||
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
|
||||
property IsBoxed: Boolean read FIsBoxed;
|
||||
end;
|
||||
|
||||
TBoundLambdaExpressionNode = class(TLambdaExpressionNode)
|
||||
private
|
||||
FScopeDescriptor: IScopeDescriptor;
|
||||
FUpvalues: TArray<TResolvedAddress>;
|
||||
FHasNestedLambdas: Boolean;
|
||||
public
|
||||
constructor Create(
|
||||
const AUnboundNode: ILambdaExpressionNode;
|
||||
const ABody: IAstNode;
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
const AScopeDescriptor: IScopeDescriptor;
|
||||
const AUpvalues: TArray<TResolvedAddress>;
|
||||
AHasNestedLambdas: Boolean
|
||||
);
|
||||
property ScopeDescriptor: IScopeDescriptor read FScopeDescriptor;
|
||||
property Upvalues: TArray<TResolvedAddress> read FUpvalues;
|
||||
property HasNestedLambdas: Boolean read FHasNestedLambdas;
|
||||
end;
|
||||
|
||||
TBoundFunctionCallNode = class(TFunctionCallNode)
|
||||
private
|
||||
FIsTailCall: Boolean;
|
||||
public
|
||||
constructor Create(
|
||||
const AUnboundNode: IFunctionCallNode;
|
||||
const ACallee: IAstNode;
|
||||
const AArguments: TArray<IAstNode>;
|
||||
AIsTailCall: Boolean
|
||||
);
|
||||
property IsTailCall: Boolean read FIsTailCall;
|
||||
end;
|
||||
|
||||
TBoundRecordLiteralNode = class(TRecordLiteralNode)
|
||||
private
|
||||
FDefinition: IScalarRecordDefinition;
|
||||
public
|
||||
constructor Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IScalarRecordDefinition);
|
||||
property Definition: IScalarRecordDefinition read FDefinition;
|
||||
end;
|
||||
|
||||
// Represents a bound record literal that maps to a generic (non-scalar) record
|
||||
TBoundGenericRecordLiteralNode = class(TRecordLiteralNode)
|
||||
private
|
||||
FDefinition: IGenericRecordDefinition;
|
||||
public
|
||||
constructor Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IGenericRecordDefinition);
|
||||
property Definition: IGenericRecordDefinition read FDefinition;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Myc.Data.Keyword;
|
||||
|
||||
{ TBoundIdentifierNode }
|
||||
constructor TBoundIdentifierNode.Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
|
||||
begin
|
||||
inherited Create(AUnboundNode.Name);
|
||||
FAddress := AAddress;
|
||||
end;
|
||||
|
||||
{ TBoundVariableDeclarationNode }
|
||||
constructor TBoundVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
|
||||
begin
|
||||
inherited Create(AIdentifier, AInitializer);
|
||||
FIsBoxed := AIsBoxed;
|
||||
end;
|
||||
|
||||
{ TBoundLambdaExpressionNode }
|
||||
constructor TBoundLambdaExpressionNode.Create(
|
||||
const AUnboundNode: ILambdaExpressionNode;
|
||||
const ABody: IAstNode;
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
const AScopeDescriptor: IScopeDescriptor;
|
||||
const AUpvalues: TArray<TResolvedAddress>;
|
||||
AHasNestedLambdas: Boolean
|
||||
);
|
||||
begin
|
||||
inherited Create(AParameters, ABody);
|
||||
FScopeDescriptor := AScopeDescriptor;
|
||||
FUpvalues := AUpvalues;
|
||||
FHasNestedLambdas := AHasNestedLambdas;
|
||||
end;
|
||||
|
||||
{ TBoundFunctionCallNode }
|
||||
constructor TBoundFunctionCallNode.Create(
|
||||
const AUnboundNode: IFunctionCallNode;
|
||||
const ACallee: IAstNode;
|
||||
const AArguments: TArray<IAstNode>;
|
||||
AIsTailCall: Boolean
|
||||
);
|
||||
begin
|
||||
inherited Create(ACallee, AArguments);
|
||||
FIsTailCall := AIsTailCall;
|
||||
end;
|
||||
|
||||
{ TBoundGenericRecordLiteralNode }
|
||||
constructor TBoundGenericRecordLiteralNode.Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IGenericRecordDefinition);
|
||||
begin
|
||||
inherited Create(AFields);
|
||||
FDefinition := ADef;
|
||||
end;
|
||||
|
||||
{ TBoundRecordLiteralNode }
|
||||
constructor TBoundRecordLiteralNode.Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IScalarRecordDefinition);
|
||||
begin
|
||||
inherited Create(AFields);
|
||||
FDefinition := ADef;
|
||||
end;
|
||||
|
||||
end.
|
||||
+12
-131
@@ -105,77 +105,13 @@ type
|
||||
): IAstNode; static;
|
||||
end;
|
||||
|
||||
TBoundIdentifierNode = class(TIdentifierNode)
|
||||
private
|
||||
FAddress: TResolvedAddress;
|
||||
public
|
||||
constructor Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
|
||||
property Address: TResolvedAddress read FAddress;
|
||||
end;
|
||||
|
||||
TBoundVariableDeclarationNode = class(TVariableDeclarationNode)
|
||||
private
|
||||
FIsBoxed: Boolean;
|
||||
public
|
||||
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
|
||||
property IsBoxed: Boolean read FIsBoxed;
|
||||
end;
|
||||
|
||||
TBoundLambdaExpressionNode = class(TLambdaExpressionNode)
|
||||
private
|
||||
FScopeDescriptor: IScopeDescriptor;
|
||||
FUpvalues: TArray<TResolvedAddress>;
|
||||
FHasNestedLambdas: Boolean;
|
||||
public
|
||||
constructor Create(
|
||||
const AUnboundNode: ILambdaExpressionNode;
|
||||
const ABody: IAstNode;
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
const AScopeDescriptor: IScopeDescriptor;
|
||||
const AUpvalues: TArray<TResolvedAddress>;
|
||||
AHasNestedLambdas: Boolean
|
||||
);
|
||||
property ScopeDescriptor: IScopeDescriptor read FScopeDescriptor;
|
||||
property Upvalues: TArray<TResolvedAddress> read FUpvalues;
|
||||
property HasNestedLambdas: Boolean read FHasNestedLambdas;
|
||||
end;
|
||||
|
||||
TBoundFunctionCallNode = class(TFunctionCallNode)
|
||||
private
|
||||
FIsTailCall: Boolean;
|
||||
public
|
||||
constructor Create(
|
||||
const AUnboundNode: IFunctionCallNode;
|
||||
const ACallee: IAstNode;
|
||||
const AArguments: TArray<IAstNode>;
|
||||
AIsTailCall: Boolean
|
||||
);
|
||||
property IsTailCall: Boolean read FIsTailCall;
|
||||
end;
|
||||
|
||||
TBoundRecordLiteralNode = class(TRecordLiteralNode)
|
||||
private
|
||||
FDefinition: IScalarRecordDefinition;
|
||||
public
|
||||
constructor Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IScalarRecordDefinition);
|
||||
property Definition: IScalarRecordDefinition read FDefinition;
|
||||
end;
|
||||
|
||||
// Represents a bound record literal that maps to a generic (non-scalar) record
|
||||
TBoundGenericRecordLiteralNode = class(TRecordLiteralNode)
|
||||
private
|
||||
FDefinition: IGenericRecordDefinition;
|
||||
public
|
||||
constructor Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IGenericRecordDefinition);
|
||||
property Definition: IGenericRecordDefinition read FDefinition;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.Generics.Defaults,
|
||||
System.Character,
|
||||
Myc.Data.Keyword;
|
||||
Myc.Data.Keyword,
|
||||
Myc.Ast.Binding.Nodes;
|
||||
|
||||
type
|
||||
TResolvedAddressComparer = class(TEqualityComparer<TResolvedAddress>)
|
||||
@@ -307,62 +243,6 @@ begin
|
||||
Result := inherited VisitRecordLiteral(Node);
|
||||
end;
|
||||
|
||||
{ TBoundIdentifierNode }
|
||||
constructor TBoundIdentifierNode.Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
|
||||
begin
|
||||
inherited Create(AUnboundNode.Name);
|
||||
FAddress := AAddress;
|
||||
end;
|
||||
|
||||
{ TBoundVariableDeclarationNode }
|
||||
constructor TBoundVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
|
||||
begin
|
||||
inherited Create(AIdentifier, AInitializer);
|
||||
FIsBoxed := AIsBoxed;
|
||||
end;
|
||||
|
||||
{ TBoundLambdaExpressionNode }
|
||||
constructor TBoundLambdaExpressionNode.Create(
|
||||
const AUnboundNode: ILambdaExpressionNode;
|
||||
const ABody: IAstNode;
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
const AScopeDescriptor: IScopeDescriptor;
|
||||
const AUpvalues: TArray<TResolvedAddress>;
|
||||
AHasNestedLambdas: Boolean
|
||||
);
|
||||
begin
|
||||
inherited Create(AParameters, ABody);
|
||||
FScopeDescriptor := AScopeDescriptor;
|
||||
FUpvalues := AUpvalues;
|
||||
FHasNestedLambdas := AHasNestedLambdas;
|
||||
end;
|
||||
|
||||
{ TBoundFunctionCallNode }
|
||||
constructor TBoundFunctionCallNode.Create(
|
||||
const AUnboundNode: IFunctionCallNode;
|
||||
const ACallee: IAstNode;
|
||||
const AArguments: TArray<IAstNode>;
|
||||
AIsTailCall: Boolean
|
||||
);
|
||||
begin
|
||||
inherited Create(ACallee, AArguments);
|
||||
FIsTailCall := AIsTailCall;
|
||||
end;
|
||||
|
||||
{ TBoundGenericRecordLiteralNode }
|
||||
constructor TBoundGenericRecordLiteralNode.Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IGenericRecordDefinition);
|
||||
begin
|
||||
inherited Create(AFields);
|
||||
FDefinition := ADef;
|
||||
end;
|
||||
|
||||
{ TBoundRecordLiteralNode }
|
||||
constructor TBoundRecordLiteralNode.Create(const AFields: TArray<TRecordFieldLiteral>; const ADef: IScalarRecordDefinition);
|
||||
begin
|
||||
inherited Create(AFields);
|
||||
FDefinition := ADef;
|
||||
end;
|
||||
|
||||
{ TResolvedAddressComparer }
|
||||
function TResolvedAddressComparer.Equals(const Left, Right: TResolvedAddress): Boolean;
|
||||
begin
|
||||
@@ -656,16 +536,17 @@ begin
|
||||
if Length(args) <> Length(signature.ParamTypes) then
|
||||
raise ETypeException.CreateFmt('Function expects %d arguments, but got %d', [Length(signature.ParamTypes), Length(args)]);
|
||||
retType := signature.ReturnType;
|
||||
end;
|
||||
|
||||
// Check argument types (param types are not yet inferred, so skip check for now)
|
||||
// for i := 0 to High(args) do
|
||||
// begin
|
||||
// var argType := (args[i] as TAstNode).StaticType;
|
||||
// var paramType := signature.ParamTypes[i];
|
||||
// if not TTypeRules.CanAssign(paramType, argType) then
|
||||
// raise ETypeException.CreateFmt('Cannot assign argument %d (type %s) to parameter (type %s)', [i, argType.ToString, paramType.ToString]);
|
||||
// end;
|
||||
// Check argument types
|
||||
for i := 0 to High(args) do
|
||||
begin
|
||||
var argType := (args[i] as TAstNode).StaticType;
|
||||
var paramType := signature.ParamTypes[i];
|
||||
if not TTypeRules.CanAssign(paramType, argType) then
|
||||
raise ETypeException
|
||||
.CreateFmt('Cannot assign argument %d (type %s) to parameter (type %s)', [i, argType.ToString, paramType.ToString]);
|
||||
end;
|
||||
end;
|
||||
|
||||
boundCall := TBoundFunctionCallNode.Create(Node, callee, args, isTailCall);
|
||||
Result := SetType(TDataValue.FromIntf<IFunctionCallNode>(boundCall), retType);
|
||||
|
||||
@@ -68,7 +68,7 @@ implementation
|
||||
|
||||
uses
|
||||
Myc.Data.Keyword,
|
||||
Myc.Ast.Binding; // For TBound...Node classes
|
||||
Myc.Ast.Binding.Nodes;
|
||||
|
||||
{ TAstDumper }
|
||||
|
||||
|
||||
@@ -71,7 +71,8 @@ uses
|
||||
Myc.Data.Keyword,
|
||||
Myc.Data.Decimal,
|
||||
Myc.Data.Series,
|
||||
Myc.Data.Scalar.JSON;
|
||||
Myc.Data.Scalar.JSON,
|
||||
Myc.Ast.Binding.Nodes;
|
||||
|
||||
// Helper type for TCO via trampolining.
|
||||
type
|
||||
|
||||
Reference in New Issue
Block a user