BadScript 2
Loading...
Searching...
No Matches
BadConstantSubstitutionOptimizer.cs
Go to the documentation of this file.
12
17
24{
25 //Try to find expressions that only reference constants AND variables that are marked constants.
26 // => traverse all expressions and keep track of all variables that are marked as constant.
27 // => if we find an expression that only contains constants and variables that are marked as constant, we can optimize it.
28
30 BadExpression expr)
31 {
32 foreach (BadExpression expression in expr.GetDescendantsAndSelf())
33 {
34 if ((expression is BadVariableExpression vExpr && scope.IsConstant(vExpr.Name)) ||
35 expression.IsConstant ||
36 expression is BadBinaryExpression ||
37 expression is BadConstantExpression)
38 {
39 continue;
40 }
41
42 return false;
43 }
44
45 return true;
46 }
47
55 {
56 switch (expr)
57 {
58 case BadVariableExpression vExpr:
59 {
60 BadExpression constant = scope.GetConstant(vExpr.Name);
61 BadLogger.Log($"Substituting {expr} => {constant}", "Optimize");
62
63 return constant;
64 }
65 case BadBinaryExpression binExpr:
66 binExpr.SetLeft(Substitute(scope, binExpr.Left));
67 binExpr.SetRight(Substitute(scope, binExpr.Right));
68
69 break;
70 }
71
72 return expr;
73 }
74
81 private static IEnumerable<BadExpression> Optimize(BadConstantSubstitutionOptimizerScope scope,
82 IEnumerable<BadExpression> expressions)
83 {
84 foreach (BadExpression expr in expressions)
85 {
86 switch (expr)
87 {
89 {
91
92 //Evaluate static body
93 BadExpression[] newStaticBody = Optimize(childScope, proto.StaticBody)
94 .ToArray();
95
96 proto.SetStaticBody(newStaticBody);
97
99
100 //Evaluate instance body
101 BadExpression[] newBody = Optimize(instanceScope, proto.Body)
102 .ToArray();
103 proto.SetBody(newBody);
104
105 yield return proto;
106
107 continue;
108 }
109 case BadWhileExpression whileExpr:
110 {
112
113 BadExpression[] newBody = Optimize(childScope, whileExpr.Body)
114 .ToArray();
115 whileExpr.SetBody(newBody);
116
117 yield return whileExpr;
118
119 continue;
120 }
121 case BadForExpression forExpr:
122 {
124
125 BadExpression[] newBody = Optimize(childScope, forExpr.Body)
126 .ToArray();
127 forExpr.SetBody(newBody);
128
129 yield return forExpr;
130
131 continue;
132 }
133 case BadForEachExpression forEachExpr:
134 {
136
137 BadExpression[] newBody = Optimize(childScope, forEachExpr.Body)
138 .ToArray();
139 forEachExpr.SetBody(newBody);
140
141 yield return forEachExpr;
142
143 continue;
144 }
145 case BadIfExpression ifExpr:
146 {
147 foreach (KeyValuePair<BadExpression, BadExpression[]> branch in
148 ifExpr.ConditionalBranches.ToArray())
149 {
151
152 BadExpression[] newBody = Optimize(childScope, branch.Value)
153 .ToArray();
154 ifExpr.ConditionalBranches[branch.Key] = newBody;
155 }
156
157 if (ifExpr.ElseBranch != null)
158 {
160
161 BadExpression[] newBody = Optimize(childScope, ifExpr.ElseBranch)
162 .ToArray();
163 ifExpr.SetElseBranch(newBody);
164 }
165
166 yield return ifExpr;
167
168 continue;
169 }
170 case BadSwitchExpression switchExpr:
171 {
172 foreach (KeyValuePair<BadExpression, BadExpression[]> branch in switchExpr.Cases.ToArray())
173 {
175
176 BadExpression[] newBody = Optimize(childScope, branch.Value)
177 .ToArray();
178 switchExpr.Cases[branch.Key] = newBody;
179 }
180
181 if (switchExpr.DefaultCase != null)
182 {
184
185 BadExpression[] newBody = Optimize(childScope, switchExpr.DefaultCase)
186 .ToArray();
187 switchExpr.SetDefaultCase(newBody);
188 }
189
190 yield return switchExpr;
191
192 continue;
193 }
194 case BadInvocationExpression invoc:
195 {
196 List<BadExpression> args = (from arg in invoc.Arguments
197 let childScope = scope.CreateChildScope()
198 select Optimize(childScope,
199 new[] { arg }
200 )
201 .ToArray()
202 into newBody
203 select newBody[0]).ToList();
204
205 invoc.SetArgs(args);
206
207 yield return invoc;
208
209 continue;
210 }
211 case BadFunctionExpression func:
212 {
214
215 BadExpression[] newBody = Optimize(childScope, func.Body)
216 .ToArray();
217 func.SetBody(newBody);
218
219 yield return func;
220
221 continue;
222 }
223 case BadBinaryExpression binExpr:
224 {
225 bool canBeOptimized = OnlyContainsConstantsAndConstantVariables(scope, binExpr);
226
227 if (canBeOptimized)
228 {
229 BadLogger.Log($"Optimizing Expression: '{expr}' with Constant Substitution", "Optimize");
230
231 BadObject obj = Substitute(scope, binExpr)
232 .Execute(null!)
233 .Last();
234
235 BadLogger.Log($"Optimized Expression: '{expr}' => '{obj}' using Constant Substitution",
236 "Optimize"
237 );
238
239 yield return new BadConstantExpression(binExpr.Position, obj);
240
241 continue;
242 }
243
244 break;
245 }
246 case BadReturnExpression { Right: not null } rExpr:
247 {
248 bool canBeOptimized = OnlyContainsConstantsAndConstantVariables(scope, rExpr.Right);
249
250 if (canBeOptimized && rExpr.Right is not IBadNativeExpression)
251 {
252 BadLogger.Log($"Optimizing Expression: '{expr}' with Constant Substitution", "Optimize");
253
254 BadObject obj = Substitute(scope, rExpr.Right)
255 .Execute(null!)
256 .Last();
257
258 BadLogger.Log($"Optimized Expression: '{expr}' => '{obj}' using Constant Substitution",
259 "Optimize"
260 );
261 rExpr.SetRight(new BadConstantExpression(rExpr.Position, obj));
262 }
263
264 break;
265 }
266 case BadAssignExpression { Left: BadVariableDefinitionExpression vDef } vAssign:
267 {
268 bool canBeOptimized = OnlyContainsConstantsAndConstantVariables(scope, vAssign.Right);
269
270 if (canBeOptimized && vAssign.Right is not IBadNativeExpression)
271 {
272 BadLogger.Log($"Optimizing Expression: '{expr}' with Constant Substitution", "Optimize");
273
274 BadObject obj = Substitute(scope, vAssign.Right)
275 .Execute(null!)
276 .Last();
277
278 BadLogger.Log($"Optimized Expression: '{expr}' => '{obj}' using Constant Substitution",
279 "Optimize"
280 );
281 vAssign.Right = new BadConstantExpression(vAssign.Position, obj);
282 }
283
284 if (vDef.IsReadOnly && canBeOptimized)
285 {
286 scope.AddConstant(vDef.Name, vAssign.Right);
287 }
288
289 break;
290 }
291 }
292
293 yield return expr;
294 }
295 }
296
302 public static IEnumerable<BadExpression> Optimize(IEnumerable<BadExpression> expressions)
303 {
304 return Optimize(new BadConstantSubstitutionOptimizerScope(), expressions);
305 }
306}
Public facing interface for a logger.
Definition BadLogger.cs:7
static void Log(string message)
Writes a Log to the Message Handler.
Definition BadLogger.cs:26
Contains the Implementation of the Constant Substitution Optimization This optimization replaces expr...
static bool OnlyContainsConstantsAndConstantVariables(BadConstantSubstitutionOptimizerScope scope, BadExpression expr)
static IEnumerable< BadExpression > Optimize(IEnumerable< BadExpression > expressions)
Runs the Constant Substitution Optimization on the given expressions.
static BadExpression Substitute(BadConstantSubstitutionOptimizerScope scope, BadExpression expr)
Substitutes all variables in the expression with their constant value.
static IEnumerable< BadExpression > Optimize(BadConstantSubstitutionOptimizerScope scope, IEnumerable< BadExpression > expressions)
Substitutes all variables in the expressions with their constant value.
BadExpression GetConstant(string name)
Returns a constant from this scope or a parent scope.
Base Implementation for all Expressions used inside the Script.
IEnumerable< BadExpression > GetDescendantsAndSelf()
Returns all Descendants of the Expression and the Expression itself.
IEnumerable< BadObject > Execute(BadExecutionContext context)
Evaluates the Expression within the current Execution Context.
bool IsConstant
Indicates if the expression stays constant at all times.
Implements the Assign Expression LEFT = RIGHT.
Base Implementation of all Binary Expressions.
void SetLeft(BadExpression expr)
Sets the Left side of the Expression.
Implements the If Statement Expression.
Implements the Switch Statement Expression.
Implements the Return expression that is used to exit the current function with an Optional Return Va...
void SetArgs(IEnumerable< BadExpression > exprs)
Sets the arguments of the invocation.
The Base Class for all BadScript Objects.
Definition BadObject.cs:14
Gets implemented by all Constant/Native Expressions to provide fast access to the value without unwra...
Contains Logging system for the BadScript Runtime.
Definition BadLog.cs:6
Contains the BadScript2 Constant Substitution Optimizations.
Contains the Binary Expressions for the BadScript2 Language.
Contains the Loop Expressions for the BadScript2 Language.
Contains the Block Expressions for the BadScript2 Language.
Contains the Constant Expressions for the BadScript2 Language.
Contains the Controlflow Expressions for the BadScript2 Language.
Contains the Function Expressions for the BadScript2 Language.
Contains the Type Expressions for the BadScript2 Language.
Contains the Variable Expressions for the BadScript2 Language.
Contains the Expressions for the BadScript2 Language.
Contains the Runtime Objects.
Definition BadArray.cs:10