private void _for(NakoNodeFor node) { int loopVarNo = node.loopVar.varNo; int labelId = GetLableId(); // (0) NakoILCode label_for_begin = createLABEL("FOR_BEGIN" + labelId.ToString()); NakoILCode label_for_end = createLABEL("FOR_END" + labelId.ToString()); NakoILCode label_for_continue = createLABEL("FOR_CONTINUE" + labelId.ToString()); // (1) 変数を初期化する result.Add(label_for_begin); Write_r(node.nodeFrom); addNewILCode(NakoILType.ST_LOCAL, loopVarNo); // (2) 条件をコードにする // i <= iTo NakoILCode label_for_cond = createLABEL("FOR_COND" + labelId.ToString()); result.Add(label_for_cond); // L addNewILCode(NakoILType.LD_LOCAL, loopVarNo); // R Write_r(node.nodeTo); // TODO:最適化 // LT_EQ addNewILCode(NakoILType.LT_EQ); // IF BRANCH FALSE addNewILCode(NakoILType.BRANCH_FALSE, label_for_end); // (3) 繰り返し文を実行する _loop_check_break_continue(node.nodeBlocks, label_for_end, label_for_continue); Write_r(node.nodeBlocks); //continue時には変数の加算が必要なので、ここに飛ばす必要がある result.Add(label_for_continue); // (4) 変数を加算する (ここ最適化できそう) addNewILCode(NakoILType.LD_LOCAL, loopVarNo); addNewILCode(NakoILType.INC); addNewILCode(NakoILType.ST_LOCAL, loopVarNo); // (5) 手順2に戻る result.Add(createJUMP(label_for_cond)); result.Add(label_for_end); }
//> _for : WORD _value _value FOR _scope_or_statement //> ; private bool _for() { NakoToken tokVar = null; TokenTry(); // local variable if (!Accept(NakoTokenType.WORD)) return false; tokVar = tok.CurrentToken; if (!(tokVar.Josi == "を" || tokVar.Josi == "で")) { return false; } tok.MoveNext(); // get argument * 2 if (!_value()) { TokenBack(); return false; } if (!_value()) { TokenBack(); return false; } NakoNodeFor fornode = new NakoNodeFor(); NakoNodeVariable v = new NakoNodeVariable(); fornode.loopVar = v; v.scope = NakoVariableScope.Local; v.Token = tokVar; v.varNo = localVar.CreateVar(tokVar.Value); fornode.nodeTo = calcStack.Pop(); fornode.nodeFrom = calcStack.Pop(); if (!Accept(NakoTokenType.FOR)) { TokenBack(); return false; } TokenFinally(); tok.MoveNext(); fornode.nodeBlocks = _scope_or_statement(); this.parentNode.AddChild(fornode); lastNode = fornode; return true; }