/*
 * Copyright 2009 Yuichiro Moriguchi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.morilib.lisp.nano;

import java.util.logging.Logger;

/**
 * 
 *
 *
 * @author MORIGUCHI, Yuichiro 2009
 */
/*package*/ final class IntLispUtils {

	//
	private IntLispUtils() {
		// do nothing
	}

	//
	/*package*/ static void bindLocal(
			Datum prms, Datum bcdr, Environment env, LispMessage mesg) {
		while(true) {
			if(prms == Nil.NIL) {
				if(bcdr != Nil.NIL) {
					throw mesg.getError("err.parameter.insufficient");
				}
				break;
			} else if(prms instanceof Atom) {
				if(!(prms instanceof Symbol)) {
					throw mesg.getError("err.symbol", prms);
				}
				env.bindDatum(prms, bcdr);
				break;
			} else if(!(bcdr instanceof Cons)) {
				throw mesg.getError("err.parameter.insufficient");
			} else if(prms instanceof Cons) {
				Datum a1 = ((Cons)prms).getCar();
				Datum a2 = ((Cons)bcdr).getCar();

				if(a1 instanceof SymbolName) {
					env.bindDatum(a1, a2);
				} else {
					throw mesg.getError("err.symbol", a1);
				}

				prms = ((Cons)prms).getCdr();
				bcdr = ((Cons)bcdr).getCdr();
			} else {
				throw mesg.getError("err.type.insufficient");
			}
		}
	}

	//
	/*package*/ static void timelog(Logger _log, String str, long bef) {
		long dt = System.currentTimeMillis() - bef;
		String msec = ("000" + (dt % 1000));

		msec = msec.substring(msec.length() - 3);
		_log.fine(str + (dt / 1000) + "." + msec + "sec");
	}

	//
	/*package*/ static void timelogFiner(
			Logger _log, String str, long bef) {
		long dt = System.currentTimeMillis() - bef;
		String msec = ("000" + (dt % 1000));

		msec = msec.substring(msec.length() - 3);
		_log.finer(str + (dt / 1000) + "." + msec + "sec");
	}

	//
	/*package*/ static void loadJavaSubr(
			Environment env, Symbol k, String v) {
		env.bindDatum(k, getJavaSubr(k, v));
	}

	//
	/*package*/ static Datum getJavaSubr(Symbol k, String v) {
		try {
			Class<?> cls = Class.forName(v);
			Datum ins = (Datum)cls.newInstance();

			if(ins instanceof Subr) {
				((Subr)ins).symbolName = k.getName();
			} else if(ins instanceof Syntax) {
				((Syntax)ins).symbolName = k.getName();
			}
			return ins;
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}

	//
	/*package*/ static void loadJavaSubr(Environment env, Symbol k,
			String v, ClassLoader loader) {
		env.bindDatum(k, getJavaSubr(k, v, loader));
	}

	//
	/*package*/ static Datum getJavaSubr(Symbol k, String v,
			ClassLoader loader) {
		try {
			Class<?> cls = loader.loadClass(v);
			Datum ins = (Datum)cls.newInstance();

			if(ins instanceof Subr) {
				((Subr)ins).symbolName = k.getName();
			} else if(ins instanceof Syntax) {
				((Syntax)ins).symbolName = k.getName();
			}
			return ins;
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}

}
