208 lines
6.9 KiB
ObjectPascal
208 lines
6.9 KiB
ObjectPascal
unit Myc.Fmx.AstEditor.Text;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
Myc.Data.Value,
|
|
Myc.Data.Scalar,
|
|
Myc.Ast.Visitor,
|
|
Myc.Ast.Nodes;
|
|
|
|
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 VisitFunctionCall(const Node: IFunctionCallNode): 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 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;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TAstToTextVisitor }
|
|
|
|
function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
|
var
|
|
seriesStr, valueStr, lookbackStr: string;
|
|
begin
|
|
seriesStr := Node.Series.Accept(Self).AsText;
|
|
valueStr := Node.Value.Accept(Self).AsText;
|
|
lookbackStr := '';
|
|
if Assigned(Node.Lookback) then
|
|
lookbackStr := ', ' + Node.Lookback.Accept(Self).AsText;
|
|
Result := Format('%s.add(%s%s)', [seriesStr, valueStr, lookbackStr]);
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue;
|
|
begin
|
|
Result := Node.Identifier.Name + ' := ' + Node.Value.Accept(Self).AsText;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
|
begin
|
|
var leftStr := Node.Left.Accept(Self).AsText;
|
|
var rightStr := Node.Right.Accept(Self).AsText;
|
|
Result := '(' + leftStr + ' ' + Node.Operator.ToString + ' ' + rightStr + ')';
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
|
begin
|
|
Result := '{...}';
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
|
|
begin
|
|
Result := Node.Value.ToString;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
|
begin
|
|
Result := 'new series(' + Node.Definition + ')';
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
|
var
|
|
i: Integer;
|
|
sb: TStringBuilder;
|
|
calleeStr: string;
|
|
begin
|
|
calleeStr := Node.Callee.Accept(Self).AsText;
|
|
|
|
sb := TStringBuilder.Create;
|
|
try
|
|
sb.Append(calleeStr);
|
|
sb.Append('(');
|
|
for i := 0 to High(Node.Arguments) do
|
|
begin
|
|
sb.Append(Node.Arguments[i].Accept(Self).AsText);
|
|
if i < High(Node.Arguments) then
|
|
sb.Append(', ');
|
|
end;
|
|
sb.Append(')');
|
|
Result := sb.ToString;
|
|
finally
|
|
sb.Free;
|
|
end;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitRecurNode(const Node: IRecurNode): TDataValue;
|
|
var
|
|
i: Integer;
|
|
sb: TStringBuilder;
|
|
begin
|
|
sb := TStringBuilder.Create;
|
|
try
|
|
sb.Append('recur(');
|
|
for i := 0 to High(Node.Arguments) do
|
|
begin
|
|
sb.Append(Node.Arguments[i].Accept(Self).AsText);
|
|
if i < High(Node.Arguments) then
|
|
sb.Append(', ');
|
|
end;
|
|
sb.Append(')');
|
|
Result := sb.ToString;
|
|
finally
|
|
sb.Free;
|
|
end;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
|
begin
|
|
Result := Node.Name;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
|
begin
|
|
Result := Node.Condition.Accept(Self).AsText;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
|
var
|
|
baseStr, indexStr: string;
|
|
begin
|
|
baseStr := Node.Base.Accept(Self).AsText;
|
|
indexStr := Node.Index.Accept(Self).AsText;
|
|
Result := Format('%s[%s]', [baseStr, indexStr]);
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
|
var
|
|
i: Integer;
|
|
sb: TStringBuilder;
|
|
begin
|
|
sb := TStringBuilder.Create;
|
|
try
|
|
sb.Append(#$03BB + '(');
|
|
if Length(Node.Parameters) > 0 then
|
|
begin
|
|
for i := 0 to High(Node.Parameters) do
|
|
begin
|
|
sb.Append(Node.Parameters[i].Name);
|
|
if i < High(Node.Parameters) then
|
|
sb.Append(', ');
|
|
end;
|
|
end;
|
|
sb.Append(') => {...}');
|
|
Result := sb.ToString;
|
|
finally
|
|
sb.Free;
|
|
end;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
|
var
|
|
baseStr: string;
|
|
begin
|
|
baseStr := Node.Base.Accept(Self).AsText;
|
|
Result := Format('%s.%s', [baseStr, Node.Member.Name]);
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
|
var
|
|
seriesStr: string;
|
|
begin
|
|
seriesStr := Node.Series.Accept(Self).AsText;
|
|
Result := Format('length(%s)', [seriesStr]);
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
|
begin
|
|
var condStr := Node.Condition.Accept(Self).AsText;
|
|
var thenStr := Node.ThenBranch.Accept(Self).AsText;
|
|
var elseStr := Node.ElseBranch.Accept(Self).AsText;
|
|
Result := Format('(%s ? %s : %s)', [condStr, thenStr, elseStr]);
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
|
|
begin
|
|
Result := Node.Operator.ToString + ' ' + Node.Right.Accept(Self).AsText;
|
|
end;
|
|
|
|
function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
|
var
|
|
initStr: string;
|
|
begin
|
|
if Assigned(Node.Initializer) then
|
|
initStr := ' := ' + Node.Initializer.Accept(Self).AsText
|
|
else
|
|
initStr := '';
|
|
Result := 'var ' + Node.Identifier.Name + initStr;
|
|
end;
|
|
|
|
end.
|