Skip to content

Commit c416b36

Browse files
committed
Added ForNode implementation
1 parent a7f4d31 commit c416b36

File tree

5 files changed

+61
-32
lines changed

5 files changed

+61
-32
lines changed

src/NodeDev.Blazor/Components/SourceViewer.razor

+4
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ else
9393

9494
Code += $"{System.Environment.NewLine}*/";
9595
}
96+
catch(Exception ex)
97+
{
98+
Code = $"/* Error during code generation: {System.Environment.NewLine}{ex}{System.Environment.NewLine}*/";
99+
}
96100
}
97101

98102
private void OnGraphChanged(Graph graph)

src/NodeDev.Core/Class/NodeClassTypeCreator.cs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using NodeDev.Core.Types;
44
using FastExpressionCompiler;
55
using NodeDev.Core.Nodes;
6+
using System.Linq.Expressions;
67

78
namespace NodeDev.Core.Class;
89

src/NodeDev.Core/Graph.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public LambdaExpression BuildExpression(BuildExpressionOptions options)
256256
info.MethodParametersExpression[parameter.Name] = variable;
257257
}
258258

259-
// Create a variable for each node input and output
259+
// Create a variable for each node's output
260260
foreach (var node in Nodes.Values)
261261
{
262262
if (node.CanBeInlined)
+50-30
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,68 @@
1-
using NodeDev.Core.Connections;
1+
using FastExpressionCompiler;
2+
using NodeDev.Core.Connections;
23
using NodeDev.Core.Types;
34
using System.Linq.Expressions;
45

56
namespace NodeDev.Core.Nodes.Flow;
67

78
public class ForNode : FlowNode
89
{
9-
public override bool IsFlowNode => true;
10+
public override bool IsFlowNode => true;
1011

11-
public override bool FetchState => true;
12+
public override bool FetchState => true;
1213

13-
public override bool ReOrderExecInputsAndOutputs => false;
14+
public override bool ReOrderExecInputsAndOutputs => false;
1415

15-
public override bool AllowRemergingExecConnections => false;
16+
public override bool AllowRemergingExecConnections => false;
1617

17-
public ForNode(Graph graph, string? id = null) : base(graph, id)
18-
{
19-
Name = "For";
18+
public ForNode(Graph graph, string? id = null) : base(graph, id)
19+
{
20+
Name = "For";
2021

21-
Inputs.Add(new("Exec", this, TypeFactory.ExecType));
22-
Inputs.Add(new("Start", this, TypeFactory.Get<int>()));
23-
Inputs.Add(new("End (Exclude)", this, TypeFactory.Get<int>()));
22+
Inputs.Add(new("Exec", this, TypeFactory.ExecType));
23+
Inputs.Add(new("Start", this, TypeFactory.Get<int>()));
24+
Inputs.Add(new("End (Exclude)", this, TypeFactory.Get<int>()));
2425

25-
Outputs.Add(new("ExecLoop", this, TypeFactory.ExecType));
26-
Outputs.Add(new("Index", this, TypeFactory.Get<int>(), linkedExec: Outputs[0]));
27-
Outputs.Add(new("ExecOut", this, TypeFactory.ExecType));
28-
}
26+
Outputs.Add(new("ExecLoop", this, TypeFactory.ExecType));
27+
Outputs.Add(new("Index", this, TypeFactory.Get<int>(), linkedExec: Outputs[0]));
28+
Outputs.Add(new("ExecOut", this, TypeFactory.ExecType));
29+
}
2930

30-
public override string GetExecOutputPathId(string pathId, Connection execOutput)
31-
{
32-
if (execOutput == Outputs[0])
33-
return pathId + "-" + execOutput.Id;
34-
else if (execOutput == Outputs[2])
35-
return pathId;
36-
else
37-
throw new Exception("Invalid exec output");
38-
}
31+
public override string GetExecOutputPathId(string pathId, Connection execOutput)
32+
{
33+
if (execOutput == Outputs[0])
34+
return pathId + "-" + execOutput.Id;
35+
else if (execOutput == Outputs[2])
36+
return pathId;
37+
else
38+
throw new Exception("Invalid exec output");
39+
}
3940

40-
public override bool DoesOutputPathAllowDeadEnd(Connection execOutput) => execOutput == Outputs[0]; // The loop exec path must be a dead end (or a breaking node, such as return, continue, break)
41+
public override bool DoesOutputPathAllowDeadEnd(Connection execOutput) => execOutput == Outputs[0]; // The loop exec path must be a dead end (or a breaking node, such as return, continue, break)
4142

42-
public override bool DoesOutputPathAllowMerge(Connection execOutput) => execOutput == Outputs[2]; // the ExecOut path allows merging, but not the loop. The loop is always a dead end.
43+
public override bool DoesOutputPathAllowMerge(Connection execOutput) => execOutput == Outputs[2]; // the ExecOut path allows merging, but not the loop. The loop is always a dead end.
4344

44-
internal override Expression BuildExpression(Dictionary<Connection, Graph.NodePathChunks>? subChunks, BuildExpressionInfo info)
45-
{
46-
throw new NotImplementedException();
47-
}
45+
internal override Expression BuildExpression(Dictionary<Connection, Graph.NodePathChunks>? subChunks, BuildExpressionInfo info)
46+
{
47+
ArgumentNullException.ThrowIfNull(subChunks);
48+
49+
var count = info.LocalVariables[Outputs[1]];
50+
var assignCount = Expression.Assign(count, info.LocalVariables[Inputs[1]]); // assign the start value to the count variable
51+
var incrementCount = Expression.PreIncrementAssign(count); // increment the count variable
52+
53+
var loopBody = Expression.Block(Graph.BuildExpression(subChunks[Outputs[0]], info).Append(incrementCount)); // Build the loop body and the counter increment
54+
var afterLoop = Expression.Block(Graph.BuildExpression(subChunks[Outputs[2]], info)); // Build the after loop body
55+
56+
var breakLabel = Expression.Label();
57+
var loop = Expression.Loop(
58+
Expression.IfThenElse(
59+
Expression.LessThan(count, info.LocalVariables[Inputs[2]]), // i < end
60+
loopBody, // does the assign for enumerator.Current, as well as the loop body
61+
Expression.Break(breakLabel) // break the loop
62+
),
63+
breakLabel
64+
);
65+
66+
return Expression.Block(assignCount, loop, afterLoop);
67+
}
4868
}

src/NodeDev.Core/Nodes/Node.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ public virtual void SelectOverload(AlternateOverload overload, out List<Connecti
100100
if (output.Type.IsExec)
101101
continue;
102102

103-
var variable = Expression.Variable(output.Type.MakeRealType(), $"{Name}_{output.Name}".Replace(" ", string.Empty).Replace(".", string.Empty));
103+
var variable = Expression.Variable(output.Type.MakeRealType(), $"{Name}_{output.Name}"
104+
.Replace(" ", string.Empty)
105+
.Replace(".", string.Empty)
106+
.Replace("<", string.Empty)
107+
.Replace(">", string.Empty));
104108
yield return (output, variable);
105109
}
106110
}

0 commit comments

Comments
 (0)