AjTalk.Language.Interpreter.Execute C# (CSharp) Метод

Execute() публичный Метод

public Execute ( ) : object
Результат object
        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();
        }