BadScript 2
Loading...
Searching...
No Matches
BadExpression.cs
Go to the documentation of this file.
1using System.Runtime.ExceptionServices;
2
16
18
22public abstract class BadExpression
23{
29 protected BadExpression(bool isConstant, BadSourcePosition position)
30 {
31 IsConstant = isConstant;
32 Position = position;
33 Attributes = [];
34 }
35
36 public IEnumerable<BadExpression> Attributes { get; private set; }
37
38 public void SetAttributes(IEnumerable<BadExpression> attributes)
39 {
40 Attributes = attributes;
41 }
42 protected IEnumerable<BadObject> ComputeAttributes(BadExecutionContext ctx, List<BadObject> attributes)
43 {
44 foreach (var attribute in Attributes)
45 {
46 var obj = BadObject.Null;
47 BadExpression? attrib = null;
48 BadExpression access;
49 IEnumerable<BadExpression> args;
50
51 if (attribute is BadInvocationExpression invoc)
52 {
53 access = invoc.Left;
54 args = invoc.Arguments;
55 }
56 else if (attribute is BadMemberAccessExpression || attribute is BadVariableExpression)
57 {
58 access = attribute;
59 args = Array.Empty<BadExpression>();
60 }
61 else
62 {
63 throw BadRuntimeException.Create(ctx.Scope, "Attribute Expression not Supported.", attribute.Position);
64 }
65
66 BadClassPrototype? attribClass = null;
67 if (access is BadVariableExpression varExpr)
68 {
69 //Check if the variable exists and is a class.
70 if (ctx.Scope.HasVariable(varExpr.Name, ctx.Scope)) // Try to get the variable
71 {
72 var attribObj = ctx.Scope.GetVariable(varExpr.Name, ctx.Scope).Dereference();
73
74 //Check if the variable is a class and inherits from IAttribute
75 if (attribObj is BadClassPrototype cls && BadNativeClassBuilder.Attribute.IsSuperClassOf(cls))
76 {
77 attribClass = cls;
78 }
79 }
80
81 //If the variable does not exist, check if the variable name + "Attribute" exists and is a class.
82 if(attribClass == null && !varExpr.Name.EndsWith("Attribute") && ctx.Scope.HasVariable(varExpr.Name + "Attribute", ctx.Scope))
83 {
84 var attribObj = ctx.Scope.GetVariable(varExpr.Name + "Attribute", ctx.Scope).Dereference();
85
86
87 //Check if the variable is a class and inherits from IAttribute
88 if (attribObj is BadClassPrototype cls && BadNativeClassBuilder.Attribute.IsSuperClassOf(cls))
89 {
90 attribClass = cls;
91 }
92 }
93 }
94 else if (access is BadMemberAccessExpression mac)
95 {
96 //evaluate left side of the member access
97 foreach (var o in mac.Left.Execute(ctx))
98 {
99 obj = o;
100 }
101 var parent = obj.Dereference();
102 //Check if parent has property
103 if (parent.HasProperty(mac.Right.Text, ctx.Scope))
104 {
105 var attribObj = parent.GetProperty(mac.Right.Text, ctx.Scope).Dereference();
106 //Check if the property is a class and inherits from IAttribute
107 if (attribObj is BadClassPrototype cls && BadNativeClassBuilder.Attribute.IsSuperClassOf(cls))
108 {
109 attribClass = cls;
110 }
111 }
112 if(parent.HasProperty(mac.Right.Text + "Attribute", ctx.Scope))
113 {
114 var attribObj = parent.GetProperty(mac.Right.Text + "Attribute", ctx.Scope).Dereference();
115 //Check if the property is a class and inherits from IAttribute
116 if (attribObj is BadClassPrototype cls && BadNativeClassBuilder.Attribute.IsSuperClassOf(cls))
117 {
118 attribClass = cls;
119 }
120 }
121 }
122
123 if(attribClass == null)
124 {
125 throw BadRuntimeException.Create(ctx.Scope, "Attribute must be a class", attribute.Position);
126 }
127
128 attrib = new BadNewExpression(
130 new BadConstantExpression(attribute.Position, attribClass),
131 args,
132 attribute.Position
133 ),
134 attribute.Position
135 );
136
137 foreach (var o in attrib.Execute(ctx))
138 {
139 yield return o;
140 obj = o;
141 }
142
143 var a = obj.Dereference();
144 if (a is not BadClass c)
145 {
146 throw BadRuntimeException.Create(ctx.Scope, "Attribute must be a class", attrib.Position);
147 }
148
149 if (!c.InheritsFrom(BadNativeClassBuilder.Attribute))
150 {
151 throw BadRuntimeException.Create(ctx.Scope, "Attribute must inherit from IAttribute", attrib.Position);
152 }
153 attributes.Add(a);
154 }
155 }
156
160 public bool IsConstant { get; }
161
165 public BadSourcePosition Position { get; private set; }
166
170 public virtual void Optimize() { }
171
176 public abstract IEnumerable<BadExpression> GetDescendants();
177
182 public IEnumerable<BadExpression> GetDescendantsAndSelf()
183 {
184 yield return this;
185
186 foreach (BadExpression? descendant in GetDescendants())
187 {
188 yield return descendant;
189 }
190 }
191
197 {
198 Position = pos;
199 }
200
206 protected abstract IEnumerable<BadObject> InnerExecute(BadExecutionContext context);
207
208 private IEnumerable<BadObject> ExecuteWithCatch(BadExecutionContext context)
209 {
210 using IEnumerator<BadObject> e = InnerExecute(context).GetEnumerator();
211
212 while (true)
213 {
214 try
215 {
216 if (!e.MoveNext())
217 {
218 break;
219 }
220 }
221 catch (BadRuntimeErrorException err)
222 {
223 ExceptionDispatchInfo.Capture(err).Throw();
224 }
225 catch (Exception exception)
226 {
228 }
229
230 yield return e.Current ?? BadObject.Null;
231 }
232 }
238 public IEnumerable<BadObject> Execute(BadExecutionContext context)
239 {
241 {
242 BadDebugger.Step(new BadDebuggerStep(context, Position, this));
243 }
244
245 if (BadRuntimeSettings.Instance.CatchRuntimeExceptions)
246 {
247 return ExecuteWithCatch(context);
248 }
249 return InnerExecute(context);
250 }
251
262 protected static IEnumerable<BadObject> ExecuteOperatorOverride(
263 BadObject left,
264 BadObject right,
265 BadExecutionContext context,
266 string name,
267 BadSourcePosition position)
268 {
269 if (left.GetProperty(name, context.Scope).Dereference() is not BadFunction func)
270 {
271 throw new BadRuntimeException(
272 $"{left.GetType().Name} has no {name} property",
273 position
274 );
275 }
276
277 foreach (BadObject o in func.Invoke(
278 new[]
279 {
280 right,
281 },
282 context
283 ))
284 {
285 yield return o;
286 }
287 }
288
298 protected static IEnumerable<BadObject> ExecuteOperatorOverride(
299 BadObject left,
300 BadExecutionContext context,
301 string name,
302 BadSourcePosition position)
303 {
304 if (left.GetProperty(name, context.Scope).Dereference() is not BadFunction func)
305 {
306 throw new BadRuntimeException(
307 $"{left.GetType().Name} has no {name} property",
308 position
309 );
310 }
311
312 foreach (BadObject o in func.Invoke(Array.Empty<BadObject>(), context))
313 {
314 yield return o;
315 }
316 }
317}
Describes a specific position inside a source file.
Public Debugger Interface.
static void Step(BadDebuggerStep stepInfo)
Sends a step event to the debugger.
static bool IsAttached
True if a debugger is attached.
Implements the Member Access to set or get properties from an object. LEFT.RIGHT.
Base Implementation for all Expressions used inside the Script.
IEnumerable< BadObject > InnerExecute(BadExecutionContext context)
Is used to evaluate the Expression.
static IEnumerable< BadObject > ExecuteOperatorOverride(BadObject left, BadObject right, BadExecutionContext context, string name, BadSourcePosition position)
Helper function that executes an operator override function if implemented.
IEnumerable< BadObject > ComputeAttributes(BadExecutionContext ctx, List< BadObject > attributes)
IEnumerable< BadExpression > GetDescendantsAndSelf()
Returns all Descendants of the Expression and the Expression itself.
IEnumerable< BadExpression > Attributes
virtual void Optimize()
Uses the Constant Folding Optimizer to optimize the expression.
static IEnumerable< BadObject > ExecuteOperatorOverride(BadObject left, BadExecutionContext context, string name, BadSourcePosition position)
Executes an operator override function if implemented.
BadSourcePosition Position
The source Position of the Expression.
BadExpression(bool isConstant, BadSourcePosition position)
Constructor.
IEnumerable< BadExpression > GetDescendants()
Returns all Descendants of the Expression.
void SetPosition(BadSourcePosition pos)
Sets the Source Position of the Expression.
void SetAttributes(IEnumerable< BadExpression > attributes)
IEnumerable< BadObject > Execute(BadExecutionContext context)
Evaluates the Expression within the current Execution Context.
IEnumerable< BadObject > ExecuteWithCatch(BadExecutionContext context)
bool IsConstant
Indicates if the expression stays constant at all times.
The Execution Context. Every execution of a script needs a context the script is running in....
BadScope Scope
The Root Scope of the Context.
string GetStackTrace()
Returns the Stack Trace of the Current scope.
Definition BadScope.cs:633
Gets thrown if the runtime encounters an error.
Implements the Error Object Type.
static BadRuntimeError FromException(Exception e, string? scriptStackTrace=null)
Creates a BadRuntimeError from an Exception.
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
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.
Implements a Type Instance in the BadScript Language.
Definition BadClass.cs:11
Implements a Class Prototype for the BadScript Language.
Helper Class that Builds a Native Class from a Prototype.
static T Instance
Returns the Instance of the Settings Provider.
Contains Shared Data Structures and Functionality.
Contains the debugging abstractions for the BadScript2 Runtime.
Definition BadDebugger.cs:7
Contains the Access Expressions for the BadScript2 Language.
Contains the Constant 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 Error Objects for the BadScript2 Language.
Contains Runtime Function Objects.
Contains the Runtime Objects.
Definition BadArray.cs:10
Contains Runtime Settings Objects.
Contains the Runtime Implementation.
Represents a Debugging Step.