001: // Copyright (C) 2005 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ../../COPYING.
003:
004: package kawa.lang;
005:
006: import gnu.mapping.*;
007: import gnu.expr.*;
008: import gnu.text.SourceMessages;
009: import gnu.lists.*;
010:
011: /* This implements the R5RS "eval" procedure. */
012:
013: public class Eval extends Procedure1or2 {
014: public static final Eval eval = new Eval();
015: static {
016: eval.setName("eval");
017: }
018:
019: final static String evalFunctionName = "atEvalLevel";
020:
021: public static void eval(Object sexpr, Environment env,
022: CallContext ctx) throws Throwable {
023: PairWithPosition body;
024: if (sexpr instanceof PairWithPosition)
025: body = new PairWithPosition((PairWithPosition) sexpr,
026: sexpr, LList.Empty);
027: else {
028: body = new PairWithPosition(sexpr, LList.Empty);
029: body.setFile("<eval>");
030: }
031: evalBody(body, env, new SourceMessages(), ctx);
032: }
033:
034: public static Object evalBody(Object body, Environment env,
035: SourceMessages messages) throws Throwable {
036: CallContext ctx = CallContext.getInstance();
037: int oldIndex = ctx.startFromContext();
038: try {
039: evalBody(body, env, messages, ctx);
040: return ctx.getFromContext(oldIndex);
041: } catch (Throwable ex) {
042: ctx.cleanupFromContext(oldIndex);
043: throw ex;
044: }
045: }
046:
047: public static Object eval(Object sexpr, Environment env)
048: throws Throwable {
049: CallContext ctx = CallContext.getInstance();
050: int oldIndex = ctx.startFromContext();
051: try {
052: eval(sexpr, env, ctx);
053: return ctx.getFromContext(oldIndex);
054: } catch (Throwable ex) {
055: ctx.cleanupFromContext(oldIndex);
056: throw ex;
057: }
058: }
059:
060: public static void evalBody(Object body, Environment env,
061: SourceMessages messages, CallContext ctx) throws Throwable {
062: Language language = Language.getDefaultLanguage();
063: Environment saveGlobalEnv = Environment.getCurrent();
064: try {
065: if (env != saveGlobalEnv)
066: Environment.setCurrent(env);
067: Translator tr = new Translator(language, messages);
068: tr.immediate = true;
069: ModuleExp mod = tr.pushNewModule((String) null);
070: Compilation save_comp = Compilation.getCurrent();
071: try {
072: Compilation.setCurrent(tr);
073: int first = tr.formStack.size();
074: tr.scanBody(body, mod, false);
075: tr.firstForm = first;
076: tr.finishModule(mod);
077: } finally {
078: Compilation.setCurrent(save_comp);
079: }
080:
081: if (body instanceof PairWithPosition)
082: mod.setFile(((PairWithPosition) body).getFileName());
083: mod.setName(evalFunctionName);
084: ModuleExp.evalModule(env, ctx, tr, null, null);
085: if (messages.seenErrors())
086: throw new RuntimeException(
087: "invalid syntax in eval form:\n"
088: + messages.toString(20));
089: } finally {
090: if (env != saveGlobalEnv)
091: Environment.setCurrent(saveGlobalEnv);
092: }
093: }
094:
095: public Object apply1(Object arg1) throws Throwable {
096: return eval(arg1, Environment.user());
097: }
098:
099: public Object apply2(Object arg1, Object arg2) throws Throwable {
100: return eval(arg1, (Environment) arg2);
101: }
102:
103: public void apply(CallContext ctx) throws Throwable {
104: Procedure.checkArgCount(this , ctx.count);
105: Object exp = ctx.getNextArg();
106: Environment env;
107: env = (Environment) ctx.getNextArg(null);
108: if (env == null)
109: env = Environment.user();
110: ctx.lastArg();
111: eval(exp, env, ctx);
112: }
113: }
|