munificent / magpie
The Magpie programming language.
Clone this repository (size: 954.7 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/munificent/magpie/
| commit 36: | 46d09f708b11 |
| parent 35: | d78a20a8a165 |
| branch: | default |
Random intrinsic.
| # Introduced |
|---|
1 |
e3e027f39344 |
using System; |
2 |
e3e027f39344 |
using System.Collections.Generic; |
3 |
e3e027f39344 |
using System.IO; |
4 |
e3e027f39344 |
using System.Linq; |
5 |
e3e027f39344 |
using System.Text; |
6 |
e3e027f39344 |
|
7 |
e3e027f39344 |
namespace Magpie.Interpreter |
8 |
e3e027f39344 |
{
|
9 |
e3e027f39344 |
public class Machine |
10 |
e3e027f39344 |
{
|
11 |
e3e027f39344 |
public event EventHandler<PrintEventArgs> Printed; |
12 |
e3e027f39344 |
|
13 |
7ed6a1b915b7 |
/// <summary> |
14 |
d78a20a8a165 |
/// Gets and sets the maximum stack depth. If set to a non-zero value, the interpreter |
15 |
d78a20a8a165 |
/// will track it during calls and immediately stop if the max is exceeded. |
16 |
7ed6a1b915b7 |
/// </summary> |
17 |
d78a20a8a165 |
public int MaxStackDepth { get; set; }
|
18 |
7ed6a1b915b7 |
|
19 |
83087846de08 |
public Machine(IForeignRuntimeInterface foreignInterface) |
20 |
83087846de08 |
{
|
21 |
83087846de08 |
mForeignInterface = foreignInterface; |
22 |
83087846de08 |
} |
23 |
83087846de08 |
|
24 |
e3e027f39344 |
public void Interpret(Stream stream) |
25 |
e3e027f39344 |
{
|
26 |
b18275779207 |
BytecodeFile bytecode = new BytecodeFile(stream); |
27 |
aa67edd44b43 |
|
28 |
aa67edd44b43 |
Interpret(bytecode, String.Empty); |
29 |
e3e027f39344 |
} |
30 |
e3e027f39344 |
|
31 |
b18275779207 |
public void Interpret(BytecodeFile file, string argument) |
32 |
e3e027f39344 |
{
|
33 |
e3e027f39344 |
mFile = file; |
34 |
e3e027f39344 |
|
35 |
e3e027f39344 |
// find "main" |
36 |
aa67edd44b43 |
Push(mFile.OffsetToMain); |
37 |
7ed6a1b915b7 |
Call(0, false); |
38 |
e3e027f39344 |
|
39 |
e3e027f39344 |
Interpret(); |
40 |
e3e027f39344 |
} |
41 |
e3e027f39344 |
|
42 |
b18275779207 |
public void Interpret(BytecodeFile file) |
43 |
e3e027f39344 |
{
|
44 |
e3e027f39344 |
Interpret(file, String.Empty); |
45 |
e3e027f39344 |
} |
46 |
e3e027f39344 |
|
47 |
e3e027f39344 |
public void Interpret() |
48 |
e3e027f39344 |
{
|
49 |
e3e027f39344 |
bool running = true; |
50 |
e3e027f39344 |
|
51 |
e3e027f39344 |
while (running) |
52 |
e3e027f39344 |
{
|
53 |
e3e027f39344 |
OpCode theOp = ReadOpCode(); |
54 |
e3e027f39344 |
//Console.WriteLine(theOp.ToString()); |
55 |
e3e027f39344 |
|
56 |
e3e027f39344 |
switch (theOp) |
57 |
e3e027f39344 |
{
|
58 |
e3e027f39344 |
case OpCode.PushNull: Push((Structure)null); break; |
59 |
e3e027f39344 |
case OpCode.PushBool: Push(ReadByte() != 0); break; |
60 |
e3e027f39344 |
case OpCode.PushInt: Push(ReadInt()); break; |
61 |
aa67edd44b43 |
case OpCode.PushString: Push(mFile.ReadString(ReadInt())); break; |
62 |
e3e027f39344 |
|
63 |
e3e027f39344 |
case OpCode.PushLocals: Push(mCurrentFrame); break; |
64 |
e3e027f39344 |
|
65 |
e3e027f39344 |
case OpCode.Alloc: |
66 |
e3e027f39344 |
{
|
67 |
e3e027f39344 |
int slots = ReadInt(); |
68 |
e3e027f39344 |
Structure structure = new Structure(slots); |
69 |
e3e027f39344 |
|
70 |
e3e027f39344 |
// initialize it |
71 |
e3e027f39344 |
// note: slots are on stack in reverse order |
72 |
e3e027f39344 |
// because they have been pushed in forward order. |
73 |
e3e027f39344 |
// this ensures that arguments are evaluated left to right. |
74 |
e3e027f39344 |
// for example: calling Foo (1, 2, 3) will create the arg |
75 |
e3e027f39344 |
// tuple by evaluating 1, 2, 3 in order. this leaves the |
76 |
e3e027f39344 |
// stack (from top down) looking like 3 2 1. |
77 |
e3e027f39344 |
for (int i = slots - 1; i >= 0; i--) |
78 |
e3e027f39344 |
{
|
79 |
e3e027f39344 |
structure[i] = Pop(); |
80 |
e3e027f39344 |
} |
81 |
e3e027f39344 |
|
82 |
e3e027f39344 |
Push(structure); |
83 |
e3e027f39344 |
} |
84 |
e3e027f39344 |
break; |
85 |
e3e027f39344 |
|
86 |
e3e027f39344 |
case OpCode.Load: |
87 |
e3e027f39344 |
{
|
88 |
e3e027f39344 |
byte index = ReadByte(); |
89 |
e3e027f39344 |
Structure struc = PopStructure(); |
90 |
e3e027f39344 |
Value op = struc[index]; |
91 |
e3e027f39344 |
|
92 |
e3e027f39344 |
Push(op); |
93 |
e3e027f39344 |
} |
94 |
e3e027f39344 |
break; |
95 |
e3e027f39344 |
|
96 |
e3e027f39344 |
case OpCode.Store: |
97 |
e3e027f39344 |
{
|
98 |
e3e027f39344 |
byte index = ReadByte(); |
99 |
e3e027f39344 |
Structure struc = PopStructure(); |
100 |
e3e027f39344 |
struc[index] = Pop(); |
101 |
e3e027f39344 |
} |
102 |
e3e027f39344 |
break; |
103 |
e3e027f39344 |
|
104 |
f597738399d6 |
case OpCode.LoadArray: |
105 |
f597738399d6 |
{
|
106 |
f597738399d6 |
Structure struc = PopStructure(); |
107 |
e28bf4a224c7 |
|
108 |
e28bf4a224c7 |
int index = struc[0].Int; |
109 |
e28bf4a224c7 |
Structure array = struc[1].Struct; |
110 |
f597738399d6 |
|
111 |
f597738399d6 |
//### bob: should bounds-check |
112 |
f597738399d6 |
|
113 |
f597738399d6 |
// add one to skip the first slot which holds the array size |
114 |
e28bf4a224c7 |
Push(array[index + 1]); |
115 |
f597738399d6 |
} |
116 |
f597738399d6 |
break; |
117 |
f597738399d6 |
|
118 |
f597738399d6 |
case OpCode.StoreArray: |
119 |
f597738399d6 |
{
|
120 |
f597738399d6 |
Structure struc = PopStructure(); |
121 |
e28bf4a224c7 |
int index = struc[0].Int; |
122 |
e28bf4a224c7 |
Structure array = struc[1].Struct; |
123 |
e28bf4a224c7 |
Value value = struc[2]; |
124 |
f597738399d6 |
|
125 |
f597738399d6 |
//### bob: should bounds-check |
126 |
f597738399d6 |
|
127 |
f597738399d6 |
// add one to skip the first slot which holds the array size |
128 |
e28bf4a224c7 |
array[index + 1] = value; |
129 |
f597738399d6 |
} |
130 |
f597738399d6 |
break; |
131 |
f597738399d6 |
|
132 |
f597738399d6 |
case OpCode.SizeArray: |
133 |
f597738399d6 |
{
|
134 |
f597738399d6 |
Structure struc = PopStructure(); |
135 |
f597738399d6 |
|
136 |
f597738399d6 |
// array size is the first element |
137 |
f597738399d6 |
Push(struc[0]); |
138 |
f597738399d6 |
} |
139 |
f597738399d6 |
break; |
140 |
f597738399d6 |
|
141 |
7ed6a1b915b7 |
case OpCode.Call0: Call(0, false); break; |
142 |
7ed6a1b915b7 |
case OpCode.Call1: Call(1, false); break; |
143 |
7ed6a1b915b7 |
case OpCode.CallN: Call(2, false); break; |
144 |
7ed6a1b915b7 |
|
145 |
7ed6a1b915b7 |
case OpCode.TailCall0: Call(0, true); break; |
146 |
7ed6a1b915b7 |
case OpCode.TailCall1: Call(1, true); break; |
147 |
7ed6a1b915b7 |
case OpCode.TailCallN: Call(2, true); break; |
148 |
e3e027f39344 |
|
149 |
4538302c85b1 |
case OpCode.ForeignCall0: ForeignCall(0); break; |
150 |
4538302c85b1 |
case OpCode.ForeignCall1: ForeignCall(1); break; |
151 |
4538302c85b1 |
case OpCode.ForeignCallN: ForeignCall(2); break; |
152 |
83087846de08 |
|
153 |
e3e027f39344 |
case OpCode.Return: |
154 |
e3e027f39344 |
{
|
155 |
aa67edd44b43 |
mInstruction = mCurrentFrame[mCurrentFrame.Count - 1].Int; |
156 |
aa67edd44b43 |
mCurrentFrame = mCurrentFrame[mCurrentFrame.Count - 2].Struct; |
157 |
e3e027f39344 |
|
158 |
e3e027f39344 |
// stop completely if we've returned from main |
159 |
aa67edd44b43 |
if (mCurrentFrame == null) running = false; |
160 |
e3e027f39344 |
} |
161 |
e3e027f39344 |
break; |
162 |
e3e027f39344 |
|
163 |
aa67edd44b43 |
case OpCode.Jump: mInstruction = ReadInt(); break; |
164 |
e3e027f39344 |
case OpCode.JumpIfFalse: int offset = ReadInt(); |
165 |
aa67edd44b43 |
if (!PopBool()) mInstruction = offset; |
166 |
e3e027f39344 |
break; |
167 |
e3e027f39344 |
|
168 |
e3e027f39344 |
case OpCode.BoolToString: Push(PopBool() ? "true" : "false"); break; |
169 |
e3e027f39344 |
case OpCode.IntToString: Push(PopInt().ToString()); break; |
170 |
e3e027f39344 |
|
171 |
e3e027f39344 |
case OpCode.EqualBool: |
172 |
e3e027f39344 |
{
|
173 |
e3e027f39344 |
Structure tuple = PopStructure(); |
174 |
e3e027f39344 |
Push(tuple[0].Bool == tuple[1].Bool); |
175 |
e3e027f39344 |
} |
176 |
e3e027f39344 |
break; |
177 |
e3e027f39344 |
|
178 |
e3e027f39344 |
case OpCode.EqualInt: |
179 |
e3e027f39344 |
{
|
180 |
e3e027f39344 |
Structure tuple = PopStructure(); |
181 |
e3e027f39344 |
Push(tuple[0].Int == tuple[1].Int); |
182 |
e3e027f39344 |
} |
183 |
e3e027f39344 |
break; |
184 |
e3e027f39344 |
|
185 |
e3e027f39344 |
case OpCode.EqualString: |
186 |
e3e027f39344 |
{
|
187 |
e3e027f39344 |
Structure tuple = PopStructure(); |
188 |
e3e027f39344 |
Push(tuple[0].String == tuple[1].String); |
189 |
e3e027f39344 |
} |
190 |
e3e027f39344 |
break; |
191 |
e3e027f39344 |
|
192 |
e3e027f39344 |
case OpCode.LessInt: |
193 |
e3e027f39344 |
{
|
194 |
e3e027f39344 |
Structure tuple = PopStructure(); |
195 |
e3e027f39344 |
Push(tuple[0].Int < tuple[1].Int); |
196 |
e3e027f39344 |
} |
197 |
e3e027f39344 |
break; |
198 |
e3e027f39344 |
|
199 |
e3e027f39344 |
case OpCode.GreaterInt: |
200 |
e3e027f39344 |
{
|
201 |
e3e027f39344 |
Structure tuple = PopStructure(); |
202 |
e3e027f39344 |
Push(tuple[0].Int > tuple[1].Int); |
203 |
e3e027f39344 |
} |
204 |
e3e027f39344 |
break; |
205 |
e3e027f39344 |
|
206 |
e3e027f39344 |
case OpCode.NegateBool: Push(!PopBool()); break; |
207 |
e3e027f39344 |
case OpCode.NegateInt: Push(-PopInt()); break; |
208 |
e3e027f39344 |
|
209 |
e3e027f39344 |
case OpCode.AndBool: |
210 |
e3e027f39344 |
{
|
211 |
e3e027f39344 |
Structure tuple = PopStructure(); |
212 |
e3e027f39344 |
Push(tuple[0].Bool && tuple[1].Bool); |
213 |
e3e027f39344 |
} |
214 |
e3e027f39344 |
break; |
215 |
e3e027f39344 |
|
216 |
e3e027f39344 |
case OpCode.OrBool: |
217 |
e3e027f39344 |
{
|
218 |
e3e027f39344 |
Structure tuple = PopStructure(); |
219 |
e3e027f39344 |
Push(tuple[0].Bool || tuple[1].Bool); |
220 |
e3e027f39344 |
} |
221 |
e3e027f39344 |
break; |
222 |
e3e027f39344 |
|
223 |
e3e027f39344 |
case OpCode.AddInt: |
224 |
e3e027f39344 |
{
|
225 |
e3e027f39344 |
Structure tuple = PopStructure(); |
226 |
e3e027f39344 |
Push(tuple[0].Int + tuple[1].Int); |
227 |
e3e027f39344 |
} |
228 |
e3e027f39344 |
break; |
229 |
e3e027f39344 |
|
230 |
e3e027f39344 |
case OpCode.SubInt: |
231 |
e3e027f39344 |
{
|
232 |
e3e027f39344 |
Structure tuple = PopStructure(); |
233 |
e3e027f39344 |
Push(tuple[0].Int - tuple[1].Int); |
234 |
e3e027f39344 |
} |
235 |
e3e027f39344 |
break; |
236 |
e3e027f39344 |
|
237 |
e3e027f39344 |
case OpCode.MultInt: |
238 |
e3e027f39344 |
{
|
239 |
e3e027f39344 |
Structure tuple = PopStructure(); |
240 |
e3e027f39344 |
Push(tuple[0].Int * tuple[1].Int); |
241 |
e3e027f39344 |
} |
242 |
e3e027f39344 |
break; |
243 |
e3e027f39344 |
|
244 |
e3e027f39344 |
case OpCode.DivInt: |
245 |
e3e027f39344 |
{
|
246 |
e3e027f39344 |
Structure tuple = PopStructure(); |
247 |
e3e027f39344 |
Push(tuple[0].Int / tuple[1].Int); |
248 |
e3e027f39344 |
} |
249 |
e3e027f39344 |
break; |
250 |
e3e027f39344 |
|
251 |
46d09f708b11 |
case OpCode.Random: |
252 |
46d09f708b11 |
{
|
253 |
46d09f708b11 |
// only create if needed |
254 |
46d09f708b11 |
if (mRandom == null) |
255 |
46d09f708b11 |
{
|
256 |
46d09f708b11 |
mRandom = new Random(); |
257 |
46d09f708b11 |
} |
258 |
e3e027f39344 |
|
259 |
46d09f708b11 |
Push(mRandom.Next(PopInt())); |
260 |
e3e027f39344 |
} |
261 |
e3e027f39344 |
break; |
262 |
e3e027f39344 |
|
263 |
e3e027f39344 |
case OpCode.AddString: |
264 |
e3e027f39344 |
{
|
265 |
e3e027f39344 |
Structure tuple = PopStructure(); |
266 |
e3e027f39344 |
Push(tuple[0].String + tuple[1].String); |
267 |
e3e027f39344 |
} |
268 |
e3e027f39344 |
break; |
269 |
e3e027f39344 |
|
270 |
e3e027f39344 |
case OpCode.Print: |
271 |
e3e027f39344 |
string text = PopString(); |
272 |
e3e027f39344 |
if (Printed != null) Printed(this, new PrintEventArgs(text)); |
273 |
e3e027f39344 |
break; |
274 |
e3e027f39344 |
|
275 |
e3e027f39344 |
case OpCode.StringSize: Push(PopString().Length); break; |
276 |
e3e027f39344 |
|
277 |
e3e027f39344 |
case OpCode.Substring: |
278 |
e3e027f39344 |
{
|
279 |
e3e027f39344 |
Structure tuple = PopStructure(); |
280 |
e3e027f39344 |
Push(tuple[0].String.Substring(tuple[1].Int, tuple[2].Int)); |
281 |
e3e027f39344 |
} |
282 |
e3e027f39344 |
break; |
283 |
e3e027f39344 |
|
284 |
e3e027f39344 |
default: throw new Exception("Unknown opcode.");
|
285 |
e3e027f39344 |
} |
286 |
e3e027f39344 |
} |
287 |
e3e027f39344 |
} |
288 |
e3e027f39344 |
|
289 |
e3e027f39344 |
private OpCode ReadOpCode() |
290 |
e3e027f39344 |
{
|
291 |
aa67edd44b43 |
return (OpCode)mFile.Bytes[mInstruction++]; |
292 |
e3e027f39344 |
} |
293 |
e3e027f39344 |
|
294 |
e3e027f39344 |
private byte ReadByte() |
295 |
e3e027f39344 |
{
|
296 |
aa67edd44b43 |
return mFile.Bytes[mInstruction++]; |
297 |
e3e027f39344 |
} |
298 |
e3e027f39344 |
|
299 |
e3e027f39344 |
private char ReadChar() |
300 |
e3e027f39344 |
{
|
301 |
aa67edd44b43 |
int c = ((int)mFile.Bytes[mInstruction++]) | |
302 |
aa67edd44b43 |
((int)mFile.Bytes[mInstruction++] << 8); |
303 |
e3e027f39344 |
|
304 |
e3e027f39344 |
return (char)c; |
305 |
e3e027f39344 |
} |
306 |
e3e027f39344 |
|
307 |
e3e027f39344 |
private int ReadInt() |
308 |
e3e027f39344 |
{
|
309 |
aa67edd44b43 |
return ((int)mFile.Bytes[mInstruction++]) | |
310 |
aa67edd44b43 |
((int)mFile.Bytes[mInstruction++] << 8) | |
311 |
aa67edd44b43 |
((int)mFile.Bytes[mInstruction++] << 16) | |
312 |
aa67edd44b43 |
((int)mFile.Bytes[mInstruction++] << 24); |
313 |
e3e027f39344 |
} |
314 |
e3e027f39344 |
|
315 |
e3e027f39344 |
private void Push(Value value) { mOperands.Push(value); }
|
316 |
e3e027f39344 |
private void Push(bool value) { Push(new Value(value)); }
|
317 |
e3e027f39344 |
private void Push(char value) { Push(new Value(value)); }
|
318 |
e3e027f39344 |
private void Push(int value) { Push(new Value(value)); }
|
319 |
e3e027f39344 |
private void Push(string value) { Push(new Value(value)); }
|
320 |
e3e027f39344 |
private void Push(Structure value) { Push(new Value(value)); }
|
321 |
e3e027f39344 |
|
322 |
e3e027f39344 |
private Value Pop() { return mOperands.Pop(); }
|
323 |
e3e027f39344 |
private bool PopBool() { return mOperands.Pop().Bool; }
|
324 |
e3e027f39344 |
private int PopInt() { return mOperands.Pop().Int; }
|
325 |
e3e027f39344 |
private string PopString() { return mOperands.Pop().String; }
|
326 |
e3e027f39344 |
private Structure PopStructure() { return mOperands.Pop().Struct; }
|
327 |
e3e027f39344 |
|
328 |
aa67edd44b43 |
private Structure MakeCallFrame(int numLocals, Structure parentFrame, int instruction) |
329 |
e3e027f39344 |
{
|
330 |
aa67edd44b43 |
var frame = new Structure(numLocals + 2); |
331 |
e3e027f39344 |
frame[numLocals] = new Value(parentFrame); |
332 |
aa67edd44b43 |
frame[numLocals + 1] = new Value(instruction); |
333 |
e3e027f39344 |
|
334 |
e3e027f39344 |
return frame; |
335 |
e3e027f39344 |
} |
336 |
e3e027f39344 |
|
337 |
7ed6a1b915b7 |
private void Call(int paramType, bool isTailCall) |
338 |
aa67edd44b43 |
{
|
339 |
aa67edd44b43 |
// jump to the function |
340 |
aa67edd44b43 |
int previousInstruction = mInstruction; |
341 |
aa67edd44b43 |
|
342 |
aa67edd44b43 |
mInstruction = PopInt(); |
343 |
aa67edd44b43 |
int numLocals = ReadInt(); |
344 |
aa67edd44b43 |
|
345 |
7ed6a1b915b7 |
// if it's a tail call, discard the parent frame |
346 |
7ed6a1b915b7 |
//### bob: not tested. compiler doesn't emit tail calls yet |
347 |
7ed6a1b915b7 |
var parent = mCurrentFrame; |
348 |
7ed6a1b915b7 |
if (isTailCall) |
349 |
7ed6a1b915b7 |
{
|
350 |
7ed6a1b915b7 |
parent = mCurrentFrame[mCurrentFrame.Count - 2].Struct; |
351 |
7ed6a1b915b7 |
previousInstruction = mCurrentFrame[mCurrentFrame.Count - 1].Int; |
352 |
7ed6a1b915b7 |
} |
353 |
7ed6a1b915b7 |
|
354 |
7ed6a1b915b7 |
mCurrentFrame = MakeCallFrame(numLocals, parent, previousInstruction); |
355 |
aa67edd44b43 |
|
356 |
3754d24a3bf3 |
// pop and store the argument |
357 |
3754d24a3bf3 |
if (paramType != 0) mCurrentFrame[0] = Pop(); |
358 |
d78a20a8a165 |
|
359 |
d78a20a8a165 |
// track stack depth |
360 |
d78a20a8a165 |
if (MaxStackDepth != 0) |
361 |
d78a20a8a165 |
{
|
362 |
d78a20a8a165 |
int stackDepth = GetStackDepth(mCurrentFrame); |
363 |
d78a20a8a165 |
|
364 |
d78a20a8a165 |
if (stackDepth > MaxStackDepth) throw new MaxStackDepthExceededException(MaxStackDepth); |
365 |
d78a20a8a165 |
} |
366 |
aa67edd44b43 |
} |
367 |
aa67edd44b43 |
|
368 |
4538302c85b1 |
private void ForeignCall(int paramType) // (int id, Value[] args) |
369 |
83087846de08 |
{
|
370 |
4538302c85b1 |
int id = ReadInt(); |
371 |
4538302c85b1 |
|
372 |
4538302c85b1 |
Value[] args; |
373 |
4538302c85b1 |
switch (paramType) |
374 |
4538302c85b1 |
{
|
375 |
4538302c85b1 |
case 0: args = new Value[0]; break; |
376 |
4538302c85b1 |
case 1: args = new Value[] { Pop() }; break;
|
377 |
4538302c85b1 |
case 2: args = PopStructure().Fields.ToArray(); break; |
378 |
4538302c85b1 |
default: throw new ArgumentException("Unknown parameter type.");
|
379 |
4538302c85b1 |
} |
380 |
4538302c85b1 |
|
381 |
83087846de08 |
Value result = mForeignInterface.ForeignCall(id, args); |
382 |
83087846de08 |
if (result != null) Push(result); |
383 |
83087846de08 |
} |
384 |
83087846de08 |
|
385 |
d78a20a8a165 |
private int GetStackDepth(Structure callFrame) |
386 |
d78a20a8a165 |
{
|
387 |
d78a20a8a165 |
if (callFrame == null) return 0; |
388 |
d78a20a8a165 |
return 1 + GetStackDepth(callFrame[callFrame.Count - 2].Struct); |
389 |
d78a20a8a165 |
} |
390 |
d78a20a8a165 |
|
391 |
b18275779207 |
private BytecodeFile mFile; |
392 |
e3e027f39344 |
|
393 |
aa67edd44b43 |
//### bob: could also just store this in the current frame |
394 |
aa67edd44b43 |
private int mInstruction; // position in bytecode file |
395 |
e3e027f39344 |
|
396 |
e3e027f39344 |
private readonly Stack<Value> mOperands = new Stack<Value>(); |
397 |
e3e027f39344 |
|
398 |
e3e027f39344 |
// call frame for the current function |
399 |
e3e027f39344 |
// contains: |
400 |
e3e027f39344 |
// 0 ... n: local variables |
401 |
e3e027f39344 |
// n + 1 : reference to parent call frame |
402 |
e3e027f39344 |
// n + 2 : instruction pointer for parent frame |
403 |
e3e027f39344 |
private Structure mCurrentFrame; |
404 |
83087846de08 |
|
405 |
46d09f708b11 |
private Random mRandom; |
406 |
46d09f708b11 |
|
407 |
83087846de08 |
private readonly IForeignRuntimeInterface mForeignInterface; |
408 |
e3e027f39344 |
} |
409 |
e3e027f39344 |
} |
