package akin.lang; import java.util.HashMap; /** Class in the runtime. Classes store methods and constants. Each object in the runtime has a class. */ public class AkinClass extends AkinObject { private String name; private AkinClass superClass; private HashMap<String, Method> methods; HashMap<String, AkinObject> constants; /** Creates a class inheriting from superClass. */ public AkinClass(String name, AkinClass superClass) { super("Class"); this.name = name; this.superClass = superClass; methods = new HashMap<String, Method>(); constants = new HashMap<String, AkinObject>(); } /** Creates a class inheriting from Object. */ public AkinClass(String name) { this(name, AkinRuntime.getObjectClass()); } public String getName() { return name; } public AkinClass getSuperClass() { return superClass; } public void setConstant(String name, AkinObject value) { constants.put(name, value); } public AkinObject getConstant(String name) { if (constants.containsKey(name)) return constants.get(name); if (superClass != null) return superClass.getConstant(name); return AkinRuntime.getNil(); } public boolean hasConstant(String name) { if (constants.containsKey(name)) return true; if (superClass != null) return superClass.hasConstant(name); return false; } public Method lookup(String name) throws MethodNotFound { if (methods.containsKey(name)) return methods.get(name); if (superClass != null) return superClass.lookup(name); throw new MethodNotFound(name); } public boolean hasMethod(String name) { if (methods.containsKey(name)) return true; if (superClass != null) return superClass.hasMethod(name); return false; } public void addMethod(String name, Method method) { methods.put(name, method); } /** Creates a new instance of the class. */ public AkinObject newInstance() { return new AkinObject(this); } /** Creates a new instance of the class, storing the value inside a ValueObject. */ public AkinObject newInstance(Object value) { return new ValueObject(this, value); } /** Creates a new subclass of this class. */ public AkinClass newSubclass(String name) { AkinClass klass = new AkinClass(name, this); AkinRuntime.getObjectClass().setConstant(name, klass); return klass; } /** Creates or returns a subclass if it already exists. */ public AkinClass subclass(String name) { AkinClass objectClass = AkinRuntime.getObjectClass(); if (objectClass.hasConstant(name)) return (AkinClass) objectClass.getConstant(name); return newSubclass(name); } /** Returns true if klass is a subclass of this class. */ public boolean isSubclass(AkinClass klass) { if (klass == this) return true; if (klass.getSuperClass() == null) return false; if (klass.getSuperClass() == this) return true; return isSubclass(klass.getSuperClass()); } @Override public boolean equals(Object other) { if (other == this) return true; if ( !(other instanceof AkinClass) ) return false; return name == ((AkinClass)other).getName(); } }