Binder refactoring, Monster refactoring
This commit is contained in:
@@ -11,82 +11,89 @@ uses
|
||||
|
||||
type
|
||||
// This visitor converts an AST expression subtree into a single string.
|
||||
TAstToTextVisitor = class(TAstVisitor)
|
||||
public
|
||||
function VisitConstant(const Node: IConstantNode): TDataValue; override;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; override;
|
||||
function VisitUnquote(const Node: IUnquoteNode): TDataValue; override;
|
||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; override;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
|
||||
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
|
||||
// It inherits from the generic visitor, returning a 'string' for each node.
|
||||
TAstToTextVisitor = class(TAstVisitor<string>)
|
||||
protected
|
||||
function VisitConstant(const Node: IConstantNode): string; override;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): string; override;
|
||||
function VisitKeyword(const Node: IKeywordNode): string; override;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): string; override;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): string; override;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): string; override;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): string; override;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): string; override;
|
||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): string; override;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): string; override;
|
||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): string; override;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): string; override;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): string; override;
|
||||
function VisitAssignment(const Node: IAssignmentNode): string; override;
|
||||
function VisitIndexer(const Node: IIndexerNode): string; override;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): string; override;
|
||||
function VisitQuasiquote(const Node: IQuasiquoteNode): string; override;
|
||||
function VisitUnquote(const Node: IUnquoteNode): string; override;
|
||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): string; override;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): string; override;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): string; override;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): string; override;
|
||||
function VisitRecurNode(const Node: IRecurNode): string; override;
|
||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): string; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.Classes, // For TStringBuilder
|
||||
Myc.Data.Keyword;
|
||||
|
||||
{ TAstToTextVisitor }
|
||||
|
||||
function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): string;
|
||||
var
|
||||
seriesStr, valueStr, lookbackStr: string;
|
||||
begin
|
||||
seriesStr := Node.Series.Accept(Self).AsText;
|
||||
valueStr := Node.Value.Accept(Self).AsText;
|
||||
seriesStr := Accept(Node.Series);
|
||||
valueStr := Accept(Node.Value);
|
||||
lookbackStr := '';
|
||||
if Assigned(Node.Lookback) then
|
||||
lookbackStr := ', ' + Node.Lookback.Accept(Self).AsText;
|
||||
lookbackStr := ', ' + Accept(Node.Lookback);
|
||||
Result := Format('%s.add(%s%s)', [seriesStr, valueStr, lookbackStr]);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): string;
|
||||
begin
|
||||
Result := Node.Identifier.Name + ' := ' + Node.Value.Accept(Self).AsText;
|
||||
Result := Node.Identifier.Name + ' := ' + Accept(Node.Value);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): string;
|
||||
begin
|
||||
var leftStr := Node.Left.Accept(Self).AsText;
|
||||
var rightStr := Node.Right.Accept(Self).AsText;
|
||||
var leftStr := Accept(Node.Left);
|
||||
var rightStr := Accept(Node.Right);
|
||||
Result := '(' + leftStr + ' ' + Node.Operator.ToString + ' ' + rightStr + ')';
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): string;
|
||||
begin
|
||||
Result := '{...}';
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): string;
|
||||
begin
|
||||
Result := Node.Value.ToString;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): string;
|
||||
begin
|
||||
Result := 'new series(' + Node.Definition + ')';
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): string;
|
||||
var
|
||||
i: Integer;
|
||||
sb: TStringBuilder;
|
||||
calleeStr: string;
|
||||
begin
|
||||
calleeStr := Node.Callee.Accept(Self).AsText;
|
||||
calleeStr := Accept(Node.Callee);
|
||||
|
||||
sb := TStringBuilder.Create;
|
||||
try
|
||||
@@ -94,7 +101,7 @@ begin
|
||||
sb.Append('(');
|
||||
for i := 0 to High(Node.Arguments) do
|
||||
begin
|
||||
sb.Append(Node.Arguments[i].Accept(Self).AsText);
|
||||
sb.Append(Accept(Node.Arguments[i]));
|
||||
if i < High(Node.Arguments) then
|
||||
sb.Append(', ');
|
||||
end;
|
||||
@@ -105,7 +112,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): string;
|
||||
begin
|
||||
// To represent a macro expansion as a single line of text, the most
|
||||
// informative representation is the original call itself. We can simply
|
||||
@@ -113,7 +120,7 @@ begin
|
||||
Result := VisitFunctionCall(Node);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitRecurNode(const Node: IRecurNode): string;
|
||||
var
|
||||
i: Integer;
|
||||
sb: TStringBuilder;
|
||||
@@ -123,7 +130,7 @@ begin
|
||||
sb.Append('recur(');
|
||||
for i := 0 to High(Node.Arguments) do
|
||||
begin
|
||||
sb.Append(Node.Arguments[i].Accept(Self).AsText);
|
||||
sb.Append(Accept(Node.Arguments[i]));
|
||||
if i < High(Node.Arguments) then
|
||||
sb.Append(', ');
|
||||
end;
|
||||
@@ -134,33 +141,38 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): string;
|
||||
begin
|
||||
Result := Node.Name;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): string;
|
||||
begin
|
||||
Result := Node.Condition.Accept(Self).AsText;
|
||||
Result := Accept(Node.Condition);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): string;
|
||||
var
|
||||
baseStr, indexStr: string;
|
||||
begin
|
||||
baseStr := Node.Base.Accept(Self).AsText;
|
||||
indexStr := Node.Index.Accept(Self).AsText;
|
||||
baseStr := Accept(Node.Base);
|
||||
indexStr := Accept(Node.Index);
|
||||
Result := Format('%s[%s]', [baseStr, indexStr]);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitKeyword(const Node: IKeywordNode): string;
|
||||
begin
|
||||
Result := ':' + Node.Value.Name;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): string;
|
||||
var
|
||||
i: Integer;
|
||||
sb: TStringBuilder;
|
||||
begin
|
||||
sb := TStringBuilder.Create;
|
||||
try
|
||||
sb.Append(#$03BB + '(');
|
||||
sb.Append(WideChar($03BB) + '('); // Lambda char
|
||||
if Length(Node.Parameters) > 0 then
|
||||
begin
|
||||
for i := 0 to High(Node.Parameters) do
|
||||
@@ -177,7 +189,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): string;
|
||||
var
|
||||
i: Integer;
|
||||
sb: TStringBuilder;
|
||||
@@ -204,56 +216,61 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): string;
|
||||
var
|
||||
baseStr: string;
|
||||
begin
|
||||
baseStr := Node.Base.Accept(Self).AsText;
|
||||
baseStr := Accept(Node.Base);
|
||||
Result := Format('%s.%s', [baseStr, Node.Member.Value.Name]);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): string;
|
||||
begin
|
||||
Result := '`' + Node.Expression.Accept(Self).AsText;
|
||||
Result := '`' + Accept(Node.Expression);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitUnquote(const Node: IUnquoteNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): string;
|
||||
begin
|
||||
Result := '~' + Node.Expression.Accept(Self).AsText;
|
||||
Result := '{...}';
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitUnquote(const Node: IUnquoteNode): string;
|
||||
begin
|
||||
Result := '~@' + Node.Expression.Accept(Self).AsText;
|
||||
Result := '~' + Accept(Node.Expression);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): string;
|
||||
begin
|
||||
Result := '~@' + Accept(Node.Expression);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): string;
|
||||
var
|
||||
seriesStr: string;
|
||||
begin
|
||||
seriesStr := Node.Series.Accept(Self).AsText;
|
||||
seriesStr := Accept(Node.Series);
|
||||
Result := Format('length(%s)', [seriesStr]);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): string;
|
||||
begin
|
||||
var condStr := Node.Condition.Accept(Self).AsText;
|
||||
var thenStr := Node.ThenBranch.Accept(Self).AsText;
|
||||
var elseStr := Node.ElseBranch.Accept(Self).AsText;
|
||||
var condStr := Accept(Node.Condition);
|
||||
var thenStr := Accept(Node.ThenBranch);
|
||||
var elseStr := Accept(Node.ElseBranch);
|
||||
Result := Format('(%s ? %s : %s)', [condStr, thenStr, elseStr]);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): string;
|
||||
begin
|
||||
Result := Node.Operator.ToString + ' ' + Node.Right.Accept(Self).AsText;
|
||||
Result := Node.Operator.ToString + ' ' + Accept(Node.Right);
|
||||
end;
|
||||
|
||||
function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||
function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): string;
|
||||
var
|
||||
initStr: string;
|
||||
begin
|
||||
if Assigned(Node.Initializer) then
|
||||
initStr := ' := ' + Node.Initializer.Accept(Self).AsText
|
||||
initStr := ' := ' + Accept(Node.Initializer)
|
||||
else
|
||||
initStr := '';
|
||||
Result := 'var ' + Node.Identifier.Name + initStr;
|
||||
|
||||
Reference in New Issue
Block a user