// Path: src/stone/StoneException.java
// public class StoneException extends RuntimeException {
//     public StoneException(String m) { super(m); }
//     public StoneException(String m, ASTree t) {
//         super(m + " " + t.location());
//     }
// }
// 
// Path: src/stone/ast/ASTree.java
// public abstract class ASTree implements Iterable<ASTree> {
//     public abstract ASTree child(int i);
//     public abstract int numChildren();
//     public abstract Iterator<ASTree> children();
//     public abstract String location();
//     public Iterator<ASTree> iterator() { return children(); }
// }
// 
// Path: src/chap6/Environment.java
// public interface Environment {
//     void put(String name, Object value);
//     Object get(String name);
// }
// 
// Path: src/chap6/BasicEvaluator.java
// @Reviser public static abstract class ASTreeEx extends ASTree {
//     public abstract Object eval(Environment env);
// }
// 
// Path: src/chap7/FuncEvaluator.java
// @Require(BasicEvaluator.class)
// @Reviser public class FuncEvaluator {
//     @Reviser public static interface EnvEx extends Environment {
//         void putNew(String name, Object value);
//         Environment where(String name);
//         void setOuter(Environment e);
//     }
//     @Reviser public static class DefStmntEx extends DefStmnt {
//         public DefStmntEx(List<ASTree> c) { super(c); }
//         public Object eval(Environment env) {
//             ((EnvEx)env).putNew(name(), new Function(parameters(), body(), env));
//             return name();
//         }
//     }
//     @Reviser public static class PrimaryEx extends PrimaryExpr {
//         public PrimaryEx(List<ASTree> c) { super(c); }
//         public ASTree operand() { return child(0); }
//         public Postfix postfix(int nest) {
//             return (Postfix)child(numChildren() - nest - 1);
//         }
//         public boolean hasPostfix(int nest) { return numChildren() - nest > 1; } 
//         public Object eval(Environment env) {
//             return evalSubExpr(env, 0);
//         }
//         public Object evalSubExpr(Environment env, int nest) {
//             if (hasPostfix(nest)) {
//                 Object target = evalSubExpr(env, nest + 1);
//                 return ((PostfixEx)postfix(nest)).eval(env, target);
//             }
//             else
//                 return ((ASTreeEx)operand()).eval(env);
//         }
//     }
//     @Reviser public static abstract class PostfixEx extends Postfix {
//         public PostfixEx(List<ASTree> c) { super(c); }
//         public abstract Object eval(Environment env, Object value);
//     }
//     @Reviser public static class ArgumentsEx extends Arguments {
//         public ArgumentsEx(List<ASTree> c) { super(c); }
//         public Object eval(Environment callerEnv, Object value) {
//             if (!(value instanceof Function))
//                 throw new StoneException("bad function", this);
//             Function func = (Function)value;
//             ParameterList params = func.parameters();
//             if (size() != params.size())
//                 throw new StoneException("bad number of arguments", this);
//             Environment newEnv = func.makeEnv();
//             int num = 0;
//             for (ASTree a: this)
//                 ((ParamsEx)params).eval(newEnv, num++,
//                                         ((ASTreeEx)a).eval(callerEnv));
//             return ((BlockEx)func.body()).eval(newEnv);
//         }
//     }
//     @Reviser public static class ParamsEx extends ParameterList {
//         public ParamsEx(List<ASTree> c) { super(c); }
//         public void eval(Environment env, int index, Object value) {
//             ((EnvEx)env).putNew(name(index), value);
//         }
//     }
// }


import java.util.List;
import stone.StoneException;
import stone.ast.ASTree;
import javassist.gluonj.*;
import chap6.Environment;
import chap6.BasicEvaluator.ASTreeEx;
import chap7.FuncEvaluator;
package chap8;

@Require(FuncEvaluator.class)
@Reviser public class NativeEvaluator {
    @Reviser public static class NativeArgEx extends FuncEvaluator.ArgumentsEx {
        public NativeArgEx(List<ASTree> c) { super(c); }
        @Override public Object eval(Environment callerEnv, Object value) {
            if (!(value instanceof NativeFunction))
                return super.eval(callerEnv, value);

            NativeFunction func = (NativeFunction)value;
            int nparams = func.numOfParameters();
            if (size() != nparams)
// Path: src/stone/StoneException.java
// public class StoneException extends RuntimeException {
//     public StoneException(String m) { super(m); }
//     public StoneException(String m, ASTree t) {
//         super(m + " " + t.location());
//     }
// }
// 
// Path: src/stone/ast/ASTree.java
// public abstract class ASTree implements Iterable<ASTree> {
//     public abstract ASTree child(int i);
//     public abstract int numChildren();
//     public abstract Iterator<ASTree> children();
//     public abstract String location();
//     public Iterator<ASTree> iterator() { return children(); }
// }
// 
// Path: src/chap6/Environment.java
// public interface Environment {
//     void put(String name, Object value);
//     Object get(String name);
// }
// 
// Path: src/chap6/BasicEvaluator.java
// @Reviser public static abstract class ASTreeEx extends ASTree {
//     public abstract Object eval(Environment env);
// }
// 
// Path: src/chap7/FuncEvaluator.java
// @Require(BasicEvaluator.class)
// @Reviser public class FuncEvaluator {
//     @Reviser public static interface EnvEx extends Environment {
//         void putNew(String name, Object value);
//         Environment where(String name);
//         void setOuter(Environment e);
//     }
//     @Reviser public static class DefStmntEx extends DefStmnt {
//         public DefStmntEx(List<ASTree> c) { super(c); }
//         public Object eval(Environment env) {
//             ((EnvEx)env).putNew(name(), new Function(parameters(), body(), env));
//             return name();
//         }
//     }
//     @Reviser public static class PrimaryEx extends PrimaryExpr {
//         public PrimaryEx(List<ASTree> c) { super(c); }
//         public ASTree operand() { return child(0); }
//         public Postfix postfix(int nest) {
//             return (Postfix)child(numChildren() - nest - 1);
//         }
//         public boolean hasPostfix(int nest) { return numChildren() - nest > 1; } 
//         public Object eval(Environment env) {
//             return evalSubExpr(env, 0);
//         }
//         public Object evalSubExpr(Environment env, int nest) {
//             if (hasPostfix(nest)) {
//                 Object target = evalSubExpr(env, nest + 1);
//                 return ((PostfixEx)postfix(nest)).eval(env, target);
//             }
//             else
//                 return ((ASTreeEx)operand()).eval(env);
//         }
//     }
//     @Reviser public static abstract class PostfixEx extends Postfix {
//         public PostfixEx(List<ASTree> c) { super(c); }
//         public abstract Object eval(Environment env, Object value);
//     }
//     @Reviser public static class ArgumentsEx extends Arguments {
//         public ArgumentsEx(List<ASTree> c) { super(c); }
//         public Object eval(Environment callerEnv, Object value) {
//             if (!(value instanceof Function))
//                 throw new StoneException("bad function", this);
//             Function func = (Function)value;
//             ParameterList params = func.parameters();
//             if (size() != params.size())
//                 throw new StoneException("bad number of arguments", this);
//             Environment newEnv = func.makeEnv();
//             int num = 0;
//             for (ASTree a: this)
//                 ((ParamsEx)params).eval(newEnv, num++,
//                                         ((ASTreeEx)a).eval(callerEnv));
//             return ((BlockEx)func.body()).eval(newEnv);
//         }
//     }
//     @Reviser public static class ParamsEx extends ParameterList {
//         public ParamsEx(List<ASTree> c) { super(c); }
//         public void eval(Environment env, int index, Object value) {
//             ((EnvEx)env).putNew(name(index), value);
//         }
//     }
// }


// Path: src/chap8/NativeEvaluator.java
import java.util.List;
import stone.StoneException;
import stone.ast.ASTree;
import javassist.gluonj.*;
import chap6.Environment;
import chap6.BasicEvaluator.ASTreeEx;
import chap7.FuncEvaluator;

package chap8;

@Require(FuncEvaluator.class)
@Reviser public class NativeEvaluator {
    @Reviser public static class NativeArgEx extends FuncEvaluator.ArgumentsEx {
        public NativeArgEx(List<ASTree> c) { super(c); }
        @Override public Object eval(Environment callerEnv, Object value) {
            if (!(value instanceof NativeFunction))
                return super.eval(callerEnv, value);

            NativeFunction func = (NativeFunction)value;
            int nparams = func.numOfParameters();
            if (size() != nparams)
                throw new StoneException("bad number of arguments", this);