Skip to content

Commit 3cbf567

Browse files
committed
Switch to using refactored dynsem entrypoint
This allows us to select our rules for ourselves and apply them with program terms and custom environments
1 parent 62771a6 commit 3cbf567

File tree

3 files changed

+97
-75
lines changed

3 files changed

+97
-75
lines changed

org.metaborg.spoofax.shell.core/src/main/java/org/metaborg/spoofax/shell/core/ClassPathInterpreterLoader.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.metaborg.spoofax.shell.core;
22

3+
import java.io.IOException;
34
import java.io.InputStream;
5+
import java.io.InputStreamReader;
46
import java.util.Properties;
57

68
import org.apache.commons.lang3.ClassUtils;
@@ -10,8 +12,10 @@
1012
import org.metaborg.meta.lang.dynsem.interpreter.DynSemContext;
1113
import org.metaborg.meta.lang.dynsem.interpreter.DynSemEntryPoint;
1214
import org.metaborg.meta.lang.dynsem.interpreter.DynSemLanguage;
13-
import org.metaborg.spoofax.shell.core.DynSemEvaluationStrategy.NonParser;
15+
import org.metaborg.meta.lang.dynsem.interpreter.ITermRegistry;
16+
import org.metaborg.meta.lang.dynsem.interpreter.nodes.rules.RuleRegistry;
1417

18+
import com.oracle.truffle.api.source.Source;
1519
import com.oracle.truffle.api.vm.PolyglotEngine;
1620

1721
/**
@@ -21,15 +25,7 @@
2125
* the supported {@link DynSemLanguage#PARSER configuration parameter}.
2226
*/
2327
public class ClassPathInterpreterLoader implements IInterpreterLoader {
24-
private NonParser nonParser;
25-
26-
/**
27-
* @param nonParser
28-
* The {@link NonParser} to inject as configuration parameter to the VM Builder.
29-
*/
30-
public ClassPathInterpreterLoader(NonParser nonParser) {
31-
this.nonParser = nonParser;
32-
}
28+
private String targetPackage;
3329

3430
@Override
3531
public PolyglotEngine loadInterpreterForLanguage(ILanguageImpl langImpl)
@@ -42,10 +38,22 @@ public PolyglotEngine loadInterpreterForLanguage(ILanguageImpl langImpl)
4238

4339
DynSemEntryPoint entryPoint = getEntryPoint(dynSemProperties);
4440

41+
targetPackage = dynSemProperties.getProperty("target.package");
42+
RuleRegistry ruleRegistry = entryPoint.getRuleRegistry();
43+
ITermRegistry termRegistry = entryPoint.getTermRegistry();
44+
4545
String mimeType = entryPoint.getMimeType();
46-
return PolyglotEngine.newBuilder().config(mimeType, DynSemLanguage.PARSER, nonParser)
47-
.config(mimeType, DynSemLanguage.RULE_REGISTRY, entryPoint.getRuleRegistry())
48-
.config(mimeType, DynSemLanguage.TERM_REGISTRY, entryPoint.getTermRegistry()).build();
46+
PolyglotEngine builtEngine =
47+
PolyglotEngine.newBuilder().config(mimeType, DynSemLanguage.RULE_REGISTRY, ruleRegistry)
48+
.config(mimeType, DynSemLanguage.TERM_REGISTRY, termRegistry).build();
49+
try {
50+
builtEngine
51+
.eval(Source.fromReader(new InputStreamReader(entryPoint.getSpecificationTerm()),
52+
"Evaluate to interpreter.").withMimeType(mimeType));
53+
} catch (IOException e) {
54+
throw new InterpreterLoadException(e);
55+
}
56+
return builtEngine;
4957
}
5058

5159
private DynSemLanguage getDynSemLanguageSingleton(Properties dynSemProperties)
@@ -71,6 +79,11 @@ private DynSemEntryPoint getEntryPoint(Properties dynSemProperties)
7179
}
7280
}
7381

82+
@Override
83+
public String getTargetPackage() {
84+
return targetPackage;
85+
}
86+
7487
private Class<?> getGeneratedClass(Properties dynSemProperties, String className)
7588
throws InterpreterLoadException {
7689
String targetPackage = dynSemProperties.getProperty("target.package");
Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,48 @@
11
package org.metaborg.spoofax.shell.core;
22

33
import java.io.IOException;
4-
import java.util.concurrent.Callable;
4+
import java.lang.reflect.InvocationTargetException;
55

6+
import org.apache.commons.beanutils.MethodUtils;
7+
import org.apache.commons.lang3.ClassUtils;
8+
import org.apache.commons.lang3.reflect.ConstructorUtils;
69
import org.metaborg.core.MetaborgException;
710
import org.metaborg.core.context.IContext;
811
import org.metaborg.core.language.ILanguageImpl;
9-
import org.metaborg.meta.lang.dynsem.interpreter.IDynSemLanguageParser;
12+
import org.metaborg.meta.lang.dynsem.interpreter.nodes.rules.RuleRegistry;
1013
import org.metaborg.meta.lang.dynsem.interpreter.nodes.rules.RuleResult;
14+
import org.metaborg.meta.lang.dynsem.interpreter.terms.ITerm;
15+
import org.metaborg.spoofax.core.shell.ShellFacet;
1116
import org.metaborg.spoofax.shell.core.IInterpreterLoader.InterpreterLoadException;
1217
import org.metaborg.spoofax.shell.output.AnalyzeResult;
1318
import org.metaborg.spoofax.shell.output.ParseResult;
19+
import org.spoofax.interpreter.core.Tools;
20+
import org.spoofax.interpreter.terms.IStrategoAppl;
21+
import org.spoofax.interpreter.terms.IStrategoConstructor;
1422
import org.spoofax.interpreter.terms.IStrategoTerm;
23+
import org.spoofax.jsglr.client.imploder.ImploderAttachment;
1524
import org.spoofax.terms.StrategoString;
1625
import org.spoofax.terms.TermFactory;
1726

18-
import com.oracle.truffle.api.source.Source;
27+
import com.github.krukow.clj_lang.PersistentHashMap;
1928
import com.oracle.truffle.api.vm.PolyglotEngine;
2029
import com.oracle.truffle.api.vm.PolyglotEngine.Value;
2130

2231
/**
2332
* An {@link IEvaluationStrategy} for DynSem-based languages.
2433
*/
2534
public class DynSemEvaluationStrategy implements IEvaluationStrategy {
26-
private IInterpreterLoader interpLoader;
35+
private final IInterpreterLoader interpLoader;
2736
private PolyglotEngine polyglotEngine;
28-
private NonParser nonParser;
37+
private String shellStartSymbol;
2938

3039
/**
3140
* Construct a new {@link DynSemEvaluationStrategy}. This does not yet load the interpreter for
3241
* the language. Rather, this is done when first invoking
3342
* {@link #evaluate(AnalyzeResult, IContext)} or {@link #evaluate(ParseResult, IContext)}.
3443
*/
3544
public DynSemEvaluationStrategy() {
36-
nonParser = new NonParser();
37-
interpLoader = new ClassPathInterpreterLoader(nonParser);
45+
interpLoader = new ClassPathInterpreterLoader();
3846
}
3947

4048
@Override
@@ -44,86 +52,82 @@ public String name() {
4452

4553
@Override
4654
public IStrategoTerm evaluate(ParseResult parsed, IContext context) throws MetaborgException {
47-
return evaluate(parsed.unit().input().text(), parsed.ast().get(), context.language());
55+
return evaluate(parsed.ast().get(), context.language());
4856
}
4957

5058
@Override
5159
public IStrategoTerm evaluate(AnalyzeResult analyzed, IContext context)
5260
throws MetaborgException {
53-
return evaluate(analyzed.unit().input().input().text(), analyzed.ast().get(),
54-
context.language());
61+
return evaluate(analyzed.ast().get(), context.language());
5562
}
5663

57-
private IStrategoTerm evaluate(String origSource, IStrategoTerm input, ILanguageImpl langImpl)
64+
private IStrategoTerm evaluate(IStrategoTerm input, ILanguageImpl langImpl)
5865
throws MetaborgException {
5966
if (uninitialized()) {
6067
initialize(langImpl);
6168
}
62-
nonParser.setCurrentTerm(input);
63-
Value eval = null;
69+
70+
ITerm programTerm = null;
6471
try {
65-
Source source = Source.fromNamedText(origSource, Integer.toHexString(input.hashCode()))
66-
.withMimeType("application/x-simpl");
67-
eval = polyglotEngine.eval(source);
68-
} catch (IOException e) {
69-
// TODO Auto-generated catch block
70-
e.printStackTrace();
72+
programTerm = getProgramTerm(input);
73+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
74+
| InvocationTargetException cause) {
75+
throw new MetaborgException("Error constructing program term from input.", cause);
7176
}
7277

73-
Value prog = polyglotEngine.findGlobalSymbol("INIT");
78+
IStrategoConstructor inputCtor = ((IStrategoAppl) input).getConstructor();
79+
String ctorName = inputCtor.getName();
80+
int arity = inputCtor.getArity();
81+
82+
if (!Tools.isTermAppl(input)) {
83+
throw new MetaborgException("Expected a StrategoAppl, but a \""
84+
+ input.getClass().getName() + "\" was found: "
85+
+ input.toString(1));
86+
}
87+
Value rule;
88+
if (getSortForTerm(input) == shellStartSymbol) {
89+
// Look up "-shell->" rule.
90+
rule = polyglotEngine.findGlobalSymbol(RuleRegistry.makeKey("shell", ctorName, arity));
91+
} else {
92+
// Look up a "-shell_init->" rule.
93+
rule = polyglotEngine.findGlobalSymbol(RuleRegistry.makeKey("init", ctorName, arity));
94+
}
7495
try {
75-
Callable<RuleResult> callable = new Callable<RuleResult>() {
76-
@Override
77-
public RuleResult call() throws Exception {
78-
return prog.execute().as(RuleResult.class);
79-
}
80-
};
81-
RuleResult ruleResult = callable.call();
96+
RuleResult ruleResult = rule.execute(programTerm).as(RuleResult.class);
8297
return new StrategoString(ruleResult.result.toString(), TermFactory.EMPTY_LIST,
8398
IStrategoTerm.IMMUTABLE);
84-
} catch (Exception e) {
85-
throw new RuntimeException(e);
99+
100+
} catch (IOException e) {
101+
throw new MetaborgException("Input/output error while evaluating.", e);
86102
}
87103
}
88104

89-
private boolean uninitialized() {
90-
return polyglotEngine == null;
105+
@SuppressWarnings("unchecked")
106+
private ITerm getProgramTerm(IStrategoTerm input) throws ClassNotFoundException,
107+
NoSuchMethodException, IllegalAccessException, InvocationTargetException {
108+
String termSort = getSortForTerm(input);
109+
// Get the abstract class for the sort of the term.
110+
Class<? extends ITerm> generatedTermClass = (Class<? extends ITerm>) ClassUtils
111+
.getClass(interpLoader.getTargetPackage() + ".terms.I" + termSort + "Term");
112+
return (ITerm) MethodUtils.invokeStaticMethod(generatedTermClass, "create", input);
91113
}
92114

93-
private void initialize(ILanguageImpl langImpl) throws InterpreterLoadException {
94-
polyglotEngine = interpLoader.loadInterpreterForLanguage(langImpl);
115+
private String getSortForTerm(IStrategoTerm input) {
116+
ImploderAttachment termAttachment = input.getAttachment(ImploderAttachment.TYPE);
117+
if (termAttachment == null) {
118+
return null;
119+
}
120+
return termAttachment.getElementSort();
95121
}
96122

97-
/**
98-
* An {@link IDynSemLanguageParser} which returns just the {@link IStrategoTerm} which is set by
99-
* the evaluation strategy. Since Truffle only supports programs parsed directly from source
100-
* code, we need this workaround to avoid having to parse source code to {@link IStrategoTerm
101-
* ASTs} again. Hence this class is called a {@link NonParser "non parser"}.
102-
*/
103-
static class NonParser implements IDynSemLanguageParser {
104-
private IStrategoTerm currentTerm;
105-
106-
/**
107-
* @return the current term.
108-
*/
109-
public IStrategoTerm getCurrentTerm() {
110-
return currentTerm;
111-
}
123+
private boolean uninitialized() {
124+
return polyglotEngine == null && shellStartSymbol == null;
125+
}
112126

113-
/**
114-
* Sets the term to be returned the next time the parser is called through
115-
* {@link PolyglotEngine#eval(Source)}.
116-
*
117-
* @param currentTerm
118-
* the current term to set.
119-
*/
120-
public void setCurrentTerm(IStrategoTerm currentTerm) {
121-
this.currentTerm = currentTerm;
122-
}
127+
private void initialize(ILanguageImpl langImpl) throws InterpreterLoadException {
128+
polyglotEngine = interpLoader.loadInterpreterForLanguage(langImpl);
123129

124-
@Override
125-
public IStrategoTerm parse(Source src) {
126-
return getCurrentTerm();
127-
}
130+
ShellFacet shellFacet = langImpl.facet(ShellFacet.class);
131+
shellStartSymbol = shellFacet.getShellStartSymbol();
128132
}
129133
}

org.metaborg.spoofax.shell.core/src/main/java/org/metaborg/spoofax/shell/core/IInterpreterLoader.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ public interface IInterpreterLoader {
2121
PolyglotEngine loadInterpreterForLanguage(ILanguageImpl langImpl)
2222
throws InterpreterLoadException;
2323

24+
/**
25+
* @return The target package of the files generated by DynSem.
26+
*/
27+
String getTargetPackage();
28+
2429
/**
2530
* Exception thrown when loading results in an error.
2631
*/

0 commit comments

Comments
 (0)