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
31 BadExpression expr)
32 {
33 foreach (BadExpression expression in expr.GetDescendantsAndSelf())
34 {
35 if (expression is BadVariableExpression vExpr && scope.IsConstant(vExpr.Name) ||
36 expression.IsConstant ||
37 expression is BadBinaryExpression ||
38 expression is BadConstantExpression)
39 {
40 continue;
41 }
42
43 return false;
44 }
45
46 return true;
47 }
48
56 {
57 switch (expr)
58 {
59 case BadVariableExpression vExpr:
60 {
61 BadExpression constant = scope.GetConstant(vExpr.Name);
62 BadLogger.Log($"Substituting {expr} => {constant}", "Optimize");
63
64 return constant;
65 }
66 case BadBinaryExpression binExpr:
67 binExpr.SetLeft(Substitute(scope, binExpr.Left));
68 binExpr.SetRight(Substitute(scope, binExpr.Right));
69
70 break;
71 }
72
73 return expr;
74 }
75
82 private static IEnumerable<BadExpression> Optimize(
84 IEnumerable<BadExpression> expressions)
85 {
86 foreach (BadExpression expr in expressions)
87 {
88 switch (expr)
89 {
91 {
93
94 //Evaluate static body
95 BadExpression[] newStaticBody = Optimize(childScope, proto.StaticBody).ToArray();
96
97 proto.SetStaticBody(newStaticBody);
98
100
101 //Evaluate instance body
102 BadExpression[] newBody = Optimize(instanceScope, proto.Body).ToArray();
103 proto.SetBody(newBody);
104
105 yield return proto;
106
107 continue;
108 }
109 case BadWhileExpression whileExpr:
110 {
112 BadExpression[] newBody = Optimize(childScope, whileExpr.Body).ToArray();
113 whileExpr.SetBody(newBody);
114
115 yield return whileExpr;
116
117 continue;
118 }
119 case BadForExpression forExpr:
120 {
122 BadExpression[] newBody = Optimize(childScope, forExpr.Body).ToArray();
123 forExpr.SetBody(newBody);
124
125 yield return forExpr;
126
127 continue;
128 }
129 case BadForEachExpression forEachExpr:
130 {
132 BadExpression[] newBody = Optimize(childScope, forEachExpr.Body).ToArray();
133 forEachExpr.SetBody(newBody);
134
135 yield return forEachExpr;
136
137 continue;
138 }
139 case BadIfExpression ifExpr:
140 {
141 foreach (KeyValuePair<BadExpression, BadExpression[]> branch in ifExpr.ConditionalBranches.ToArray())
142 {
144 BadExpression[] newBody = Optimize(childScope, branch.Value).ToArray();
145 ifExpr.ConditionalBranches[branch.Key] = newBody;
146 }
147
148 if (ifExpr.ElseBranch != null)
149 {
151 BadExpression[] newBody = Optimize(childScope, ifExpr.ElseBranch).ToArray();
152 ifExpr.SetElseBranch(newBody);
153 }
154
155 yield return ifExpr;
156
157 continue;
158 }
159 case BadSwitchExpression switchExpr:
160 {
161 foreach (KeyValuePair<BadExpression, BadExpression[]> branch in switchExpr.Cases.ToArray())
162 {
164 BadExpression[] newBody = Optimize(childScope, branch.Value).ToArray();
165 switchExpr.Cases[branch.Key] = newBody;
166 }
167
168 if (switchExpr.DefaultCase != null)
169 {
171 BadExpression[] newBody = Optimize(childScope, switchExpr.DefaultCase).ToArray();
172 switchExpr.SetDefaultCase(newBody);
173 }
174
175 yield return switchExpr;
176
177 continue;
178 }
179 case BadInvocationExpression invoc:
180 {
181 List<BadExpression> args = (from arg in invoc.Arguments
182 let childScope = scope.CreateChildScope()
183 select Optimize(
184 childScope,
185 new[]
186 {
187 arg,
188 }
189 )
190 .ToArray()
191 into newBody
192 select newBody[0]).ToList();
193
194 invoc.SetArgs(args);
195
196 yield return invoc;
197
198 continue;
199 }
200 case BadFunctionExpression func:
201 {
203 BadExpression[] newBody = Optimize(childScope, func.Body).ToArray();
204 func.SetBody(newBody);
205
206 yield return func;
207
208 continue;
209 }
210 case BadBinaryExpression binExpr:
211 {
212 bool canBeOptimized = OnlyContainsConstantsAndConstantVariables(scope, binExpr);
213
214 if (canBeOptimized)
215 {
216 BadLogger.Log($"Optimizing Expression: '{expr}' with Constant Substitution", "Optimize");
217 BadObject obj = Substitute(scope, binExpr).Execute(null!).Last();
218 BadLogger.Log($"Optimized Expression: '{expr}' => '{obj}' using Constant Substitution", "Optimize");
219
220 yield return new BadConstantExpression(binExpr.Position, obj);
221
222 continue;
223 }
224
225 break;
226 }
227 case BadReturnExpression { Right: not null } rExpr:
228 {
229 bool canBeOptimized = OnlyContainsConstantsAndConstantVariables(scope, rExpr.Right);
230
231 if (canBeOptimized && rExpr.Right is not IBadNativeExpression)
232 {
233 BadLogger.Log($"Optimizing Expression: '{expr}' with Constant Substitution", "Optimize");
234 BadObject obj = Substitute(scope, rExpr.Right).Execute(null!).Last();
235 BadLogger.Log($"Optimized Expression: '{expr}' => '{obj}' using Constant Substitution", "Optimize");
236 rExpr.SetRight(new BadConstantExpression(rExpr.Position, obj));
237 }
238
239 break;
240 }
241 case BadAssignExpression { Left: BadVariableDefinitionExpression vDef } vAssign:
242 {
243 bool canBeOptimized = OnlyContainsConstantsAndConstantVariables(scope, vAssign.Right);
244
245 if (canBeOptimized && vAssign.Right is not IBadNativeExpression)
246 {
247 BadLogger.Log($"Optimizing Expression: '{expr}' with Constant Substitution", "Optimize");
248 BadObject obj = Substitute(scope, vAssign.Right).Execute(null!).Last();
249 BadLogger.Log($"Optimized Expression: '{expr}' => '{obj}' using Constant Substitution", "Optimize");
250 vAssign.Right = new BadConstantExpression(vAssign.Position, obj);
251 }
252
253 if (vDef.IsReadOnly && canBeOptimized)
254 {
255 scope.AddConstant(vDef.Name, vAssign.Right);
256 }
257
258 break;
259 }
260 }
261
262 yield return expr;
263 }
264 }
265
271 public static IEnumerable<BadExpression> Optimize(IEnumerable<BadExpression> expressions)
272 {
273 return Optimize(new BadConstantSubstitutionOptimizerScope(), expressions);
274 }
275}
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