package st.gravel.support.compiler.testtools; import static org.junit.Assert.assertEquals; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import st.gravel.core.Symbol; import st.gravel.support.compiler.ast.ClassNode; import st.gravel.support.compiler.ast.EmptyTraitUsageNode; import st.gravel.support.compiler.ast.MethodNode; import st.gravel.support.compiler.ast.Parser; import st.gravel.support.compiler.ast.SharedDeclarationNode; import st.gravel.support.compiler.ast.SystemDefinitionNode; import st.gravel.support.compiler.ast.VariableDeclarationNode; import st.gravel.support.jvm.runtime.ImageBootstrapper; public class ClassBuilder { private static int evaluateCounter = 0; private final String name; private String superclassName = "st.gravel.lang.Object"; private final ArrayList<MethodNode> methods = new ArrayList<>(); private final ArrayList<MethodNode> classMethods = new ArrayList<>(); private final ArrayList<VariableDeclarationNode> instVars = new ArrayList<>(); public ClassBuilder(String name) { this.name = name; } public ClassBuilder method(String source) { methods.add(Parser.factory.parseMethod_(source)); return this; } public ClassBuilder superclassName(String superclassName) { this.superclassName = superclassName; return this; } public ClassBuilder classMethod(String source) { classMethods.add(Parser.factory.parseMethod_(source)); return this; } public ClassBuilder instVar(String string) { instVars.add(VariableDeclarationNode.factory.name_(string)); return this; } public Class build() { Map<String, String> _properties = new HashMap<>(); VariableDeclarationNode[] _instVars = instVars .toArray(new VariableDeclarationNode[instVars.size()]); VariableDeclarationNode[] _classInstVars = new VariableDeclarationNode[0]; MethodNode[] _methods = methods.toArray(new MethodNode[methods.size()]); MethodNode[] _classMethods = classMethods .toArray(new MethodNode[classMethods.size()]); Symbol[] _namespace = new Symbol[] { Symbol.value("ClassBuilder") }; ClassNode classNode = ClassNode.factory .name_superclassPath_properties_instVars_classInstVars_sharedVariables_methods_classMethods_namespace_isExtension_isTrait_traitUsage_classTraitUsage_( Symbol.value(name), superclassName, _properties, _instVars, _classInstVars, new SharedDeclarationNode[0], _methods, _classMethods, _namespace, false, false, EmptyTraitUsageNode.factory.basicNew(), EmptyTraitUsageNode.factory.basicNew()); SystemDefinitionNode systemDefinitionNode = ImageBootstrapper.systemMapping .systemDefinitionNode(); ImageBootstrapper.systemMapping.updateTo_(systemDefinitionNode .withPackageNamed_classNode_(Symbol.value(name), classNode)); return ImageBootstrapper.systemMapping.classMappingAtReference_( classNode.reference()).identityClass(); } public static Object evaluate(String string) { Class stClass = new ClassBuilder("Evaluate" + evaluateCounter++) .method("foo ^" + string).build(); try { Object fooObject = stClass.newInstance(); Method method = fooObject.getClass().getMethod("foo"); return method.invoke(fooObject); } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException(e); } } }