Files
IPyConsole/Model/TempTest.cs

184 lines
6.8 KiB
C#
Raw Permalink Normal View History

2024-11-29 17:53:12 +08:00
using System.Linq.Expressions;
namespace Model
{
public class TempTest
{
public void Run()
{
var nArgument = Expression.Parameter(typeof(int), "n");
var result = Expression.Variable(typeof(int), "result");
LabelTarget label = Expression.Label(typeof(int));
var initializeResult = Expression.Assign(result, Expression.Constant(1));
var block = Expression.Block(
Expression.Assign(result, Expression.Multiply(result, nArgument)),
Expression.PostDecrementAssign(nArgument)
);
//int[] array = new Array();
}
}
public abstract class Visitor
{
private readonly Expression node;
protected Visitor(Expression node) => this.node = node;
public abstract void Visit(string prefix);
public ExpressionType NodeType => node.NodeType;
public static Visitor CreateFromExpression(Expression node) => node.NodeType switch
{
ExpressionType.Constant => new ConstantVisitor((ConstantExpression)node),
ExpressionType.Lambda => new LambdaVisitor((LambdaExpression)node),
ExpressionType.Parameter => new ParameterVisitor((ParameterExpression)node),
ExpressionType.Add => new BinaryVisitor((BinaryExpression)node),
ExpressionType.Equal => new BinaryVisitor((BinaryExpression)node),
ExpressionType.Multiply => new BinaryVisitor((BinaryExpression)node),
ExpressionType.Conditional => new ConditionalVisitor((ConditionalExpression)node),
ExpressionType.Call => new MethodCallVisitor((MethodCallExpression)node),
_ => throw new NotImplementedException($"Node not processed yet: {node.NodeType}"),
};
}
// Lambda Visitor
public class LambdaVisitor : Visitor
{
private readonly LambdaExpression node;
public LambdaVisitor(LambdaExpression node) : base(node) => this.node = node;
public override void Visit(string prefix)
{
Console.WriteLine($"{prefix}This expression is a {NodeType} expression type");
Console.WriteLine($"{prefix}The name of the lambda is {((node.Name == null) ? "<null>" : node.Name)}");
Console.WriteLine($"{prefix}The return type is {node.ReturnType}");
Console.WriteLine($"{prefix}The expression has {node.Parameters.Count} argument(s). They are:");
// Visit each parameter:
foreach (var argumentExpression in node.Parameters)
{
var argumentVisitor = CreateFromExpression(argumentExpression);
argumentVisitor.Visit(prefix + "\t");
}
Console.WriteLine($"{prefix}The expression body is:");
// Visit the body:
var bodyVisitor = CreateFromExpression(node.Body);
bodyVisitor.Visit(prefix + "\t");
}
}
// Binary Expression Visitor:
public class BinaryVisitor : Visitor
{
private readonly BinaryExpression node;
public BinaryVisitor(BinaryExpression node) : base(node) => this.node = node;
public override void Visit(string prefix)
{
Console.WriteLine($"{prefix}This binary expression is a {NodeType} expression");
var left = CreateFromExpression(node.Left);
Console.WriteLine($"{prefix}The Left argument is:");
left.Visit(prefix + "\t");
var right = CreateFromExpression(node.Right);
Console.WriteLine($"{prefix}The Right argument is:");
right.Visit(prefix + "\t");
}
}
// Parameter visitor:
public class ParameterVisitor : Visitor
{
private readonly ParameterExpression node;
public ParameterVisitor(ParameterExpression node) : base(node)
{
this.node = node;
}
public override void Visit(string prefix)
{
Console.WriteLine($"{prefix}This is an {NodeType} expression type");
Console.WriteLine($"{prefix}Type: {node.Type}, Name: {node.Name}, ByRef: {node.IsByRef}");
}
}
internal class ConstantVisitor : Visitor
{
private readonly ConstantExpression node;
public ConstantVisitor(ConstantExpression node) : base(node) => this.node = node;
public override void Visit(string prefix)
{
Console.WriteLine($"{prefix}This is an {NodeType} expression type");
Console.WriteLine($"{prefix}The type of the constant value is {node.Type}");
Console.WriteLine($"{prefix}The value of the constant value is {node.Value}");
}
}
public class ConditionalVisitor : Visitor
{
private readonly ConditionalExpression node;
public ConditionalVisitor(ConditionalExpression node) : base(node)
{
this.node = node;
}
public override void Visit(string prefix)
{
Console.WriteLine($"{prefix}This expression is a {NodeType} expression");
var testVisitor = Visitor.CreateFromExpression(node.Test);
Console.WriteLine($"{prefix}The Test for this expression is:");
testVisitor.Visit(prefix + "\t");
var trueVisitor = Visitor.CreateFromExpression(node.IfTrue);
Console.WriteLine($"{prefix}The True clause for this expression is:");
trueVisitor.Visit(prefix + "\t");
var falseVisitor = Visitor.CreateFromExpression(node.IfFalse);
Console.WriteLine($"{prefix}The False clause for this expression is:");
falseVisitor.Visit(prefix + "\t");
}
}
public class MethodCallVisitor : Visitor
{
private readonly MethodCallExpression node;
public MethodCallVisitor(MethodCallExpression node) : base(node)
{
this.node = node;
}
public override void Visit(string prefix)
{
Console.WriteLine($"{prefix}This expression is a {NodeType} expression");
if (node.Object == null)
Console.WriteLine($"{prefix}This is a static method call");
else
{
Console.WriteLine($"{prefix}The receiver (this) is:");
var receiverVisitor = Visitor.CreateFromExpression(node.Object);
receiverVisitor.Visit(prefix + "\t");
}
var methodInfo = node.Method;
Console.WriteLine($"{prefix}The method name is {methodInfo.DeclaringType}.{methodInfo.Name}");
// There is more here, like generic arguments, and so on.
Console.WriteLine($"{prefix}The Arguments are:");
foreach (var arg in node.Arguments)
{
var argVisitor = Visitor.CreateFromExpression(arg);
argVisitor.Visit(prefix + "\t");
}
}
}
}