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; }
internal override void Compile(CompileParameter param) { foreach (var im in Imports) { im.Compile(param); } Block.Compile(param); }
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()); }
// 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()); }