.forEach(this.updateDisambiguationCode(toGen,ntEnv,methNum));
res.setClassName(javaClassName);
String pic = res.getParserInitCode();
TypedAST parserInitAST;
if (pic == null)
parserInitAST = new Sequence();
else
parserInitAST = LangUtil.splice(new IParseBuffer(pic), "parser init");
String defNamePIA = "initGEN" + methNum.get();
toGenDefs.put(defNamePIA, parserInitAST);
methNum.set(methNum.get()+1);
res.setParserInitCode(String.format("Util.invokeValueVarargs(%s, \"%s\");\n", PAIRED_OBJECT_NAME, defNamePIA));
String ppc = res.getPostParseCode();
TypedAST postParseAST;
if (ppc == null)
postParseAST = new Sequence();
else
postParseAST = LangUtil.splice(new IParseBuffer(ppc), "post parse");
String defNameP = "postGEN" + methNum.get();
toGenDefs.put(defNameP, postParseAST);
methNum.set(methNum.get() + 1);
res.setPostParseCode(String.format("Util.invokeValueVarargs(%s, \"%s\");\n", PAIRED_OBJECT_NAME, defNameP));
res.setPreambleCode("import wyvern.tools.typedAST.interfaces.Value;\n" +
"import wyvern.tools.typedAST.core.values.StringConstant;\n" +
"import wyvern.tools.typedAST.extensions.interop.java.Util;\n" +
"import wyvern.tools.errors.FileLocation;\n" +
"import wyvern.tools.typedAST.core.values.IntegerConstant;\n" +
"import wyvern.tools.typedAST.core.values.TupleValue;\n" +
"import wyvern.tools.typedAST.core.values.UnitVal;\n" +
"import wyvern.tools.typedAST.extensions.interop.java.objects.JavaObj;\n" +
"import wyvern.tools.typedAST.extensions.ExternalFunction;\n" +
"import wyvern.tools.types.extensions.*;" +
"");
res.setParserClassAuxCode(
"Value "+PAIRED_OBJECT_NAME+" = null;\n" +
"ExternalFunction pushTokenV = new ExternalFunction(new Arrow(new Tuple(Util.javaToWyvType(Terminals.class),Str.getInstance()), Unit.getInstance()), (ee,v)->{\n" +
"\tpushToken((Terminals)(((JavaObj)((TupleValue)v).getValue(0)).getObj()), ((StringConstant)((TupleValue)v).getValue(1)).getValue());\n" +
"\treturn UnitVal.getInstance(FileLocation.UNKNOWN);\n" +
"});\n" +
"Value terminals;");
res.setParserInitCode("pushTokenV = new ExternalFunction(new Arrow(new Tuple(Util.javaToWyvType(Terminals.class),Str.getInstance()), Unit.getInstance()), (ee,v)->{\n" +
"\tpushToken((Terminals)(((JavaObj)((TupleValue)v).getValue(0)).getObj()), ((StringConstant)((TupleValue)v).getValue(1)).getValue());\n" +
"\treturn UnitVal.getInstance(FileLocation.UNKNOWN);\n" +
"});\n" +
"terminals = Util.javaToWyvDecl("+javaClassName+".Terminals.class).getClassObj();");
FileLocation unkLoc = FileLocation.UNKNOWN;
ParserCompilerParameters pcp = new ParserCompilerParameters();
ByteArrayOutputStream target = new ByteArrayOutputStream();
pcp.setOutputStream(new PrintStream(target));
pcp.setOutputType(CopperIOType.STREAM);
ByteArrayOutputStream dump = new ByteArrayOutputStream();
pcp.setDumpOutputType(CopperIOType.STREAM);
pcp.setDumpFormat(CopperDumpType.PLAIN);
pcp.setDump(CopperDumpControl.ON);
pcp.setDumpStream(new PrintStream(dump));
try {
ParserCompiler.compile(res, pcp);
} catch (CopperException e) {
throw new RuntimeException(e);
}
if (target.toString().isEmpty() ) {
System.out.println("Parser error! Parser debug dump");
System.out.println(dump.toString());
throw new RuntimeException();
}
System.out.println(dump.toString());
JavaCompiler jc = javax.tools.ToolProvider.getSystemJavaCompiler();
List<StringFileObject> compilationUnits = Arrays.asList(new StringFileObject(javaClassName, target.toString()));
StoringClassLoader loader = new StoringClassLoader(this.getClass().getClassLoader());
StoringFileManager sfm = new StoringFileManager(jc.getStandardFileManager(null, null, null),
loader);
StringFileObject sfo = new StringFileObject(javaClassName, target.toString());
sfm.putFileForInput(StandardLocation.SOURCE_PATH, "", javaClassName, sfo);
JavaCompiler.CompilationTask ct = jc.getTask(null, sfm, null, null, null, Arrays.asList(sfo));
if (!ct.call())
throw new RuntimeException();
loader.applyTransformer(name->name.equals(javaClassName), cw -> new ClassVisitor(Opcodes.ASM5, new CheckClassAdapter(cw)) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (!name.equals("<init>"))
return super.visitMethod(access, name, desc, signature, exceptions);
String ndesc = org.objectweb.asm.Type.getMethodDescriptor(org.objectweb.asm.Type.VOID_TYPE,
org.objectweb.asm.Type.getType(Value.class));
org.objectweb.asm.Type thisType = org.objectweb.asm.Type.getType("L" + javaClassName + ";");
MethodVisitor res = new CheckMethodAdapter(super.visitMethod(access, name, ndesc, null, exceptions));
GeneratorAdapter generator = new GeneratorAdapter(
res,
Opcodes.ASM5,
"<init>",
ndesc);
generator.visitCode();
generator.loadThis();
generator.invokeConstructor(org.objectweb.asm.Type.getType(SingleDFAEngine.class), Method.getMethod("void <init>()"));
generator.loadThis();
generator.loadArg(0);
generator.putField(thisType, PAIRED_OBJECT_NAME,
org.objectweb.asm.Type.getType(Value.class));
generator.returnValue();
generator.visitMaxs(2, 2);
generator.visitEnd();
return new MethodVisitor(Opcodes.ASM5) {};
}
});
Class javaClass = sfm.getClassLoader().loadClass(javaClassName);
JavaClassDecl jcd = Util.javaToWyvDecl(javaClass);
JavaClassDecl terminalsDecl = StreamSupport.stream(jcd.getDecls().getDeclIterator().spliterator(), false)
.filter(decl -> decl instanceof JavaClassDecl)
.<JavaClassDecl>map(decl -> (JavaClassDecl) decl)
.filter(decl -> decl.getName().equals("Terminals"))
.findFirst().orElseThrow(() -> new RuntimeException("Cannot find terminals class"));
Type terminalClassType = terminalsDecl
.extend(Environment.getEmptyEnvironment(), Environment.getEmptyEnvironment())
.lookup("Terminals").getType();
Type terminalObjType = terminalsDecl
.extend(Environment.getEmptyEnvironment(), Environment.getEmptyEnvironment())
.lookupType("Terminals").getType();
splicers.forEach(splicer -> splicer.accept(terminalClassType,terminalObjType));
AtomicInteger cdIdx = new AtomicInteger();
TypedAST[] classDecls = new TypedAST[toGen.size() + toGenDefs.size() + 1];
toGen.entrySet().stream().forEach(entry->classDecls[cdIdx.getAndIncrement()]
= new ValDeclaration(entry.getKey(), DefDeclaration.getMethodType(entry.getValue().second().getArgBindings(), entry.getValue().first()), entry.getValue().second(), unkLoc));
toGenDefs.entrySet().stream().forEach(entry->classDecls[cdIdx.getAndIncrement()]
= new DefDeclaration(entry.getKey(), new Arrow(Unit.getInstance(), Unit.getInstance()), new LinkedList<>(), entry.getValue(), false));
classDecls[cdIdx.getAndIncrement()] = new DefDeclaration("create", new Arrow(Unit.getInstance(),
new UnresolvedType(wyvClassName)),
Arrays.asList(),
new New(new DeclSequence(), unkLoc), true);
ArrayList<TypedAST> pairedObjDecls = new ArrayList<>();
pairedObjDecls.addAll(Arrays.asList(classDecls));
TypedAST pairedObj = new ClassDeclaration(wyvClassName, "", "", new DeclSequence(pairedObjDecls), unkLoc);
Type parseBufferType = Util.javaToWyvType(ParseBuffer.class);
Type javaClassType = Util.javaToWyvType(javaClass);
TypedAST bufGet = new Application(
new Invocation(new Variable(new NameBindingImpl("buf", null), unkLoc), "getSrcString", null, unkLoc),
UnitVal.getInstance(unkLoc),
unkLoc);
ClassType emptyType =
new ClassType(new Reference<>(Environment.getEmptyEnvironment()), new Reference<>(Environment.getEmptyEnvironment()), new LinkedList<>(), "empty");
TypedAST javaObjInit = new Application(new ExternalFunction(new Arrow(emptyType, Util.javaToWyvType(Value.class)), (env,arg)->{
return Util.toWyvObj(arg);
}),
new Application(
new Invocation(new Variable(new NameBindingImpl(wyvClassName, null), unkLoc), "create", null, unkLoc),
UnitVal.getInstance(unkLoc), unkLoc), unkLoc);
TypedAST body = new Application(new ExternalFunction(new Arrow(Util.javaToWyvType(Object.class), Util.javaToWyvType(TypedAST.class)),
(env,arg)-> (Value)Util.toJavaObject(arg,Value.class)),
new Application(new Invocation(new Application(
new Invocation(new Variable(new NameBindingImpl(javaClassName, null), unkLoc), "create", null, unkLoc),
javaObjInit, unkLoc), "parse", null, unkLoc),
new TupleObject(new TypedAST[] {bufGet, new StringConstant("TSL code")}), unkLoc), unkLoc);