Skip to content

Commit

Permalink
New AST builder.
Browse files Browse the repository at this point in the history
  • Loading branch information
Washi1337 committed Nov 5, 2023
1 parent ac3fb60 commit 0b3df04
Show file tree
Hide file tree
Showing 60 changed files with 1,789 additions and 1,550 deletions.
34 changes: 34 additions & 0 deletions src/Core/Echo.Ast/Analysis/AstPurityClassifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Echo.Code;

namespace Echo.Ast.Analysis;

/// <summary>
/// Provides a wrapper around a <see cref="IPurityClassifier{TInstruction}"/> that is able to classify statements
/// and expressions with <typeparamref name="TInstruction"/> instructions by purity.
/// </summary>
/// <typeparam name="TInstruction">The type of instructions the statements store.</typeparam>
public class AstPurityClassifier<TInstruction> : IPurityClassifier<Statement<TInstruction>>
{
/// <summary>
/// Creates a new instance of the <see cref="AstPurityClassifier{TInstruction}"/> class.
/// </summary>
/// <param name="baseClassifier">The base classifier to use for classifying individual instructions in the AST.</param>
public AstPurityClassifier(IPurityClassifier<TInstruction> baseClassifier)
{
BaseClassifier = baseClassifier;
}

/// <summary>
/// Gets the base classifier to use for classifying individual instructions in the AST.
/// </summary>
public IPurityClassifier<TInstruction> BaseClassifier
{
get;
}

/// <inheritdoc />
public Trilean IsPure(in Statement<TInstruction> instruction)
{
return instruction.Accept(AstPurityVisitor<TInstruction>.Instance, BaseClassifier);
}
}
44 changes: 44 additions & 0 deletions src/Core/Echo.Ast/Analysis/AstPurityVisitor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Echo.Code;

namespace Echo.Ast.Analysis;

/// <summary>
/// Provides a mechanism for traversing an AST and determining its purity.
/// </summary>
/// <typeparam name="TInstruction">The type of instructions to store in each expression.</typeparam>
public class AstPurityVisitor<TInstruction> : IAstNodeVisitor<TInstruction, IPurityClassifier<TInstruction>, Trilean>
{
/// <summary>
/// Gets the singleton instance of the <see cref="AstPurityVisitor{TInstruction}"/> class.
/// </summary>
public static AstPurityVisitor<TInstruction> Instance
{
get;
} = new();

/// <inheritdoc />
public Trilean Visit(AssignmentStatement<TInstruction> statement, IPurityClassifier<TInstruction> state) => false;

/// <inheritdoc />
public Trilean Visit(ExpressionStatement<TInstruction> statement, IPurityClassifier<TInstruction> state)
{
return statement.Expression.Accept(this, state);
}

/// <inheritdoc />
public Trilean Visit(PhiStatement<TInstruction> statement, IPurityClassifier<TInstruction> state) => false;

/// <inheritdoc />
public Trilean Visit(InstructionExpression<TInstruction> expression, IPurityClassifier<TInstruction> state)
{
var result = state.IsPure(expression.Instruction);

for (int i = 0; i < expression.Arguments.Count && result != Trilean.False; i++)
result &= expression.Arguments[i].Accept(this, state);

return result;
}

/// <inheritdoc />
public Trilean Visit(VariableExpression<TInstruction> expression, IPurityClassifier<TInstruction> state) => true;
}
16 changes: 8 additions & 8 deletions src/Core/Echo.Ast/Analysis/FlowControlDeterminer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ internal sealed class FlowControlDeterminer<TInstruction>
internal FlowControlDeterminer(IArchitecture<TInstruction> isa) =>
_isa = isa;

public InstructionFlowControl Visit(AssignmentStatement<TInstruction> assignmentStatement, object state) =>
assignmentStatement.Expression.Accept(this, state);
public InstructionFlowControl Visit(AssignmentStatement<TInstruction> statement, object state) =>
statement.Expression.Accept(this, state);

public InstructionFlowControl Visit(ExpressionStatement<TInstruction> expressionStatement, object state) =>
expressionStatement.Expression.Accept(this, state);
public InstructionFlowControl Visit(ExpressionStatement<TInstruction> statement, object state) =>
statement.Expression.Accept(this, state);

public InstructionFlowControl Visit(PhiStatement<TInstruction> phiStatement, object state) =>
public InstructionFlowControl Visit(PhiStatement<TInstruction> statement, object state) =>
InstructionFlowControl.Fallthrough;

public InstructionFlowControl Visit(InstructionExpression<TInstruction> instructionExpression, object state) =>
_isa.GetFlowControl(instructionExpression.Instruction);
public InstructionFlowControl Visit(InstructionExpression<TInstruction> expression, object state) =>
_isa.GetFlowControl(expression.Instruction);

public InstructionFlowControl Visit(VariableExpression<TInstruction> variableExpression, object state) =>
public InstructionFlowControl Visit(VariableExpression<TInstruction> expression, object state) =>
InstructionFlowControl.Fallthrough;
}
}
2 changes: 1 addition & 1 deletion src/Core/Echo.Ast/Analysis/ReadVariableFinderWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Echo.Ast.Analysis
{
internal sealed class ReadVariableFinderWalker<TInstruction> : AstNodeWalkerBase<TInstruction>
internal sealed class ReadVariableFinderWalker<TInstruction> : AstNodeWalker<TInstruction>
{
internal int Count => Variables.Count;

Expand Down
4 changes: 2 additions & 2 deletions src/Core/Echo.Ast/Analysis/WrittenVariableFinderWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Echo.Ast.Analysis
{
internal sealed class WrittenVariableFinderWalker<TInstruction> : AstNodeWalkerBase<TInstruction>
internal sealed class WrittenVariableFinderWalker<TInstruction> : AstNodeWalker<TInstruction>
{
internal int Count => Variables.Count;

Expand All @@ -19,6 +19,6 @@ protected override void ExitAssignmentStatement(AssignmentStatement<TInstruction
}

protected override void ExitPhiStatement(PhiStatement<TInstruction> phiStatement) =>
Variables.Add(phiStatement.Target);
Variables.Add(phiStatement.Representative);
}
}
18 changes: 11 additions & 7 deletions src/Core/Echo.Ast/AstArchitecture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ public class AstArchitecture<TInstruction>
private readonly FlowControlDeterminer<TInstruction> _flowControlDeterminer;

/// <summary>
/// Create a new decorator around the <paramref name="isa"/>
/// Create a new decorator around the <paramref name="baseArchitecture"/>
/// </summary>
/// <param name="isa">The <see cref="IArchitecture{TInstruction}"/> to decorate</param>
public AstArchitecture(IArchitecture<TInstruction> isa) =>
_flowControlDeterminer = new FlowControlDeterminer<TInstruction>(isa);
/// <param name="baseArchitecture">The <see cref="IArchitecture{TInstruction}"/> to decorate</param>
public AstArchitecture(IArchitecture<TInstruction> baseArchitecture)
{
_flowControlDeterminer = new FlowControlDeterminer<TInstruction>(baseArchitecture);
}

/// <inheritdoc />
public long GetOffset(in Statement<TInstruction> instruction) => throw new NotSupportedException();
Expand All @@ -27,9 +29,11 @@ public AstArchitecture(IArchitecture<TInstruction> isa) =>
public int GetSize(in Statement<TInstruction> instruction) => 1;

/// <inheritdoc />
public InstructionFlowControl GetFlowControl(in Statement<TInstruction> instruction) =>
instruction.Accept(_flowControlDeterminer, null);

public InstructionFlowControl GetFlowControl(in Statement<TInstruction> instruction)
{
return instruction.Accept(_flowControlDeterminer, null);
}

/// <inheritdoc />
public int GetStackPushCount(in Statement<TInstruction> instruction) => 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Echo.Ast
/// <summary>
/// Provides a base contract for all Ast nodes
/// </summary>
public abstract class AstNodeBase<TInstruction> : TreeNodeBase
public abstract class AstNode<TInstruction> : TreeNodeBase
{
/// <summary>
/// Implements the visitor pattern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Echo.Ast
/// Provides a base contract for Ast walkers
/// </summary>
/// <typeparam name="TInstruction">The type of the instruction</typeparam>
public abstract class AstNodeWalkerBase<TInstruction> : IAstNodeVisitor<TInstruction, object>
public abstract class AstNodeWalker<TInstruction> : IAstNodeVisitor<TInstruction, object>
{
/// <summary>
/// Begin visiting a given <see cref="AssignmentStatement{TInstruction}"/>
Expand Down Expand Up @@ -64,60 +64,60 @@ protected virtual void ExitInstructionExpression(InstructionExpression<TInstruct
/// <param name="variableExpression">The <see cref="VariableExpression{TInstruction}"/> that is will be visited</param>
protected virtual void VisitVariableExpression(VariableExpression<TInstruction> variableExpression) { }

private void VisitChildren(AstNodeBase<TInstruction> node)
private void VisitChildren(AstNode<TInstruction> node)
{
foreach (var child in node.GetChildren())
((AstNodeBase<TInstruction>) child).Accept(this, null);
((AstNode<TInstruction>) child).Accept(this, null);
}

/// <inheritdoc />
void IAstNodeVisitor<TInstruction, object>.Visit(AssignmentStatement<TInstruction> assignmentStatement,
void IAstNodeVisitor<TInstruction, object>.Visit(AssignmentStatement<TInstruction> statement,
object state)
{
EnterAssignmentStatement(assignmentStatement);
EnterAssignmentStatement(statement);

assignmentStatement.Expression.Accept(this, state);
statement.Expression.Accept(this, state);

ExitAssignmentStatement(assignmentStatement);
ExitAssignmentStatement(statement);
}

/// <inheritdoc />
void IAstNodeVisitor<TInstruction, object>.Visit(ExpressionStatement<TInstruction> expressionStatement,
void IAstNodeVisitor<TInstruction, object>.Visit(ExpressionStatement<TInstruction> expression,
object state)
{
EnterExpressionStatement(expressionStatement);
EnterExpressionStatement(expression);

expressionStatement.Expression.Accept(this, state);
expression.Expression.Accept(this, state);

ExitExpressionStatement(expressionStatement);
ExitExpressionStatement(expression);
}

/// <inheritdoc />
void IAstNodeVisitor<TInstruction, object>.Visit(PhiStatement<TInstruction> phiStatement, object state)
void IAstNodeVisitor<TInstruction, object>.Visit(PhiStatement<TInstruction> statement, object state)
{
EnterPhiStatement(phiStatement);
EnterPhiStatement(statement);

foreach (var source in phiStatement.Sources)
foreach (var source in statement.Sources)
source.Accept(this, state);

ExitPhiStatement(phiStatement);
ExitPhiStatement(statement);
}

/// <inheritdoc />
void IAstNodeVisitor<TInstruction, object>.Visit(InstructionExpression<TInstruction> instructionExpression, object state)
void IAstNodeVisitor<TInstruction, object>.Visit(InstructionExpression<TInstruction> expression, object state)
{
EnterInstructionExpression(instructionExpression);
EnterInstructionExpression(expression);

foreach (var parameter in instructionExpression.Arguments)
foreach (var parameter in expression.Arguments)
parameter.Accept(this, state);

ExitInstructionExpression(instructionExpression);
ExitInstructionExpression(expression);
}

/// <inheritdoc />
void IAstNodeVisitor<TInstruction, object>.Visit(VariableExpression<TInstruction> variableExpression, object state)
void IAstNodeVisitor<TInstruction, object>.Visit(VariableExpression<TInstruction> expression, object state)
{
VisitVariableExpression(variableExpression);
VisitVariableExpression(expression);
}
}
}
42 changes: 0 additions & 42 deletions src/Core/Echo.Ast/AstVariable.cs

This file was deleted.

Loading

0 comments on commit 0b3df04

Please sign in to comment.