Skip to content

Commit

Permalink
Merge pull request #1863 from usethesource/import-optimizations
Browse files Browse the repository at this point in the history
Experimenting with some low hanging fruit in the code that parses and imports modules for the sake of DSL loading time in VScode
  • Loading branch information
jurgenvinju authored Sep 20, 2023
2 parents 774953d + a443cca commit 1e3218f
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 102 deletions.
2 changes: 0 additions & 2 deletions src/org/rascalmpl/interpreter/result/JavaMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
import org.rascalmpl.interpreter.utils.JavaBridge;
import org.rascalmpl.interpreter.utils.Names;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.uri.file.TempURIResolver;

import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.type.Type;
Expand Down
3 changes: 1 addition & 2 deletions src/org/rascalmpl/interpreter/utils/Modules.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ public static ISet getSyntax(ITree tree) {
return get(tree, "syntax");
}

public static List<Toplevel> getTypeDeclarations(ITree tree) {
public static List<Toplevel> getTypeDeclarations(ITree tree, ASTBuilder builder) {
ITree body = TreeAdapter.getArg(tree, "body");
ITree toplevels = TreeAdapter.getArg(body, "toplevels");
List<Toplevel> result = new LinkedList<>();
ASTBuilder builder = new ASTBuilder();

for (IValue toplevel : TreeAdapter.getListASTArgs(toplevels)) {
ITree declaration = TreeAdapter.getArg((ITree) toplevel, "declaration");
Expand Down
146 changes: 87 additions & 59 deletions src/org/rascalmpl/parser/ASTBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@
import org.rascalmpl.ast.Expression;
import org.rascalmpl.ast.Module;
import org.rascalmpl.ast.Statement;
import org.rascalmpl.ast.Sym;
import org.rascalmpl.exceptions.ImplementationError;
import org.rascalmpl.interpreter.asserts.Ambiguous;
import org.rascalmpl.parser.gtd.util.PointerKeyedHashMap;
import org.rascalmpl.semantics.dynamic.Tree;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.IList;
import io.usethesource.vallang.IListWriter;
import io.usethesource.vallang.ISet;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.exceptions.FactTypeUseException;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.parsetrees.ITree;
import org.rascalmpl.values.parsetrees.ProductionAdapter;
import org.rascalmpl.values.parsetrees.SymbolAdapter;
import org.rascalmpl.values.parsetrees.TreeAdapter;
Expand All @@ -52,8 +52,9 @@ public class ASTBuilder {
private static final String MODULE_SORT = "Module";

private final PointerKeyedHashMap<IValue, Expression> constructorCache = new PointerKeyedHashMap<IValue, Expression>();

private final static HashMap<String, Constructor<?>> astConstructors = new HashMap<String,Constructor<?>>();
private final static HashMap<String, Class<?>> astClasses = new HashMap<String,Class<?>>();

private final static ClassLoader classLoader = ASTBuilder.class.getClassLoader();

public static <T extends AbstractAST> T make(String sort, ISourceLocation src, Object... args) {
Expand Down Expand Up @@ -108,7 +109,7 @@ public Command buildCommand(org.rascalmpl.values.parsetrees.ITree parseTree) {
return buildSort(parseTree, "Command");
}

public Command buildSym(org.rascalmpl.values.parsetrees.ITree parseTree) {
public Sym buildSym(org.rascalmpl.values.parsetrees.ITree parseTree) {
return buildSort(parseTree, "Sym");
}

Expand Down Expand Up @@ -179,11 +180,17 @@ public AbstractAST buildValue(IValue arg) {
}

private List<AbstractAST> buildList(org.rascalmpl.values.parsetrees.ITree in) {
IList args = TreeAdapter.getListASTArgs(in);
List<AbstractAST> result = new ArrayList<AbstractAST>(args.length());
for (IValue arg: args) {
List<AbstractAST> result = new ArrayList<AbstractAST>(TreeAdapter.getListLength(in));

IList args = in.getArgs();
int seps = TreeAdapter.getSeparatorCount(in);

for (int i = 0; i < args.length(); i++) {
ITree arg = (ITree) args.get(i);
result.add(buildValue(arg));
i += seps;
}

return result;
}

Expand All @@ -210,26 +217,33 @@ private AbstractAST buildContextFreeNode(org.rascalmpl.values.parsetrees.ITree t
sort = "KeywordArguments_Expression"; break;
}

IList args = getASTArgs(tree);
int arity = args.length();
Object actuals[] = new Object[arity+2];
actuals[0] = TreeAdapter.getLocation(tree);
actuals[1] = tree;

int i = 2;
for (IValue arg : args) {
org.rascalmpl.values.parsetrees.ITree argTree = (org.rascalmpl.values.parsetrees.ITree) arg;

if (TreeAdapter.isList(argTree)) {
actuals[i] = buildList((org.rascalmpl.values.parsetrees.ITree) arg);
}
else {
actuals[i] = buildValue(arg);
// Here we see how precisely the constructors of the generated AST hierarchy
// are connected to the shape of the grammar rules for the Rascal syntax.
// The hierarchy is generated from the same grammar that these parse trees
// come from, and that's why this works.
Constructor<?> constructor = getConstructor(sort, cons);
int parameterCount = constructor.getParameterCount();
Object[] actuals = new Object[parameterCount];
int i = 0;
actuals[i++] = TreeAdapter.getLocation(tree);
actuals[i++] = tree;

IList args = tree.getArgs();

for (int j = 0; j < args.length(); j += 2 /* skipping layout */) {
ITree argTree = (ITree) args.get(j);

if (!TreeAdapter.isLiteral(argTree) && !TreeAdapter.isCILiteral(argTree) && !TreeAdapter.isEmpty(argTree)) {
if (TreeAdapter.isList(argTree)) {
actuals[i++] = buildList((org.rascalmpl.values.parsetrees.ITree) argTree);
}
else {
actuals[i++] = buildValue(argTree);
}
}
i++;
}

return callMakerMethod(sort, cons, actuals, null);
return callMakerMethod(constructor, actuals, null);
}

private AbstractAST buildLexicalNode(org.rascalmpl.values.parsetrees.ITree tree) {
Expand Down Expand Up @@ -364,22 +378,6 @@ private String getLayoutName(IConstructor production) {
return null;
}

private IList getASTArgs(org.rascalmpl.values.parsetrees.ITree tree) {
IList children = TreeAdapter.getArgs(tree);
IListWriter writer = ValueFactoryFactory.getValueFactory().listWriter();

for (int i = 0; i < children.length(); i++) {
org.rascalmpl.values.parsetrees.ITree kid = (org.rascalmpl.values.parsetrees.ITree) children.get(i);
if (!TreeAdapter.isLiteral(kid) && !TreeAdapter.isCILiteral(kid) && !TreeAdapter.isEmpty(kid)) {
writer.append(kid);
}
// skip layout
i++;
}

return writer.done();
}

private String sortName(org.rascalmpl.values.parsetrees.ITree tree) {
if (TreeAdapter.isAppl(tree)) {
return TreeAdapter.getSortName(tree);
Expand Down Expand Up @@ -422,10 +420,7 @@ private boolean isNewEmbedding(org.rascalmpl.values.parsetrees.ITree tree) {
}

private boolean isLexical(org.rascalmpl.values.parsetrees.ITree tree) {
if (TreeAdapter.isRascalLexical(tree)) {
return true;
}
return false;
return TreeAdapter.isRascalLexical(tree);
}

private AbstractAST newLift(org.rascalmpl.values.parsetrees.ITree tree, boolean match) {
Expand All @@ -434,31 +429,50 @@ private AbstractAST newLift(org.rascalmpl.values.parsetrees.ITree tree, boolean
return liftRec(fragment, false, getPatternLayout(tree));
}

private static AbstractAST callMakerMethod(String sort, String cons, Object actuals[], Object keywordActuals[]) {
private static Class<?> loadClass(String name) throws ClassNotFoundException {
if (astClasses.containsKey(name)) {
return astClasses.get(name);
}

Class<?> result = null;

try {
result = classLoader.loadClass("org.rascalmpl.semantics.dynamic." + name);
}
catch (ClassNotFoundException e) {
result = classLoader.loadClass("org.rascalmpl.ast." + name);
}

astClasses.put(name, result);
return result;
}

private static Constructor<?> getConstructor(String sort, String cons) {
try {
String name = sort + '$' + cons;
Constructor<?> constructor = astConstructors.get(name);

if (constructor == null) {
Class<?> clazz = null;

try {
clazz = classLoader.loadClass("org.rascalmpl.semantics.dynamic." + name);
}
catch (ClassNotFoundException e) {
// it happens
}

if (clazz == null) {
clazz = classLoader.loadClass("org.rascalmpl.ast." + name);
}
Class<?> clazz = loadClass(name);

constructor = clazz.getConstructors()[0];
constructor.setAccessible(true);
astConstructors.put(name, constructor);
}

return (AbstractAST) constructor.newInstance(actuals);
return constructor;
} catch (SecurityException e) {
throw unexpectedError(e);
} catch (IllegalArgumentException e) {
throw unexpectedError(e);
} catch (ClassNotFoundException e) {
throw unexpectedError(e);
}
}

private static AbstractAST callMakerMethod(String sort, String cons, Object actuals[], Object keywordActuals[]) {
try {
return (AbstractAST) getConstructor(sort, cons).newInstance(actuals);
} catch (SecurityException e) {
throw unexpectedError(e);
} catch (IllegalArgumentException e) {
Expand All @@ -467,7 +481,21 @@ private static AbstractAST callMakerMethod(String sort, String cons, Object actu
throw unexpectedError(e);
} catch (InvocationTargetException e) {
throw unexpectedError(e);
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
throw unexpectedError(e);
}
}

private static AbstractAST callMakerMethod(Constructor<?> constructor, Object actuals[], Object keywordActuals[]) {
try {
return (AbstractAST) constructor.newInstance(actuals);
} catch (SecurityException e) {
throw unexpectedError(e);
} catch (IllegalArgumentException e) {
throw unexpectedError(e);
} catch (IllegalAccessException e) {
throw unexpectedError(e);
} catch (InvocationTargetException e) {
throw unexpectedError(e);
} catch (InstantiationException e) {
throw unexpectedError(e);
Expand Down
27 changes: 21 additions & 6 deletions src/org/rascalmpl/semantics/dynamic/Import.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
import io.usethesource.vallang.type.Type;

public abstract class Import {

private static final ThreadLocal<ASTBuilder> builder = ThreadLocal.withInitial(() -> new ASTBuilder());
static public class External extends org.rascalmpl.ast.Import.External {

public External(ISourceLocation src, IConstructor node, QualifiedName name,
Expand Down Expand Up @@ -381,7 +381,7 @@ private static Module buildModule(ISourceLocation uri, ModuleEnvironment env, I
}

private static ASTBuilder getBuilder() {
return new ASTBuilder();
return builder.get();
}

private static void addImportToCurrentModule(ISourceLocation src, String name, IEvaluator<Result<IValue>> eval) {
Expand Down Expand Up @@ -490,7 +490,7 @@ else if (reg.exists(parserCacheFile)) {
}

private static void declareTypesWhichDoNotNeedImportedModulesAlready(IEvaluator<Result<IValue>> eval, ModuleEnvironment env, ITree top) {
List<org.rascalmpl.ast.Toplevel> decls = Modules.getTypeDeclarations(top);
List<org.rascalmpl.ast.Toplevel> decls = Modules.getTypeDeclarations(top, getBuilder());

eval.__getTypeDeclarator().evaluateDeclarations(decls, eval.getCurrentEnvt(), true);
}
Expand Down Expand Up @@ -538,7 +538,12 @@ public ITree visitTreeAppl(ITree tree) {
IListWriter w = vf.listWriter();
IList args = TreeAdapter.getArgs(tree);
for (IValue arg : args) {
w.append(arg.accept(this));
if (!TreeAdapter.isLayout(tree) && !TreeAdapter.isLexical(tree)) {
w.append(arg.accept(this));
}
else {
w.append(arg);
}
}
args = w.done();

Expand Down Expand Up @@ -686,7 +691,12 @@ public ITree visitTreeAppl(ITree tree) {
IListWriter w = vf.listWriter();
IList args = TreeAdapter.getArgs(tree);
for (IValue arg : args) {
w.append(arg.accept(this));
if (!TreeAdapter.isLayout((ITree) arg)) {
w.append(arg.accept(this));
}
else {
w.append(arg);
}
}
args = w.done();

Expand Down Expand Up @@ -772,7 +782,12 @@ public ITree visitTreeAppl(ITree tree) {
IListWriter w = vf.listWriter();
IList args = TreeAdapter.getArgs(tree);
for (IValue elem : args) {
w.append(elem.accept(this));
if (!TreeAdapter.isLayout((ITree) elem)) {
w.append(elem.accept(this));
}
else {
w.append(elem);
}
}
args = w.done();

Expand Down
9 changes: 8 additions & 1 deletion src/org/rascalmpl/values/RascalFunctionValueFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.rascalmpl.values.functions.IFunction;
import org.rascalmpl.values.parsetrees.ITree;
import org.rascalmpl.values.parsetrees.SymbolAdapter;
import org.rascalmpl.values.parsetrees.SymbolFactory;
import org.rascalmpl.values.parsetrees.TreeAdapter;

import com.github.benmanes.caffeine.cache.Caffeine;
Expand Down Expand Up @@ -369,7 +370,13 @@ public IFunction bootstrapParsers() {
}

public IString createHole(ITree part, IInteger index) {
return getParserGenerator().createHole(part, index);
ITree hole = TreeAdapter.getArg(part, "hole");
ITree sym = TreeAdapter.getArg(hole, "symbol");
IConstructor symbol = SymbolFactory.typeToSymbol(sym , false, null);

IString result = ctx.getValueFactory().string("\u0000" + symbol.toString() + ":" + index + "\u0000");

return result;
}

public IConstructor sym2symbol(ITree parsedSym) {
Expand Down
11 changes: 6 additions & 5 deletions src/org/rascalmpl/values/parsetrees/ProductionAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ public static IConstructor getType(IConstructor tree) {
}

public static IConstructor getDefined(IConstructor tree) {
return (IConstructor) tree.get("def");
return (IConstructor) tree.get(0);
}

public static IConstructor setDefined(IConstructor tree, IConstructor sym) {
return (IConstructor) tree.set("def", sym);
return (IConstructor) tree.set(0 /*def */, sym);
}

public static IList getSymbols(IConstructor tree) {
if (isDefault(tree)) {
return (IList) tree.get("symbols");
return (IList) tree.get(1 /*symbols */);
}
return null;
}
Expand All @@ -84,7 +84,8 @@ public static IList getASTSymbols(IConstructor tree) {
}

public static boolean isContextFree(IConstructor tree) {
return SymbolAdapter.isSort(getType(tree));
IConstructor t = getType(tree);
return SymbolAdapter.isSort(t) || SymbolAdapter.isParameterizedSort(t);
}

public static boolean isLayout(IConstructor tree) {
Expand All @@ -107,7 +108,7 @@ public static String getSortName(IConstructor tree) {

public static ISet getAttributes(IConstructor tree) {
if (isDefault(tree)) {
return (ISet) tree.get("attributes");
return (ISet) tree.get(2 /* "attributes" */);
}

return ValueFactoryFactory.getValueFactory().set();
Expand Down
Loading

0 comments on commit 1e3218f

Please sign in to comment.