// 手动分配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; }
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); } }