BadScript 2
Loading...
Searching...
No Matches
BadForEachExpression.cs
Go to the documentation of this file.
9
14
19{
23 public readonly BadWordToken LoopVariable;
24
28 private readonly List<BadExpression> m_Body;
29
34
43 BadExpression target,
44 BadWordToken loopVariable,
45 IEnumerable<BadExpression> body,
46 BadSourcePosition position) : base(
47 false,
48 position
49 )
50 {
51 Target = target;
52 LoopVariable = loopVariable;
53 m_Body = body.ToList();
54 }
55
59 public IEnumerable<BadExpression> Body => m_Body;
60
65 public void SetBody(IEnumerable<BadExpression> body)
66 {
67 m_Body.Clear();
68 m_Body.AddRange(body);
69 }
70
71
73 public override void Optimize()
74 {
76
77 for (int i = 0; i < m_Body.Count; i++)
78 {
80 }
81 }
82
84 public override IEnumerable<BadExpression> GetDescendants()
85 {
86 foreach (BadExpression expression in Target.GetDescendantsAndSelf())
87 {
88 yield return expression;
89 }
90
91 foreach (BadExpression descendant in m_Body.SelectMany(expression => expression.GetDescendantsAndSelf()))
92 {
93 yield return descendant;
94 }
95 }
96
104 public static (BadFunction moveNext, BadFunction getCurrent) FindEnumerator(BadObject target, BadExecutionContext context, BadSourcePosition position)
105 {
106 if (!target.HasProperty("MoveNext", context.Scope))
107 {
108 throw new BadRuntimeException("Invalid enumerator", position);
109 }
110
111 if (target.GetProperty("MoveNext", context.Scope).Dereference() is not BadFunction moveNext)
112 {
113 throw new BadRuntimeException("Invalid enumerator", position);
114 }
115
116 if (!target.HasProperty("GetCurrent", context.Scope))
117 {
118 throw new BadRuntimeException("Invalid enumerator", position);
119 }
120
121 if (target.GetProperty("GetCurrent", context.Scope).Dereference() is BadFunction getCurrent)
122 {
123 return (moveNext, getCurrent);
124 }
125
126 throw new BadRuntimeException("Invalid enumerator", position);
127 }
128public static IEnumerable<BadObject> Enumerate(BadExecutionContext context, BadObject target, BadSourcePosition position, Func<Action, BadExecutionContext, BadObject, IEnumerable<BadObject>> action)
129 {
130 if (target.HasProperty("GetEnumerator", context.Scope))
131 {
132 if (target.GetProperty("GetEnumerator", context.Scope).Dereference() is not BadFunction getEnumerator)
133 {
134 throw new BadRuntimeException("Invalid enumerator", position);
135 }
136
137 BadObject newTarget = BadObject.Null;
138
139 foreach (BadObject o in getEnumerator.Invoke(Array.Empty<BadObject>(), context))
140 {
141 yield return o;
142
143 newTarget = o;
144 }
145
146
147 if (newTarget == BadObject.Null)
148 {
149 throw BadRuntimeException.Create(context.Scope, $"Invalid enumerator: {target}", position);
150 }
151
152 target = newTarget.Dereference();
153 }
154
155 (BadFunction moveNext, BadFunction getCurrent) = FindEnumerator(target, context, position);
156
157
158 BadObject cond = BadObject.Null;
159
160 foreach (BadObject o in moveNext.Invoke(Array.Empty<BadObject>(), context))
161 {
162 cond = o;
163
164 yield return o;
165 }
166
167
168 IBadBoolean bRet = cond.Dereference() as IBadBoolean ??
169 throw new BadRuntimeException("While Condition is not a boolean", position);
170
171 while (bRet.Value)
172 {
173 using BadExecutionContext loopContext = new BadExecutionContext(
174 context.Scope.CreateChild(
175 "ForEachLoop",
176 context.Scope,
177 null,
178 BadScopeFlags.Breakable | BadScopeFlags.Continuable
179 )
180 );
181
182 BadObject current = BadObject.Null;
183
184 foreach (BadObject o in getCurrent.Invoke(Array.Empty<BadObject>(), loopContext))
185 {
186 current = o;
187
188 yield return o;
189 }
190
191
192
193 bool bBreak = false;
194 foreach (BadObject? o in action(() => bBreak = true, loopContext, current.Dereference()))
195 {
196 yield return o;
197 }
198
199 if (bBreak)
200 {
201 break;
202 }
203
204 foreach (BadObject o in moveNext.Invoke(Array.Empty<BadObject>(), loopContext))
205 {
206 cond = o;
207
208 yield return o;
209 }
210
211
212
213 bRet = cond.Dereference() as IBadBoolean ??
215 context.Scope,
216 "Enumerator MoveNext did not return a boolean",
217 position
218 );
219 }
220 }
221 protected override IEnumerable<BadObject> InnerExecute(BadExecutionContext context)
222 {
223 BadObject target = BadObject.Null;
224
225 foreach (BadObject o in Target.Execute(context))
226 {
227 target = o;
228
229 yield return o;
230 }
231
232
233 target = target.Dereference();
234
235 foreach (BadObject? o in Enumerate(context, target, Position, LoopBody))
236 {
237 yield return o;
238 }
239 }
240 private IEnumerable<BadObject> LoopBody(Action breakLoop, BadExecutionContext loopContext, BadObject current)
241 {
242 if (m_Body.Count != 0)
243 {
244 current = current.Dereference();
245 loopContext.Scope.DefineVariable(LoopVariable.Text, current);
246
247 foreach (BadObject o in loopContext.Execute(m_Body))
248 {
249 yield return o;
250 }
251
252 if (loopContext.Scope.IsBreak || loopContext.Scope.ReturnValue != null /*|| loopContext.Scope.IsError*/)
253 {
254 breakLoop();
255 }
256 }
257 }
258}
Describes a specific position inside a source file.
static BadExpression Optimize(BadExpression expr)
Optimizes the given expression.
Base Implementation for all Expressions used inside the Script.
IEnumerable< BadExpression > GetDescendantsAndSelf()
Returns all Descendants of the Expression and the Expression itself.
BadSourcePosition Position
The source Position of the Expression.
IEnumerable< BadObject > Execute(BadExecutionContext context)
Evaluates the Expression within the current Execution Context.
override void Optimize()
Uses the Constant Folding Optimizer to optimize the expression.
readonly BadWordToken LoopVariable
The Variable Name of the Current Loop iteration.
void SetBody(IEnumerable< BadExpression > body)
Sets the Body of the Loop.
BadExpression Target
The Enumerable/Enumerator Expression of the Loop.
static IEnumerable< BadObject > Enumerate(BadExecutionContext context, BadObject target, BadSourcePosition position, Func< Action, BadExecutionContext, BadObject, IEnumerable< BadObject > > action)
static BadFunction BadFunction getCurrent FindEnumerator(BadObject target, BadExecutionContext context, BadSourcePosition position)
static BadFunction moveNext
Helper Function that returns the MoveNext/GetCurrent function of the Target.
override IEnumerable< BadObject > InnerExecute(BadExecutionContext context)
BadForEachExpression(BadExpression target, BadWordToken loopVariable, IEnumerable< BadExpression > body, BadSourcePosition position)
Constructor of the For Each Expression.
IEnumerable< BadObject > LoopBody(Action breakLoop, BadExecutionContext loopContext, BadObject current)
string Text
The Text Representation of the Token.
Definition BadToken.cs:27
The Execution Context. Every execution of a script needs a context the script is running in....
IEnumerable< BadObject > Execute(IEnumerable< BadExpression > expressions)
Executes an enumeration of expressions.
BadScope Scope
The Root Scope of the Context.
BadScope CreateChild(string name, BadScope? caller, bool? useVisibility, BadScopeFlags flags=BadScopeFlags.RootScope)
Creates a subscope of the current scope.
Definition BadScope.cs:792
bool IsBreak
Is true if the Break Keyword was set.
Definition BadScope.cs:404
BadObject? ReturnValue
The Return value of the scope.
Definition BadScope.cs:414
void DefineVariable(string name, BadObject value, BadScope? caller=null, BadPropertyInfo? info=null, BadObject[]? attributes=null)
Defines a new Variable in the current scope.
Definition BadScope.cs:929
static BadRuntimeException Create(BadScope? scope, string message)
Creates a new BadScriptException.
The Base Class for all BadScript Objects.
Definition BadObject.cs:14
virtual BadObjectReference GetProperty(string propName, BadScope? caller=null)
Returns a Reference to the Property with the given Name.
Definition BadObject.cs:129
virtual bool HasProperty(string propName, BadScope? caller=null)
Returns true if the object contains a given property or there exists an extension for the current Ins...
Definition BadObject.cs:118
static readonly BadObject Null
The Null Value for the BadScript Language.
Definition BadObject.cs:28
Implements a function that can be called from the script.
IEnumerable< BadObject > Invoke(BadObject[] args, BadExecutionContext caller)
Invokes the function with the specified arguments.
Implements the Interface for Native Boolean.
Definition IBadBoolean.cs:7
Contains Shared Data Structures and Functionality.
Contains the BadScript2 Constant Folding Optimizations.
Contains the Loop Expressions for the BadScript2 Language.
Contains the Reader Tokens for the BadScript2 Language.
Contains the Error Objects for the BadScript2 Language.
Contains Runtime Function Objects.
Contains the Native Runtime Objects.
Definition BadBoolean.cs:6
Contains the Runtime Objects.
Definition BadArray.cs:10
Contains the Runtime Implementation.
BadScopeFlags
Defines Different Behaviours for the Current Scope.