ScriptStack 1.0.5
Loading...
Searching...
No Matches
ScriptStack.Runtime.Interpreter Class Reference

The Interpreter finally interprets the parse tree in form of a token stream returned from the ScriptStack.Compiler.Parser. More...

Classes

class  FunctionFrame
 For every forward declared function, a new function frame is created including a memory object holding its local variables. The values are pushed on the stack before they are called. More...

Public Member Functions

 Interpreter (Function function, List< object > parameters, InterpreterOptions? options=null)
 Interpreter (Function function)
 Interpreter (Script script, List< object > parameters, InterpreterOptions? options=null)
 Interpreter (Script script, InterpreterOptions? options=null)
void Reset ()
uint Interpret (uint instructions)
uint Interpret (TimeSpan interval)
uint Interpret ()

Properties

Script Script [get]
bool Interrupt [get, set]
ReadOnlyCollection< InterpreterJobs [get]
bool Interrupted [get]
bool Finished [get]
int NextInstruction [get]
ReadOnlyCollection< FunctionFunctionStack [get]
ReadOnlyCollection< object > ParameterStack [get]
Memory LocalMemory [get]
Host Handler [get, set]

Private Member Functions

int ToInt32Bitwise (object value, string opName="bitwise")
object Evaluate (Operand operand)
void Assignment (Operand dst, object val)
void Arithmetic ()
 Ausführung arithmetischer Operationen.
void Relation ()
 Ausführung einer Vergleichsoperation.
void Logic ()
 Usually its a boolean operation but it allows numerics too.
void Iterator (ArrayList array)
void Iterator (IDictionary dict)
void Iterator (string str)
void DBG ()
void NOP ()
void INT ()
void RET ()
 Return from current function frame to the last one on the stack, copying local memory to the new one.
void PUSH ()
void POP ()
 Pop a value from the stack into an atom.
void MOV ()
 Basic assignment.
void ADD ()
void SUB ()
void MUL ()
void DIV ()
void MOD ()
void INC ()
void DEC ()
void NEG ()
 Negate a literal (* -1).
void SHL ()
void SHR ()
void TEST ()
void CEQ ()
void CNE ()
void CG ()
void CGE ()
void CL ()
void CLE ()
void OR ()
void AND ()
void NOT ()
 Negate a boolean or int.
void ORB ()
void ANDB ()
void NOTB ()
void XOR ()
void JMP ()
 Jump to the address the first operator points at.
void JZ ()
 Jump to the instruction the second operand is pointing at if the first operand is true.
void JNZ ()
 Jump to the instruction the second operand is pointing at if the first operand is false.
void DSB ()
void DB ()
void DC ()
void DCO ()
void PTR ()
 A pointer in foreach loops.
void CALL ()
 Call a Function.
void INV ()
 Invoke a Routine, if no result is specified a null is pushed onto the stack.
void MIV ()
 Invoke a CLR instance method via reflection.
void RUN ()
 Run a Function in Background.
void LOCK ()
void FREE ()
uint ExecuteBackgroundJobs ()
void ExecuteInstruction ()
void Iterator (IList list)

Private Attributes

Function function
Script script
Executable executable
Stack< FunctionFramefunctionStack
Stack< object > parameterStack
Dictionary< object, Instructionlocks
List< Interpreterjobs
Instruction instruction
Memory localMemory
bool interrupt
bool interrupted
bool finished
ClrBridge _clr
InterpreterOptions _options
Host host

Detailed Description

The Interpreter finally interprets the parse tree in form of a token stream returned from the ScriptStack.Compiler.Parser.

Todo
Evaluate!!! member access

Definition at line 17 of file Interpreter.cs.

Constructor & Destructor Documentation

◆ Interpreter() [1/4]

ScriptStack.Runtime.Interpreter.Interpreter ( Function function,
List< object > parameters,
InterpreterOptions? options = null )

Definition at line 1874 of file Interpreter.cs.

1875 {
1876
1877 if (function.ParameterCount != parameters.Count)
1878 throw new ExecutionException("Die Funktion '" + function.Name + "' wurde mit " + parameters.Count + " statt erwartet " + function.ParameterCount + " Parametern aufgerufen.");
1879
1880 _options = options ?? new InterpreterOptions();
1881 _clr = new ClrBridge(_options.ResolveClrPolicy());
1882
1883 this.function = function;
1884
1885 script = function.Executable.Script;
1886
1887 executable = script.Executable;
1888
1889 functionStack = new Stack<FunctionFrame>();
1890
1891 parameterStack = new Stack<object>();
1892
1893 locks = new Dictionary<object, Instruction>();
1894
1895 jobs = new List<Interpreter>();
1896
1897 host = null;
1898
1899 interrupt = false;
1900
1901 Reset();
1902
1903 foreach (object parameter in parameters)
1904 {
1905
1906 if (parameter == null)
1907 parameterStack.Push(NullReference.Instance);
1908
1909 else
1910 {
1911
1912 Type parameterType = parameter.GetType();
1913
1914 if (parameterType == typeof(NullReference))
1915 parameterStack.Push(NullReference.Instance);
1916
1917 else if (parameterType == typeof(int)
1918 || parameterType == typeof(float)
1919 || parameterType == typeof(double)
1920 || parameterType == typeof(bool)
1921 || parameterType == typeof(string)
1922 || parameterType == typeof(char)
1923 || parameterType == typeof(ArrayList))
1924 parameterStack.Push(parameter);
1925
1926 else
1927 throw new ExecutionException("Der Typ '" + parameterType.Name + "' ist kein generischer Typ.");
1928
1929 }
1930
1931 }
1932
1933 }

References _clr, _options, executable, functionStack, host, interrupt, jobs, locks, parameterStack, Reset(), and script.

Referenced by ExecuteBackgroundJobs(), LOCK(), and RUN().

◆ Interpreter() [2/4]

ScriptStack.Runtime.Interpreter.Interpreter ( Function function)

Definition at line 1935 of file Interpreter.cs.

1935 :
1936 this(function, new List<object>())
1937 {
1938 }

References function.

◆ Interpreter() [3/4]

ScriptStack.Runtime.Interpreter.Interpreter ( Script script,
List< object > parameters,
InterpreterOptions? options = null )

Definition at line 1940 of file Interpreter.cs.

1940 :
1941 this(script.Executable.MainFunction, parameters, options)
1942 {
1943 }

References Script, and script.

◆ Interpreter() [4/4]

ScriptStack.Runtime.Interpreter.Interpreter ( Script script,
InterpreterOptions? options = null )

Definition at line 1945 of file Interpreter.cs.

1945 :
1946 this(script.Executable.MainFunction, new List<object>(), options)
1947 {
1948 }

References Script, and script.

Member Function Documentation

◆ ADD()

void ScriptStack.Runtime.Interpreter.ADD ( )
private

Definition at line 951 of file Interpreter.cs.

952 {
953 Arithmetic();
954 }

References Arithmetic().

◆ AND()

void ScriptStack.Runtime.Interpreter.AND ( )
private

Definition at line 1217 of file Interpreter.cs.

1218 {
1219 Logic();
1220 }

References Logic().

Referenced by ExecuteInstruction().

◆ ANDB()

void ScriptStack.Runtime.Interpreter.ANDB ( )
private

Definition at line 1278 of file Interpreter.cs.

1279 {
1280
1281 string identifier = null;
1282
1283 object val = Evaluate(instruction.Second);
1284
1285 Operand operand = instruction.First;
1286
1287 switch (operand.Type)
1288 {
1289
1290 case OperandType.Variable:
1291 //int res = (int)localMemory[(string)operand.Value] & (int)val;
1292 int res = ToInt32Bitwise(localMemory[(string)operand.Value], "&") & ToInt32Bitwise(val, "&");
1293
1294 identifier = operand.Value.ToString();
1295
1296 localMemory[identifier] = res;
1297
1298 break;
1299
1300 default:
1301 throw new ExecutionException("Operand type '" + operand.Type + "' not supported by logical AND instruction.");
1302
1303 }
1304
1305 }

References Evaluate(), instruction, localMemory, ToInt32Bitwise(), ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ExecuteInstruction().

◆ Arithmetic()

void ScriptStack.Runtime.Interpreter.Arithmetic ( )
private

Ausführung arithmetischer Operationen.

dest = dest OP source

Special rules for strings and arrays

Definition at line 298 of file Interpreter.cs.

299 {
300
301 String strIdentifierDest = (String)instruction.First.Value;
302
303 object objectValueDest = Evaluate(instruction.First);
304 object objectValueSource = Evaluate(instruction.Second);
305
306 Type typeDest = objectValueDest.GetType();
307 Type typeSource = objectValueSource.GetType();
308
309 // handle array and string concatenation
310 if (instruction.OpCode == OpCode.ADD)
311 {
312 if (typeDest == typeof(String))
313 {
314 Assignment(instruction.First, objectValueDest.ToString() + objectValueSource.ToString());
315 return;
316 }
317
318 if (typeDest == typeof(ArrayList))
319 {
320 ((ArrayList)objectValueDest).Add(objectValueSource);
321 return;
322 }
323 }
324
325 // handle array and string subtraction
326 if (instruction.OpCode == OpCode.SUB)
327 {
328 if (typeDest == typeof(String))
329 {
330 Assignment(instruction.First,
331 objectValueDest.ToString().Replace(objectValueSource.ToString(), ""));
332 return;
333 }
334 if (typeDest == typeof(ArrayList))
335 {
336 ((ArrayList)objectValueDest).Subtract(objectValueSource);
337 return;
338 }
339 }
340
341 /*
342 float fValueDest = 0.0f;
343 float fValueSource = 0.0f;
344 float fResult = 0.0f;
345 */
346
347 /*
348 var fValueDest = 0.0;
349 var fValueSource = 0.0;
350 var fResult = 0.0;
351
352 if (typeDest == typeof(int))
353 fValueDest = (float)(int)objectValueDest;
354 else if (typeDest == typeof(float))
355 fValueDest = (float)objectValueDest;
356 else if (typeDest == typeof(double))
357 fValueDest = (double)objectValueDest;
358 else if (typeDest == typeof(decimal))
359 fValueDest = (decimal)objectValueDest;
360 else
361 throw new ScriptStackException("Values of type '" + typeDest.Name + "' cannot be used in arithmetic instructions.");
362
363 if (typeSource == typeof(int))
364 fValueSource = (float)(int)objectValueSource;
365 else if (typeSource == typeof(float))
366 fValueSource = (float)objectValueSource;
367 else if (typeSource == typeof(float))
368 fValueSource = (double)objectValueSource;
369 else if (typeSource == typeof(decimal))
370 fValueSource = (decimal)objectValueSource;
371 else
372 throw new ScriptStackException("Values of type '" + typeSource.Name + "' cannot be used in arithmetic instructions.");
373
374 switch (instruction.OpCode)
375 {
376 case OpCode.ADD: fResult = fValueDest + fValueSource; break;
377 case OpCode.SUB: fResult = fValueDest - fValueSource; break;
378 case OpCode.MUL: fResult = fValueDest * fValueSource; break;
379 case OpCode.DIV: fResult = fValueDest / fValueSource; break;
380 case OpCode.MOD: fResult = fValueDest % fValueSource; break;
381 default:
382 throw new ExecutionException("Invalid arithmetic instruction '" + instruction.OpCode + "'.");
383 }
384
385 if (typeDest == typeof(int) && typeSource == typeof(int))
386 Assignment(instruction.First, (int)fResult);
387 else if (typeDest == typeof(float) && typeSource == typeof(float))
388 Assignment(instruction.First, (float)fResult);
389 else if (typeDest == typeof(double) && typeSource == typeof(double))
390 Assignment(instruction.First, (double)fResult);
391 else
392 Assignment(instruction.First, (decimal)fResult);
393 */
394
395 /*
396 decimal a = ToDecimal(objectValueDest, typeDest);
397 decimal b = ToDecimal(objectValueSource, typeSource);
398
399 decimal r = instruction.OpCode switch
400 {
401 OpCode.ADD => a + b,
402 OpCode.SUB => a - b,
403 OpCode.MUL => a * b,
404 OpCode.DIV => a / b,
405 OpCode.MOD => a % b,
406 _ => throw new ExecutionException($"Invalid arithmetic instruction '{instruction.OpCode}'.")
407 };
408
409 // Ergebnis in den Zieltyp (dest) zurück
410 if (typeDest == typeof(int)) Assignment(instruction.First, (int)r);
411 else if (typeDest == typeof(float)) Assignment(instruction.First, (float)r);
412 else if (typeDest == typeof(double)) Assignment(instruction.First, (double)r);
413 else if (typeDest == typeof(decimal)) Assignment(instruction.First, r);
414 else throw new ScriptStackException($"Values of type '{typeDest.Name}' cannot be used in arithmetic instructions.");
415 */
416
417 decimal valueDest;
418 decimal valueSource;
419 decimal result;
420
421 // DEST -> decimal
422 switch (Type.GetTypeCode(typeDest))
423 {
424 case TypeCode.Int32: valueDest = (int)objectValueDest; break;
425 case TypeCode.Single: valueDest = (decimal)(float)objectValueDest; break;
426 case TypeCode.Double: valueDest = (decimal)(double)objectValueDest; break;
427 case TypeCode.Decimal: valueDest = (decimal)objectValueDest; break;
428 default:
429 throw new ScriptStackException("Values of type '" + typeDest.Name + "' cannot be used as destination in arithmetic instructions.");
430 }
431
432 // SOURCE -> decimal
433 switch (Type.GetTypeCode(typeSource))
434 {
435 case TypeCode.Int32: valueSource = (int)objectValueSource; break;
436 case TypeCode.Single: valueSource = (decimal)(float)objectValueSource; break;
437 case TypeCode.Double: valueSource = (decimal)(double)objectValueSource; break;
438 case TypeCode.Decimal: valueSource = (decimal)objectValueSource; break;
439 default:
440 throw new ScriptStackException("Values of type '" + typeSource.Name + "' cannot be used as source in arithmetic instructions.");
441 }
442
443 // Arithmetic (decimal)
444 switch (instruction.OpCode)
445 {
446 case OpCode.ADD: result = valueDest + valueSource; break;
447 case OpCode.SUB: result = valueDest - valueSource; break;
448 case OpCode.MUL: result = valueDest * valueSource; break;
449 case OpCode.DIV: result = valueDest / valueSource; break;
450 case OpCode.MOD: result = valueDest % valueSource; break;
451 default:
452 throw new ExecutionException("Invalid arithmetic instruction '" + instruction.OpCode + "'.");
453 }
454
455 // Back to DEST type
456 switch (Type.GetTypeCode(typeDest))
457 {
458 case TypeCode.Int32: Assignment(instruction.First, (int)result); break;
459 case TypeCode.Single: Assignment(instruction.First, (float)result); break;
460 case TypeCode.Double: Assignment(instruction.First, (double)result); break;
461 case TypeCode.Decimal: Assignment(instruction.First, result); break;
462 default:
463 // eigentlich schon oben abgefangen, aber zur Sicherheit:
464 throw new ScriptStackException("Values of type '" + typeDest.Name + "' cannot be used in arithmetic instructions.");
465 }
466
467 }

References Assignment(), Evaluate(), instruction, and ScriptStack.Compiler.String.

Referenced by ADD(), DIV(), ExecuteInstruction(), MOD(), MUL(), and SUB().

◆ Assignment()

void ScriptStack.Runtime.Interpreter.Assignment ( Operand dst,
object val )
private
Parameters
dst
val

Definition at line 235 of file Interpreter.cs.

236 {
237
238 string identifier = (string)dst.Value;
239
240 switch (dst.Type)
241 {
242
243 case OperandType.Variable:
244 localMemory[identifier] = val;
245 break;
246
247 case OperandType.Member:
248 {
249 object target = localMemory.Exists(identifier) ? localMemory[identifier] : NullReference.Instance;
250
251 if (target is ArrayList arr)
252 {
253 arr[dst.Member] = val;
254 break;
255 }
256
257 // NEU: C# Objekt Member setzen
258 _clr.SetMember(target, dst.Member.ToString()!, val);
259 break;
260 }
261 case OperandType.Pointer:
262 {
263 object container = localMemory.Exists(identifier) ? localMemory[identifier] : NullReference.Instance;
264 object key = localMemory[dst.Pointer];
265
266 // ScriptStack Array
267 if (container is ArrayList arr)
268 {
269 arr[key] = val;
270 break;
271 }
272
273 // Strings are read-only in this language
274 if (container is string)
275 throw new ExecutionException("Ein String ist nicht schreibbar.");
276
277 // CLR arrays / lists / dictionaries / indexers
278 if (_clr.TrySetIndex(container, key, val))
279 break;
280
281 throw new ExecutionException($"Das Ziel '{dst}' vom Typ '{container?.GetType().FullName}' ist nicht indexierbar.");
282 }
283
284 case OperandType.Literal:
285 throw new ExecutionException("Einem Literal kann nichts zugewiesen werden.");
286
287 }
288
289 }

References _clr, localMemory, ScriptStack.Runtime.Operand.Member, ScriptStack.Runtime.Operand.Pointer, ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by Arithmetic(), Logic(), MOV(), POP(), and Relation().

◆ CALL()

void ScriptStack.Runtime.Interpreter.CALL ( )
private

Call a Function.

Definition at line 1517 of file Interpreter.cs.

1518 {
1519
1520 Function function = instruction.First.FunctionPointer;
1521
1522 FunctionFrame frame = new FunctionFrame();
1523
1524 frame.function = function;
1525
1526 frame.localMemory = Memory.AllocateLocalMemory(executable.ScriptMemory);
1527
1528 frame.nextInstruction = (int) function.EntryPoint.Address;
1529
1530 functionStack.Push(frame);
1531
1532 }

References ScriptStack.Runtime.Memory.AllocateLocalMemory(), executable, functionStack, and instruction.

Referenced by ExecuteInstruction().

◆ CEQ()

void ScriptStack.Runtime.Interpreter.CEQ ( )
private

Definition at line 1165 of file Interpreter.cs.

1166 {
1167 Relation();
1168 }

References Relation().

Referenced by ExecuteInstruction().

◆ CG()

void ScriptStack.Runtime.Interpreter.CG ( )
private

Definition at line 1181 of file Interpreter.cs.

1182 {
1183 Relation();
1184 }

References Relation().

Referenced by ExecuteInstruction().

◆ CGE()

void ScriptStack.Runtime.Interpreter.CGE ( )
private

Definition at line 1189 of file Interpreter.cs.

1190 {
1191 Relation();
1192 }

References Relation().

Referenced by ExecuteInstruction().

◆ CL()

void ScriptStack.Runtime.Interpreter.CL ( )
private

Definition at line 1197 of file Interpreter.cs.

1198 {
1199 Relation();
1200 }

References Relation().

Referenced by ExecuteInstruction().

◆ CLE()

void ScriptStack.Runtime.Interpreter.CLE ( )
private

Definition at line 1205 of file Interpreter.cs.

1206 {
1207 Relation();
1208 }

References Relation().

Referenced by ExecuteInstruction().

◆ CNE()

void ScriptStack.Runtime.Interpreter.CNE ( )
private

Definition at line 1173 of file Interpreter.cs.

1174 {
1175 Relation();
1176 }

References Relation().

Referenced by ExecuteInstruction().

◆ DB()

void ScriptStack.Runtime.Interpreter.DB ( )
private

Definition at line 1406 of file Interpreter.cs.

1407 {
1408
1409 localMemory[(string)instruction.First.Value] = NullReference.Instance;
1410
1411 }

References instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ DBG()

void ScriptStack.Runtime.Interpreter.DBG ( )
private

Definition at line 885 of file Interpreter.cs.

886 {
887 }

Referenced by ExecuteInstruction().

◆ DC()

void ScriptStack.Runtime.Interpreter.DC ( )
private

Definition at line 1413 of file Interpreter.cs.

1414 {
1415
1416 if (instruction.First.Type != OperandType.Variable)
1417 throw new ExecutionException("Error in array declaration.");
1418
1419 ArrayList array = new ArrayList();
1420
1421 localMemory[instruction.First.Value.ToString()] = array;
1422
1423 }

References instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ DCO()

void ScriptStack.Runtime.Interpreter.DCO ( )
private

Definition at line 1425 of file Interpreter.cs.

1426 {
1427
1428 string strIdentifier = null;
1429
1430 object objectValue = Evaluate(instruction.Second);
1431
1432 Operand operand = instruction.First;
1433
1434 switch (operand.Type)
1435 {
1436
1437 case OperandType.Variable:
1438 int res = (int)objectValue ^ (int)localMemory[(string)operand.Value];
1439
1440 strIdentifier = operand.Value.ToString();
1441
1442 localMemory[strIdentifier] = res;
1443
1444 break;
1445
1446 default:
1447 throw new ExecutionException("Operand type '" + operand.Type + "' not supported by logical LNEG instruction.");
1448
1449 }
1450
1451 }

References Evaluate(), instruction, localMemory, ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ExecuteInstruction().

◆ DEC()

void ScriptStack.Runtime.Interpreter.DEC ( )
private

Definition at line 1027 of file Interpreter.cs.

1028 {
1029
1030 string identifier = (string)instruction.First.Value;
1031
1032 object val = Evaluate(instruction.First);
1033
1034 Type typeDest = val.GetType();
1035
1036 if (typeDest == typeof(char))
1037 {
1038 char c = (char)val;
1039 localMemory[identifier] = (char)(c - 1);
1040 }
1041 else if (typeDest == typeof(int))
1042 localMemory[identifier] = (int)val - 1;
1043
1044 else if (typeDest == typeof(float))
1045 localMemory[identifier] = (float)val - 1;
1046
1047 else if (typeDest == typeof(double))
1048 localMemory[identifier] = (double)val - 1;
1049
1050 else if (typeDest == typeof(decimal))
1051 localMemory[identifier] = (decimal)val - 1;
1052
1053 else
1054 throw new ExecutionException("Der Typ '" + typeDest.Name + "' kann nicht dekrementiert werden.");
1055
1056 }

References Evaluate(), instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ DIV()

void ScriptStack.Runtime.Interpreter.DIV ( )
private

Definition at line 975 of file Interpreter.cs.

976 {
977 Arithmetic();
978 }

References Arithmetic().

◆ DSB()

void ScriptStack.Runtime.Interpreter.DSB ( )
private

Definition at line 1399 of file Interpreter.cs.

1400 {
1401
1402 throw new ExecutionException("DCG opcodes cannot be executed within a function frame.");
1403
1404 }

Referenced by ExecuteInstruction().

◆ Evaluate()

object ScriptStack.Runtime.Interpreter.Evaluate ( Operand operand)
private

Definition at line 93 of file Interpreter.cs.

94 {
95
96 object src = null;
97
98 switch (operand.Type)
99 {
100
101 case OperandType.Literal:
102 return operand.Value;
103
104 case OperandType.Variable:
105 return localMemory[(string) operand.Value];
106
107 /*
108 * Members are indexed with a '.' like
109 *
110 * var a = [];
111 * a.b = 1;
112 *
113 * currently only arrays can have members but strings can be numerically indexed
114 *
115 */
116 case OperandType.Member:
117
118 src = localMemory[(string)operand.Value];
119
120 if (src.GetType() == typeof(ArrayList))
121 {
122
123 /*
124 * An array has an internal member "toString"
125 * \deprecated
126 */
127 if ((string)operand.Member == "toString")
128 {
129
130 ArrayList array = (ArrayList)src;
131
132 StringBuilder sb = new StringBuilder();
133
134 foreach (KeyValuePair<object, object> element in array)
135 {
136 sb.Append(element.Value.ToString());
137 }
138
139 return sb;
140
141 }
142
143 ArrayList associativeArray = (ArrayList)src;
144
145 object objectValue = associativeArray[operand.Member];
146
147 return objectValue;
148 }
149
150 else if (src.GetType() == typeof(string))
151 {
152
153 string strSource = (string)src;
154
155 object objectIndex = operand.Member;
156
157 if (objectIndex.GetType() == typeof(string))
158 if (((string)objectIndex) == "length")
159 return strSource.Length;
160
161 if (objectIndex.GetType() != typeof(int))
162 throw new ExecutionException("Ein String ist nur numerisch indexierbar.");
163
164 return strSource[(int)objectIndex] + "";
165
166 }
167
168 else
169 {
170 src = localMemory[(string)operand.Value];
171 var memberName = operand.Member?.ToString() ?? "";
172 return _clr.GetMember(src, memberName);
173 }
174
175 //else throw new ExecutionException("Der Typ '"+ operand.Type + "' kann an dieser Stelle nicht verarbeitet werden.");
176
177 /*
178 * Arrays can be indexed with a "string" like
179 *
180 * var a = [];
181 * a["str"] = "Hello world";
182 *
183 * accually a pointer is an associative array
184 *
185 */
186 case OperandType.Pointer:
187
188 src = localMemory[(string)operand.Value];
189
190 if (src.GetType() == typeof(ArrayList))
191 {
192
193 object objectIndex = localMemory[operand.Pointer];
194
195 return ((ArrayList)src)[objectIndex];
196
197 }
198
199 else if (src.GetType() == typeof(string))
200 {
201
202 string strSource = (string)src;
203
204 object objectIndex = localMemory[operand.Pointer];
205
206 if (objectIndex.GetType() != typeof(int))
207 throw new ExecutionException("Ein String ist nur numerisch indexierbar.");
208
209 return strSource[(int)objectIndex] + "";
210
211 }
212
213 else
214 {
215 // IDictionary / Indexer-Property
216 object objectIndex = localMemory[operand.Pointer];
217 if (_clr.TryGetIndex(src, objectIndex, out var v))
218 return v;
219 throw new ExecutionException("Nur Arrays, Dictionaries und Strings sind indexierbar.");
220 }
221
222
223 default:
224 throw new ExecutionException("Der Typ '"+ operand.Type + "' kann an dieser Stelle nicht verarbeitet werden.");
225
226 }
227
228 }

References _clr, localMemory, ScriptStack.Runtime.Operand.Member, ScriptStack.Runtime.Operand.Pointer, ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ANDB(), Arithmetic(), DCO(), DEC(), FREE(), INC(), Iterator(), Iterator(), Iterator(), Iterator(), JNZ(), JZ(), LOCK(), Logic(), MOV(), NEG(), NOT(), NOTB(), ORB(), PUSH(), Relation(), SHL(), SHR(), TEST(), and XOR().

◆ ExecuteBackgroundJobs()

uint ScriptStack.Runtime.Interpreter.ExecuteBackgroundJobs ( )
private

Definition at line 1784 of file Interpreter.cs.

1785 {
1786
1787 uint executed = 0;
1788
1789 foreach (Interpreter job in jobs)
1790 if (!job.Finished)
1791 executed += job.Interpret(1);
1792
1793 for (int i = jobs.Count - 1; i >= 0; i--)
1794 if (jobs[i].Finished)
1795 jobs.RemoveAt(i);
1796
1797 return executed;
1798
1799 }
uint Interpret(uint instructions)

References Finished, Interpret(), Interpreter(), and jobs.

Referenced by Interpret(), Interpret(), and Interpret().

◆ ExecuteInstruction()

void ScriptStack.Runtime.Interpreter.ExecuteInstruction ( )
private

Definition at line 1801 of file Interpreter.cs.

1802 {
1803
1804 instruction = executable.InstructionsInternal[functionStack.Peek().nextInstruction++];
1805
1806 switch (instruction.OpCode)
1807 {
1808
1809 case OpCode.DBG: DBG(); break;
1810 case OpCode.NOP: NOP(); break;
1811
1812 case OpCode.INT: INT(); break;
1813 case OpCode.RET: RET(); break;
1814
1815 case OpCode.PUSH: PUSH(); break;
1816 case OpCode.POP: POP(); break;
1817 case OpCode.MOV: MOV(); break;
1818
1819 case OpCode.ADD: Arithmetic(); break;
1820 case OpCode.SUB: Arithmetic(); break;
1821 case OpCode.MUL: Arithmetic(); break;
1822 case OpCode.DIV: Arithmetic(); break;
1823 case OpCode.MOD: Arithmetic(); break;
1824
1825 case OpCode.INC: INC(); break;
1826 case OpCode.DEC: DEC(); break;
1827 case OpCode.NEG: NEG(); break;
1828 case OpCode.SHL: SHL(); break;
1829 case OpCode.SHR: SHR(); break;
1830
1831 case OpCode.TEST: TEST(); break;
1832 case OpCode.CEQ: CEQ(); break;
1833 case OpCode.CNE: CNE(); break;
1834 case OpCode.CG: CG(); break;
1835 case OpCode.CGE: CGE(); break;
1836 case OpCode.CL: CL(); break;
1837 case OpCode.CLE: CLE(); break;
1838
1839 case OpCode.OR: OR(); break;
1840 case OpCode.AND: AND(); break;
1841 case OpCode.NOT: NOT(); break;
1842
1843 case OpCode.ORB: ORB(); break;
1844 case OpCode.ANDB: ANDB(); break;
1845 case OpCode.NOTB: NOTB(); break;
1846 case OpCode.XOR: XOR(); break;
1847
1848 case OpCode.JMP: JMP(); break;
1849 case OpCode.JZ: JZ(); break;
1850 case OpCode.JNZ: JNZ(); break;
1851
1852 case OpCode.DSB: DSB(); break;
1853 case OpCode.DB: DB(); break;
1854 case OpCode.DC: DC(); break;
1855 case OpCode.DCO: DCO(); break;
1856 case OpCode.PTR: PTR(); break;
1857
1858 case OpCode.CALL: CALL(); break;
1859 case OpCode.INV: INV(); break;
1860 case OpCode.MIV: MIV(); break;
1861 case OpCode.RUN: RUN(); break;
1862
1863 case OpCode.LOCK: LOCK(); break;
1864 case OpCode.FREE: FREE(); break;
1865
1866 }
1867
1868 }
@ MIV
Invoke a CLR instance method via reflection. Parameters are taken from the parameter stack.
Definition Opcode.cs:48

References AND(), ANDB(), Arithmetic(), CALL(), CEQ(), CG(), CGE(), CL(), CLE(), CNE(), DB(), DBG(), DC(), DCO(), DEC(), DSB(), executable, FREE(), functionStack, INC(), instruction, INT(), INV(), JMP(), JNZ(), JZ(), LOCK(), MIV(), MOV(), NEG(), NOP(), NOT(), NOTB(), OR(), ORB(), POP(), PTR(), PUSH(), RET(), RUN(), SHL(), SHR(), TEST(), and XOR().

Referenced by Interpret(), Interpret(), and Interpret().

◆ FREE()

void ScriptStack.Runtime.Interpreter.FREE ( )
private

Definition at line 1766 of file Interpreter.cs.

1767 {
1768
1769 object first = Evaluate(instruction.First);
1770
1771 if (first.GetType() == typeof(NullReference))
1772 throw new ExecutionException("Lock key must be a literal value.");
1773
1774 if (!script.Manager.Locks.ContainsKey(first))
1775 throw new ExecutionException("Lock '" + first + "' is already unlocked.");
1776
1777 locks.Remove(first);
1778
1779 script.Manager.Locks.Remove(first);
1780
1781 }

References Evaluate(), instruction, locks, and script.

Referenced by ExecuteInstruction().

◆ INC()

void ScriptStack.Runtime.Interpreter.INC ( )
private

Definition at line 993 of file Interpreter.cs.

994 {
995
996 string identifier = (string)instruction.First.Value;
997
998 object val = Evaluate(instruction.First);
999
1000 Type typeDest = val.GetType();
1001
1002 if (typeDest == typeof(char))
1003 {
1004 char c = (char)val;
1005 localMemory[identifier] = (char)(c + 1);
1006 }
1007 else if (typeDest == typeof(int))
1008 localMemory[identifier] = (int)val + 1;
1009
1010 else if (typeDest == typeof(float))
1011 localMemory[identifier] = (float)val + 1;
1012
1013 else if (typeDest == typeof(double))
1014 localMemory[identifier] = (double)val + 1;
1015
1016 else if (typeDest == typeof(decimal))
1017 localMemory[identifier] = (decimal)val + 1;
1018
1019 else
1020 throw new ExecutionException("Der Typ '" + typeDest.Name + "' kann nicht inkrementiert werden.");
1021
1022 }

References Evaluate(), instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ INT()

void ScriptStack.Runtime.Interpreter.INT ( )
private

Definition at line 893 of file Interpreter.cs.

894 {
895 interrupted = true;
896 }

References interrupted.

Referenced by ExecuteInstruction().

◆ Interpret() [1/3]

uint ScriptStack.Runtime.Interpreter.Interpret ( )

Definition at line 2039 of file Interpreter.cs.

2040 {
2041
2042 localMemory.ExposeTemporaryVariables();
2043
2044 interrupted = false;
2045
2046 uint executed = 0;
2047
2048 while (!Finished && !interrupted)
2049 {
2050
2051 ExecuteInstruction();
2052
2053 ++executed;
2054
2055 executed += ExecuteBackgroundJobs();
2056
2057 }
2058
2059 localMemory.HideTemporaryVariables();
2060
2061 return executed;
2062
2063 }

References ExecuteBackgroundJobs(), ExecuteInstruction(), Finished, interrupted, and localMemory.

◆ Interpret() [2/3]

uint ScriptStack.Runtime.Interpreter.Interpret ( TimeSpan interval)

Definition at line 2008 of file Interpreter.cs.

2009 {
2010
2011 DateTime end = DateTime.Now + interval;
2012
2013 localMemory.ExposeTemporaryVariables();
2014
2015 interrupted = false;
2016
2017 uint executed = 0;
2018
2019 while (!Finished && !interrupted)
2020 {
2021
2022 ExecuteInstruction();
2023
2024 ++executed;
2025
2026 executed += ExecuteBackgroundJobs();
2027
2028 if (DateTime.Now >= end)
2029 break;
2030
2031 }
2032
2033 localMemory.HideTemporaryVariables();
2034
2035 return executed;
2036
2037 }

References ExecuteBackgroundJobs(), ExecuteInstruction(), Finished, interrupted, and localMemory.

◆ Interpret() [3/3]

uint ScriptStack.Runtime.Interpreter.Interpret ( uint instructions)

Definition at line 1982 of file Interpreter.cs.

1983 {
1984
1985 localMemory.ExposeTemporaryVariables();
1986
1987 interrupted = false;
1988
1989 uint executed = 0;
1990
1991 while (!Finished && !interrupted && executed < instructions)
1992 {
1993
1994 ExecuteInstruction();
1995
1996 ++executed;
1997
1998 executed += ExecuteBackgroundJobs();
1999
2000 }
2001
2002 localMemory.HideTemporaryVariables();
2003
2004 return executed;
2005
2006 }

References ExecuteBackgroundJobs(), ExecuteInstruction(), Finished, interrupted, and localMemory.

Referenced by ExecuteBackgroundJobs().

◆ INV()

void ScriptStack.Runtime.Interpreter.INV ( )
private

Invoke a Routine, if no result is specified a null is pushed onto the stack.

The Verify() function will skip null and void parameters.

Todo
get rid of try-catch

Definition at line 1540 of file Interpreter.cs.

1541 {
1542
1543 Routine routine = instruction.First.RoutinePointer;
1544
1545 Host stackHandler = null;
1546
1547 if (routine.Handler == null)
1548 {
1549 if (host != null)
1550 stackHandler = host;
1551 }
1552
1553 else
1554 stackHandler = routine.Handler;
1555
1556 List<object> parameters = new List<object>();
1557
1558 for (int i = 0; i < routine.ParameterTypes.Count; i++)
1559 parameters.Insert(0, parameterStack.Pop());
1560
1561 routine.Verify(parameters);
1562
1563 object objectResult = null;
1564
1565 if (stackHandler != null)
1566 {
1567
1568 try {
1569 objectResult = stackHandler.Invoke(routine.Name, parameters);
1570 }
1571 catch (Exception) {
1572
1573 parameterStack.Push(NullReference.Instance);
1574 return;
1575
1576 }
1577
1578 routine.Verify(objectResult);
1579
1580 }
1581
1582 if (objectResult == null)
1583 objectResult = NullReference.Instance;
1584
1585 parameterStack.Push(objectResult);
1586
1587 if (interrupt)
1588 interrupted = true;
1589
1590 }
void Verify(List< object > parameters)
Verify the parameter types of a Routine. If null or void was specified values arent verified.
Definition Routine.cs:224
List< Type > ParameterTypes
Definition Routine.cs:313
object Invoke(string routine, List< object > parameters)
Called when a Routine is invoked.

References ScriptStack.Runtime.Routine.Handler, host, instruction, interrupt, interrupted, ScriptStack.Runtime.Host.Invoke(), ScriptStack.Runtime.Routine.Name, parameterStack, ScriptStack.Runtime.Routine.ParameterTypes, and ScriptStack.Runtime.Routine.Verify().

Referenced by ExecuteInstruction().

◆ Iterator() [1/4]

void ScriptStack.Runtime.Interpreter.Iterator ( ArrayList array)
private

Definition at line 771 of file Interpreter.cs.

772 {
773
774 if (array.Count == 0)
775 return;
776
777 object iterator = Evaluate(instruction.First);
778
779 bool key = false;
780
781 object next = null;
782
783 foreach (object tmp in array.Keys)
784 {
785
786 if (key)
787 {
788 next = tmp;
789 break;
790 }
791
792 if (Equals(tmp, iterator))
793 key = true;
794
795 }
796
797 if (!key)
798 {
799
800 Dictionary<object, object>.KeyCollection.Enumerator keys = array.Keys.GetEnumerator();
801
802 keys.MoveNext();
803
804 next = keys.Current;
805
806 }
807
808 if (next == null)
809 next = NullReference.Instance;
810
811 localMemory[instruction.First.Value.ToString()] = next;
812
813 }

References Evaluate(), instruction, and localMemory.

Referenced by PTR().

◆ Iterator() [2/4]

void ScriptStack.Runtime.Interpreter.Iterator ( IDictionary dict)
private

Definition at line 815 of file Interpreter.cs.

816 {
817
818 if (dict.Count == 0)
819 return;
820
821 object iterator = Evaluate(instruction.First);
822
823 bool found = false;
824
825 object next = null;
826
827 foreach (object tmp in dict.Keys)
828 {
829
830 if (found)
831 {
832 next = tmp;
833 break;
834 }
835
836 if (Equals(tmp, iterator))
837 found = true;
838
839 }
840
841 if (!found)
842 {
843 IDictionaryEnumerator en = dict.GetEnumerator();
844 if (en.MoveNext())
845 next = en.Key;
846 }
847
848 if (next == null)
849 next = NullReference.Instance;
850
851 localMemory[instruction.First.Value.ToString()] = next;
852
853 }

References Evaluate(), instruction, and localMemory.

◆ Iterator() [3/4]

void ScriptStack.Runtime.Interpreter.Iterator ( IList list)
private

Definition at line 2134 of file Interpreter.cs.

2135 {
2136 if (list.Count == 0)
2137 return;
2138
2139 object iterator = Evaluate(instruction.First);
2140
2141 if (iterator.GetType() != typeof(int))
2142 {
2143 localMemory[instruction.First.Value.ToString()] = 0;
2144 return;
2145 }
2146
2147 int i = (int)iterator;
2148
2149 if (i < list.Count - 1)
2150 localMemory[instruction.First.Value.ToString()] = i + 1;
2151 else
2152 localMemory[instruction.First.Value.ToString()] = NullReference.Instance;
2153 }

References Evaluate(), instruction, and localMemory.

◆ Iterator() [4/4]

void ScriptStack.Runtime.Interpreter.Iterator ( string str)
private

Definition at line 856 of file Interpreter.cs.

857 {
858
859 if (str.Length == 0)
860 return;
861
862 object iterator = Evaluate(instruction.First);
863
864 if (iterator.GetType() != typeof(int))
865 {
866
867 localMemory[instruction.First.Value.ToString()] = 0;
868
869 return;
870
871 }
872
873 int elements = (int)iterator;
874
875 if (elements < str.Length - 1)
876 localMemory[instruction.First.Value.ToString()] = elements + 1;
877
878 else
879 localMemory[instruction.First.Value.ToString()] = NullReference.Instance;
880
881 }

References Evaluate(), instruction, and localMemory.

◆ JMP()

void ScriptStack.Runtime.Interpreter.JMP ( )
private

Jump to the address the first operator points at.

Definition at line 1356 of file Interpreter.cs.

1357 {
1358
1359 FunctionFrame frame = functionStack.Peek();
1360
1361 frame.nextInstruction = (int)instruction.First.InstructionPointer.Address;
1362
1363 }

References functionStack, and instruction.

Referenced by ExecuteInstruction().

◆ JNZ()

void ScriptStack.Runtime.Interpreter.JNZ ( )
private

Jump to the instruction the second operand is pointing at if the first operand is false.

Definition at line 1385 of file Interpreter.cs.

1386 {
1387
1388 if (!(bool)Evaluate(instruction.First))
1389 return;
1390
1391 FunctionFrame frame = functionStack.Peek();
1392
1393 frame.nextInstruction = (int)instruction.Second.InstructionPointer.Address;
1394
1395 }

References Evaluate(), functionStack, and instruction.

Referenced by ExecuteInstruction().

◆ JZ()

void ScriptStack.Runtime.Interpreter.JZ ( )
private

Jump to the instruction the second operand is pointing at if the first operand is true.

Definition at line 1368 of file Interpreter.cs.

1369 {
1370
1371 if ((bool)Evaluate(instruction.First))
1372 return;
1373
1374 Instruction target = instruction.Second.InstructionPointer;
1375
1376 FunctionFrame frame = functionStack.Peek();
1377
1378 frame.nextInstruction = (int)target.Address;
1379
1380 }

References ScriptStack.Runtime.Instruction.Address, Evaluate(), functionStack, and instruction.

Referenced by ExecuteInstruction().

◆ LOCK()

void ScriptStack.Runtime.Interpreter.LOCK ( )
private

Definition at line 1733 of file Interpreter.cs.

1734 {
1735
1736 object first = Evaluate(instruction.First);
1737
1738 if (first.GetType() == typeof(NullReference))
1739 throw new ExecutionException("Lock key must be a literal value.");
1740
1741 if (script.Manager.Locks.ContainsKey(first))
1742 {
1743
1744 Interpreter locked = script.Manager.Locks[first];
1745
1746 if (locked == this && locks[first] != instruction)
1747 throw new ExecutionException("Nested locks cannot share the same locking key.");
1748
1749 FunctionFrame functionFrame = functionStack.Peek();
1750 --functionFrame.nextInstruction;
1751 interrupted = true;
1752
1753 }
1754
1755 else
1756 {
1757
1758 script.Manager.Locks[first] = this;
1759
1760 locks[first] = instruction;
1761
1762 }
1763
1764 }

References Evaluate(), functionStack, instruction, Interpreter(), interrupted, locks, ScriptStack.Runtime.Interpreter.FunctionFrame.nextInstruction, and script.

Referenced by ExecuteInstruction().

◆ Logic()

void ScriptStack.Runtime.Interpreter.Logic ( )
private

Usually its a boolean operation but it allows numerics too.

Todo
what about numerics in relations?

Definition at line 713 of file Interpreter.cs.

714 {
715
716 string identifier = (string)instruction.First.Value;
717
718 object dst = Evaluate(instruction.First);
719
720 object src = Evaluate(instruction.Second);
721
722 Type typeDest = dst.GetType();
723
724 Type typeSource = src.GetType();
725
726 bool result = false;
727
728 bool dstVal = false;
729
730 bool srcVal = false;
731
732 if (typeSource == typeof(bool))
733 srcVal = (bool)src;
734
735 else if (typeSource == typeof(NullReference))
736 srcVal = false;
737
738 else
739 srcVal = ((double)src != 0.0) ? true : false;
740
741
742 if (typeDest == typeof(bool))
743 dstVal = (bool)dst;
744
745 else if (typeDest == typeof(NullReference))
746 dstVal = false;
747
748 else
749 dstVal = ((double)dst != 0.0) ? true : false;
750
751 switch (instruction.OpCode)
752 {
753
754 case OpCode.AND:
755 result = dstVal && srcVal;
756 break;
757
758 case OpCode.OR:
759 result = dstVal || srcVal;
760 break;
761
762 default:
763 throw new ExecutionException("Der OpCode '" + instruction.OpCode + "' kann in einer logischen Operation nicht verarbeitet werden.");
764
765 }
766
767 Assignment(instruction.First, result);
768
769 }

References Assignment(), Evaluate(), and instruction.

Referenced by AND(), and OR().

◆ MIV()

void ScriptStack.Runtime.Interpreter.MIV ( )
private

Invoke a CLR instance method via reflection.

The compiler lowers

obj.Method(a, b)

into: PUSH a; PUSH b; MIV obj.Method, <argc>; POP result

Definition at line 1598 of file Interpreter.cs.

1599 {
1600
1601 if (instruction.First.Type != OperandType.Member)
1602 throw new ExecutionException("Error in MIV.");
1603
1604 string targetIdentifier = instruction.First.Value.ToString();
1605 string methodName = instruction.First.Member?.ToString() ?? "";
1606
1607 int argc = 0;
1608 if (instruction.Second != null)
1609 {
1610 object raw = instruction.Second.Value;
1611 if (raw is int i) argc = i;
1612 else if (raw is string s && int.TryParse(s, out var j)) argc = j;
1613 else throw new ExecutionException("Error in MIV.");
1614 }
1615
1616 object target = localMemory[targetIdentifier];
1617 if (target == null || target is NullReference)
1618 {
1619 parameterStack.Push(NullReference.Instance);
1620 return;
1621 }
1622
1623 // Collect args (preserve order)
1624 List<object> args = new List<object>(argc);
1625 for (int i = 0; i < argc; i++)
1626 args.Insert(0, parameterStack.Pop());
1627
1628 object result = _clr.Invoke(target, methodName, args);
1629 if (result == null)
1630 result = NullReference.Instance;
1631
1632 parameterStack.Push(result);
1633
1634 if (interrupt)
1635 interrupted = true;
1636
1637 }

References _clr, instruction, interrupt, interrupted, localMemory, and parameterStack.

Referenced by ExecuteInstruction().

◆ MOD()

void ScriptStack.Runtime.Interpreter.MOD ( )
private

Definition at line 983 of file Interpreter.cs.

984 {
985 Arithmetic();
986 }

References Arithmetic().

◆ MOV()

void ScriptStack.Runtime.Interpreter.MOV ( )
private

Basic assignment.

Definition at line 941 of file Interpreter.cs.

942 {
943
944 Assignment(instruction.First, Evaluate(instruction.Second));
945 }

References Assignment(), Evaluate(), and instruction.

Referenced by ExecuteInstruction().

◆ MUL()

void ScriptStack.Runtime.Interpreter.MUL ( )
private

Definition at line 967 of file Interpreter.cs.

968 {
969 Arithmetic();
970 }

References Arithmetic().

◆ NEG()

void ScriptStack.Runtime.Interpreter.NEG ( )
private

Negate a literal (* -1).

Definition at line 1061 of file Interpreter.cs.

1062 {
1063
1064 string identifier = (string)instruction.First.Value;
1065
1066 object val = Evaluate(instruction.First);
1067
1068 Type typeDest = val.GetType();
1069
1070 if (typeDest == typeof(int))
1071 localMemory[identifier] = (int)val * -1;
1072
1073 else if (typeDest == typeof(float))
1074 localMemory[identifier] = (float)val * -1;
1075
1076 else if (typeDest == typeof(double))
1077 localMemory[identifier] = (double)val * -1;
1078
1079 else if (typeDest == typeof(char))
1080 localMemory[identifier] = (char)val * -1;
1081
1082 else
1083 throw new ExecutionException("Der Typ '" + typeDest.Name + "' kann nicht negiert werden.");
1084
1085 }

References Evaluate(), instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ NOP()

void ScriptStack.Runtime.Interpreter.NOP ( )
private

Definition at line 889 of file Interpreter.cs.

890 {
891 }

Referenced by ExecuteInstruction().

◆ NOT()

void ScriptStack.Runtime.Interpreter.NOT ( )
private

Negate a boolean or int.

Todo
int?

Definition at line 1227 of file Interpreter.cs.

1228 {
1229
1230 string identifier = (string)instruction.First.Value;
1231
1232 object val = Evaluate(instruction.First);
1233
1234 Type typeDest = val.GetType();
1235
1236 if (typeDest != typeof(bool) && typeDest != typeof(int))
1237 throw new ExecutionException("Der Typ '" + typeDest.Name + "' kann nicht negiert werden.");
1238
1239 if (typeDest == typeof(bool))
1240 localMemory[identifier] = !((bool)val);
1241
1242 else if (typeDest == typeof(int))
1243 localMemory[identifier] = (int)val * -1;
1244
1245 }

References Evaluate(), instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ NOTB()

void ScriptStack.Runtime.Interpreter.NOTB ( )
private

Definition at line 1307 of file Interpreter.cs.

1308 {
1309
1310 if (instruction.First.Type != OperandType.Variable)
1311 throw new ExecutionException("Operand type '" + instruction.First.Type + "' not supported by NOTB instruction.");
1312
1313 string dest = (string)instruction.First.Value;
1314
1315 object srcObj = Evaluate(instruction.Second);
1316
1317 // (aktuell unterstützt dein Interpreter bei BitOps sowieso int)
1318 int src = (int)srcObj;
1319
1320 localMemory[dest] = ~src;
1321
1322 }

References Evaluate(), instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ OR()

void ScriptStack.Runtime.Interpreter.OR ( )
private

Definition at line 1212 of file Interpreter.cs.

1213 {
1214 Logic();
1215 }

References Logic().

Referenced by ExecuteInstruction().

◆ ORB()

void ScriptStack.Runtime.Interpreter.ORB ( )
private

Definition at line 1249 of file Interpreter.cs.

1250 {
1251
1252 string identifier = null;
1253
1254 object val = Evaluate(instruction.Second);
1255
1256 Operand operand = instruction.First;
1257
1258 switch (operand.Type)
1259 {
1260
1261 case OperandType.Variable:
1262 //int res = (int)val | (int)localMemory[(string)operand.Value];
1263 int res = ToInt32Bitwise(localMemory[(string)operand.Value], "|") | ToInt32Bitwise(val, "|");
1264
1265 identifier = operand.Value.ToString();
1266
1267 localMemory[identifier] = res;
1268
1269 break;
1270
1271 default:
1272 throw new ExecutionException("Der Typ '" + operand.Type + "' kann an dieser Stelle nicht verarbeitet werden.");
1273
1274 }
1275
1276 }

References Evaluate(), instruction, localMemory, ToInt32Bitwise(), ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ExecuteInstruction().

◆ POP()

void ScriptStack.Runtime.Interpreter.POP ( )
private

Pop a value from the stack into an atom.

Definition at line 926 of file Interpreter.cs.

927 {
928
929 object tmp = parameterStack.Pop();
930
931 Operand operand = instruction.First;
932
933 // Delegate to the unified Assignment() so Member/Pointer also work for CLR objects.
934 Assignment(operand, tmp);
935
936 }

References Assignment(), instruction, and parameterStack.

Referenced by ExecuteInstruction().

◆ PTR()

void ScriptStack.Runtime.Interpreter.PTR ( )
private

A pointer in foreach loops.

Todo
error messages

Definition at line 1457 of file Interpreter.cs.

1458 {
1459
1460 if (instruction.First.Type != OperandType.Variable)
1461 throw new ExecutionException("Error in PTR.");
1462
1463 if (instruction.Second.Type != OperandType.Variable)
1464 throw new ExecutionException("Error in PTR.");
1465
1466 string enumerableVar = instruction.Second.Value.ToString();
1467 object enumerable = localMemory[enumerableVar];
1468
1469 if (enumerable is ArrayList a)
1470 {
1471 Iterator(a);
1472 return;
1473 }
1474
1475 if (enumerable is string s)
1476 {
1477 Iterator(s);
1478 return;
1479 }
1480
1481 if (enumerable is IList list)
1482 {
1483 Iterator(list);
1484 return;
1485 }
1486
1487
1488 if (enumerable is IDictionary dict)
1489 {
1490 Iterator(dict);
1491 return;
1492 }
1493
1494 // Any other IEnumerable (e.g. HashSet, IEnumerable<T>, LINQ results)
1495 if (enumerable is IEnumerable en)
1496 {
1497 var materialized = new ArrayList();
1498 foreach (var item in en)
1499 materialized.Add(item ?? NullReference.Instance);
1500
1501 // Replace variable with materialized ArrayList so the existing foreach bytecode
1502 // (which indexes via array[key]) keeps working.
1503 localMemory[enumerableVar] = materialized;
1504 Iterator(materialized);
1505 return;
1506 }
1507
1508 throw new ExecutionException("Error in PTR.");
1509
1510 }

References instruction, Iterator(), and localMemory.

Referenced by ExecuteInstruction().

◆ PUSH()

void ScriptStack.Runtime.Interpreter.PUSH ( )
private

Definition at line 918 of file Interpreter.cs.

919 {
920 parameterStack.Push(Evaluate(instruction.First));
921 }

References Evaluate(), instruction, and parameterStack.

Referenced by ExecuteInstruction().

◆ Relation()

void ScriptStack.Runtime.Interpreter.Relation ( )
private

Ausführung einer Vergleichsoperation.

If one of both is of type 'null' only certain operations are allowed.

If one of both is a string, both are converted to string and alphabetically evaluated.

Numbers are converted to type 'double'.

Todo
separation of double and float, result is always double (if not int or string)

Only equations may reference null

Todo
check null

If one of both is a string both are converted to string and alphabetically compared

Todo
check string

Definition at line 480 of file Interpreter.cs.

481 {
482
483 string identifier = (string)instruction.First.Value;
484
485 object dst = Evaluate(instruction.First);
486
487 object src = Evaluate(instruction.Second);
488
489 Type typeDest = dst.GetType();
490
491 Type typeSource = src.GetType();
492
493 bool result = false;
494
499 if (typeDest == typeof(NullReference) || typeSource == typeof(NullReference))
500 {
501
502 switch (instruction.OpCode)
503 {
504
505 case OpCode.CEQ:
506 result = dst == src;
507 break;
508
509 case OpCode.CNE:
510 result = dst != src;
511 break;
512
513 default:
514 string message = "";
515
516 if (typeDest == typeof(NullReference) && typeSource == typeof(NullReference))
517 message = "Die Operation '" + instruction.OpCode + "' kann nicht auf den Typ 'null' angewendet werden.";
518
519 else if (typeDest == typeof(NullReference))
520 message = "Die Operation '" + instruction.OpCode + "' kann nicht auf den Typ 'null' als Ziel (links des Operators) angewendet werden.";
521
522 else
523 message = "Die Operation '" + instruction.OpCode + "' kann nicht auf den Typ 'null' als Quelle (rechts des Operators) angewendet werden.";
524
525 throw new ExecutionException(message);
526
527
528 }
529
530 // As a last resort, just assign it
531 Assignment(instruction.First, result);
532
533 return;
534
535 }
536
541 if (typeDest == typeof(string) || typeSource == typeof(string))
542 {
543
544 string strDst = "" + dst;
545
546 string strSrc = "" + src;
547
548 switch (instruction.OpCode)
549 {
550
551 case OpCode.CEQ:
552 result = strDst == strSrc;
553 break;
554
555 case OpCode.CNE:
556 result = strDst != strSrc;
557 break;
558
559 case OpCode.CG:
560 result = strDst.CompareTo(strSrc) > 0;
561 break;
562
563 case OpCode.CGE:
564 result = strDst.CompareTo(strSrc) >= 0;
565 break;
566
567 case OpCode.CL:
568 result = strDst.CompareTo(strSrc) < 0;
569 break;
570
571 case OpCode.CLE:
572 result = strDst.CompareTo(strSrc) <= 0;
573 break;
574
575 default:
576 throw new ExecutionException("Die Operation '" + instruction.OpCode + "' kann nicht auf den Typ 'String' angewendet werden.");
577
578 }
579
580 Assignment(instruction.First, result);
581
582 return;
583
584 }
585
586 // NEW: CLR/object support while preserving ScriptStack numeric semantics
587 bool numericDest =
588 typeDest == typeof(int) ||
589 typeDest == typeof(float) ||
590 typeDest == typeof(double) ||
591 typeDest == typeof(char);
592
593 bool numericSource =
594 typeSource == typeof(int) ||
595 typeSource == typeof(float) ||
596 typeSource == typeof(double) ||
597 typeSource == typeof(char);
598
599 // Equality/inequality for arbitrary CLR objects (and ScriptStack objects),
600 // BUT keep the old numeric cross-type behaviour (int == float etc.)
601 if ((instruction.OpCode == OpCode.CEQ || instruction.OpCode == OpCode.CNE) && !(numericDest && numericSource))
602 {
603 bool eq = Equals(ClrBridge.ScriptNullToClr(dst), ClrBridge.ScriptNullToClr(src));
604 result = (instruction.OpCode == OpCode.CEQ) ? eq : !eq;
605 Assignment(instruction.First, result);
606 return;
607 }
608
609 // Ordering comparisons for arbitrary CLR objects via IComparable,
610 // again only when we are NOT in the numeric fast-path.
611 if (!(numericDest && numericSource) &&
612 (instruction.OpCode == OpCode.CG || instruction.OpCode == OpCode.CGE || instruction.OpCode == OpCode.CL || instruction.OpCode == OpCode.CLE) &&
613 dst is IComparable cmpDst)
614 {
615 int cmp;
616 try
617 {
618 cmp = cmpDst.CompareTo(ClrBridge.ScriptNullToClr(src));
619 }
620 catch
621 {
622 // last resort: string compare
623 cmp = string.Compare(dst.ToString(), src.ToString(), StringComparison.Ordinal);
624 }
625
626 switch (instruction.OpCode)
627 {
628 case OpCode.CG: result = cmp > 0; break;
629 case OpCode.CGE: result = cmp >= 0; break;
630 case OpCode.CL: result = cmp < 0; break;
631 case OpCode.CLE: result = cmp <= 0; break;
632 }
633
634 Assignment(instruction.First, result);
635 return;
636 }
637
638 double dstVal = 0.0;
639
640 double srcVal = 0.0;
641
642 if (typeDest == typeof(int))
643 dstVal = double.Parse("" + (int)dst);
644
645 else if (typeDest == typeof(float))
646 dstVal = double.Parse("" + (float)dst);
647
648 else if (typeDest == typeof(char))
649 dstVal = double.Parse("" + (char)dst);
650
651 else if (typeDest == typeof(double))
652 dstVal = (double)dst;
653
654 else
655 throw new ExecutionException("Der Typ '" + typeDest.Name + "' kann in relationalen Operationen als Ziel (links des Operators) nicht verarbeitet werden.");
656
657 if (typeSource == typeof(int))
658 srcVal = double.Parse("" + (int)src);
659
660 else if (typeSource == typeof(float))
661 srcVal = double.Parse("" + (float)src);
662
663 else if (typeSource == typeof(char))
664 srcVal = double.Parse("" + (char)src);
665
666 else if (typeSource == typeof(double))
667 srcVal = (double)src;
668
669 else
670 throw new ExecutionException("Der Typ '" + typeSource.Name + "' kann in relationalen Operationen als Quelle (rechts des Operators) nicht verarbeitet werden.");
671
672 switch (instruction.OpCode)
673 {
674
675 case OpCode.CEQ:
676 result = dstVal == srcVal;
677 break;
678
679 case OpCode.CNE:
680 result = dstVal != srcVal;
681 break;
682
683 case OpCode.CG:
684 result = dstVal > srcVal;
685 break;
686
687 case OpCode.CGE:
688 result = dstVal >= srcVal;
689 break;
690
691 case OpCode.CL:
692 result = dstVal < srcVal;
693 break;
694
695 case OpCode.CLE:
696 result = dstVal <= srcVal;
697 break;
698
699 default:
700 throw new ExecutionException("Der OpCode '" + instruction.OpCode + "' kann in einer relationalen Operation nicht verarbeitet werden.");
701
702 }
703
704 Assignment(instruction.First, result);
705
706 }

References Assignment(), Evaluate(), and instruction.

Referenced by CEQ(), CG(), CGE(), CL(), CLE(), and CNE().

◆ Reset()

void ScriptStack.Runtime.Interpreter.Reset ( )

Definition at line 1950 of file Interpreter.cs.

1951 {
1952
1953 functionStack.Clear();
1954
1955 FunctionFrame functionFrame = new FunctionFrame();
1956
1957 functionFrame.function = function;
1958
1959 functionFrame.localMemory = Memory.AllocateLocalMemory(executable.ScriptMemory);
1960
1961 functionFrame.nextInstruction = (int) function.EntryPoint.Address;
1962
1963 functionStack.Push(functionFrame);
1964
1965 parameterStack.Clear();
1966
1967 instruction = null;
1968
1969 localMemory = functionFrame.localMemory;
1970
1971 foreach (object currentLock in locks.Keys)
1972 script.Manager.Locks.Remove(currentLock);
1973
1974 locks.Clear();
1975
1976 finished = false;
1977
1978 interrupted = false;
1979
1980 }

References ScriptStack.Runtime.Memory.AllocateLocalMemory(), executable, finished, functionStack, instruction, interrupted, ScriptStack.Runtime.Interpreter.FunctionFrame.localMemory, localMemory, locks, parameterStack, and script.

Referenced by Interpreter().

◆ RET()

void ScriptStack.Runtime.Interpreter.RET ( )
private

Return from current function frame to the last one on the stack, copying local memory to the new one.

Definition at line 901 of file Interpreter.cs.

902 {
903
904 functionStack.Pop();
905
906 if (functionStack.Count == 0)
907 {
908 finished = true;
909 return;
910 }
911
912 localMemory = functionStack.Peek().localMemory;
913
914 }

References finished, functionStack, and localMemory.

Referenced by ExecuteInstruction().

◆ RUN()

void ScriptStack.Runtime.Interpreter.RUN ( )
private

Run a Function in Background.

An example

var LOCK;
var queue;
function enqueue()
{
var value = 0;
while (true)
{
lock LOCK
{
queue += value;
print("Queued: " + value + "\n");
++value;
}
}
}
function dequeue()
{
while (true)
{
lock LOCK
{
var index, value;
foreach (index, value in queue)
{
queue -= value;
print("Dequeued: " + value + "\n");
break;
}
}
}
}
function main()
{
LOCK = "queue_lock";
queue = { };
run enqueue();
run dequeue();
while (true)
yield;
}

Definition at line 1715 of file Interpreter.cs.

1716 {
1717
1718 Function function = instruction.First.FunctionPointer;
1719
1720 List<object> parameters = new List<object>();
1721
1722 for (int i = 0; i < function.ParameterCount; i++)
1723 parameters.Insert(0, parameterStack.Pop());
1724
1725 Interpreter job = new Interpreter(function, parameters, _options);
1726
1727 job.Handler = host;
1728
1729 jobs.Add(job);
1730
1731 }

References _options, host, instruction, Interpreter(), jobs, and parameterStack.

Referenced by ExecuteInstruction().

◆ SHL()

void ScriptStack.Runtime.Interpreter.SHL ( )
private

Definition at line 1090 of file Interpreter.cs.

1091 {
1092
1093 string identifier = null;
1094
1095 object val = Evaluate(instruction.Second);
1096
1097 Operand operand = instruction.First;
1098
1099 switch (operand.Type)
1100 {
1101
1102 case OperandType.Variable:
1103 int res = (int)localMemory[(string)operand.Value] << (int)val;
1104
1105 identifier = operand.Value.ToString();
1106
1107 localMemory[identifier] = res;
1108
1109 break;
1110
1111 default:
1112 throw new ExecutionException("Der Typ '" + operand.Type + "' kann in Bitoperationen nicht verarbeitet werden.");
1113
1114 }
1115
1116 }

References Evaluate(), instruction, localMemory, ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ExecuteInstruction().

◆ SHR()

void ScriptStack.Runtime.Interpreter.SHR ( )
private

Definition at line 1121 of file Interpreter.cs.

1122 {
1123
1124 string identifier = null;
1125
1126 object val = Evaluate(instruction.Second);
1127
1128 Operand operand = instruction.First;
1129
1130 switch (operand.Type)
1131 {
1132
1133 case OperandType.Variable:
1134 int res = (int)localMemory[(string)operand.Value] >> (int)val;
1135
1136 identifier = operand.Value.ToString();
1137
1138 localMemory[identifier] = res;
1139
1140 break;
1141
1142 default:
1143 throw new ExecutionException("Der Typ '" + operand.Type + "' kann in Bitoperationen nicht verarbeitet werden.");
1144
1145 }
1146
1147 }

References Evaluate(), instruction, localMemory, ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ExecuteInstruction().

◆ SUB()

void ScriptStack.Runtime.Interpreter.SUB ( )
private

Definition at line 959 of file Interpreter.cs.

960 {
961 Arithmetic();
962 }

References Arithmetic().

◆ TEST()

void ScriptStack.Runtime.Interpreter.TEST ( )
private

Definition at line 1151 of file Interpreter.cs.

1152 {
1153
1154 string identifier = (string)instruction.First.Value;
1155
1156 object val = Evaluate(instruction.First);
1157
1158 localMemory[identifier] = val == NullReference.Instance;
1159
1160 }

References Evaluate(), instruction, and localMemory.

Referenced by ExecuteInstruction().

◆ ToInt32Bitwise()

int ScriptStack.Runtime.Interpreter.ToInt32Bitwise ( object value,
string opName = "bitwise" )
private

Definition at line 59 of file Interpreter.cs.

60 {
61 if (value == null) throw new ExecutionException($"Cannot apply {opName} operation to null.");
62 if (value is NullReference) throw new ExecutionException($"Cannot apply {opName} operation to 'null'.");
63
64 Type t = value.GetType();
65
66 try
67 {
68 switch (Type.GetTypeCode(t))
69 {
70 case TypeCode.Int32: return (int)value;
71 case TypeCode.Boolean: return ((bool)value) ? 1 : 0;
72 case TypeCode.Char: return (char)value;
73 case TypeCode.SByte: return (sbyte)value;
74 case TypeCode.Byte: return (byte)value;
75 case TypeCode.Int16: return (short)value;
76 case TypeCode.UInt16: return (ushort)value;
77 case TypeCode.UInt32: { uint u = (uint)value; if (u > int.MaxValue) throw new OverflowException(); return (int)u; }
78 case TypeCode.Int64: { long l = (long)value; if (l < int.MinValue || l > int.MaxValue) throw new OverflowException(); return (int)l; }
79 case TypeCode.UInt64: { ulong ul = (ulong)value; if (ul > (ulong)int.MaxValue) throw new OverflowException(); return (int)ul; }
80 case TypeCode.Single: { float f = (float)value; if (float.IsNaN(f) || float.IsInfinity(f) || f < int.MinValue || f > int.MaxValue) throw new OverflowException(); return (int)f; }
81 case TypeCode.Double: { double d = (double)value; if (double.IsNaN(d) || double.IsInfinity(d) || d < int.MinValue || d > int.MaxValue) throw new OverflowException(); return (int)d; }
82 case TypeCode.Decimal: return decimal.ToInt32((decimal)value);
83 default: throw new InvalidCastException();
84 }
85 }
86 catch
87 {
88 throw new ExecutionException($"Values of type '{t.Name}' cannot be used in {opName} operations.");
89 }
90 }

Referenced by ANDB(), ORB(), and XOR().

◆ XOR()

void ScriptStack.Runtime.Interpreter.XOR ( )
private

Definition at line 1324 of file Interpreter.cs.

1325 {
1326
1327 string identifier = null;
1328
1329 object val = Evaluate(instruction.Second);
1330
1331 Operand operand = instruction.First;
1332
1333 switch (operand.Type)
1334 {
1335
1336 case OperandType.Variable:
1337 //int res = (int)val ^ (int)localMemory[(string)operand.Value];
1338 int res = ToInt32Bitwise(localMemory[(string)operand.Value], "^") ^ ToInt32Bitwise(val, "^");
1339
1340 identifier = operand.Value.ToString();
1341
1342 localMemory[identifier] = res;
1343
1344 break;
1345
1346 default:
1347 throw new ExecutionException("Der Typ '" + operand.Type + "' kann an dieser Stelle nicht verarbeitet werden.");
1348
1349 }
1350
1351 }

References Evaluate(), instruction, localMemory, ToInt32Bitwise(), ScriptStack.Runtime.Operand.Type, and ScriptStack.Runtime.Operand.Value.

Referenced by ExecuteInstruction().

Member Data Documentation

◆ _clr

ClrBridge ScriptStack.Runtime.Interpreter._clr
private

Definition at line 49 of file Interpreter.cs.

Referenced by Assignment(), Evaluate(), Interpreter(), and MIV().

◆ _options

InterpreterOptions ScriptStack.Runtime.Interpreter._options
private

Definition at line 50 of file Interpreter.cs.

Referenced by Interpreter(), and RUN().

◆ executable

Executable ScriptStack.Runtime.Interpreter.executable
private

Definition at line 39 of file Interpreter.cs.

Referenced by CALL(), ExecuteInstruction(), Interpreter(), and Reset().

◆ finished

bool ScriptStack.Runtime.Interpreter.finished
private

Definition at line 48 of file Interpreter.cs.

Referenced by Reset(), and RET().

◆ function

Function ScriptStack.Runtime.Interpreter.function
private

Definition at line 37 of file Interpreter.cs.

Referenced by Interpreter().

◆ functionStack

Stack<FunctionFrame> ScriptStack.Runtime.Interpreter.functionStack
private

Definition at line 40 of file Interpreter.cs.

Referenced by CALL(), ExecuteInstruction(), Interpreter(), JMP(), JNZ(), JZ(), LOCK(), Reset(), and RET().

◆ host

Host ScriptStack.Runtime.Interpreter.host
private

Definition at line 57 of file Interpreter.cs.

Referenced by Interpreter(), INV(), and RUN().

◆ instruction

◆ interrupt

bool ScriptStack.Runtime.Interpreter.interrupt
private

Definition at line 46 of file Interpreter.cs.

Referenced by Interpreter(), INV(), and MIV().

◆ interrupted

bool ScriptStack.Runtime.Interpreter.interrupted
private

Definition at line 47 of file Interpreter.cs.

Referenced by INT(), Interpret(), Interpret(), Interpret(), INV(), LOCK(), MIV(), and Reset().

◆ jobs

List<Interpreter> ScriptStack.Runtime.Interpreter.jobs
private

Definition at line 43 of file Interpreter.cs.

Referenced by ExecuteBackgroundJobs(), Interpreter(), and RUN().

◆ localMemory

Memory ScriptStack.Runtime.Interpreter.localMemory
private

◆ locks

Dictionary<object, Instruction> ScriptStack.Runtime.Interpreter.locks
private

Definition at line 42 of file Interpreter.cs.

Referenced by FREE(), Interpreter(), LOCK(), and Reset().

◆ parameterStack

Stack<object> ScriptStack.Runtime.Interpreter.parameterStack
private

Definition at line 41 of file Interpreter.cs.

Referenced by Interpreter(), INV(), MIV(), POP(), PUSH(), Reset(), and RUN().

◆ script

Script ScriptStack.Runtime.Interpreter.script
private

Definition at line 38 of file Interpreter.cs.

Referenced by FREE(), Interpreter(), Interpreter(), Interpreter(), LOCK(), and Reset().

Property Documentation

◆ Finished

bool ScriptStack.Runtime.Interpreter.Finished
get

Definition at line 2090 of file Interpreter.cs.

2091 {
2092 get { return finished; }
2093 }

Referenced by ExecuteBackgroundJobs(), Interpret(), Interpret(), and Interpret().

◆ FunctionStack

ReadOnlyCollection<Function> ScriptStack.Runtime.Interpreter.FunctionStack
get

Definition at line 2104 of file Interpreter.cs.

2105 {
2106 get
2107 {
2108 List<Function> listFunctions = new List<Function>();
2109 foreach (FunctionFrame functionFrame in functionStack)
2110 listFunctions.Add(functionFrame.function);
2111 return new List<Function>(listFunctions).AsReadOnly();
2112 }
2113 }

◆ Handler

Host ScriptStack.Runtime.Interpreter.Handler
getset

Definition at line 2125 of file Interpreter.cs.

2126 {
2127 get { return host; }
2128 set { host = value; }
2129 }

◆ Interrupt

bool ScriptStack.Runtime.Interpreter.Interrupt
getset

Definition at line 2074 of file Interpreter.cs.

2075 {
2076 get { return interrupt; }
2077 set { interrupt = value; }
2078 }

◆ Interrupted

bool ScriptStack.Runtime.Interpreter.Interrupted
get

Definition at line 2085 of file Interpreter.cs.

2086 {
2087 get { return interrupted; }
2088 }

◆ Jobs

ReadOnlyCollection<Interpreter> ScriptStack.Runtime.Interpreter.Jobs
get

Definition at line 2080 of file Interpreter.cs.

2081 {
2082 get { return jobs.AsReadOnly(); }
2083 }

◆ LocalMemory

Memory ScriptStack.Runtime.Interpreter.LocalMemory
get

Definition at line 2120 of file Interpreter.cs.

2121 {
2122 get { return localMemory; }
2123 }

◆ NextInstruction

int ScriptStack.Runtime.Interpreter.NextInstruction
get

Definition at line 2095 of file Interpreter.cs.

2096 {
2097 get
2098 {
2099 if (functionStack.Count == 0) return -1;
2100 return functionStack.Peek().nextInstruction;
2101 }
2102 }

◆ ParameterStack

ReadOnlyCollection<object> ScriptStack.Runtime.Interpreter.ParameterStack
get

Definition at line 2115 of file Interpreter.cs.

2116 {
2117 get { return new List<object>(parameterStack).AsReadOnly(); }
2118 }

◆ Script

Script ScriptStack.Runtime.Interpreter.Script
get

Definition at line 2069 of file Interpreter.cs.

2070 {
2071 get { return script; }
2072 }

Referenced by Interpreter(), and Interpreter().


The documentation for this class was generated from the following file: