Skip to content

Commit c4b5be5

Browse files
committed
Implement selection action interface for for/each/while
1 parent 3e6fc46 commit c4b5be5

4 files changed

Lines changed: 217 additions & 5 deletions

File tree

src/PatchManager.SassyPatching/Nodes/Statements/Each.cs

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
using JetBrains.Annotations;
22
using PatchManager.SassyPatching.Exceptions;
3+
using PatchManager.SassyPatching.Interfaces;
34
using PatchManager.SassyPatching.Nodes.Expressions;
5+
using PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;
46
using Environment = PatchManager.SassyPatching.Execution.Environment;
57

68
namespace PatchManager.SassyPatching.Nodes.Statements;
79

810
/// <summary>
911
/// Represents a loop that iterates over a list/dictionary/string
1012
/// </summary>
11-
public class Each : Node
13+
public class Each : Node, ISelectionAction
1214
{
1315
/// <summary>
1416
/// The variable to store the keys of iterations of this list node (optional)
@@ -121,4 +123,100 @@ private void ExecuteChildren(Environment environment)
121123
child.ExecuteIn(environment);
122124
}
123125
}
126+
127+
public void ExecuteOn(Environment environment, ISelectable selectable, IModifiable modifiable)
128+
{
129+
var value = Iterator.Compute(environment);
130+
if (value.IsList)
131+
{
132+
EachList(environment, selectable, modifiable, value);
133+
return;
134+
}
135+
136+
if (value.IsString)
137+
{
138+
EachString(environment, selectable, modifiable, value);
139+
return;
140+
}
141+
142+
if (value.IsDictionary)
143+
{
144+
EachDictionary(environment, selectable, modifiable, value);
145+
return;
146+
}
147+
148+
throw new InterpreterException(Coordinate,
149+
$"cannot iterate over a value of type {value.Type.ToString().ToLowerInvariant()}");
150+
}
151+
152+
private void EachDictionary(Environment environment, ISelectable selectable, IModifiable modifiable, DataValue value)
153+
{
154+
foreach (var (k, v) in value.Dictionary)
155+
{
156+
if (KeyName != null)
157+
{
158+
environment[KeyName] = k;
159+
}
160+
161+
environment[ValueName] = v;
162+
ExecuteChildren(environment,selectable,modifiable);
163+
}
164+
}
165+
166+
private void EachString(Environment environment, ISelectable selectable, IModifiable modifiable, DataValue value)
167+
{
168+
if (KeyName != null)
169+
{
170+
for (var i = 0; i < value.String.Length; i++)
171+
{
172+
environment[KeyName] = i;
173+
environment[ValueName] = value.String[i];
174+
ExecuteChildren(environment,selectable,modifiable);
175+
}
176+
}
177+
else
178+
{
179+
foreach (var v in value.String)
180+
{
181+
environment[ValueName] = v;
182+
ExecuteChildren(environment,selectable,modifiable);
183+
}
184+
}
185+
}
186+
187+
private void EachList(Environment environment, ISelectable selectable, IModifiable modifiable, DataValue value)
188+
{
189+
if (KeyName != null)
190+
{
191+
for (var i = 0; i < value.List.Count; i++)
192+
{
193+
environment[KeyName] = i;
194+
environment[ValueName] = value.List[i];
195+
ExecuteChildren(environment,selectable,modifiable);
196+
}
197+
}
198+
else
199+
{
200+
foreach (var v in value.List)
201+
{
202+
environment[ValueName] = v;
203+
ExecuteChildren(environment,selectable,modifiable);
204+
}
205+
}
206+
}
207+
208+
private void ExecuteChildren(Environment environment, ISelectable selectable, IModifiable modifiable)
209+
{
210+
foreach (var child in Children)
211+
{
212+
if (child is ISelectionAction selectionAction)
213+
{
214+
selectionAction.ExecuteOn(environment,selectable,modifiable);
215+
}
216+
else
217+
{
218+
child.ExecuteIn(environment);
219+
}
220+
}
221+
}
124222
}

src/PatchManager.SassyPatching/Nodes/Statements/For.cs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
using PatchManager.SassyPatching.Exceptions;
2+
using PatchManager.SassyPatching.Interfaces;
23
using PatchManager.SassyPatching.Nodes.Expressions;
4+
using PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;
35
using Environment = PatchManager.SassyPatching.Execution.Environment;
46

57
namespace PatchManager.SassyPatching.Nodes.Statements;
68

79
/// <summary>
810
/// Represents a loop that iterates over a range of numbers
911
/// </summary>
10-
public class For : Node
12+
public class For : Node, ISelectionAction
1113
{
1214
/// <summary>
1315
/// The variable that is set to the current iteration value
@@ -248,4 +250,97 @@ private void ExecuteChildren(Environment environment)
248250
child.ExecuteIn(environment);
249251
}
250252
}
253+
254+
public void ExecuteOn(Environment environment, ISelectable selectable, IModifiable modifiable)
255+
{
256+
var start = InitialValue.Compute(environment);
257+
var end = EndingValue.Compute(environment);
258+
if (start.IsInteger)
259+
{
260+
SetupIntegerIteration(environment, selectable, modifiable, end, start);
261+
return;
262+
}
263+
264+
if (start.IsReal)
265+
{
266+
SetupRealIteration(environment, selectable, modifiable, end, start);
267+
return;
268+
}
269+
270+
throw new InterpreterException(Coordinate, $"cannot do a for loop w/ a value that is of type {start.Type.ToString().ToLowerInvariant()}");
271+
}
272+
private void SetupRealIteration(Environment environment, ISelectable selectable, IModifiable modifiable, DataValue end, DataValue start)
273+
{
274+
Func<double, bool> endCheck;
275+
bool inverted;
276+
if (end.IsReal)
277+
{
278+
inverted = SetupRealRealIteration(end, start, out endCheck);
279+
}
280+
else if (end.IsInteger)
281+
{
282+
inverted = SetupRealIntegerIteration(end, start, out endCheck);
283+
}
284+
else
285+
{
286+
throw new InterpreterException(Coordinate, $"cannot do a for loop through/to a value of type {end.Type.ToString().ToLowerInvariant()}");
287+
}
288+
289+
IterateReal(environment, selectable, modifiable, start.Real, inverted, endCheck);
290+
}
291+
292+
private void SetupIntegerIteration(Environment environment, ISelectable selectable, IModifiable modifiable, DataValue end, DataValue start)
293+
{
294+
Func<long, bool> endCheck;
295+
bool inverted;
296+
if (end.IsReal)
297+
{
298+
inverted = SetupIntegerRealIteration(end, start, out endCheck);
299+
}
300+
else if (end.IsInteger)
301+
{
302+
inverted = SetupIntegerIntegerIteration(end, start, out endCheck);
303+
}
304+
else
305+
{
306+
throw new InterpreterException(Coordinate, $"cannot do a for loop through/to a value of type {end.Type.ToString().ToLowerInvariant()}");
307+
}
308+
309+
IterateInteger(environment, selectable, modifiable, start.Integer, inverted, endCheck);
310+
}
311+
312+
313+
private void IterateInteger(Environment environment, ISelectable selectable, IModifiable modifiable, long start, bool inverted, Func<long, bool> end)
314+
{
315+
while (!end(start))
316+
{
317+
environment[VariableName] = start;
318+
ExecuteChildren(environment, selectable, modifiable);
319+
start += inverted ? -1 : 1;
320+
}
321+
}
322+
323+
private void IterateReal(Environment environment, ISelectable selectable, IModifiable modifiable, double start, bool inverted, Func<double, bool> end)
324+
{
325+
while (!end(start))
326+
{
327+
environment[VariableName] = start;
328+
ExecuteChildren(environment, selectable, modifiable);
329+
start += inverted ? -1 : 1;
330+
}
331+
}
332+
private void ExecuteChildren(Environment environment, ISelectable selectable, IModifiable modifiable)
333+
{
334+
foreach (var child in Children)
335+
{
336+
if (child is ISelectionAction selectionAction)
337+
{
338+
selectionAction.ExecuteOn(environment,selectable,modifiable);
339+
}
340+
else
341+
{
342+
child.ExecuteIn(environment);
343+
}
344+
}
345+
}
251346
}

src/PatchManager.SassyPatching/Nodes/Statements/SelectionBlock.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ public override void ExecuteIn(Environment environment)
144144

145145
var patcher = new SassyTextPatcher(snapshot, this);
146146
environment.GlobalEnvironment.Universe.RegisterPatcherToUniverse(patcher);
147-
148147
}
149148

150149
/// <inheritdoc />

src/PatchManager.SassyPatching/Nodes/Statements/While.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
using PatchManager.SassyPatching.Nodes.Expressions;
1+
using PatchManager.SassyPatching.Interfaces;
2+
using PatchManager.SassyPatching.Nodes.Expressions;
3+
using PatchManager.SassyPatching.Nodes.Statements.SelectionLevel;
24
using Environment = PatchManager.SassyPatching.Execution.Environment;
35

46
namespace PatchManager.SassyPatching.Nodes.Statements;
57

68
/// <summary>
79
/// Represents a loop that iterates while a condition remains true
810
/// </summary>
9-
public class While : Node
11+
public class While : Node, ISelectionAction
1012
{
1113
/// <summary>
1214
/// The condition to test
@@ -33,4 +35,22 @@ public override void ExecuteIn(Environment environment)
3335
}
3436
}
3537
}
38+
39+
public void ExecuteOn(Environment environment, ISelectable selectable, IModifiable modifiable)
40+
{
41+
while (Condition.Compute(environment).Truthy)
42+
{
43+
foreach (var child in Children)
44+
{
45+
if (child is ISelectionAction selectionAction)
46+
{
47+
selectionAction.ExecuteOn(environment,selectable,modifiable);
48+
}
49+
else
50+
{
51+
child.ExecuteIn(environment);
52+
}
53+
}
54+
}
55+
}
3656
}

0 commit comments

Comments
 (0)