Пример #1
0
        private IP5Any Caller(bool noarg, int level, Opcode.ContextValues cxt)
        {
            if (level >= CallStack.Count)
            {
                if (cxt == Opcode.ContextValues.SCALAR)
                    return new P5Scalar(this);
                else
                    return new P5List(this);
            }

            StackFrame frame;

            if (level == 0)
                frame = CallStack.Peek();
            else
            {
                frame = new StackFrame();

                foreach (var f in CallStack)
                {
                    frame = f;

                    if (level == 0)
                        break;
                    --level;
                }
            }

            if (cxt == Opcode.ContextValues.SCALAR)
                return new P5Scalar(this, frame.Package);
            else if (noarg)
                return new P5List(
                    this,
                    new P5Scalar(this, frame.Package),
                    new P5Scalar(this, frame.File),
                    new P5Scalar(this, frame.Line));
            else
            {
                var callcxt =
                    frame.Context == Opcode.ContextValues.VOID   ? new P5Scalar(this) :
                    frame.Context == Opcode.ContextValues.SCALAR ? new P5Scalar(this, "") :
                                                                   new P5Scalar(this, 1);
                var subname = frame.Code != null ?
                    new P5Scalar(this, frame.Code.Name) : new P5Scalar(this);

                return new P5List(
                    this,
                    new P5Scalar(this, frame.Package),
                    new P5Scalar(this, frame.File),
                    new P5Scalar(this, frame.Line),
                    subname,
                    new P5Scalar(this), // hasargs
                    callcxt, // context
                    new P5Scalar(this), // evaltext
                    new P5Scalar(this), // is_require
                    new P5Scalar(this), // hints
                    new P5Scalar(this)); // warnings
            }
        }
Пример #2
0
        public virtual IP5Any Call(Runtime runtime, Opcode.ContextValues context,
                                   P5Array args)
        {
            // TODO emit this in the subroutine prologue/epilogue code,
            //      as is done for eval BLOCK
            P5ScratchPad pad = scratchpad;
            if (scratchpad != null && !is_main)
                pad = scratchpad.NewScope(runtime);
            int size = runtime.CallStack.Count;

            try
            {
                runtime.CallStack.Push(new StackFrame(runtime.Package,
                                                      runtime.File,
                                                      runtime.Line, this,
                                                      context, false));
                return subref(runtime, context, pad, args);
            }
            finally
            {
                StackFrame frame = new StackFrame();

                // the while() is required for tail calls,
                // until proper tail calls are implemented
                while (runtime.CallStack.Count > size)
                    frame = runtime.CallStack.Pop();

                if (size > 0)
                {
                    runtime.Package = frame.Package;
                    runtime.File = frame.File;
                    runtime.Line = frame.Line;
                }
            }
        }