예제 #1
0
        /*
         * Internal implementation of Invoke
         */
        private IodineObject Invoke(IodineMethod method, IodineObject[] arguments)
        {
            if (method.Bytecode.Instructions.Length > 0)
            {
                currentLocation = method.Bytecode.Instructions [0].Location;
            }

            int insCount      = method.Bytecode.Instructions.Length;
            int prevStackSize = stackSize;
            int i             = 0;

            lastObject = null;

            /*
             * Store function arguments into their respective local variable slots
             */
            foreach (string param in method.Parameters)
            {
                if (param == method.VarargsParameter)
                {
                    // Variable list arguments
                    IodineObject[] tupleItems = new IodineObject[arguments.Length - i];
                    Array.Copy(arguments, i, tupleItems, 0, arguments.Length - i);
                    Top.StoreLocalExplicit(param, new IodineTuple(tupleItems));
                }
                else if (param == method.KwargsParameter)
                {
                    /*
                     * At the moment, keyword arguments are passed to the function as an IodineHashMap,
                     */
                    if (i < arguments.Length && arguments [i] is IodineDictionary)
                    {
                        Top.StoreLocalExplicit(param, arguments [i]);
                    }
                    else
                    {
                        Top.StoreLocalExplicit(param, new IodineDictionary());
                    }
                }
                else
                {
                    if (arguments.Length <= i && method.HasDefaultValues)
                    {
                        Top.StoreLocalExplicit(param, method.DefaultValues [i - method.DefaultValuesStartIndex]);
                    }
                    else
                    {
                        Top.StoreLocalExplicit(param, arguments [i++]);
                    }
                }
            }

            StackFrame top = Top;

            top.Module = method.Module;
            if (traceCallback != null)
            {
                Trace(TraceType.Function, top, currentLocation);
            }

            IodineObject retVal = EvalCode(method.Bytecode);

            if (top.Yielded)
            {
                top.Pop();
            }

            /*
             * Calls __exit__ on any object used in a with statement
             */
            while (!top.Yielded && top.DisposableObjects.Count > 0)
            {
                top.DisposableObjects.Pop().Exit(this);
            }

            stackSize = prevStackSize;

            if (top.AbortExecution)
            {
                /*
                 * If AbortExecution was set, something went wrong and we most likely just
                 * raised an exception. We'll return right here and let what ever catches
                 * the exception clean up the stack
                 */
                return(retVal);
            }

            EndFrame();

            return(retVal);
        }
예제 #2
0
        /// <summary>
        /// Evaluates an Iodine code object
        /// </summary>
        /// <returns>The code.</returns>
        /// <param name="bytecode">Bytecode.</param>
        public IodineObject EvalCode(CodeObject bytecode)
        {
            int insCount = bytecode.Instructions.Length;

            int pc = Top.InstructionPointer;

            StackFrame   top           = Top;
            IodineObject selfReference = null;

            top.SetLocationAccessor(() => {
                return(instruction.Location);
            });

            top.SetInstructionPointerAccessor(
                () => { return(pc); },
                (newIp) => { pc = newIp; }
                );

            while (pc < insCount && !top.AbortExecution && !top.Yielded)
            {
                instruction = bytecode.Instructions [pc++];


                switch (instruction.OperationCode)
                {
                case Opcode.Pop: {
                    top.Pop();
                    break;
                }

                case Opcode.Dup: {
                    var val = top.Pop();
                    top.Push(val);
                    top.Push(val);
                    break;
                }

                case Opcode.LoadConst: {
                    top.Push(instruction.ArgumentObject);
                    break;
                }

                case Opcode.LoadNull: {
                    top.Push(IodineNull.Instance);
                    break;
                }

                case Opcode.LoadSelf: {
                    top.Push(Top.Self);

                    if (Top.Self == null)
                    {
                        RaiseException(new IodineFunctionInvocationException());
                    }

                    break;
                }

                case Opcode.LoadTrue: {
                    top.Push(IodineBool.True);
                    break;
                }

                case Opcode.LoadException: {
                    top.Push(lastException);
                    break;
                }

                case Opcode.LoadFalse: {
                    top.Push(IodineBool.False);
                    break;
                }

                case Opcode.StoreLocal: {
                    Top.StoreLocal(instruction.ArgumentString, top.Pop());
                    break;
                }

                case Opcode.LoadLocal: {
                    top.Push(Top.LoadLocal(instruction.ArgumentString));
                    break;
                }

                case Opcode.StoreGlobal: {
                    Top.Module.SetAttribute(this, instruction.ArgumentString, top.Pop());
                    break;
                }

                case Opcode.LoadGlobal: {
                    if (instruction.ArgumentString == "_")
                    {
                        top.Push(Top.Module);
                    }
                    else if (Top.Module.Attributes.ContainsKey(instruction.ArgumentString))
                    {
                        top.Push(Top.Module.GetAttribute(this, instruction.ArgumentString));
                    }
                    else
                    {
                        RaiseException(new IodineAttributeNotFoundException(instruction.ArgumentString));
                    }
                    break;
                }

                case Opcode.StoreAttribute: {
                    var target = top.Pop();
                    var value  = top.Pop();

                    string attribute = instruction.ArgumentString;

                    if (target.Attributes.ContainsKey(attribute) &&
                        target.Attributes [attribute] is IIodineProperty)
                    {
                        var property = (IIodineProperty)target.Attributes [attribute];
                        property.Set(this, value);
                        break;
                    }
                    target.SetAttribute(this, attribute, value);
                    break;
                }

                case Opcode.LoadAttribute: {
                    var    target    = top.Pop();
                    string attribute = instruction.ArgumentString;
                    if (target.Attributes.ContainsKey(attribute) &&
                        target.Attributes [attribute] is IIodineProperty)
                    {
                        var property = (IIodineProperty)target.Attributes [attribute];
                        top.Push(property.Get(this));
                        selfReference = target;
                        break;
                    }
                    top.Push(target.GetAttribute(this, attribute));
                    selfReference = target;
                    break;
                }

                case Opcode.LoadAttributeOrNull: {
                    var    target    = top.Pop();
                    string attribute = instruction.ArgumentString;

                    if (target.Attributes.ContainsKey(attribute))
                    {
                        top.Push(target.GetAttribute(this, attribute));
                    }
                    else
                    {
                        top.Push(IodineNull.Instance);
                    }
                    selfReference = top.Stack.LastObject;
                    break;
                }

                case Opcode.StoreIndex: {
                    var index  = top.Pop();
                    var target = top.Pop();
                    var value  = top.Pop();
                    target.SetIndex(this, index, value);
                    break;
                }

                case Opcode.LoadIndex: {
                    var index  = top.Pop();
                    var target = top.Pop();
                    top.Push(target.GetIndex(this, index));
                    break;
                }

                case Opcode.CastLocal: {
                    var type = top.Pop() as IodineTypeDefinition;

                    var o = Top.LoadLocal(instruction.ArgumentString);

                    if (type == null)
                    {
                        RaiseException(new IodineTypeException("TypeDef"));
                        break;
                    }
                    if (o.InstanceOf(type))
                    {
                        top.Push(o);
                    }
                    else
                    {
                        RaiseException(new IodineTypeException(type.Name));
                    }
                    break;
                }

                case Opcode.Equals: {
                    top.Push(top.Pop().Equals(this, top.Pop()));
                    break;
                }

                case Opcode.NotEquals: {
                    top.Push(top.Pop().NotEquals(this, top.Pop()));
                    break;
                }

                case Opcode.BoolAnd: {
                    var left  = top.Pop();
                    var right = top.Pop();

                    top.Push(left.LogicalAnd(this, right));

                    break;
                }

                case Opcode.BoolOr: {
                    var left  = top.Pop();
                    var right = top.Pop();

                    top.Push(left.LogicalOr(this, right));

                    break;
                }

                case Opcode.Add: {
                    top.Push(top.Pop().Add(this, top.Pop()));
                    break;
                }

                case Opcode.Sub: {
                    top.Push(top.Pop().Sub(this, top.Pop()));
                    break;
                }

                case Opcode.Mul: {
                    top.Push(top.Pop().Mul(this, top.Pop()));
                    break;
                }

                case Opcode.Div: {
                    top.Push(top.Pop().Div(this, top.Pop()));
                    break;
                }

                case Opcode.Mod: {
                    top.Push(top.Pop().Mod(this, top.Pop()));
                    break;
                }

                case Opcode.Xor: {
                    top.Push(top.Pop().Xor(this, top.Pop()));
                    break;
                }

                case Opcode.And: {
                    top.Push(top.Pop().And(this, top.Pop()));
                    break;
                }

                case Opcode.Or: {
                    top.Push(top.Pop().Or(this, top.Pop()));
                    break;
                }

                case Opcode.LeftShift: {
                    top.Push(top.Pop().LeftShift(this, top.Pop()));
                    break;
                }

                case Opcode.RightShift: {
                    top.Push(top.Pop().RightShift(this, top.Pop()));
                    break;
                }

                case Opcode.GreaterThan: {
                    top.Push(top.Pop().GreaterThan(this, top.Pop()));
                    break;
                }

                case Opcode.GreaterThanOrEqu: {
                    top.Push(top.Pop().GreaterThanOrEqual(this, top.Pop()));
                    break;
                }

                case Opcode.LessThan: {
                    top.Push(top.Pop().LessThan(this, top.Pop()));
                    break;
                }

                case Opcode.LessThanOrEqu: {
                    top.Push(top.Pop().LessThanOrEqual(this, top.Pop()));
                    break;
                }

                case Opcode.HalfRange: {
                    top.Push(top.Pop().HalfRange(this, top.Pop()));
                    break;
                }

                case Opcode.ClosedRange: {
                    top.Push(top.Pop().ClosedRange(this, top.Pop()));
                    break;
                }

                case Opcode.UnaryOp: {
                    top.Push(top.Pop().PerformUnaryOperation(this,
                                                             (UnaryOperation)instruction.Argument));
                    break;
                }

                case Opcode.Invoke: {
                    var target    = top.Pop();
                    var arguments = new IodineObject [instruction.Argument];
                    for (int i = 1; i <= instruction.Argument; i++)
                    {
                        arguments [instruction.Argument - i] = top.Pop();
                    }
                    top.Push(target.Invoke(this, arguments));
                    break;
                }

                case Opcode.InvokeVar: {
                    var target    = top.Pop();
                    var arguments = new List <IodineObject> ();
                    var tuple     = top.Pop() as IodineTuple;
                    if (tuple == null)
                    {
                        RaiseException(new IodineTypeException("Tuple"));
                        break;
                    }
                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        arguments.Add(top.Pop());
                    }
                    arguments.AddRange(tuple.Objects);
                    top.Push(target.Invoke(this, arguments.ToArray()));
                    break;
                }

                case Opcode.InvokeSuper: {
                    var target    = top.Pop() as IodineTypeDefinition;
                    var arguments = new IodineObject [instruction.Argument];

                    for (int i = 1; i <= instruction.Argument; i++)
                    {
                        arguments [instruction.Argument - i] = top.Pop();
                    }

                    target.Inherit(this, Top.Self, arguments);
                    break;
                }

                case Opcode.Return: {
                    pc = int.MaxValue;
                    break;
                }

                case Opcode.Yield: {
                    Top.Yielded = true;
                    break;
                }

                case Opcode.JumpIfTrue: {
                    if (top.Pop().IsTrue())
                    {
                        pc = instruction.Argument;
                    }
                    break;
                }

                case Opcode.JumpIfFalse: {
                    if (!top.Pop().IsTrue())
                    {
                        pc = instruction.Argument;
                    }
                    break;
                }

                case Opcode.Jump: {
                    pc = instruction.Argument;
                    break;
                }

                case Opcode.BuildClass: {
                    var name        = top.Pop() as IodineName;
                    var doc         = top.Pop() as IodineString;
                    var constructor = top.Pop() as IodineMethod;
                    //CodeObject initializer = Pop as CodeObject;
                    var baseClass  = top.Pop() as IodineTypeDefinition;
                    var interfaces = top.Pop() as IodineTuple;
                    var clazz      = new IodineClass(name.ToString(), new CodeObject(), constructor);

                    if (baseClass != null)
                    {
                        clazz.BaseClass = baseClass;
                        baseClass.BindAttributes(clazz);
                    }

                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var val = top.Pop();
                        var key = top.Pop();

                        clazz.Attributes [val.ToString()] = key;
                    }

                    foreach (IodineObject obj in interfaces.Objects)
                    {
                        var contract = obj as IodineContract;
                        if (!contract.InstanceOf(clazz))
                        {
                            //RaiseException (new IodineTypeException (contract.Name));
                            break;
                        }
                    }

                    clazz.SetAttribute("__doc__", doc);

                    top.Push(clazz);
                    break;
                }

                case Opcode.BuildMixin: {
                    var name = top.Pop() as IodineName;

                    var mixin = new IodineMixin(name.ToString());

                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var val = top.Pop();
                        var key = top.Pop();

                        mixin.Attributes [val.ToString()] = key;
                    }

                    top.Push(mixin);
                    break;
                }

                case Opcode.BuildEnum: {
                    var name  = top.Pop() as IodineName;
                    var ienum = new IodineEnum(name.ToString());

                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var val = top.Pop() as IodineInteger;
                        var key = top.Pop() as IodineName;
                        ienum.AddItem(key.ToString(), (int)val.Value);
                    }

                    top.Push(ienum);
                    break;
                }

                case Opcode.BuildContract: {
                    var name = top.Pop() as IodineName;

                    var contract = new IodineContract(name.ToString());
                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var val = top.Pop() as IodineMethod;
                        contract.AddMethod(val);
                    }

                    top.Push(contract);
                    break;
                }

                case Opcode.BuildTrait: {
                    var name  = top.Pop() as IodineName;
                    var trait = new IodineTrait(name.ToString());

                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var val = top.Pop() as IodineMethod;
                        trait.AddMethod(val);
                    }

                    top.Push(trait);
                    break;
                }

                case Opcode.BuildHash: {
                    var hash = new IodineDictionary();

                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var val = top.Pop();
                        var key = top.Pop();
                        hash.Set(key, val);
                    }
                    top.Push(hash);
                    break;
                }

                case Opcode.BuildList: {
                    var items = new IodineObject [instruction.Argument];

                    for (int i = 1; i <= instruction.Argument; i++)
                    {
                        items [instruction.Argument - i] = top.Pop();
                    }

                    top.Push(new IodineList(items));
                    break;
                }

                case Opcode.BuildTuple: {
                    var items = new IodineObject [instruction.Argument];
                    for (int i = 1; i <= instruction.Argument; i++)
                    {
                        items [instruction.Argument - i] = top.Pop();
                    }
                    top.Push(new IodineTuple(items));
                    break;
                }

                case Opcode.BuildClosure: {
                    var obj    = top.Pop();
                    var method = obj as IodineMethod;
                    top.Push(new IodineClosure(Top, method));
                    break;
                }

                case Opcode.BuildGenExpr: {
                    var method = top.Pop() as CodeObject;
                    top.Push(new IodineGeneratorExpr(Top, method));
                    break;
                }

                case Opcode.BuildRegex: {
                    var str = top.Pop() as IodineString;
                    top.Push(new RegexModule.IodineRegex(str.Value));
                    break;
                }

                case Opcode.Slice: {
                    var target = top.Pop();

                    var arguments = new IodineInteger [3];

                    for (int i = 0; i < 3; i++)
                    {
                        var obj = top.Pop();
                        arguments [i] = obj as IodineInteger;

                        if (obj != IodineNull.Instance && arguments [i] == null)
                        {
                            RaiseException(new IodineTypeException("Int"));
                            break;
                        }
                    }

                    var slice = new IodineSlice(arguments [0], arguments [1], arguments [2]);

                    top.Push(target.Slice(this, slice));

                    break;
                }

                case Opcode.RangeCheck: {
                    var range   = top.Pop() as IodineRange;
                    var matchee = top.Pop();


                    long longVal;


                    if (!MarshalUtil.MarshalAsInt64(matchee, out longVal) ||
                        range == null)
                    {
                        top.Stack.Push(IodineBool.False);
                        break;
                    }

                    top.Stack.Push(IodineBool.Create(
                                       range.LowerBound <= longVal &&
                                       range.UpperBound >= longVal
                                       ));

                    break;
                }

                case Opcode.MatchPattern: {
                    var collection = top.Pop().GetIterator(this);

                    var items = new IodineObject [instruction.Argument];
                    for (int i = 1; i <= instruction.Argument; i++)
                    {
                        items [instruction.Argument - i] = top.Pop();
                    }


                    int index = 0;

                    collection.IterReset(this);

                    while (collection.IterMoveNext(this) && index < items.Length)
                    {
                        var o = collection.IterGetCurrent(this);

                        if (items [index] is IodineTypeDefinition)
                        {
                            if (!o.InstanceOf(items [index] as IodineTypeDefinition))
                            {
                                top.Push(IodineBool.False);
                                break;
                            }
                        }
                        else if (items [index] is IodineRange)
                        {
                            var range = items [index] as IodineRange;

                            long longValue;

                            if (MarshalUtil.MarshalAsInt64(o, out longValue))
                            {
                                if (longValue > range.UpperBound ||
                                    longValue < range.LowerBound)
                                {
                                    top.Push(IodineBool.False);
                                    break;
                                }
                            }
                            else
                            {
                                top.Push(IodineBool.False);
                                break;
                            }
                        }
                        else
                        {
                            if (!o.Equals(items [index]))
                            {
                                top.Push(IodineBool.False);
                                break;
                            }
                        }

                        index++;
                    }

                    top.Push(IodineBool.Create(index == items.Length));

                    break;
                }

                case Opcode.Unwrap: {
                    var container = top.Pop();

                    var value = container.Unwrap(this);

                    if (instruction.Argument > 0)
                    {
                        var len = value.Len(this) as IodineInteger;

                        if (len == null || len.Value != instruction.Argument)
                        {
                            top.Push(IodineBool.False);
                            break;
                        }
                    }

                    top.Push(value);
                    top.Push(IodineBool.True);

                    break;
                }

                case Opcode.Unpack: {
                    var tuple = top.Pop() as IodineTuple;

                    if (tuple == null)
                    {
                        RaiseException(new IodineTypeException("Tuple"));
                        break;
                    }

                    if (tuple.Objects.Length != instruction.Argument)
                    {
                        RaiseException(new IodineUnpackException(instruction.Argument));
                        break;
                    }
                    for (int i = tuple.Objects.Length - 1; i >= 0; i--)
                    {
                        top.Push(tuple.Objects [i]);
                    }
                    break;
                }

                case Opcode.GetIter: {
                    top.Push(top.Pop().GetIterator(this));
                    break;
                }

                case Opcode.IterGetNext: {
                    top.Push(top.Pop().IterGetCurrent(this));
                    break;
                }

                case Opcode.IterMoveNext: {
                    top.Push(IodineBool.Create(top.Pop().IterMoveNext(this)));
                    break;
                }

                case Opcode.IterReset: {
                    top.Pop().IterReset(this);
                    break;
                }

                case Opcode.PushExceptionHandler: {
                    Top.ExceptionHandlers.Push(new IodineExceptionHandler(frameCount, instruction.Argument));
                    break;
                }

                case Opcode.PopExceptionHandler: {
                    Top.ExceptionHandlers.Pop();
                    break;
                }

                case Opcode.InstanceOf: {
                    var o    = top.Pop();
                    var type = top.Pop() as IodineTypeDefinition;
                    if (type == null)
                    {
                        RaiseException(new IodineTypeException("TypeDef"));
                        break;
                    }
                    top.Push(IodineBool.Create(o.InstanceOf(type)));
                    break;
                }

                case Opcode.DynamicCast: {
                    var o    = top.Pop();
                    var type = top.Pop() as IodineTypeDefinition;
                    if (type == null)
                    {
                        RaiseException(new IodineTypeException("TypeDef"));
                        break;
                    }
                    if (o.InstanceOf(type))
                    {
                        top.Push(o);
                    }
                    else
                    {
                        top.Push(IodineNull.Instance);
                    }
                    break;
                }

                case Opcode.NullCoalesce: {
                    var o1 = top.Pop();
                    var o2 = top.Pop();
                    if (o1 is IodineNull)
                    {
                        top.Push(o2);
                    }
                    else
                    {
                        top.Push(o1);
                    }
                    break;
                }

                case Opcode.BeginExcept: {
                    bool rethrow = true;

                    for (int i = 1; i <= instruction.Argument; i++)
                    {
                        var type = top.Pop() as IodineTypeDefinition;

                        if (type == null)
                        {
                            RaiseException(new IodineTypeException("TypeDef"));
                            break;
                        }

                        if (lastException.InstanceOf(type))
                        {
                            rethrow = false;
                            break;
                        }
                    }

                    if (rethrow)
                    {
                        RaiseException(lastException);
                    }
                    break;
                }

                case Opcode.Raise: {
                    var e = top.Pop();
                    if (e.InstanceOf(IodineException.TypeDefinition))
                    {
                        RaiseException(e);
                    }
                    else
                    {
                        RaiseException(new IodineTypeException("Exception"));
                    }
                    break;
                }

                case Opcode.SwitchLookup: {
                    var lookup = new Dictionary <int, IodineObject> ();
                    var needle = top.Pop().GetHashCode();

                    for (int i = 0; i < instruction.Argument; i++)
                    {
                        var value = top.Pop();
                        var key   = top.Pop();
                        lookup [key.GetHashCode()] = value;
                    }
                    if (lookup.ContainsKey(needle))
                    {
                        lookup [needle].Invoke(this, new IodineObject [] { });
                        top.Push(IodineBool.True);
                    }
                    else
                    {
                        top.Push(IodineBool.False);
                    }
                    break;
                }

                case Opcode.BeginWith: {
                    var obj = top.Pop();
                    obj.Enter(this);
                    Top.DisposableObjects.Push(obj);
                    break;
                }

                case Opcode.EndWith: {
                    Top.DisposableObjects.Pop().Exit(this);
                    break;
                }

                case Opcode.IncludeMixin: {
                    var obj  = top.Pop();
                    var type = top.Pop();

                    foreach (var attr in obj.Attributes)
                    {
                        type.SetAttribute(attr.Key, attr.Value);
                    }
                    break;
                }

                case Opcode.ApplyMixin: {
                    var type  = top.Pop();
                    var mixin = instruction.ArgumentObject as IodineMixin;

                    foreach (var attr in mixin.Attributes)
                    {
                        type.SetAttribute(attr.Key, attr.Value);
                    }
                    break;
                }

                case Opcode.BuildFunction: {
                    var flags = (MethodFlags)instruction.Argument;

                    var name       = top.Pop() as IodineString;
                    var doc        = top.Pop() as IodineString;
                    var codeObj    = top.Pop() as CodeObject;
                    var parameters = top.Pop() as IodineTuple;

                    var defaultValues = new IodineObject [] { };

                    int defaultValuesStart = 0;

                    if (flags.HasFlag(MethodFlags.HasDefaultParameters))
                    {
                        var defaultValuesTuple = top.Pop() as IodineTuple;
                        var startInt           = top.Pop() as IodineInteger;
                        defaultValues      = defaultValuesTuple.Objects;
                        defaultValuesStart = (int)startInt.Value;
                    }

                    var method = new IodineMethod(
                        Top.Module,
                        name,
                        codeObj,
                        parameters,
                        flags,
                        defaultValues,
                        defaultValuesStart
                        );

                    method.SetAttribute("__doc__", doc);

                    top.Push(method);

                    break;
                }
                }
            }
            return(top.Stack.LastObject ?? IodineNull.Instance);
        }
예제 #3
0
 private IodineObject Pop()
 {
     stackSize--;
     return(Top.Pop());
 }
예제 #4
0
        /*
         * Internal implementation of Invoke
         */
        IodineObject Invoke(IodineMethod method, IodineObject [] arguments)
        {
            if (method.Bytecode.Instructions.Length > 0)
            {
                instruction = method.Bytecode.Instructions [0];
            }
            int insCount      = method.Bytecode.Instructions.Length;
            int prevStackSize = stackSize;
            int i             = 0;

            /*
             * Store function arguments into their respective local variable slots
             */
            foreach (IodineParameter param in method.Parameters)
            {
                var namedParam = param as IodineNamedParameter;

                if (namedParam != null)
                {
                    StoreNamedParameter(method, arguments, namedParam, i);
                }

                var tupleParam = param as IodineTupleParameter;

                if (tupleParam != null)
                {
                    var tuple = arguments [i] as IodineTuple;

                    if (tuple == null)
                    {
                        RaiseException(new IodineException("Tuple"));
                        return(null);
                    }

                    DecomposeTupleParameter(tuple, tupleParam);
                }

                i++;
            }

            StackFrame top = Top;

            top.Module = method.Module;

            if (traceCallback != null)
            {
                Trace(TraceType.Function, top, instruction.Location);
            }

            var retVal = EvalCode(method.Bytecode);

            if (top.Yielded)
            {
                top.Pop();
            }

            /*
             * Calls __exit__ on any object used in a with statement
             */
            while (!top.Yielded && top.DisposableObjects.Count > 0)
            {
                top.DisposableObjects.Pop().Exit(this);
            }

            stackSize = prevStackSize;

            if (top.AbortExecution)
            {
                /*
                 * If AbortExecution was set, something went wrong and we most likely just
                 * raised an exception. We'll return right here and let what ever catches
                 * the exception clean up the stack
                 */
                return(retVal);
            }

            EndFrame();

            return(retVal);
        }