Пример #1
0
        internal override void Compile(CompileParameter param)
        {
            ObjectName on = new ObjectName(param.Pkg.Name, Name.Name);

            if (ClassName != null)
            {
                // 成员函数必须有至少1个参数(self)
                if (TypeInfo.Params.Count < 1)
                {
                    throw new CompileException("Expect 'self' in method", TypeInfo.FuncPos);
                }

                on.ClassName = ClassName.Name;
            }

            var newset = new ValuePhoFunc(on, TypeInfo.FuncPos, TypeInfo.ScopeInfo.CalcUsedReg(), TypeInfo.ScopeInfo);

            bodyCS = newset;

            _proc = param.Exe.AddFunc(newset);

            if (ClassName != null)
            {
                param.NextPassToResolve(this);
            }

            var funcParam = param.SetLHS(false).SetCmdSet(newset);

            Body.Compile(funcParam);

            TypeInfo.GenDefaultRet(Body.Child(), funcParam);

            newset.InputValueCount = TypeInfo.Params.Count;

            newset.OutputValueCount = FuncType.CalcReturnValueCount(Body.Child());
        }
Пример #2
0
        // foo  var a
        // closure var b   间接UpValue a
        // closure2 var c  直接UpValue a, b

        // LINKU和LOADU对应
        // 引用模式分为2种
        // 1. 引用最近的上一层作用域,  LINKU第一个参数=0(当前执行体不是闭包时)
        // 1. 引用上N层作用域,  LINKU第一个参数=1 (当前执行体为闭包时)
        //
        // UpValue索引计算
        // 不使用被引用的变量在它归属作用域分配的寄存器索引
        // 直接引用并使用的UpValue

        internal override void Compile(CompileParameter param)
        {
            var newset = new ValuePhoFunc(param.Pkg.GenClosureName(), TypeInfo.FuncPos, TypeInfo.ScopeInfo.CalcUsedReg(), TypeInfo.ScopeInfo);

            var proc = param.Exe.AddFunc(newset);

            var closureCmd = new Command(Opcode.CLOSURE).SetCodePos(TypeInfo.FuncPos);

            closureCmd.EntryName = newset.Name;

            param.CS.Add(closureCmd);

            var funcParam = param.SetLHS(false).SetCmdSet(newset);

            // 深度遍历, 所以最终引用层会先被遍历到
            Body.Compile(funcParam);

            // 找到这一层闭包用的upvalues集合(引用上面函数作用域的)
            FindUsedUpvalue(Body);

            // 给每一个upvalue添加引用的upvalue
            foreach (var uv in UpValues)
            {
                AddRefUpvalueInNode(TypeInfo.ScopeInfo, uv.Symbol.RegBelong, uv);
            }

            int ThisLevelIndex = 0;

            foreach (var uv in UpValues)
            {
                var cmd = param.CS.Add(new Command(Opcode.LINKU, -1, -1))
                          .SetComment(uv.ToString())
                          .SetCodePos(TypeInfo.FuncPos);


                // 引用的上一层的upvalue的索引, 对应指令引用LocalReg的Index
                int UplevelIndex = GetRegIndex(TypeInfo.ScopeInfo, uv.Name);
                if (UplevelIndex != -1)
                {
                    cmd.DataA = 0;
                    cmd.DataB = UplevelIndex;
                }
                else
                {
                    // 引用上层自己的Upvalue(间接引用)
                    UplevelIndex = GetUpvalueIndex(TypeInfo.ScopeInfo, uv.Name);

                    cmd.DataA = 1;
                    cmd.DataB = UplevelIndex;
                }


                // LOADU的对应的Upvalue的索引, 修改下
                uv.CmdGen.DataA = ThisLevelIndex;

                ThisLevelIndex++;
            }

            TypeInfo.GenDefaultRet(Body.Child(), funcParam);

            newset.InputValueCount = TypeInfo.Params.Count;

            newset.OutputValueCount = FuncType.CalcReturnValueCount(Body.Child());
        }