-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTransition.cs
More file actions
77 lines (58 loc) · 2.15 KB
/
Transition.cs
File metadata and controls
77 lines (58 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System.Diagnostics;
using System.Linq.Expressions;
using static System.Linq.Expressions.Expression;
namespace Hyperbee.Expressions.CompilerServices.Transitions;
[DebuggerDisplay( "Transition = {GetType().Name,nq}" )]
internal abstract class Transition
{
internal abstract StateNode FallThroughNode { get; }
public virtual void AddExpressions( List<Expression> expressions, StateMachineContext context )
{
SetResult( expressions, context );
}
private static void SetResult( List<Expression> expressions, StateMachineContext context )
{
var (variable, value) = context.StateNode.Result;
if ( variable == null )
{
return;
}
if ( expressions.Count > 1 )
{
var lastExpression = expressions[^1];
if ( variable.Type.IsAssignableFrom( lastExpression.Type ) )
{
expressions[^1] = Assign( variable, EnsureConvert( lastExpression, variable.Type ) );
}
return;
}
if ( value != null && variable.Type.IsAssignableFrom( value.Type ) )
{
expressions.Add( Assign( variable, EnsureConvert( value, variable.Type ) ) );
}
}
protected static Expression EnsureConvert( Expression expression, Type targetType )
{
if ( expression.Type != targetType && expression.Type.IsValueType )
return Convert( expression, targetType );
return expression;
}
internal abstract void Optimize( HashSet<LabelTarget> references );
protected static StateNode OptimizeGotos( StateNode node )
{
while ( IsNoOp( node ) && node.Transition is GotoTransition gotoTransition )
{
node = gotoTransition.TargetNode;
}
return node;
static bool IsNoOp( StateNode node ) => node.Expressions.Count == 0 && node.Result.Variable == null;
}
protected static Expression GotoOrFallThrough( int order, StateNode node, bool allowNull = false )
{
if ( order + 1 == node.StateOrder )
{
return allowNull ? null : Empty();
}
return Goto( node.NodeLabel );
}
}