// // ListIter.java : 引数リストを順に取り出すためのクラス // // This is a part of miolisp sourcefile // Copyright (C) 1998 Nishiyama, Naoki / Mio software lab. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // final class ListIter { // 繰り返し処理用コールバックインターフェイスクラス abstract static class cb { Environment env ; Object arg = SAtom.nil , result = SAtom.nil ; // 蓄積用変数。doeach の戻り値になる。 cb(Environment x) {env = x ;} cb(Environment x,Object a) {env = x ; arg = a ;} abstract boolean repeat(Object o) throws Exception ; // 戻り値が偽で中断 } ; int count ; Object o = SAtom.nil,last = SAtom.nil ; ListIter(Object x) { o = x ; count = 0 ;} // 繰り返し処理(o は進めない) Object doeach(String msg,ListIter.cb cb) throws Exception { Object start = o,i = o ; while (i != SAtom.nil) { if (i instanceof Cons) { Cons c = (Cons)i ; if (!cb.repeat(c.car)) break ; // 戻り値が偽のとき中断 i = c.cdr ; if (i == start) break ; } else { throw new EvalException(msg+" : Illeagal Argument list") ; } } return cb.result ; } // 次がなんであっても返す Object getNextObjForce() { if (!(o instanceof Cons)) { last = o ; return last ; } count++ ; last = ((Cons)o).car ; o = ((Cons)o).cdr ; return last ; } // 次の要素(中間)を返す Object getNextObj(String msg) throws EvalException { if (!(o instanceof Cons)) { throw new EvalException(msg+" : Too Few Arguments") ; } count++ ; last = ((Cons)o).car ; o = ((Cons)o).cdr ; return last ; } // 次の要素(最終)を返す Object getFinalObj(String msg) throws EvalException { last = getNextObj(msg) ; if (o != SAtom.nil) throw new EvalException(msg+" : Too Much Arguments") ; return last ; } // 次の要素(中間)を評価して返す Object getNextObjEval(String msg,Environment e) throws Exception { last = Eval.eval(getNextObj(msg),e) ; return last ; } // 次の要素(中間)を評価して、Cons であれば返す。 Cons getNextConsEval(String msg,Environment e) throws Exception { last = Evalutil.mustbecons(msg+" :",Eval.eval(getNextObj(msg),e)) ; return (Cons)last ; } // 次の要素(中間)が SAtom であれば返す SAtom getNextSAtom(String msg) throws EvalException { last = getNextObj(msg) ; if (!(last instanceof SAtom)) { throw new EvalException(msg+" : Arg "+count+" must be SAtom") ; } return (SAtom)last ; } // 次の要素(最終)を評価して返す Object getFinalObjEval(String msg,Environment e) throws Exception { last = Eval.eval(getFinalObj(msg),e) ; return last ; } // 残りの要素をまとめて返す Object getRest() { return o ; } // 残りの要素を評価したものをまとめて返す // (Evalutil.evalall 類似だが、Vector を使わない、ループが 1 重なので高速。 // ただし、評価が途中で失敗した場合、環境に影響が残る) Object getRestEval(String msg,Environment e) throws Exception { Object start = o,res = SAtom.nil ; Cons l = null ; while (o != SAtom.nil) { if (o instanceof Cons) { Object a = ((Cons)o).car,d = ((Cons)o).cdr ; Cons n = new Cons(Eval.eval(a,e),SAtom.nil) ; // 新しいコンスを得る if (l != null) { // これが第一要素でないなら l.cdr = n ; // 前のセルの cdr 部に新しいセルへのポインタをいれる } else { res = n ; // 第一要素なら、リストの先頭を戻り値として記憶 } l = n ; // 次のために記憶 o = d ; if (o == start) break ; // 循環リスト? } else { throw new EvalException(msg+" : Invalid list") ; } } last = res ; return res ; } }