Skip to content

Instantly share code, notes, and snippets.

@edefazio
Created December 17, 2019 21:36
Show Gist options
  • Save edefazio/22f7a0f209018c8658c3cf4391e4f7ed to your computer and use it in GitHub Desktop.
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
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