/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package abs.backend.java.lib.runtime.metaABS; import abs.backend.java.lib.runtime.ABSClosure; import abs.backend.java.lib.runtime.ABSDynamicClass; import abs.backend.java.lib.runtime.ABSDynamicObject; import abs.backend.java.lib.runtime.COG; import abs.backend.java.lib.types.*; /* Class ABSObjectMirror * * The builtin ABS function reflect(o) creates an object mirror for * the given object o. Here we (dynamically) define the class of the meta-object, * including its interface, i.e. the meta-object protocol for object mirrors. */ public class ObjectMirror { private static ABSDynamicClass thisClass; /* * Create the class object for object mirrors. This only happens once. */ public static ABSDynamicClass singleton() { if (thisClass == null) { thisClass = new ABSDynamicClass(); setupAPI(); } return thisClass; } public static void setupAPI() { thisClass.setName("ObjectMirror"); /* * getClassName: get name of object's class */ thisClass.addMethod(/*ABSString*/ "getClassName", new ABSClosure() { @Override public ABSString exec(ABSDynamicObject t, ABSValue... params) { ABSString name; name = ABSString.fromString(((ABSDynamicObject)t.dispatch("getObject")).getClassName()); return name; } }); /* * getClass: get class of object */ thisClass.addMethod(/*ABSDynamicObject<Clazz>*/ "getClass", new ABSClosure() { @Override public ABSDynamicObject exec(ABSDynamicObject t, ABSValue... params) { ABSDynamicClass cls = ((ABSDynamicObject)t.dispatch("getObject")).getClazz(); ABSDynamicObject o = new ABSDynamicObject(Clazz.singleton()); o.setFieldValue("class", cls); return o; } }); /* * setClass: set new class for object */ thisClass.addMethod(/*Unit*/ "setClass", new ABSClosure() { @Override public ABSUnit exec(ABSDynamicObject t, ABSValue... params) { ABSDynamicClass cls = (ABSDynamicClass)((ABSDynamicObject)params[0]).getFieldValue_Internal("class"); ((ABSDynamicObject)t.dispatch("getObject")).setClazz(cls); return ABSUnit.UNIT; } }); /* * respondsTo: find out whether object responds to given method */ thisClass.addMethod(/*ABSBool*/ "respondsTo", new ABSClosure() { @Override public ABSBool exec(ABSDynamicObject t, ABSValue... params) { ABSDynamicClass cls = (ABSDynamicClass)((ABSDynamicObject)t.dispatch("getObject")).getClazz(); return ABSBool.fromBoolean(cls.hasMethod(((ABSString)params[0]).getString())); } }); // TODO: getFieldValue(), setFieldValue() thisClass.addMethod(/*ABSDynamicObject<COG>*/ "getCog", new ABSClosure() { @Override public ABSDynamicObject exec(ABSDynamicObject t, ABSValue... params) { COG cog = ((ABSDynamicObject)t.dispatch("getObject")).getCOG(); ABSDynamicObject o = new ABSDynamicObject(Cog.singleton()); o.setFieldValue("cog", cog); return o; } }); thisClass.addMethod(/*Unit*/ "setCog", new ABSClosure() { @Override public ABSUnit exec(ABSDynamicObject t, ABSValue... params) { ((ABSDynamicObject)t.dispatch("getObject")).setCOG((COG)params[0]); return ABSUnit.UNIT; } }); /* * getObject: obtain the mirrored object */ thisClass.addMethod(/*ABSDynamicObject*/ "getObject", new ABSClosure() { @Override public ABSDynamicObject exec(ABSDynamicObject t, ABSValue... params) { ABSDynamicObject object; object = (ABSDynamicObject)t.getFieldValue_Internal("object"); return object; } }); } }