예제 #1
0
        internal override void Compile(CompileParameter param)
        {
            int SelfCount = 0;


            // 尝试放入self作为第一个参数
            var selector = Func as SelectorExpr;

            if (selector != null)
            {
                SelfCount += selector.CompileSelfParameter(param.SetLHS(false));
            }


            // 先放参数
            foreach (var arg in Args)
            {
                arg.Compile(param.SetLHS(false));
            }

            // 本包及动态闭包调用
            Func.Compile(param.SetLHS(false));

            param.CS.Add(new Command(Opcode.CALL, Args.Count + SelfCount, GetReceiverCount())).SetCodePos(LParen);
        }
예제 #2
0
        internal override void Compile(CompileParameter param)
        {
            Condition.Compile(param.SetLHS(false));

            var jnzCmd = param.CS.Add(new Command(Opcode.JZ, 0))
                         .SetCodePos(IfPos)
                         .SetComment("if condition false");

            Body.Compile(param.SetLHS(false));

            var jmpCmd = param.CS.Add(new Command(Opcode.JMP, 0))
                         .SetCodePos(IfPos)
                         .SetComment("if condition true");

            // false body跳入
            jnzCmd.DataA = param.CS.CurrCmdID;

            if (ElseBody.Stmts.Count > 0)
            {
                ElseBody.Compile(param.SetLHS(false));
            }

            // true body执行完毕跳出
            jmpCmd.DataA = param.CS.CurrCmdID;
        }
예제 #3
0
 internal override void Compile(CompileParameter param)
 {
     foreach (var b in Stmts)
     {
         b.Compile(param.SetLHS(false));
     }
 }
예제 #4
0
        internal int CompileSelfParameter(CompileParameter param)
        {
            var xident = X as Ident;

            if (xident != null)
            {
                if (xident.Symbol == null)
                {
                    throw new CompileException("undefined symbol: " + xident.Name, DotPos);
                }

                // a.Do()的a 放入
                switch (xident.Symbol.Usage)
                {
                case SymbolUsage.Parameter:
                case SymbolUsage.Variable:
                {
                    X.Compile(param.SetLHS(false));
                    return(1);
                }
                }
            }

            return(0);
        }
예제 #5
0
        internal override void Compile(CompileParameter param)
        {
            Index.Compile(param.SetLHS(false));

            X.Compile(param.SetLHS(false));

            if (param.LHS)
            {
                // 赋值
                param.CS.Add(new Command(Opcode.SETI)).SetCodePos(LBrackPos);
            }
            else
            {
                // 取值
                param.CS.Add(new Command(Opcode.LOADI)).SetCodePos(LBrackPos);
            }
        }
예제 #6
0
        internal override void Compile(CompileParameter param)
        {
            for (int i = Results.Count - 1; i >= 0; i--)
            {
                Results[i].Compile(param.SetLHS(false));
            }


            param.CS.Add(new Command(Opcode.RET)).SetCodePos(RetPos);
        }
예제 #7
0
        internal override void Compile(CompileParameter param)
        {
            LoopBeginCmdID = param.CS.CurrCmdID;

            Condition.Compile(param.SetLHS(false));

            var jzCmd = param.CS.Add(new Command(Opcode.JZ, 0))
                        .SetCodePos(Pos)
                        .SetComment("while condition");

            param.LHS = false;
            Body.Compile(param.SetLHS(false));

            param.CS.Add(new Command(Opcode.JMP, LoopBeginCmdID))
            .SetCodePos(Pos)
            .SetComment("while loop");

            // false body跳入
            LoopEndCmdID = param.CS.CurrCmdID;
            jzCmd.DataA  = LoopEndCmdID;
        }
예제 #8
0
        internal override void Compile(CompileParameter param)
        {
            if (Init != null)
            {
                Init.Compile(param.SetLHS(false));
            }

            LoopBeginCmdID = param.CS.CurrCmdID;

            Command jzCmd = null;

            if (Condition != null)
            {
                Condition.Compile(param.SetLHS(false));

                jzCmd = param.CS.Add(new Command(Opcode.JZ, -1))
                        .SetCodePos(Pos)
                        .SetComment("for condition");
            }

            Body.Compile(param.SetLHS(false));

            if (Post != null)
            {
                Post.Compile(param.SetLHS(false));
            }


            param.CS.Add(new Command(Opcode.JMP, LoopBeginCmdID))
            .SetCodePos(Pos)
            .SetComment("for loop");

            // false body跳入
            if (jzCmd != null)
            {
                jzCmd.DataA = param.CS.CurrCmdID;
            }

            LoopEndCmdID = param.CS.CurrCmdID;
        }
예제 #9
0
        internal override void Compile(CompileParameter param)
        {
            switch (Op)
            {
            case TokenType.Assign:
            {
                foreach (var e in RHS)
                {
                    e.Compile(param.SetLHS(false));
                }
            }
            break;

            case TokenType.AddAssign:
            case TokenType.SubAssign:
            case TokenType.MulAssign:
            case TokenType.QuoAssign:
            {
                // 这种操作只允许一个一个来
                if (LHS.Count != 1 || RHS.Count != 1)
                {
                    throw new CompileException("assignment require 1 operand", AssignPos);
                }

                LHS[0].Compile(param.SetLHS(false));

                RHS[0].Compile(param.SetLHS(false));

                param.CS.Add(new Command(Token2OpCode(Op)))
                .SetCodePos(AssignPos);
            }
            break;
            }

            foreach (var e in LHS)
            {
                e.Compile(param.SetLHS(true));
            }
        }
예제 #10
0
        internal override void Compile(CompileParameter param)
        {
            foreach (var b in X)
            {
                // ExprStmt下不出现CallExpr可能是-foo();  1+foo() 这种奇葩写法
                // 返回值无法被回收, 所以直接报错
                if (!(b is CallExpr))
                {
                    throw new CompileException("invalid expression statement", DefPos);
                }

                b.Compile(param.SetLHS(false));
            }
        }
예제 #11
0
        // 手动分配1个iterator变量
        // k, v, iter = ITER( x, iter )
        //
        internal override void Compile(CompileParameter param)
        {
            var iterVar = DelcareIteratorVar();

            param.CS.Add(new Command(Opcode.INITR, iterVar.Symbol.RegIndex))
            .SetCodePos(Pos)
            .SetComment("init iterator");


            LoopBeginCmdID = param.CS.CurrCmdID;

            X.Compile(param);

            iterVar.Compile(param);

            var jmpCmd = param.CS.Add(new Command(Opcode.VISIT, -1))
                         .SetCodePos(Pos)
                         .SetComment("for kv");

            Key.Compile(param.SetLHS(true));

            Value.Compile(param.SetLHS(true));

            iterVar.Compile(param.SetLHS(true));

            Body.Compile(param.SetLHS(false));


            param.CS.Add(new Command(Opcode.JMP, LoopBeginCmdID))
            .SetCodePos(Pos)
            .SetComment("for kv loop");

            // 循环结束
            LoopEndCmdID = param.CS.CurrCmdID;
            jmpCmd.DataA = LoopEndCmdID;
        }
예제 #12
0
        internal override void Compile(CompileParameter param)
        {
            var cmd = param.CS.Add(new Command(Opcode.NEW)).SetCodePos(LBracePos).SetComment("Builtin.Map");

            cmd.EntryName = new ObjectName("Builtin", "Map");


            var kvParam = param.SetLHS(false);

            foreach (var kv in Values)
            {
                kv.Key.Compile(kvParam);
                kv.Value.Compile(kvParam);
            }

            param.CS.Add(new Command(Opcode.SETD, Values.Count)).SetCodePos(LBracePos);
        }
예제 #13
0
        internal override void Compile(CompileParameter param)
        {
            var opcode = Token2OpCode(Op);

            if (opcode != Opcode.NOP)
            {
                X.Compile(param);
            }
            else
            {
                throw new CompileException("Unknown unary operator", OpPos);
            }

            param.CS.Add(new Command(opcode)).SetCodePos(OpPos);

            // 赋值
            X.Compile(param.SetLHS(true));
        }
예제 #14
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());
        }
예제 #15
0
        internal override void Compile(CompileParameter param)
        {
            var xident = X as Ident;

            if (xident != null)
            {
                if (xident.Symbol == null)
                {
                    throw new CompileException("undefined symbol: " + xident.Name, DotPos);
                }

                switch (xident.Symbol.Usage)
                {
                // 包.函数名
                case SymbolUsage.Package:
                {
                    var pkg = param.Exe.GetPackageByName(xident.Name);

                    if (pkg == null)
                    {
                        throw new CompileException("package not found: " + xident.Name, DotPos);
                    }

                    // Ident直接出代码
                    Selector.Compile(param.SetLHS(false).SetPackage(pkg));
                }
                break;

                // 实例.函数名  转换为  函数名( 实例, p2...)
                // 类成员访问
                case SymbolUsage.Parameter:
                case SymbolUsage.Variable:
                case SymbolUsage.SelfParameter:
                {
                    X.Compile(param.SetLHS(false));


                    var ci = param.Constants.AddString(Selector.Name);

                    Opcode cm = param.LHS ? Opcode.SETM : Opcode.LOADM;

                    // 无法推导X类型, 所以这里只能用动态方法直接加载,或设置
                    param.CS.Add(new Command(cm, ci))
                    .SetCodePos(DotPos).SetComment(Selector.Name);
                }
                break;

                default:
                    throw new CompileException("unknown symbol usage", DotPos);
                }
            }
            else if (X is BaseLit)
            {
                // 提供一个self, 因为LOADB会吃掉self
                GetFuncSelf().Compile(param.SetLHS(false));


                var ci = param.Constants.AddString(Selector.Name);

                // 无法推导X类型, 所以这里只能用动态方法直接加载,或设置
                param.CS.Add(new Command(Opcode.LOADB, ci))
                .SetCodePos(DotPos).SetComment(Selector.Name);
            }
            else
            {
                // 动态表达式, 需要用指令解析
                X.Compile(param);

                var ci = param.Constants.AddString(Selector.Name);

                param.CS.Add(new Command(Opcode.SEL, ci))
                .SetCodePos(DotPos).SetComment(Selector.Name);
            }
        }
예제 #16
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());
        }