// 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/chap14/TypeInfo.java
// public static class UnknownType extends TypeInfo {
//     @Override public TypeInfo type() { return ANY; }
//     @Override public String toString() { return type().toString(); }
//     @Override public boolean isUnknownType() { return true; }
//     @Override public UnknownType toUnknownType() { return this; }
// }


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import stone.ast.ASTree;
import javassist.gluonj.Reviser;
import chap14.TypeInfo.UnknownType;
package chap14;

@Reviser public class InferTypes {
    @Reviser public static class TypeInfoEx extends TypeInfo {
        @Override
        public void assertSubtypeOf(TypeInfo type, TypeEnv tenv, ASTree where)
            throws TypeException
        {
            if (type.isUnknownType())
                ((UnknownTypeEx)type.toUnknownType()).assertSupertypeOf(this,
                                                                tenv, where);
            else
                super.assertSubtypeOf(type, tenv, where);
        }
        @Override public TypeInfo union(TypeInfo right, TypeEnv tenv) {
            if (right.isUnknownType())
                return right.union(this, tenv);
            else
                return super.union(right, tenv);
        }
        @Override public TypeInfo plus(TypeInfo right, TypeEnv tenv) {
            if (right.isUnknownType())
                return right.plus(this, tenv);
            else
                return super.plus(right, tenv);
        }
    }
// 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/chap14/TypeInfo.java
// public static class UnknownType extends TypeInfo {
//     @Override public TypeInfo type() { return ANY; }
//     @Override public String toString() { return type().toString(); }
//     @Override public boolean isUnknownType() { return true; }
//     @Override public UnknownType toUnknownType() { return this; }
// }


// Path: src/chap14/InferTypes.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import stone.ast.ASTree;
import javassist.gluonj.Reviser;
import chap14.TypeInfo.UnknownType;

package chap14;

@Reviser public class InferTypes {
    @Reviser public static class TypeInfoEx extends TypeInfo {
        @Override
        public void assertSubtypeOf(TypeInfo type, TypeEnv tenv, ASTree where)
            throws TypeException
        {
            if (type.isUnknownType())
                ((UnknownTypeEx)type.toUnknownType()).assertSupertypeOf(this,
                                                                tenv, where);
            else
                super.assertSubtypeOf(type, tenv, where);
        }
        @Override public TypeInfo union(TypeInfo right, TypeEnv tenv) {
            if (right.isUnknownType())
                return right.union(this, tenv);
            else
                return super.union(right, tenv);
        }
        @Override public TypeInfo plus(TypeInfo right, TypeEnv tenv) {
            if (right.isUnknownType())
                return right.plus(this, tenv);
            else
                return super.plus(right, tenv);
        }
    }
    @Reviser public static class UnknownTypeEx extends TypeInfo.UnknownType {