public object Execute()
{
this.context.InstructionPointer = 0;
string mthname;
object[] args;
// TODO refactor lastreceiver process
// TODO refactor switch
if (this.context.Block.Bytecodes != null)
while (true)
{
while (this.context.Sender != null && (this.context.HasReturnValue || this.context.Block.Bytecodes == null || this.context.InstructionPointer >= this.context.Block.ByteCodes.Length))
{
object retvalue = this.GetReturnValue();
this.PopContext(retvalue);
this.context.InstructionPointer++;
}
if (this.context.HasReturnValue || this.context.Block.Bytecodes == null || this.context.InstructionPointer >= this.context.Block.ByteCodes.Length)
break;
ByteCode bc = (ByteCode)this.context.Block.ByteCodes[this.context.InstructionPointer];
byte arg;
if (codes[(int)bc] != null)
{
codes[(int)bc](this.context);
this.context.InstructionPointer++;
continue;
}
switch (bc)
{
case ByteCode.ReturnSub:
this.context.HasReturnValue = true;
this.context.ReturnValue = null;
ExecutionContext retcontext = this.context.ReturnExecutionContext;
if (retcontext != null)
{
this.ReturnToContext(retcontext, null);
break;
}
break;
case ByteCode.ReturnPop:
this.context.HasReturnValue = true;
this.context.ReturnValue = this.context.Pop();
retcontext = this.context.ReturnExecutionContext;
if (retcontext != null)
{
this.ReturnToContext(retcontext, this.context.ReturnValue);
break;
}
break;
case ByteCode.Value:
Block newblock = (Block)this.context.Pop();
this.context.LastReceiver = newblock;
this.PushContext(newblock.CreateContext(this.context.Machine, null));
continue;
case ByteCode.MultiValue:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
object[] mvargs = new object[arg];
for (int k = arg - 1; k >= 0; k--)
mvargs[k] = this.context.Pop();
newblock = (Block)this.context.Pop();
this.context.LastReceiver = newblock;
this.PushContext(newblock.CreateContext(this.context.Machine, mvargs));
continue;
case ByteCode.GetLocal:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
this.context.Push(this.context.GetLocal(arg));
break;
case ByteCode.GetSuper:
this.context.Push(super);
break;
case ByteCode.GetSelf:
if (this.context.NativeSelf != null)
this.context.Push(this.context.NativeSelf);
else
this.context.Push(this.context.Self);
break;
case ByteCode.GetSuperClass:
this.context.Push(this.context.Self.Behavior.SuperClass);
break;
case ByteCode.GetNil:
this.context.Push(null);
break;
case ByteCode.GetInstanceVariable:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
this.context.Push(this.context.Self[arg]);
break;
case ByteCode.GetClassVariable:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
this.context.Push(((IClassDescription)((IMethod)this.context.Block).Behavior).GetClassVariable(arg));
break;
case ByteCode.NewObject:
IBehavior ibeh = (IBehavior)this.context.Pop();
this.context.LastReceiver = ibeh;
this.context.Push(ibeh.NewObject());
break;
case ByteCode.Nop:
break;
case ByteCode.Pop:
this.context.Pop();
break;
case ByteCode.BasicInstSize:
IObject iobj = (IObject)this.context.Pop();
this.context.LastReceiver = iobj;
this.context.Push(iobj.Behavior.NoInstanceVariables);
break;
case ByteCode.BasicInstVarAt:
int pos = (int)this.context.Pop();
iobj = (IObject)this.context.Pop();
this.context.LastReceiver = iobj;
this.context.Push(iobj[pos - 1]);
break;
case ByteCode.BasicInstVarAtPut:
object par = this.context.Pop();
pos = (int)this.context.Pop();
iobj = (IObject)this.context.Pop();
this.context.LastReceiver = iobj;
iobj[pos - 1] = par;
this.context.Push(par);
break;
case ByteCode.BasicAt:
pos = (int)this.context.Pop();
IIndexedObject indexedObj = (IIndexedObject)this.context.Pop();
this.context.LastReceiver = indexedObj;
this.context.Push(indexedObj.GetIndexedValue(pos - 1));
break;
case ByteCode.BasicAtPut:
par = this.context.Pop();
pos = (int)this.context.Pop();
indexedObj = (IIndexedObject)this.context.Pop();
this.context.LastReceiver = indexedObj;
indexedObj.SetIndexedValue(pos - 1, par);
this.context.Push(par);
break;
case ByteCode.ChainedSend:
this.context.Pop();
this.context.Push(this.context.LastReceiver);
break;
case ByteCode.Send:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
mthname = (string)this.context.Block.GetConstant(arg);
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
args = new object[arg];
for (int k = arg - 1; k >= 0; k--)
{
args[k] = this.context.Pop();
}
object obj = this.context.Pop();
this.context.LastReceiver = obj;
object value;
if (obj == super)
//// TODO this.context.nativeSelf processing
value = ((IMethod)this.context.Block).Behavior.SuperClass.SendMessageToObject(this.context.Self, this.context.Machine, mthname, args);
//// TODO this.context.Machine is null in many tests, not in real world
else if (this.context.Machine == null)
value = ((IObject)obj).SendMessage(null, mthname, args);
else
value = this.context.Machine.SendMessage(obj, mthname, args, this);
if (value == this)
continue;
this.context.Push(value);
break;
case ByteCode.MakeCollection:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
args = new object[arg];
for (int k = arg - 1; k >= 0; k--)
args[k] = this.context.Pop();
this.context.Push(new ArrayList(args));
break;
case ByteCode.NewDotNetObject:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
args = new object[arg];
for (int k = arg - 1; k >= 0; k--)
args[k] = this.context.Pop();
obj = this.context.Pop();
this.context.LastReceiver = obj;
this.context.Push(DotNetObject.NewObject((Type)obj, args));
break;
case ByteCode.InvokeDotNetMethod:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
mthname = (string)this.context.Block.GetConstant(arg);
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
args = new object[arg];
for (int k = arg - 1; k >= 0; k--)
args[k] = this.context.Pop();
obj = this.context.Pop();
this.context.LastReceiver = obj;
Type type = obj as Type;
if (type != null)
this.context.Push(DotNetObject.SendNativeStaticMessage(type, mthname, args));
else
this.context.Push(DotNetObject.SendNativeMessage(this.context.Machine, obj, mthname, args));
break;
case ByteCode.SetLocal:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
value = this.context.Pop();
this.context.SetLocal(arg, value);
this.context.Push(value);
this.context.LastReceiver = null;
break;
case ByteCode.JumpIfFalse:
bool cond = (bool)this.context.Pop();
this.context.InstructionPointer++;
int jump = this.context.Block.Bytecodes[this.context.InstructionPointer];
this.context.InstructionPointer++;
jump = (jump * 256) + this.context.Block.Bytecodes[this.context.InstructionPointer];
if (!cond)
{
this.context.InstructionPointer = jump;
continue;
}
break;
case ByteCode.JumpIfTrue:
cond = (bool)this.context.Pop();
this.context.InstructionPointer++;
jump = this.context.Block.Bytecodes[this.context.InstructionPointer];
this.context.InstructionPointer++;
jump = (jump * 256) + this.context.Block.Bytecodes[this.context.InstructionPointer];
if (cond)
{
this.context.InstructionPointer = jump;
continue;
}
break;
case ByteCode.Jump:
this.context.InstructionPointer++;
jump = this.context.Block.Bytecodes[this.context.InstructionPointer];
this.context.InstructionPointer++;
jump = (jump * 256) + this.context.Block.Bytecodes[this.context.InstructionPointer];
this.context.InstructionPointer = jump;
continue;
case ByteCode.SetInstanceVariable:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
value = this.context.Pop();
this.context.Self[arg] = value;
this.context.Push(value);
this.context.LastReceiver = this.context.Self;
break;
case ByteCode.SetClassVariable:
this.context.InstructionPointer++;
arg = this.context.Block.ByteCodes[this.context.InstructionPointer];
value = this.context.Pop();
((IClassDescription)((IMethod)this.context.Block).Behavior).SetClassVariable(arg, value);
this.context.Push(value);
this.context.LastReceiver = this.context.Self;
break;
case ByteCode.RaiseException:
throw (Exception)this.context.Pop();
default:
throw new Exception("Not implemented");
}
this.context.InstructionPointer++;
}
return this.GetReturnValue();
}