Last active
August 25, 2015 21:38
-
-
Save k33g/4783f8d03194230c8185 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module frankenstein | |
| import gololang.Adapters | |
| struct dynamicClass = { | |
| className, | |
| fields, | |
| methods, | |
| _ctClass | |
| } | |
| augment dynamicClass { | |
| function field = |this, fieldName, fieldType| { | |
| this: fields(): put(fieldName, fieldType) | |
| return this | |
| } | |
| function implements = |this, methodName, typeReturn, arguments, method| { | |
| this: methods(): put(methodName, [typeReturn, arguments, method]) | |
| return this | |
| } | |
| function toAdapter = |this| { | |
| let resolveCtClass = |clazz| { | |
| let pool = javassist.ClassPool.getDefault() | |
| return pool: get(clazz: getName()) | |
| } | |
| this: fields(): each(|fieldName, fieldType| { | |
| let field = javassist.CtField(resolveCtClass(clazz= fieldType), fieldName, this: _ctClass()) | |
| field: setModifiers(javassist.Modifier.PUBLIC()) | |
| this: _ctClass(): addField(field) | |
| }) | |
| this: methods(): each(|methodName, entry| { | |
| let counter = Observable(0) | |
| let params = entry: get(1)?: map(|type| { | |
| counter: set(counter: get() + 1) | |
| return type: getName() + " arg" + counter: get() | |
| })?: join(", ") orIfNull "" | |
| let method = javassist.CtNewMethod.make( | |
| "public " + (entry: get(0)?: getName() orIfNull "void") + " " + methodName +"("+ params +") { return null ; }" | |
| , this: _ctClass() | |
| ) | |
| this: _ctClass(): addMethod(method) | |
| }) | |
| let klass = this: _ctClass(): toClass() | |
| let klassDef = Adapter(): extends(this: className()) | |
| this: methods(): each(|methodName, entry| { | |
| klassDef: implements(methodName, entry: get(2)) | |
| }) | |
| return klassDef | |
| } | |
| } | |
| function DynamicClass = |className| { | |
| let pool = javassist.ClassPool.getDefault() | |
| let ctClass = pool: makeClass(className) | |
| let dynaKlass = dynamicClass(className, map[], map[], ctClass) | |
| return dynaKlass | |
| } | |
| function main = |args| { | |
| let Human = DynamicClass("org.k33g.Human") | |
| : field("name", String.class) | |
| : field("age", Integer.class) | |
| : implements( | |
| methodName= "hello", | |
| typeReturn= null, | |
| arguments= null, | |
| method = |this| -> println("Hello " + this: name() + "!") | |
| ) | |
| : implements( | |
| methodName= "yo", | |
| typeReturn= null, | |
| arguments= null, | |
| method = |this| -> println(">>> " + this: age() + "!") | |
| ) | |
| : implements( | |
| methodName= "toString", | |
| typeReturn= String.class, | |
| arguments= null, | |
| method = |this| -> this: name() + " - " + this: age() | |
| ) | |
| : implements( | |
| methodName= "changeAge", | |
| typeReturn= null, | |
| arguments= [Integer.class], | |
| method = |this, newAge| -> this: age(newAge) | |
| ) | |
| : implements( | |
| methodName= "say", | |
| typeReturn= String.class, | |
| arguments= [String.class, String.class], | |
| method = |this, message, someBody| { | |
| return "Hey " + someBody + "! I'am " + this: name() + ", " + message | |
| } | |
| ) | |
| : toAdapter() | |
| let bob = Human: newInstance() | |
| bob: name("Bob Morane"): age(42) | |
| bob: hello() | |
| bob: yo() | |
| bob: changeAge(24) | |
| println(bob: toString()) | |
| println(bob: say(message="I'm happy", someBody="Sam")) | |
| #let objDef = Adapter(): extends("org.k33g.Human") | |
| #let sam = objDef: newInstance() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment