//Iterator実装テスト //TODO:try finallyを入れる必要がある private void _foreachUseIterator(NakoNodeForeach node) { int labelId = GetLableId(); int loopVarNo = node.loopVarNo; int valueVarNo = node.valueVarNo; int taisyouVarNo = node.taisyouVarNo; int kaisuVarNo = node.kaisuVarNo; int enumeratorVarNo = node.enumeratorVarNo; int enumeratorFuncNo = node.enumeratorFuncNo; int moveresultFuncNo = node.moveresultFuncNo; int getcurrentFuncNo = node.getcurrentFuncNo; int getdisposeFuncNo = node.getdisposeFuncNo; // (0) NakoILCode label_for_begin = createLABEL("ITERATOR_BEGIN" + labelId.ToString()); NakoILCode label_for_end = createLABEL("ITERATOR_END" + labelId.ToString()); NakoILCode label_for_continue = createLABEL("ITERATOR_CONTINUE" + labelId.ToString()); // (1) 変数を初期化する result.Add(label_for_begin); // カウンタ変数を初期化 addNewILCode(NakoILType.LD_CONST_INT, 0L); addNewILCode(NakoILType.ST_LOCAL, loopVarNo); // 反復要素の評価 //TODO:反復要素のGetEnumerator()を評価 //GetEnumerator(); addNewILCode(NakoILType.CALL,"GetEnumerator")? //addNewILCode(NakoILType.ST_LOCAL, valueVarNo); Write_r(node.nodeValue); // 値を評価 addNewILCode(NakoILType.ST_LOCAL, valueVarNo); addNewILCode(NakoILType.LD_LOCAL_REF, valueVarNo); addNewILCode(NakoILType.SYSCALL, enumeratorFuncNo); addNewILCode(NakoILType.ST_LOCAL, enumeratorVarNo); // (2) 条件をコードにする //TODO: MoveNext()=true NakoILCode label_for_cond = createLABEL("ITERATOR_COND" + labelId.ToString()); result.Add(label_for_cond); // L //MoveNext()に変更 addNewILCode(NakoILType.LD_LOCAL_REF, enumeratorVarNo); addNewILCode(NakoILType.SYSCALL, moveresultFuncNo); // R addNewILCode(NakoILType.LD_CONST_INT, true);//TODO:実際にコンパイルする時にこれはまずいはずなので、何か考える // LT addNewILCode(NakoILType.EQ); // IF BRANCH FALSE addNewILCode(NakoILType.BRANCH_FALSE, label_for_end); // 反復する値を変数「対象」にセット // ** 対象=値\(ループカウンタ) //TODO:対象=オブジェクト.Currentに変更 addNewILCode(NakoILType.LD_LOCAL_REF, enumeratorVarNo); addNewILCode(NakoILType.SYSCALL,getcurrentFuncNo); //addNewILCode(NakoILType.NOP, "let-taisyou"); // for DEBUG addNewILCode(NakoILType.ST_LOCAL, taisyouVarNo); //TODO:key // ** 回数=ループカウンタ+1 addNewILCode(NakoILType.LD_LOCAL, loopVarNo); addNewILCode(NakoILType.INC); addNewILCode(NakoILType.ST_LOCAL, kaisuVarNo); // (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.INC_LOCAL, loopVarNo); // (5) 手順2に戻る result.Add(createJUMP(label_for_cond)); result.Add(label_for_end); addNewILCode(NakoILType.LD_LOCAL_REF, enumeratorVarNo); addNewILCode(NakoILType.SYSCALL,getdisposeFuncNo); //TODO: EnumeratorをDisposeする }
//> _foreach : _value FOREACH _scope_or_statement //> ; private bool _foreachUseIterator() { TokenTry(); if (!_value()) return false; if (!Accept(NakoTokenType.FOREACH)) { TokenBack(); return false; } TokenFinally(); tok.MoveNext(); // skip FOREACH NakoNodeForeach repnode = new NakoNodeForeach(); // ローカル変数の領域を確保 repnode.taisyouVarNo = localVar.GetIndex(NakoReservedWord.TAISYOU, true); // 変数「対象」の変数番号を取得 repnode.kaisuVarNo = localVar.GetIndex(NakoReservedWord.KAISU, true); // カウンタ変数「回数」の変数番号を取得 repnode.loopVarNo = localVar.CreateVarNameless(); // ループカウンタ repnode.lenVarNo = localVar.CreateVarNameless(); // 要素サイズを記録 repnode.valueVarNo = localVar.CreateVarNameless(); // valueを評価した値を保持 //下二行を追加(9-23) repnode.enumeratorVarNo = localVar.CreateVarNameless(); // valueのGetEnumeratorを保持 repnode.enumeratorFuncNo = (int)globalVar.GetVar("GetEnumerator").Body; repnode.moveresultFuncNo = (int)globalVar.GetVar("MoveNext").Body; repnode.getcurrentFuncNo = (int)globalVar.GetVar("Current").Body; repnode.getdisposeFuncNo = (int)globalVar.GetVar("Dispose").Body; // ノードの取得 repnode.nodeValue = calcStack.Pop(); repnode.nodeBlocks = _scope_or_statement(); this.parentNode.AddChild(repnode); lastNode = repnode; return true; }
//TODO:_foreachUseIteratorがOKならば消す private void _foreach(NakoNodeForeach node) { int labelId = GetLableId(); int loopVarNo = node.loopVarNo; int lenVarNo = node.lenVarNo; int valueVarNo = node.valueVarNo; int taisyouVarNo = node.taisyouVarNo; int kaisuVarNo = node.kaisuVarNo; // (0) NakoILCode label_for_begin = createLABEL("FOREACH_BEGIN" + labelId.ToString()); NakoILCode label_for_end = createLABEL("FOREACH_END" + labelId.ToString()); // (1) 変数を初期化する result.Add(label_for_begin); // カウンタ変数を初期化 addNewILCode(NakoILType.LD_CONST_INT, 0L); addNewILCode(NakoILType.ST_LOCAL, loopVarNo); // 反復要素の評価 Write_r(node.nodeValue); // 値を評価 addNewILCode(NakoILType.ST_LOCAL, valueVarNo); // 要素数を得る addNewILCode(NakoILType.LD_LOCAL, valueVarNo); addNewILCode(NakoILType.ARR_LENGTH); addNewILCode(NakoILType.ST_LOCAL, lenVarNo); // (2) 条件をコードにする // i < iTo NakoILCode label_for_cond = createLABEL("FOREACH_COND" + labelId.ToString()); result.Add(label_for_cond); // L addNewILCode(NakoILType.LD_LOCAL, loopVarNo); // R addNewILCode(NakoILType.LD_LOCAL, lenVarNo); // LT addNewILCode(NakoILType.LT); // IF BRANCH FALSE addNewILCode(NakoILType.BRANCH_FALSE, label_for_end); // 反復する値を変数「対象」にセット // ** 対象=値\(ループカウンタ) addNewILCode(NakoILType.LD_LOCAL, valueVarNo); addNewILCode(NakoILType.LD_LOCAL, loopVarNo); addNewILCode(NakoILType.LD_ELEM_REF); //addNewILCode(NakoILType.NOP, "let-taisyou"); // for DEBUG addNewILCode(NakoILType.ST_LOCAL, taisyouVarNo); // ** 回数=ループカウンタ+1 addNewILCode(NakoILType.LD_LOCAL, loopVarNo); addNewILCode(NakoILType.INC); addNewILCode(NakoILType.ST_LOCAL, kaisuVarNo); // (3) 繰り返し文を実行する _loop_check_break_continue(node.nodeBlocks, label_for_end, label_for_begin); Write_r(node.nodeBlocks); // (4) 変数を加算する addNewILCode(NakoILType.INC_LOCAL, loopVarNo); // (5) 手順2に戻る result.Add(createJUMP(label_for_cond)); result.Add(label_for_end); }
//TODO:foreachUseIteratorがOKならば消す //> _foreach : _value FOREACH _scope_or_statement //> ; private bool _foreach() { TokenTry(); if (!_value()) return false; if (!Accept(NakoTokenType.FOREACH)) { TokenBack(); return false; } TokenFinally(); tok.MoveNext(); // skip FOREACH NakoNodeForeach repnode = new NakoNodeForeach(); // ローカル変数の領域を確保 repnode.taisyouVarNo = localVar.GetIndex(NakoReservedWord.TAISYOU, true); // 変数「対象」の変数番号を取得 repnode.kaisuVarNo = localVar.GetIndex(NakoReservedWord.KAISU, true); // カウンタ変数「回数」の変数番号を取得 repnode.loopVarNo = localVar.CreateVarNameless(); // ループカウンタ repnode.lenVarNo = localVar.CreateVarNameless(); // 要素サイズを記録 repnode.valueVarNo = localVar.CreateVarNameless(); // valueを評価した値を保持 // ノードの取得 repnode.nodeValue = calcStack.Pop(); repnode.nodeBlocks = _scope_or_statement(); this.parentNode.AddChild(repnode); lastNode = repnode; return true; }