// Path: Support/rsense-0.2/src/org/cx4a/rsense/ruby/IRubyObject.java
// public interface IRubyObject {
//     public Ruby getRuntime();
//     public RubyClass getMetaClass();
//     public void setMetaClass(RubyClass metaClass);
//     public RubyClass getSingletonClass();
//     public RubyClass makeMetaClass(RubyClass superClass);
//     public IRubyObject getInstVar(String name);
//     public void setInstVar(String name, IRubyObject value);
//     public boolean isNil();
//     public boolean isInstanceOf(RubyModule klass);
//     public boolean isKindOf(RubyModule klass);
//     public Object getTag();
//     public void setTag(Object tag);
// }
// 
// Path: Support/rsense-0.2/src/org/cx4a/rsense/ruby/RubyObject.java
// public class RubyObject implements IRubyObject {
//     protected Ruby runtime;
//     protected RubyClass metaClass;
//     private Map<String, IRubyObject> instVars;
//     private Object tag;
// 
//     protected RubyObject(Ruby runtime) {
//         this(runtime, null);
//     }
// 
//     public RubyObject(Ruby runtime, RubyClass metaClass) {
//         this.runtime = runtime;
//         this.metaClass = metaClass;
//     }
// 
//     public Ruby getRuntime() {
//         return runtime;
//     }
// 
//     public RubyClass getMetaClass() {
//         return metaClass;
//     }
//     
//     public void setMetaClass(RubyClass metaClass) {
//         this.metaClass = metaClass;
//     }
// 
//     public RubyClass getSingletonClass() {
//         RubyClass klass;
//         if (getMetaClass().isSingleton() && ((MetaClass) getMetaClass()).getAttached() == this) {
//             klass = getMetaClass();
//         } else {
//             klass = makeMetaClass(getMetaClass());
//         }
//         return klass;
//     }
// 
//     public RubyClass makeMetaClass(RubyClass superClass) {
//         MetaClass klass = new MetaClass(runtime, superClass);
//         setMetaClass(klass);
// 
//         klass.setAttached(this);
//         klass.setMetaClass(superClass.getRealClass().getMetaClass());
// 
//         superClass.addSubclass(klass);
// 
//         return klass;
//     }
// 
//     public IRubyObject getInstVar(String name) {
//         return instVars == null ? null : instVars.get(name);
//     }
// 
//     public void setInstVar(String name, IRubyObject value) {
//         if (instVars == null) {
//             instVars = new HashMap<String, IRubyObject>();
//         }
//         instVars.put(name, value);
//     }
// 
//     public boolean isNil() {
//         return this == getRuntime().getNil();
//     }
// 
//     public boolean isInstanceOf(RubyModule klass) {
//         return runtime.isInstanceOf(this, klass);
//     }
// 
//     public boolean isKindOf(RubyModule klass) {
//         return runtime.isKindOf(this, klass);
//     }
// 
//     public Object getTag() {
//         return tag;
//     }
// 
//     public void setTag(Object tag) {
//         this.tag = tag;
//     }
// 
//     @Override
//     public String toString() {
//         return "<obj:" + metaClass.toString() + ">";
//     }
// }


import java.util.Collection;
import java.util.HashSet;
import org.cx4a.rsense.ruby.IRubyObject;
import org.cx4a.rsense.ruby.RubyObject;
import org.cx4a.rsense.util.Logger;
package org.cx4a.rsense.typing;



public class TypeSet extends HashSet<IRubyObject> {
    private static final long serialVersionUID = 0L;
    public static final int MEGAMORPHIC_THRESHOLD = 5;
    public static final TypeSet EMPTY = new TypeSet();

    private boolean megamorphic;

    public TypeSet() {
        super();
    }

    public TypeSet(TypeSet other) {
        super(other);
    }

    public boolean add(IRubyObject e) {
        if (megamorphic) return false;

        if (size() >= MEGAMORPHIC_THRESHOLD) {
            megamorphic = true;
            // FIXME simple way
            Logger.warn("megamorphic detected");
            clear();
// Path: Support/rsense-0.2/src/org/cx4a/rsense/ruby/IRubyObject.java
// public interface IRubyObject {
//     public Ruby getRuntime();
//     public RubyClass getMetaClass();
//     public void setMetaClass(RubyClass metaClass);
//     public RubyClass getSingletonClass();
//     public RubyClass makeMetaClass(RubyClass superClass);
//     public IRubyObject getInstVar(String name);
//     public void setInstVar(String name, IRubyObject value);
//     public boolean isNil();
//     public boolean isInstanceOf(RubyModule klass);
//     public boolean isKindOf(RubyModule klass);
//     public Object getTag();
//     public void setTag(Object tag);
// }
// 
// Path: Support/rsense-0.2/src/org/cx4a/rsense/ruby/RubyObject.java
// public class RubyObject implements IRubyObject {
//     protected Ruby runtime;
//     protected RubyClass metaClass;
//     private Map<String, IRubyObject> instVars;
//     private Object tag;
// 
//     protected RubyObject(Ruby runtime) {
//         this(runtime, null);
//     }
// 
//     public RubyObject(Ruby runtime, RubyClass metaClass) {
//         this.runtime = runtime;
//         this.metaClass = metaClass;
//     }
// 
//     public Ruby getRuntime() {
//         return runtime;
//     }
// 
//     public RubyClass getMetaClass() {
//         return metaClass;
//     }
//     
//     public void setMetaClass(RubyClass metaClass) {
//         this.metaClass = metaClass;
//     }
// 
//     public RubyClass getSingletonClass() {
//         RubyClass klass;
//         if (getMetaClass().isSingleton() && ((MetaClass) getMetaClass()).getAttached() == this) {
//             klass = getMetaClass();
//         } else {
//             klass = makeMetaClass(getMetaClass());
//         }
//         return klass;
//     }
// 
//     public RubyClass makeMetaClass(RubyClass superClass) {
//         MetaClass klass = new MetaClass(runtime, superClass);
//         setMetaClass(klass);
// 
//         klass.setAttached(this);
//         klass.setMetaClass(superClass.getRealClass().getMetaClass());
// 
//         superClass.addSubclass(klass);
// 
//         return klass;
//     }
// 
//     public IRubyObject getInstVar(String name) {
//         return instVars == null ? null : instVars.get(name);
//     }
// 
//     public void setInstVar(String name, IRubyObject value) {
//         if (instVars == null) {
//             instVars = new HashMap<String, IRubyObject>();
//         }
//         instVars.put(name, value);
//     }
// 
//     public boolean isNil() {
//         return this == getRuntime().getNil();
//     }
// 
//     public boolean isInstanceOf(RubyModule klass) {
//         return runtime.isInstanceOf(this, klass);
//     }
// 
//     public boolean isKindOf(RubyModule klass) {
//         return runtime.isKindOf(this, klass);
//     }
// 
//     public Object getTag() {
//         return tag;
//     }
// 
//     public void setTag(Object tag) {
//         this.tag = tag;
//     }
// 
//     @Override
//     public String toString() {
//         return "<obj:" + metaClass.toString() + ">";
//     }
// }


// Path: Support/rsense-0.2/src/org/cx4a/rsense/typing/TypeSet.java
import java.util.Collection;
import java.util.HashSet;
import org.cx4a.rsense.ruby.IRubyObject;
import org.cx4a.rsense.ruby.RubyObject;
import org.cx4a.rsense.util.Logger;

package org.cx4a.rsense.typing;



public class TypeSet extends HashSet<IRubyObject> {
    private static final long serialVersionUID = 0L;
    public static final int MEGAMORPHIC_THRESHOLD = 5;
    public static final TypeSet EMPTY = new TypeSet();

    private boolean megamorphic;

    public TypeSet() {
        super();
    }

    public TypeSet(TypeSet other) {
        super(other);
    }

    public boolean add(IRubyObject e) {
        if (megamorphic) return false;

        if (size() >= MEGAMORPHIC_THRESHOLD) {
            megamorphic = true;
            // FIXME simple way
            Logger.warn("megamorphic detected");
            clear();
            return super.add(new RubyObject(e.getRuntime(), e.getRuntime().getObject()));