// // Environment.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 // import java.util.* ; class Environment implements Cloneable { public static final int ENTRIES = 12 ; public static final String JAVANULL = "*JAVANULL*" ; Vector dics ; Environment() { dics = new Vector() ; } Environment(Vector defaultdic) { dics = defaultdic ; } void addNewDic(Hashtable h) { dics.addElement(h) ; } // 「テーブルのクローンを作成」して返す(旧版) Environment __getLocalVars() throws CloneNotSupportedException { Environment ne = null ; if (!dics.isEmpty()) { // ローカル変数があるときのみ作成 ne = new Environment() ; // 頭から追加してゆく。 for (int i=0; i < dics.size() ;i++) ne.addNewDic((Hashtable)((Hashtable)dics.elementAt(i)).clone()) ; } return ne ; } // 「環境のコピーを作成」して返す。上の関数の代替。問題ないはず(多分) Environment getLocalVars() throws CloneNotSupportedException { Environment ne = null ; if (!dics.isEmpty()) { // ローカル変数があるときのみ作成 ne = new Environment((Vector)this.dics.clone()) ; } return ne ; } // 引数の辞書を加えた新たな環境を作成して返す(辞書テーブル自身は同一) Environment getNewDic(Environment e) throws CloneNotSupportedException { Environment ne = new Environment((Vector)this.dics.clone()) ; if (e != null) { // お尻から追加してゆく。 for (int i=0 ;i < e.dics.size() ;i++) ne.addNewDic((Hashtable)e.dics.elementAt(i)) ; } return ne ; } // 辞書を参照する Object lookup(SAtom s) { Object res = null ; for (int i = dics.size()-1 ; (res == null) && (i >= 0) ; i--) { res = ((Hashtable)dics.elementAt(i)).get(s) ; } // 大域値の参照 if (res == null) res = s.getGlobal() ; if (res == JAVANULL) res = null ; // null を取り扱うためのイカサマ return res ; } // 現在の環境に束縛 void bind(SAtom s,Object m) { Hashtable h ; if (m == null) m = JAVANULL ; // null を取り扱うためのイカサマ for (int i = dics.size()-1 ; i >= 0 ; i--) { h = (Hashtable)dics.elementAt(i) ; if (h.containsKey(s)) { h.put(s,m) ; return ; } } s.setGlobal(m) ; // 大域値への代入 } // ローカル辞書を表示する void printDics() { System.out.println(Sexpr.toStr(getlist(dics.elements()))) ; System.out.println("-------------------------------------") ; } // 環境全体を alist のリストとして得る public Object toalist() { return getlist(dics.elements()) ; } // 環境全体を alist のリストとして得る(下請け) private Object getlist(Enumeration e) { if (e.hasMoreElements()) { Hashtable h = (Hashtable)e.nextElement() ; return new Cons(getdicalist(h,h.keys()),getlist(e)) ; } return SAtom.nil ; } // 辞書(ハッシュテーブル)を lisp の連想リストとして得る(汎用) public static Object getdicalist(Hashtable h,Enumeration e) { if (e.hasMoreElements()) { Object o = e.nextElement() ; return new Cons(new Cons(o,h.get(o)),getdicalist(h,e)) ; } return SAtom.nil ; } }