Created
December 17, 2019 21:36
-
-
Save edefazio/22f7a0f209018c8658c3cf4391e4f7ed to your computer and use it in GitHub Desktop.
Use case for building dynamic Java Code at runtime which represents a LookupTable implemented via switch statements
This file contains 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
package use.jdraft.lut; | |
import java.util.Map; | |
import org.mrcode.Translator; | |
import org.mrcode.java.Stmt; | |
import org.mrcode.java._class; | |
import org.mrcode.java._method; | |
import org.mrcode.java.pattern.$case; | |
import org.mrcode.java.pattern.$method; | |
import org.mrcode.java.pattern.$stmt; | |
import org.mrcode.java.runtime._runtime; | |
import com.github.javaparser.ast.NodeList; | |
import com.github.javaparser.ast.stmt.BlockStmt; | |
import com.github.javaparser.ast.stmt.Statement; | |
import com.github.javaparser.ast.stmt.SwitchEntry; | |
import com.github.javaparser.ast.stmt.SwitchStmt; | |
import com.github.javaparser.ast.stmt.ThrowStmt; | |
import com.github.javaparser.ast.stmt.SwitchEntry.Type; | |
/** | |
* Given a Map, builds a Class that implements a lookup on the Map | |
* using | |
* | |
* @author Eric | |
*/ | |
public class LutBuilder { | |
public static final $method $LUT_METHOD = $method.of( | |
"public $valueType$ lookup( $keyType$ key ){", | |
" switch(key){", | |
" }", | |
"}"); | |
public static final $case $LUT_CASE = $case.of("case $key$: return $value$;"); | |
public static final Statement DEFAULT_STATEMENT = | |
Stmt.of("throw new RuntimeException(\"invalid key: \" + key);"); | |
//I need a new Translator that does Strings as \" \" (LITERALS) | |
public static final Translator StringLiteralTranslate = new Translator() { | |
@Override | |
public Object translate(Object source) { | |
if( source instanceof String) { | |
return "\""+source.toString()+"\""; | |
} | |
return Translator.DEFAULT_TRANSLATOR.translate(source); | |
} | |
}; | |
public static _class buildLutClass(String className, Class keyType, Class valueType, Map keyValues) { | |
return buildLutClass( className, keyType, valueType, keyValues, DEFAULT_STATEMENT); | |
} | |
public static _class buildLutClass(String className, Class keyType, Class valueType, Map keyValues, Statement defaultStatement) { | |
_class _c = _class.of(className); | |
_c.method( buildLutMethod(keyType, valueType, keyValues, defaultStatement) ); | |
return _c; | |
} | |
public static _method buildLutMethod(Class keyType, Class valueType, Map keyValues, Statement defaultStatement) { | |
_method _m = $LUT_METHOD.fill(valueType, keyType); | |
SwitchStmt ss = $stmt.switchStmt().firstIn(_m); | |
NodeList<SwitchEntry> ses = ss.getEntries(); | |
keyValues.forEach( (k,v)->ses.add($LUT_CASE.fill(StringLiteralTranslate, k, v)) ); | |
NodeList<Statement>sts = new NodeList<Statement>(); | |
sts.add(defaultStatement); | |
SwitchEntry defaultEntry; | |
if( defaultStatement instanceof ThrowStmt ) { | |
defaultEntry = new SwitchEntry(new NodeList<>(), Type.THROWS_STATEMENT, sts); | |
} | |
else if( defaultStatement instanceof BlockStmt) { | |
defaultEntry = new SwitchEntry(new NodeList<>(), Type.BLOCK, sts); | |
} | |
else { | |
defaultEntry = new SwitchEntry(new NodeList<>(), Type.STATEMENT_GROUP, sts); | |
} | |
ses.add( defaultEntry ); | |
return _m; | |
} | |
/** This is a specific example of building a String to int LUT with the map */ | |
public static Lut.String_to_int runtimeStringToIntLut(String className, Map<String,Integer> keyValues) { | |
_class _c = buildLutClass(className, String.class,int.class,keyValues); | |
_c.implement(Lut.String_to_int.class); | |
//System.out.println( _c ); | |
return (Lut.String_to_int)_runtime.instanceOf(_c); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment