Ast ternary expr replaced by cond expr
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -23,7 +23,7 @@ type
|
|||||||
function VisitConstant(const Node: IConstantNode): Boolean; override;
|
function VisitConstant(const Node: IConstantNode): Boolean; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): Boolean; override;
|
function VisitKeyword(const Node: IKeywordNode): Boolean; override;
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): Boolean; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): Boolean; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): Boolean; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): Boolean; override; // Replaces Ternary
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): Boolean; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): Boolean; override;
|
||||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): Boolean; override;
|
function VisitRecordLiteral(const Node: IRecordLiteralNode): Boolean; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean; override;
|
||||||
@@ -184,9 +184,18 @@ begin
|
|||||||
Result := Accept(Node.Condition) and Accept(Node.ThenBranch) and Accept(Node.ElseBranch);
|
Result := Accept(Node.Condition) and Accept(Node.ThenBranch) and Accept(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPurityAnalyzer.VisitTernaryExpression(const Node: ITernaryExpressionNode): Boolean;
|
function TPurityAnalyzer.VisitCondExpression(const Node: ICondExpressionNode): Boolean;
|
||||||
|
var
|
||||||
|
pair: TCondPair;
|
||||||
begin
|
begin
|
||||||
Result := Accept(Node.Condition) and Accept(Node.ThenBranch) and Accept(Node.ElseBranch);
|
// All conditions and all branches must be pure
|
||||||
|
for pair in Node.Pairs do
|
||||||
|
begin
|
||||||
|
if not (Accept(pair.Condition) and Accept(pair.Branch)) then
|
||||||
|
Exit(False);
|
||||||
|
end;
|
||||||
|
// And the Else branch
|
||||||
|
Result := Accept(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPurityAnalyzer.VisitBlockExpression(const Node: IBlockExpressionNode): Boolean;
|
function TPurityAnalyzer.VisitBlockExpression(const Node: IBlockExpressionNode): Boolean;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ type
|
|||||||
// Overrides for TCO propagation
|
// Overrides for TCO propagation
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): IAstNode; override; // Replaces Ternary
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||||
function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
|
function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
|
||||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
|
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
|
||||||
@@ -160,27 +160,46 @@ begin
|
|||||||
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTCO.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
function TAstTCO.VisitCondExpression(const Node: ICondExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
isContextTail: Boolean;
|
isContextTail: Boolean;
|
||||||
newCond, newThen, newElse: IAstNode;
|
hasChanged: Boolean;
|
||||||
|
i: Integer;
|
||||||
|
newPairs: TArray<TCondPair>;
|
||||||
|
newElse: IAstNode;
|
||||||
|
newCond, newBranch: IAstNode;
|
||||||
begin
|
begin
|
||||||
isContextTail := FIsTailStack.Peek;
|
isContextTail := FIsTailStack.Peek;
|
||||||
|
hasChanged := False;
|
||||||
|
SetLength(newPairs, Length(Node.Pairs));
|
||||||
|
|
||||||
// Condition is never in tail position
|
for i := 0 to High(Node.Pairs) do
|
||||||
FNextIsTail := False;
|
begin
|
||||||
newCond := Accept(Node.Condition);
|
// 1. Condition is never in tail position
|
||||||
|
FNextIsTail := False;
|
||||||
|
newCond := Accept(Node.Pairs[i].Condition);
|
||||||
|
|
||||||
// Then/Else branches ARE in tail position if the TernaryExpr is
|
// 2. Branch IS in tail position (if CondExpr is)
|
||||||
|
FNextIsTail := isContextTail;
|
||||||
|
newBranch := Accept(Node.Pairs[i].Branch);
|
||||||
|
|
||||||
|
newPairs[i] := TCondPair.Create(newCond, newBranch);
|
||||||
|
|
||||||
|
if (newCond <> Node.Pairs[i].Condition) or (newBranch <> Node.Pairs[i].Branch) then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 3. Else Branch IS in tail position
|
||||||
FNextIsTail := isContextTail;
|
FNextIsTail := isContextTail;
|
||||||
newThen := Accept(Node.ThenBranch);
|
|
||||||
newElse := Accept(Node.ElseBranch);
|
newElse := Accept(Node.ElseBranch);
|
||||||
|
|
||||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
if newElse <> Node.ElseBranch then
|
||||||
|
hasChanged := True;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
// CoW: Reuse Identity
|
Result := TAst.CondExpr(Node.Identity, newPairs, newElse, Node.StaticType);
|
||||||
Result := TAst.TernaryExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ type
|
|||||||
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): IAstNode; override; // Replaced Ternary
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): IAstNode; override;
|
function VisitMemberAccess(const Node: IMemberAccessNode): IAstNode; override;
|
||||||
function VisitIndexer(const Node: IIndexerNode): IAstNode; override;
|
function VisitIndexer(const Node: IIndexerNode): IAstNode; override;
|
||||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
|
function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
|
||||||
@@ -221,7 +221,7 @@ begin
|
|||||||
for i := 0 to Node.Arguments.Count - 1 do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
newArgs[i] := Accept(Node.Arguments[i]);
|
newArgs[i] := Accept(Node.Arguments[i]);
|
||||||
|
|
||||||
// FIX: Wrap in List
|
// Wrap in List
|
||||||
var argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
var argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
||||||
Result := TAst.Recur(Node.Identity, argList, TTypes.Void);
|
Result := TAst.Recur(Node.Identity, argList, TTypes.Void);
|
||||||
end;
|
end;
|
||||||
@@ -395,7 +395,7 @@ begin
|
|||||||
temp.Free;
|
temp.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// FIX: Wrap in List
|
// Wrap in List
|
||||||
var paramList := TParameterList.Create(newParams, Node.Parameters.Identity);
|
var paramList := TParameterList.Create(newParams, Node.Parameters.Identity);
|
||||||
|
|
||||||
Result :=
|
Result :=
|
||||||
@@ -493,7 +493,7 @@ begin
|
|||||||
retType := TTypes.Unknown;
|
retType := TTypes.Unknown;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// FIX: Wrap in List
|
// Wrap in List
|
||||||
var argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
var argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
||||||
|
|
||||||
Result := TAst.FunctionCall(Node.Identity, newCallee, argList, retType, Node.IsTailCall, nil, False);
|
Result := TAst.FunctionCall(Node.Identity, newCallee, argList, retType, Node.IsTailCall, nil, False);
|
||||||
@@ -514,7 +514,7 @@ begin
|
|||||||
else
|
else
|
||||||
blockType := TTypes.Void;
|
blockType := TTypes.Void;
|
||||||
|
|
||||||
// FIX: Wrap in List
|
// Wrap in List
|
||||||
var exprList := TExpressionList.Create(newExprs, Node.Expressions.Identity);
|
var exprList := TExpressionList.Create(newExprs, Node.Expressions.Identity);
|
||||||
Result := TAst.Block(Node.Identity, exprList, blockType);
|
Result := TAst.Block(Node.Identity, exprList, blockType);
|
||||||
end;
|
end;
|
||||||
@@ -553,36 +553,80 @@ begin
|
|||||||
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTypeChecker.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
function TTypeChecker.VisitCondExpression(const Node: ICondExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
conditionType, thenType, elseType, resultType: IStaticType;
|
i: Integer;
|
||||||
newCond, newThen, newElse: IAstNode;
|
newPairs: TArray<TCondPair>;
|
||||||
|
newElse: IAstNode;
|
||||||
|
condType, branchType, resultType: IStaticType;
|
||||||
begin
|
begin
|
||||||
newCond := Accept(Node.Condition);
|
SetLength(newPairs, Length(Node.Pairs));
|
||||||
newThen := Accept(Node.ThenBranch);
|
resultType := nil; // Start with nothing
|
||||||
|
|
||||||
|
for i := 0 to High(Node.Pairs) do
|
||||||
|
begin
|
||||||
|
// 1. Visit Condition
|
||||||
|
var newCond := Accept(Node.Pairs[i].Condition);
|
||||||
|
condType := newCond.AsTypedNode.StaticType;
|
||||||
|
|
||||||
|
if (condType.Kind <> stUnknown)
|
||||||
|
and not TTypeRules.CanAssign(TTypes.Ordinal, condType)
|
||||||
|
and not TTypeRules.CanAssign(TTypes.Boolean, condType) then
|
||||||
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError(Format('Cond condition must be Boolean or Ordinal, but got %s', [condType.ToString]), Node);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 2. Visit Branch
|
||||||
|
var newBranch := Accept(Node.Pairs[i].Branch);
|
||||||
|
branchType := newBranch.AsTypedNode.StaticType;
|
||||||
|
|
||||||
|
newPairs[i] := TCondPair.Create(newCond, newBranch);
|
||||||
|
|
||||||
|
// 3. Promote Result Type
|
||||||
|
if resultType = nil then
|
||||||
|
resultType := branchType
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
var promoted := TTypeRules.Promote(resultType, branchType);
|
||||||
|
if promoted = nil then
|
||||||
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError(
|
||||||
|
Format('Incompatible types in Cond branches: %s and %s', [resultType.ToString, branchType.ToString]),
|
||||||
|
Node
|
||||||
|
);
|
||||||
|
resultType := TTypes.Unknown;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
resultType := promoted;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 4. Visit Else
|
||||||
newElse := Accept(Node.ElseBranch);
|
newElse := Accept(Node.ElseBranch);
|
||||||
|
// Else branch is mandatory in our new AST structure (can be Nop/Void, but is present)
|
||||||
|
var elseType := newElse.AsTypedNode.StaticType;
|
||||||
|
|
||||||
conditionType := newCond.AsTypedNode.StaticType;
|
|
||||||
if (conditionType.Kind <> stUnknown)
|
|
||||||
and not TTypeRules.CanAssign(TTypes.Ordinal, conditionType)
|
|
||||||
and not TTypeRules.CanAssign(TTypes.Boolean, conditionType) then
|
|
||||||
begin
|
|
||||||
if Assigned(FLog) then
|
|
||||||
FLog.AddError(Format('Ternary condition must be Boolean or Ordinal, but got %s', [conditionType.ToString]), Node);
|
|
||||||
end;
|
|
||||||
|
|
||||||
thenType := newThen.AsTypedNode.StaticType;
|
|
||||||
elseType := newElse.AsTypedNode.StaticType;
|
|
||||||
|
|
||||||
resultType := TTypeRules.Promote(thenType, elseType);
|
|
||||||
if resultType = nil then
|
if resultType = nil then
|
||||||
|
resultType := elseType
|
||||||
|
else
|
||||||
begin
|
begin
|
||||||
if Assigned(FLog) then
|
var promoted := TTypeRules.Promote(resultType, elseType);
|
||||||
FLog.AddError(Format('Cannot promote types %s and %s in Ternary-Expression', [thenType.ToString, elseType.ToString]), Node);
|
if promoted = nil then
|
||||||
resultType := TTypes.Unknown;
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError(
|
||||||
|
Format('Incompatible types in Cond branches (Else): %s and %s', [resultType.ToString, elseType.ToString]),
|
||||||
|
Node
|
||||||
|
);
|
||||||
|
resultType := TTypes.Unknown;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
resultType := promoted;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := TAst.TernaryExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
Result := TAst.CondExpr(Node.Identity, newPairs, newElse, resultType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTypeChecker.VisitMemberAccess(const Node: IMemberAccessNode): IAstNode;
|
function TTypeChecker.VisitMemberAccess(const Node: IMemberAccessNode): IAstNode;
|
||||||
@@ -726,7 +770,7 @@ begin
|
|||||||
scalarDefFields[i] := TScalarRecordField.Create(newFields[i].Key.Value, scalarKind);
|
scalarDefFields[i] := TScalarRecordField.Create(newFields[i].Key.Value, scalarKind);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// FIX: Wrap in List
|
// Wrap in List
|
||||||
var fieldList := TRecordFieldList.Create(newFields, Node.Fields.Identity);
|
var fieldList := TRecordFieldList.Create(newFields, Node.Fields.Identity);
|
||||||
|
|
||||||
if allScalar then
|
if allScalar then
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type
|
|||||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
|
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
|
function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): TDataValue; override; // Replaces Ternary
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
||||||
@@ -250,12 +250,15 @@ begin
|
|||||||
AppendLine(Format('} -> %s', [Result.ToString]));
|
AppendLine(Format('} -> %s', [Result.ToString]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDebugEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function TDebugEvaluatorVisitor.VisitCondExpression(const Node: ICondExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
AppendLine('TernaryExpr {');
|
AppendLine(Format('CondExpr (%d pairs) {', [Length(Node.Pairs)]));
|
||||||
Indent;
|
Indent;
|
||||||
try
|
try
|
||||||
Result := inherited VisitTernaryExpression(Node);
|
// We just call inherited, which does the logic.
|
||||||
|
// We don't log every branch check here to avoid spamming output,
|
||||||
|
// but the recursive evaluation of conditions will show up in the log naturally.
|
||||||
|
Result := inherited VisitCondExpression(Node);
|
||||||
finally
|
finally
|
||||||
Unindent;
|
Unindent;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ type
|
|||||||
function VisitIdentifier(const Node: IIdentifierNode): TVoid; override;
|
function VisitIdentifier(const Node: IIdentifierNode): TVoid; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TVoid; override;
|
function VisitKeyword(const Node: IKeywordNode): TVoid; override;
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TVoid; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TVoid; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TVoid; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): TVoid; override; // Replaced Ternary
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TVoid; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TVoid; override;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TVoid; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TVoid; override;
|
||||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TVoid; override;
|
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TVoid; override;
|
||||||
@@ -187,14 +187,22 @@ begin
|
|||||||
Unindent;
|
Unindent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstDumper.VisitTernaryExpression(const Node: ITernaryExpressionNode): TVoid;
|
function TAstDumper.VisitCondExpression(const Node: ICondExpressionNode): TVoid;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Log('TernaryExpression', Node);
|
LogFmt('CondExpression (%d pairs)', [Length(Node.Pairs)], Node);
|
||||||
Indent;
|
Indent;
|
||||||
Log('Condition:');
|
for i := 0 to High(Node.Pairs) do
|
||||||
Node.Condition.Accept(Self);
|
begin
|
||||||
Log('Then:');
|
LogFmt('Pair %d:', [i]);
|
||||||
Node.ThenBranch.Accept(Self);
|
Indent;
|
||||||
|
Log('Condition:');
|
||||||
|
Node.Pairs[i].Condition.Accept(Self);
|
||||||
|
Log('Branch:');
|
||||||
|
Node.Pairs[i].Branch.Accept(Self);
|
||||||
|
Unindent;
|
||||||
|
end;
|
||||||
Log('Else:');
|
Log('Else:');
|
||||||
Node.ElseBranch.Accept(Self);
|
Node.ElseBranch.Accept(Self);
|
||||||
Unindent;
|
Unindent;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ type
|
|||||||
function VisitRecordField(const Node: IRecordFieldNode): TDataValue; virtual;
|
function VisitRecordField(const Node: IRecordFieldNode): TDataValue; virtual;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual;
|
function VisitCondExpression(const Node: ICondExpressionNode): TDataValue; virtual; // Replaces Ternary
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
|
||||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual;
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual;
|
||||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; virtual;
|
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; virtual;
|
||||||
@@ -590,12 +590,20 @@ begin
|
|||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitCondExpression(const Node: ICondExpressionNode): TDataValue;
|
||||||
|
var
|
||||||
|
pair: TCondPair;
|
||||||
begin
|
begin
|
||||||
if IsTruthy(Node.Condition.Accept(Self)) then
|
for pair in Node.Pairs do
|
||||||
Result := Node.ThenBranch.Accept(Self)
|
begin
|
||||||
else
|
if IsTruthy(pair.Condition.Accept(Self)) then
|
||||||
Result := Node.ElseBranch.Accept(Self);
|
begin
|
||||||
|
Result := pair.Branch.Accept(Self);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
// Else branch is mandatory in AST (though can be Nop/Void in source if omitted and normalized)
|
||||||
|
Result := Node.ElseBranch.Accept(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
|
|||||||
+57
-19
@@ -31,7 +31,8 @@ type
|
|||||||
function JsonToIdentifierNode(const AObj: TJSONObject): IIdentifierNode;
|
function JsonToIdentifierNode(const AObj: TJSONObject): IIdentifierNode;
|
||||||
function JsonToKeywordNode(const AObj: TJSONObject): IKeywordNode;
|
function JsonToKeywordNode(const AObj: TJSONObject): IKeywordNode;
|
||||||
function JsonToIfExprNode(const AObj: TJSONObject): IIfExpressionNode;
|
function JsonToIfExprNode(const AObj: TJSONObject): IIfExpressionNode;
|
||||||
function JsonToTernaryExprNode(const AObj: TJSONObject): ITernaryExpressionNode;
|
function JsonToCondExprNode(const AObj: TJSONObject): ICondExpressionNode;
|
||||||
|
function JsonToTernaryExprNode(const AObj: TJSONObject): IAstNode; // Backward Compatibility
|
||||||
function JsonToLambdaExprNode(const AObj: TJSONObject): ILambdaExpressionNode;
|
function JsonToLambdaExprNode(const AObj: TJSONObject): ILambdaExpressionNode;
|
||||||
function JsonToMacroDefNode(const AObj: TJSONObject): IMacroDefinitionNode;
|
function JsonToMacroDefNode(const AObj: TJSONObject): IMacroDefinitionNode;
|
||||||
function JsonToQuasiquoteNode(const AObj: TJSONObject): IQuasiquoteNode;
|
function JsonToQuasiquoteNode(const AObj: TJSONObject): IQuasiquoteNode;
|
||||||
@@ -44,7 +45,7 @@ type
|
|||||||
function JsonToVarDeclNode(const AObj: TJSONObject): IVariableDeclarationNode;
|
function JsonToVarDeclNode(const AObj: TJSONObject): IVariableDeclarationNode;
|
||||||
function JsonToAssignmentNode(const AObj: TJSONObject): IAssignmentNode;
|
function JsonToAssignmentNode(const AObj: TJSONObject): IAssignmentNode;
|
||||||
function JsonToIndexerNode(const AObj: TJSONObject): IIndexerNode;
|
function JsonToIndexerNode(const AObj: TJSONObject): IIndexerNode;
|
||||||
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode; // <--- KORRIGIERT
|
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode;
|
||||||
function JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
|
function JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
|
||||||
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
||||||
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
||||||
@@ -57,7 +58,7 @@ type
|
|||||||
function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
|
function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
|
function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
|
||||||
|
|
||||||
// List Visitors (stubbed mostly, as parents handle array generation for JSON structure)
|
// List Visitors
|
||||||
function VisitParameterList(const Node: IParameterList): TJSONObject; override;
|
function VisitParameterList(const Node: IParameterList): TJSONObject; override;
|
||||||
function VisitArgumentList(const Node: IArgumentList): TJSONObject; override;
|
function VisitArgumentList(const Node: IArgumentList): TJSONObject; override;
|
||||||
function VisitExpressionList(const Node: IExpressionList): TJSONObject; override;
|
function VisitExpressionList(const Node: IExpressionList): TJSONObject; override;
|
||||||
@@ -65,7 +66,7 @@ type
|
|||||||
function VisitRecordField(const Node: IRecordFieldNode): TJSONObject; override;
|
function VisitRecordField(const Node: IRecordFieldNode): TJSONObject; override;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): TJSONObject; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
|
||||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TJSONObject; override;
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TJSONObject; override;
|
||||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TJSONObject; override;
|
function VisitQuasiquote(const Node: IQuasiquoteNode): TJSONObject; override;
|
||||||
@@ -186,19 +187,32 @@ begin
|
|||||||
Result.AddPair('ElseBranch', TJSONNull.Create);
|
Result.AddPair('ElseBranch', TJSONNull.Create);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject;
|
function TJsonAstConverter.VisitCondExpression(const Node: ICondExpressionNode): TJSONObject;
|
||||||
var
|
var
|
||||||
condObj, thenObj, elseObj: TJSONObject;
|
pairsArray: TJSONArray;
|
||||||
|
pairObj: TJSONObject;
|
||||||
|
elseObj: TJSONObject;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
condObj := Accept(Node.Condition);
|
pairsArray := TJSONArray.Create;
|
||||||
thenObj := Accept(Node.ThenBranch);
|
for i := 0 to High(Node.Pairs) do
|
||||||
elseObj := Accept(Node.ElseBranch);
|
begin
|
||||||
|
pairObj := TJSONObject.Create;
|
||||||
|
pairObj.AddPair('Condition', Accept(Node.Pairs[i].Condition));
|
||||||
|
pairObj.AddPair('Branch', Accept(Node.Pairs[i].Branch));
|
||||||
|
pairsArray.Add(pairObj);
|
||||||
|
end;
|
||||||
|
|
||||||
|
elseObj := Accept(Node.ElseBranch); // Accept handles nil
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('TernaryExpr'));
|
Result.AddPair('NodeType', TJSONString.Create('CondExpr'));
|
||||||
Result.AddPair('Condition', condObj);
|
Result.AddPair('Pairs', pairsArray);
|
||||||
Result.AddPair('ThenBranch', thenObj);
|
|
||||||
Result.AddPair('ElseBranch', elseObj);
|
if Assigned(elseObj) then
|
||||||
|
Result.AddPair('ElseBranch', elseObj)
|
||||||
|
else
|
||||||
|
Result.AddPair('ElseBranch', TJSONNull.Create);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject;
|
function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject;
|
||||||
@@ -451,10 +465,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// --- List Visitors (Placeholder return) ---
|
// --- List Visitors (Placeholder return) ---
|
||||||
// Since we iterate manually in parent nodes to form JSON Arrays, these are technically not used
|
|
||||||
// by the current logic, but required by the interface.
|
|
||||||
// Note: If we wanted strict visitor compliance, VisitFunctionCall would call Accept(List),
|
|
||||||
// which would return TJSONObject wrapping the array. We skip that level of nesting here.
|
|
||||||
|
|
||||||
function TJsonAstConverter.VisitParameterList(const Node: IParameterList): TJSONObject;
|
function TJsonAstConverter.VisitParameterList(const Node: IParameterList): TJSONObject;
|
||||||
begin
|
begin
|
||||||
@@ -544,13 +554,39 @@ begin
|
|||||||
Result := TAst.IfExpr(condNode, thenNode, elseNode);
|
Result := TAst.IfExpr(condNode, thenNode, elseNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToTernaryExprNode(const AObj: TJSONObject): ITernaryExpressionNode;
|
function TJsonAstConverter.JsonToCondExprNode(const AObj: TJSONObject): ICondExpressionNode;
|
||||||
|
var
|
||||||
|
pairsArray: TJSONArray;
|
||||||
|
pairs: TArray<TCondPair>;
|
||||||
|
elseNode: IAstNode;
|
||||||
|
i: Integer;
|
||||||
|
pairObj: TJSONObject;
|
||||||
|
begin
|
||||||
|
pairsArray := AObj.GetValue<TJSONArray>('Pairs');
|
||||||
|
SetLength(pairs, pairsArray.Count);
|
||||||
|
for i := 0 to pairsArray.Count - 1 do
|
||||||
|
begin
|
||||||
|
pairObj := pairsArray.Items[i] as TJSONObject;
|
||||||
|
pairs[i] := TCondPair.Create(JsonToNode(pairObj.GetValue('Condition')), JsonToNode(pairObj.GetValue('Branch')));
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not (AObj.GetValue('ElseBranch') is TJSONNull) then
|
||||||
|
elseNode := JsonToNode(AObj.GetValue('ElseBranch'))
|
||||||
|
else
|
||||||
|
elseNode := nil;
|
||||||
|
|
||||||
|
Result := TAst.CondExpr(pairs, elseNode);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.JsonToTernaryExprNode(const AObj: TJSONObject): IAstNode;
|
||||||
var
|
var
|
||||||
condNode, thenNode, elseNode: IAstNode;
|
condNode, thenNode, elseNode: IAstNode;
|
||||||
begin
|
begin
|
||||||
condNode := JsonToNode(AObj.GetValue('Condition'));
|
condNode := JsonToNode(AObj.GetValue('Condition'));
|
||||||
thenNode := JsonToNode(AObj.GetValue('ThenBranch'));
|
thenNode := JsonToNode(AObj.GetValue('ThenBranch'));
|
||||||
elseNode := JsonToNode(AObj.GetValue('ElseBranch'));
|
elseNode := JsonToNode(AObj.GetValue('ElseBranch'));
|
||||||
|
|
||||||
|
// Map to CondExpr using the helper in TAst
|
||||||
Result := TAst.TernaryExpr(condNode, thenNode, elseNode);
|
Result := TAst.TernaryExpr(condNode, thenNode, elseNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -775,8 +811,10 @@ begin
|
|||||||
Result := JsonToKeywordNode(obj)
|
Result := JsonToKeywordNode(obj)
|
||||||
else if nodeType = 'IfExpr' then
|
else if nodeType = 'IfExpr' then
|
||||||
Result := JsonToIfExprNode(obj)
|
Result := JsonToIfExprNode(obj)
|
||||||
|
else if nodeType = 'CondExpr' then
|
||||||
|
Result := JsonToCondExprNode(obj)
|
||||||
else if nodeType = 'TernaryExpr' then
|
else if nodeType = 'TernaryExpr' then
|
||||||
Result := JsonToTernaryExprNode(obj)
|
Result := JsonToTernaryExprNode(obj) // Backward Compatibility
|
||||||
else if nodeType = 'LambdaExpr' then
|
else if nodeType = 'LambdaExpr' then
|
||||||
Result := JsonToLambdaExprNode(obj)
|
Result := JsonToLambdaExprNode(obj)
|
||||||
else if nodeType = 'MacroDef' then
|
else if nodeType = 'MacroDef' then
|
||||||
|
|||||||
+46
-34
@@ -91,7 +91,7 @@ type
|
|||||||
|
|
||||||
// Control Flow & Structure
|
// Control Flow & Structure
|
||||||
IIfExpressionNode = interface;
|
IIfExpressionNode = interface;
|
||||||
ITernaryExpressionNode = interface;
|
ICondExpressionNode = interface;
|
||||||
ILambdaExpressionNode = interface;
|
ILambdaExpressionNode = interface;
|
||||||
IFunctionCallNode = interface;
|
IFunctionCallNode = interface;
|
||||||
IMacroExpansionNode = interface;
|
IMacroExpansionNode = interface;
|
||||||
@@ -123,7 +123,7 @@ type
|
|||||||
akRecordFieldList,
|
akRecordFieldList,
|
||||||
akRecordField,
|
akRecordField,
|
||||||
akIfExpression,
|
akIfExpression,
|
||||||
akTernaryExpression,
|
akCondExpression,
|
||||||
akLambdaExpression,
|
akLambdaExpression,
|
||||||
akFunctionCall,
|
akFunctionCall,
|
||||||
akMacroExpansion,
|
akMacroExpansion,
|
||||||
@@ -149,6 +149,13 @@ type
|
|||||||
function ToString: string;
|
function ToString: string;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Represents a single branch in a Cond expression (Condition -> Branch)
|
||||||
|
TCondPair = record
|
||||||
|
Condition: IAstNode;
|
||||||
|
Branch: IAstNode;
|
||||||
|
constructor Create(const ACondition, ABranch: IAstNode);
|
||||||
|
end;
|
||||||
|
|
||||||
// --- Base Interfaces ---
|
// --- Base Interfaces ---
|
||||||
|
|
||||||
IAstNode = interface
|
IAstNode = interface
|
||||||
@@ -173,7 +180,7 @@ type
|
|||||||
function AsRecordField: IRecordFieldNode;
|
function AsRecordField: IRecordFieldNode;
|
||||||
|
|
||||||
function AsIfExpression: IIfExpressionNode;
|
function AsIfExpression: IIfExpressionNode;
|
||||||
function AsTernaryExpression: ITernaryExpressionNode;
|
function AsCondExpression: ICondExpressionNode;
|
||||||
function AsLambdaExpression: ILambdaExpressionNode;
|
function AsLambdaExpression: ILambdaExpressionNode;
|
||||||
function AsFunctionCall: IFunctionCallNode;
|
function AsFunctionCall: IFunctionCallNode;
|
||||||
function AsMacroExpansion: IMacroExpansionNode;
|
function AsMacroExpansion: IMacroExpansionNode;
|
||||||
@@ -279,14 +286,12 @@ type
|
|||||||
property ElseBranch: IAstNode read GetElseBranch;
|
property ElseBranch: IAstNode read GetElseBranch;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ITernaryExpressionNode = interface(IAstTypedNode)
|
ICondExpressionNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetCondition: IAstNode;
|
function GetPairs: TArray<TCondPair>;
|
||||||
function GetThenBranch: IAstNode;
|
|
||||||
function GetElseBranch: IAstNode;
|
function GetElseBranch: IAstNode;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Condition: IAstNode read GetCondition;
|
property Pairs: TArray<TCondPair> read GetPairs;
|
||||||
property ThenBranch: IAstNode read GetThenBranch;
|
|
||||||
property ElseBranch: IAstNode read GetElseBranch;
|
property ElseBranch: IAstNode read GetElseBranch;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -467,7 +472,7 @@ type
|
|||||||
function VisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
function VisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function VisitCondExpression(const Node: ICondExpressionNode): TDataValue;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||||
@@ -515,7 +520,7 @@ type
|
|||||||
function AsRecordField: IRecordFieldNode; virtual;
|
function AsRecordField: IRecordFieldNode; virtual;
|
||||||
|
|
||||||
function AsIfExpression: IIfExpressionNode; virtual;
|
function AsIfExpression: IIfExpressionNode; virtual;
|
||||||
function AsTernaryExpression: ITernaryExpressionNode; virtual;
|
function AsCondExpression: ICondExpressionNode; virtual;
|
||||||
function AsLambdaExpression: ILambdaExpressionNode; virtual;
|
function AsLambdaExpression: ILambdaExpressionNode; virtual;
|
||||||
function AsFunctionCall: IFunctionCallNode; virtual;
|
function AsFunctionCall: IFunctionCallNode; virtual;
|
||||||
function AsMacroExpansion: IMacroExpansionNode; virtual;
|
function AsMacroExpansion: IMacroExpansionNode; virtual;
|
||||||
@@ -694,21 +699,22 @@ type
|
|||||||
function AsIfExpression: IIfExpressionNode; override;
|
function AsIfExpression: IIfExpressionNode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TTernaryExpressionNode = class(TAstTypedNode, ITernaryExpressionNode)
|
TCondExpressionNode = class(TAstTypedNode, ICondExpressionNode)
|
||||||
private
|
private
|
||||||
FCondition, FThenBranch, FElseBranch: IAstNode;
|
FPairs: TArray<TCondPair>;
|
||||||
function GetCondition: IAstNode;
|
FElseBranch: IAstNode;
|
||||||
function GetThenBranch: IAstNode;
|
function GetPairs: TArray<TCondPair>;
|
||||||
function GetElseBranch: IAstNode;
|
function GetElseBranch: IAstNode;
|
||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(
|
constructor Create(
|
||||||
const ACondition, AThenBranch, AElseBranch: IAstNode;
|
const APairs: TArray<TCondPair>;
|
||||||
|
const AElseBranch: IAstNode;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const AIdentity: IAstIdentity
|
const AIdentity: IAstIdentity
|
||||||
);
|
);
|
||||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
function AsTernaryExpression: ITernaryExpressionNode; override;
|
function AsCondExpression: ICondExpressionNode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode, IFunctionDefinition)
|
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode, IFunctionDefinition)
|
||||||
@@ -1004,6 +1010,14 @@ begin
|
|||||||
Result := Result.Substring(2);
|
Result := Result.Substring(2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TCondPair }
|
||||||
|
|
||||||
|
constructor TCondPair.Create(const ACondition, ABranch: IAstNode);
|
||||||
|
begin
|
||||||
|
Condition := ACondition;
|
||||||
|
Branch := ABranch;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TCompilerError }
|
{ TCompilerError }
|
||||||
|
|
||||||
constructor TCompilerError.Create(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode);
|
constructor TCompilerError.Create(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode);
|
||||||
@@ -1174,7 +1188,7 @@ function TAstNode.AsIfExpression: IIfExpressionNode;
|
|||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
function TAstNode.AsTernaryExpression: ITernaryExpressionNode;
|
function TAstNode.AsCondExpression: ICondExpressionNode;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
@@ -1567,45 +1581,43 @@ begin
|
|||||||
Result := akIfExpression;
|
Result := akIfExpression;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTernaryExpressionNode }
|
{ TCondExpressionNode }
|
||||||
|
|
||||||
constructor TTernaryExpressionNode.Create(
|
constructor TCondExpressionNode.Create(
|
||||||
const ACondition, AThenBranch, AElseBranch: IAstNode;
|
const APairs: TArray<TCondPair>;
|
||||||
|
const AElseBranch: IAstNode;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const AIdentity: IAstIdentity
|
const AIdentity: IAstIdentity
|
||||||
);
|
);
|
||||||
begin
|
begin
|
||||||
inherited Create(AStaticType, AIdentity);
|
inherited Create(AStaticType, AIdentity);
|
||||||
FCondition := ACondition;
|
FPairs := APairs;
|
||||||
FThenBranch := AThenBranch;
|
|
||||||
FElseBranch := AElseBranch;
|
FElseBranch := AElseBranch;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
function TCondExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := Visitor.VisitTernaryExpression(Self);
|
Result := Visitor.VisitCondExpression(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTernaryExpressionNode.AsTernaryExpression: ITernaryExpressionNode;
|
function TCondExpressionNode.AsCondExpression: ICondExpressionNode;
|
||||||
begin
|
begin
|
||||||
Result := Self;
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTernaryExpressionNode.GetCondition: IAstNode;
|
function TCondExpressionNode.GetPairs: TArray<TCondPair>;
|
||||||
begin
|
begin
|
||||||
Result := FCondition;
|
Result := FPairs;
|
||||||
end;
|
end;
|
||||||
function TTernaryExpressionNode.GetThenBranch: IAstNode;
|
|
||||||
begin
|
function TCondExpressionNode.GetElseBranch: IAstNode;
|
||||||
Result := FThenBranch;
|
|
||||||
end;
|
|
||||||
function TTernaryExpressionNode.GetElseBranch: IAstNode;
|
|
||||||
begin
|
begin
|
||||||
Result := FElseBranch;
|
Result := FElseBranch;
|
||||||
end;
|
end;
|
||||||
function TTernaryExpressionNode.GetKind: TAstNodeKind;
|
|
||||||
|
function TCondExpressionNode.GetKind: TAstNodeKind;
|
||||||
begin
|
begin
|
||||||
Result := akTernaryExpression;
|
Result := akCondExpression;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLambdaExpressionNode }
|
{ TLambdaExpressionNode }
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type
|
|||||||
|
|
||||||
// --- Structural Nodes (Replace Logic) ---
|
// --- Structural Nodes (Replace Logic) ---
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): IAstNode; override; // Replaces Ternary
|
||||||
function VisitAssignment(const Node: IAssignmentNode): IAstNode; override;
|
function VisitAssignment(const Node: IAssignmentNode): IAstNode; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||||
@@ -279,18 +279,38 @@ begin
|
|||||||
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstNodeRemover.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
function TAstNodeRemover.VisitCondExpression(const Node: ICondExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
newCond, newThen, newElse: IAstNode;
|
i: Integer;
|
||||||
|
newPairs: TArray<TCondPair>;
|
||||||
|
newElse: IAstNode;
|
||||||
|
newCond, newBranch: IAstNode;
|
||||||
|
hasChanged: Boolean;
|
||||||
begin
|
begin
|
||||||
newCond := EnsureNode(Accept(Node.Condition), Node);
|
SetLength(newPairs, Length(Node.Pairs));
|
||||||
newThen := EnsureNode(Accept(Node.ThenBranch), Node);
|
hasChanged := False;
|
||||||
newElse := EnsureNode(Accept(Node.ElseBranch), Node);
|
|
||||||
|
|
||||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
for i := 0 to High(Node.Pairs) do
|
||||||
|
begin
|
||||||
|
// Ensure mandatory children exist (replace with Nop if removed)
|
||||||
|
newCond := EnsureNode(Accept(Node.Pairs[i].Condition), Node);
|
||||||
|
newBranch := EnsureNode(Accept(Node.Pairs[i].Branch), Node);
|
||||||
|
|
||||||
|
newPairs[i] := TCondPair.Create(newCond, newBranch);
|
||||||
|
|
||||||
|
if (newCond <> Node.Pairs[i].Condition) or (newBranch <> Node.Pairs[i].Branch) then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Else branch is effectively mandatory in the structure, even if it's Nop/Void
|
||||||
|
newElse := EnsureNode(Accept(Node.ElseBranch), Node);
|
||||||
|
if newElse <> Node.ElseBranch then
|
||||||
|
hasChanged := True;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
Exit(Node);
|
Exit(Node);
|
||||||
|
|
||||||
Result := TAst.TernaryExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
Result := TAst.CondExpr(Node.Identity, newPairs, newElse, Node.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstNodeRemover.VisitAssignment(const Node: IAssignmentNode): IAstNode;
|
function TAstNodeRemover.VisitAssignment(const Node: IAssignmentNode): IAstNode;
|
||||||
|
|||||||
+25
-10
@@ -50,7 +50,7 @@ var
|
|||||||
list_content ::= special_form | function_call
|
list_content ::= special_form | function_call
|
||||||
|
|
||||||
special_form ::= "if" expression expression expression?
|
special_form ::= "if" expression expression expression?
|
||||||
| "?" expression expression expression
|
| "?" (expression expression)* expression (* cond1 branch1 ... else *)
|
||||||
| "def" identifier expression?
|
| "def" identifier expression?
|
||||||
| "defmacro" identifier parameter_list expression
|
| "defmacro" identifier parameter_list expression
|
||||||
| "assign" identifier expression
|
| "assign" identifier expression
|
||||||
@@ -206,7 +206,7 @@ type
|
|||||||
function VisitRecordField(const Node: IRecordFieldNode): TVoid; override;
|
function VisitRecordField(const Node: IRecordFieldNode): TVoid; override;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TVoid; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TVoid; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TVoid; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): TVoid; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TVoid; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TVoid; override;
|
||||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TVoid; override;
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TVoid; override;
|
||||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TVoid; override;
|
function VisitQuasiquote(const Node: IQuasiquoteNode): TVoid; override;
|
||||||
@@ -642,9 +642,19 @@ begin
|
|||||||
end
|
end
|
||||||
else if SameText(head.Token.Text, '?') then
|
else if SameText(head.Token.Text, '?') then
|
||||||
begin
|
begin
|
||||||
if Length(tailNodes) <> 3 then
|
// (? test1 branch1 test2 branch2 ... else)
|
||||||
Error('Syntax Error in ternary statement.');
|
// Requires odd number of tailNodes (pairs + 1 else)
|
||||||
Result := TAst.TernaryExpr(tailNodes[0], tailNodes[1], tailNodes[2], startLoc);
|
var count := Length(tailNodes);
|
||||||
|
if (count < 1) or ((count mod 2) = 0) then
|
||||||
|
Error('Syntax Error: ''?'' (cond) requires an odd number of arguments (pairs of condition/branch and one final else).');
|
||||||
|
|
||||||
|
var pairs: TArray<TCondPair>;
|
||||||
|
SetLength(pairs, count div 2);
|
||||||
|
for var i := 0 to High(pairs) do
|
||||||
|
pairs[i] := TCondPair.Create(tailNodes[i * 2], tailNodes[i * 2 + 1]);
|
||||||
|
|
||||||
|
var elseNode := tailNodes[High(tailNodes)];
|
||||||
|
Result := TAst.CondExpr(pairs, elseNode, startLoc);
|
||||||
end
|
end
|
||||||
else if SameText(head.Token.Text, 'def') then
|
else if SameText(head.Token.Text, 'def') then
|
||||||
begin
|
begin
|
||||||
@@ -946,13 +956,18 @@ begin
|
|||||||
Append(')');
|
Append(')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPrettyPrintVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TVoid;
|
function TPrettyPrintVisitor.VisitCondExpression(const Node: ICondExpressionNode): TVoid;
|
||||||
begin
|
begin
|
||||||
Append('(? ');
|
Append('(?');
|
||||||
Node.Condition.Accept(Self);
|
|
||||||
Indent;
|
Indent;
|
||||||
NewLine;
|
for var pair in Node.Pairs do
|
||||||
Node.ThenBranch.Accept(Self);
|
begin
|
||||||
|
NewLine;
|
||||||
|
pair.Condition.Accept(Self);
|
||||||
|
Append(' ');
|
||||||
|
pair.Branch.Accept(Self);
|
||||||
|
end;
|
||||||
|
// Else
|
||||||
NewLine;
|
NewLine;
|
||||||
Node.ElseBranch.Accept(Self);
|
Node.ElseBranch.Accept(Self);
|
||||||
Unindent;
|
Unindent;
|
||||||
|
|||||||
+38
-16
@@ -26,7 +26,7 @@ type
|
|||||||
function IAstVisitor.VisitRecordField = DoVisitRecordField;
|
function IAstVisitor.VisitRecordField = DoVisitRecordField;
|
||||||
|
|
||||||
function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
|
function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
|
||||||
function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
|
function IAstVisitor.VisitCondExpression = DoVisitCondExpression; // Updated
|
||||||
function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
|
function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
|
||||||
function IAstVisitor.VisitFunctionCall = DoVisitFunctionCall;
|
function IAstVisitor.VisitFunctionCall = DoVisitFunctionCall;
|
||||||
function IAstVisitor.VisitMacroExpansionNode = DoVisitMacroExpansionNode;
|
function IAstVisitor.VisitMacroExpansionNode = DoVisitMacroExpansionNode;
|
||||||
@@ -58,7 +58,7 @@ type
|
|||||||
function DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
function DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
|
||||||
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function DoVisitCondExpression(const Node: ICondExpressionNode): TDataValue; // Updated
|
||||||
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
function DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
function DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
function DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||||
@@ -94,7 +94,7 @@ type
|
|||||||
function VisitRecordField(const Node: IRecordFieldNode): T; virtual;
|
function VisitRecordField(const Node: IRecordFieldNode): T; virtual;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): T; virtual;
|
function VisitIfExpression(const Node: IIfExpressionNode): T; virtual;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): T; virtual;
|
function VisitCondExpression(const Node: ICondExpressionNode): T; virtual; // Updated
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): T; virtual;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): T; virtual;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): T; virtual;
|
function VisitFunctionCall(const Node: IFunctionCallNode): T; virtual;
|
||||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): T; virtual;
|
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): T; virtual;
|
||||||
@@ -128,7 +128,7 @@ type
|
|||||||
function VisitRecordField(const Node: IRecordFieldNode): IAstNode; override;
|
function VisitRecordField(const Node: IRecordFieldNode): IAstNode; override;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): IAstNode; override; // Updated
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
||||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
|
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
|
||||||
@@ -204,9 +204,9 @@ function TAstVisitor<T>.DoVisitIfExpression(const Node: IIfExpressionNode): TDat
|
|||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitIfExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitIfExpression(Node));
|
||||||
end;
|
end;
|
||||||
function TAstVisitor<T>.DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitCondExpression(const Node: ICondExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitTernaryExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitCondExpression(Node));
|
||||||
end;
|
end;
|
||||||
function TAstVisitor<T>.DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
@@ -341,11 +341,16 @@ begin
|
|||||||
Accept(Node.ElseBranch);
|
Accept(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitTernaryExpression(const Node: ITernaryExpressionNode): T;
|
function TAstVisitor<T>.VisitCondExpression(const Node: ICondExpressionNode): T;
|
||||||
|
var
|
||||||
|
pair: TCondPair;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Condition);
|
for pair in Node.Pairs do
|
||||||
Accept(Node.ThenBranch);
|
begin
|
||||||
|
Accept(pair.Condition);
|
||||||
|
Accept(pair.Branch);
|
||||||
|
end;
|
||||||
Accept(Node.ElseBranch);
|
Accept(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -621,18 +626,35 @@ begin
|
|||||||
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
function TAstTransformer.VisitCondExpression(const Node: ICondExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
newCond, newThen, newElse: IAstNode;
|
newPairs: TArray<TCondPair>;
|
||||||
|
newElse: IAstNode;
|
||||||
|
hasChanged: Boolean;
|
||||||
|
i: Integer;
|
||||||
|
newCond, newBranch: IAstNode;
|
||||||
begin
|
begin
|
||||||
newCond := Accept(Node.Condition);
|
hasChanged := False;
|
||||||
newThen := Accept(Node.ThenBranch);
|
SetLength(newPairs, Length(Node.Pairs));
|
||||||
newElse := Accept(Node.ElseBranch);
|
|
||||||
|
|
||||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
for i := 0 to High(Node.Pairs) do
|
||||||
|
begin
|
||||||
|
newCond := Accept(Node.Pairs[i].Condition);
|
||||||
|
newBranch := Accept(Node.Pairs[i].Branch);
|
||||||
|
newPairs[i] := TCondPair.Create(newCond, newBranch);
|
||||||
|
|
||||||
|
if (newCond <> Node.Pairs[i].Condition) or (newBranch <> Node.Pairs[i].Branch) then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
newElse := Accept(Node.ElseBranch); // Accept handles nil
|
||||||
|
if newElse <> Node.ElseBranch then
|
||||||
|
hasChanged := True;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
Result := TAst.TernaryExpr(Node.Identity, newCond, newThen, newElse, Node.StaticType);
|
Result := TAst.CondExpr(Node.Identity, newPairs, newElse, Node.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
function TAstTransformer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||||
|
|||||||
+32
-17
@@ -101,19 +101,26 @@ type
|
|||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): IIfExpressionNode; overload; static;
|
): IIfExpressionNode; overload; static;
|
||||||
|
|
||||||
// --- TERNARY ---
|
// --- COND (Previously Ternary) ---
|
||||||
|
class function CondExpr(
|
||||||
|
const APairs: TArray<TCondPair>;
|
||||||
|
const AElseBranch: IAstNode;
|
||||||
|
const Loc: ISourceLocation = nil
|
||||||
|
): ICondExpressionNode; overload; static;
|
||||||
|
|
||||||
|
class function CondExpr(
|
||||||
|
const Identity: IAstIdentity;
|
||||||
|
const APairs: TArray<TCondPair>;
|
||||||
|
const AElseBranch: IAstNode;
|
||||||
|
const AStaticType: IStaticType = nil
|
||||||
|
): ICondExpressionNode; overload; static;
|
||||||
|
|
||||||
|
// Convenience wrapper for Ternary operator behavior using CondExpr
|
||||||
class function TernaryExpr(
|
class function TernaryExpr(
|
||||||
const ACondition: IAstNode;
|
const ACondition: IAstNode;
|
||||||
const AThenBranch, AElseBranch: IAstNode;
|
const AThenBranch, AElseBranch: IAstNode;
|
||||||
const Loc: ISourceLocation = nil
|
const Loc: ISourceLocation = nil
|
||||||
): ITernaryExpressionNode; overload; static;
|
): ICondExpressionNode; overload; static;
|
||||||
|
|
||||||
class function TernaryExpr(
|
|
||||||
const Identity: IAstIdentity;
|
|
||||||
const ACondition: IAstNode;
|
|
||||||
const AThenBranch, AElseBranch: IAstNode;
|
|
||||||
const AStaticType: IStaticType = nil
|
|
||||||
): ITernaryExpressionNode; overload; static;
|
|
||||||
|
|
||||||
// --- LAMBDA ---
|
// --- LAMBDA ---
|
||||||
class function LambdaExpr(
|
class function LambdaExpr(
|
||||||
@@ -488,22 +495,22 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.TernaryExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): ITernaryExpressionNode;
|
class function TAst.CondExpr(const APairs: TArray<TCondPair>; const AElseBranch: IAstNode; const Loc: ISourceLocation): ICondExpressionNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch, TTypes.Unknown, id);
|
Result := TCondExpressionNode.Create(APairs, AElseBranch, TTypes.Unknown, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.TernaryExpr(
|
class function TAst.CondExpr(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const ACondition, AThenBranch, AElseBranch: IAstNode;
|
const APairs: TArray<TCondPair>;
|
||||||
|
const AElseBranch: IAstNode;
|
||||||
const AStaticType: IStaticType
|
const AStaticType: IStaticType
|
||||||
): ITernaryExpressionNode;
|
): ICondExpressionNode;
|
||||||
begin
|
begin
|
||||||
Result :=
|
Result :=
|
||||||
TTernaryExpressionNode.Create(
|
TCondExpressionNode.Create(
|
||||||
ACondition,
|
APairs,
|
||||||
AThenBranch,
|
|
||||||
AElseBranch,
|
AElseBranch,
|
||||||
if AStaticType <> nil then AStaticType
|
if AStaticType <> nil then AStaticType
|
||||||
else TTypes.Unknown,
|
else TTypes.Unknown,
|
||||||
@@ -511,6 +518,14 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TAst.TernaryExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): ICondExpressionNode;
|
||||||
|
var
|
||||||
|
pair: TCondPair;
|
||||||
|
begin
|
||||||
|
pair := TCondPair.Create(ACondition, AThenBranch);
|
||||||
|
Result := TAst.CondExpr([pair], AElseBranch, Loc);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TAst.LambdaExpr(
|
class function TAst.LambdaExpr(
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: TArray<IIdentifierNode>;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
|
|||||||
@@ -32,12 +32,20 @@ type
|
|||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TTernaryExpressionNodeHandler = class(TBaseNodeHandler<ITernaryExpressionNode>)
|
// Handles the 'cond' expression (multi-branch if/else)
|
||||||
|
TCondExpressionNodeHandler = class(TBaseNodeHandler<ICondExpressionNode>)
|
||||||
private
|
private
|
||||||
FConditionNode: TAstViewNode;
|
type
|
||||||
FThenNode: TAstViewNode;
|
TBranchView = record
|
||||||
|
Condition: TAstViewNode;
|
||||||
|
Branch: TAstViewNode;
|
||||||
|
end;
|
||||||
|
private
|
||||||
|
FBranchNodes: TList<TBranchView>;
|
||||||
FElseNode: TAstViewNode;
|
FElseNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
|
constructor Create(const ANode: ICondExpressionNode);
|
||||||
|
destructor Destroy; override;
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -152,26 +160,74 @@ begin
|
|||||||
Result := TAst.IfExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, elseAst, FNode.StaticType);
|
Result := TAst.IfExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, elseAst, FNode.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTernaryExpressionNodeHandler }
|
{ TCondExpressionNodeHandler }
|
||||||
|
|
||||||
procedure TTernaryExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
constructor TCondExpressionNodeHandler.Create(const ANode: ICondExpressionNode);
|
||||||
|
begin
|
||||||
|
inherited Create(ANode);
|
||||||
|
FBranchNodes := TList<TBranchView>.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TCondExpressionNodeHandler.Destroy;
|
||||||
|
begin
|
||||||
|
FBranchNodes.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCondExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
|
pair: TCondPair;
|
||||||
|
i: Integer;
|
||||||
|
row: TAutoFitLayout;
|
||||||
|
bv: TBranchView;
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loHorizontal;
|
OwnerNode.Orientation := loVertical;
|
||||||
FConditionNode := visu.CallAccept(FNode.Condition);
|
OwnerNode.Alignment := laFlush;
|
||||||
OwnerNode.AddLabel(OwnerNode, '?');
|
|
||||||
FThenNode := visu.CallAccept(FNode.ThenBranch);
|
var title := OwnerNode.AddLabel(OwnerNode, '?');
|
||||||
OwnerNode.AddLabel(OwnerNode, ':');
|
title.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
|
||||||
|
for i := 0 to High(FNode.Pairs) do
|
||||||
|
begin
|
||||||
|
pair := FNode.Pairs[i];
|
||||||
|
row := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
||||||
|
row.Margins := TMarginRect.Create(0, 2, 0, 2);
|
||||||
|
|
||||||
|
bv.Condition := visu.CallAccept(pair.Condition);
|
||||||
|
row.AddChild(bv.Condition);
|
||||||
|
|
||||||
|
OwnerNode.AddLabel(row, '->');
|
||||||
|
bv.Branch := visu.CallAccept(pair.Branch);
|
||||||
|
row.AddChild(bv.Branch);
|
||||||
|
|
||||||
|
FBranchNodes.Add(bv);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Else Branch
|
||||||
|
var elseRow := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
||||||
|
elseRow.Margins := TMarginRect.Create(0, 4, 0, 0); // Extra spacing
|
||||||
|
OwnerNode.AddLabel(elseRow, 'else ->');
|
||||||
FElseNode := visu.CallAccept(FNode.ElseBranch);
|
FElseNode := visu.CallAccept(FNode.ElseBranch);
|
||||||
|
// FIX: Use AddChild instead of assigning Parent directly
|
||||||
|
elseRow.AddChild(FElseNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTernaryExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TCondExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
var
|
||||||
|
newPairs: TArray<TCondPair>;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := TAst.TernaryExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst, FNode.StaticType);
|
SetLength(newPairs, FBranchNodes.Count);
|
||||||
|
for i := 0 to FBranchNodes.Count - 1 do
|
||||||
|
begin
|
||||||
|
newPairs[i] := TCondPair.Create(FBranchNodes[i].Condition.CreateAst, FBranchNodes[i].Branch.CreateAst);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := TAst.CondExpr(FNode.Identity, newPairs, FElseNode.CreateAst, FNode.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLambdaExpressionNodeHandler }
|
{ TLambdaExpressionNodeHandler }
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type
|
|||||||
|
|
||||||
// Control Flow
|
// Control Flow
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstViewNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TAstViewNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstViewNode; override;
|
function VisitCondExpression(const Node: ICondExpressionNode): TAstViewNode; override; // Replaces Ternary
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstViewNode; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstViewNode; override;
|
||||||
function VisitRecurNode(const Node: IRecurNode): TAstViewNode; override;
|
function VisitRecurNode(const Node: IRecurNode): TAstViewNode; override;
|
||||||
function VisitNop(const Node: INopNode): TAstViewNode; override;
|
function VisitNop(const Node: INopNode): TAstViewNode; override;
|
||||||
@@ -225,9 +225,9 @@ begin
|
|||||||
Result := TAstViewNode.Create(Self, TIfExpressionNodeHandler.Create(Node));
|
Result := TAstViewNode.Create(Self, TIfExpressionNodeHandler.Create(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisualizer.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstViewNode;
|
function TAstVisualizer.VisitCondExpression(const Node: ICondExpressionNode): TAstViewNode;
|
||||||
begin
|
begin
|
||||||
Result := TAstViewNode.Create(Self, TTernaryExpressionNodeHandler.Create(Node));
|
Result := TAstViewNode.Create(Self, TCondExpressionNodeHandler.Create(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TAstViewNode;
|
function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TAstViewNode;
|
||||||
|
|||||||
Reference in New Issue
Block a user