diff --git a/src/org/rascalmpl/interpreter/result/ConcreteSyntaxResult.java b/src/org/rascalmpl/interpreter/result/ConcreteSyntaxResult.java index dc2d0bd7bc4..8eaf7ff7211 100644 --- a/src/org/rascalmpl/interpreter/result/ConcreteSyntaxResult.java +++ b/src/org/rascalmpl/interpreter/result/ConcreteSyntaxResult.java @@ -55,6 +55,7 @@ public Result is(Name name) { return ResultFactory.bool(Names.name(name).equals(consName), ctx); } } + return ResultFactory.bool(false, ctx); } @@ -145,6 +146,22 @@ public Result has(Name name) { } } } + else if (ProductionAdapter.isError(prod)) { + var eprod = ProductionAdapter.getErrorProd(prod); + int dot = ProductionAdapter.getErrorDot(prod); + IList syms = ProductionAdapter.getSymbols(eprod); + String tmp = Names.name(name); + + // only look before the dot. + for (int i = 0; i < dot; i++) { + var sym = syms.get(i); + if (SymbolAdapter.isLabel((IConstructor) sym)) { + if (SymbolAdapter.getLabel((IConstructor) sym).equals(tmp)) { + return ResultFactory.bool(true, ctx); + } + } + } + } } return super.has(name); } diff --git a/src/org/rascalmpl/values/parsetrees/ProductionAdapter.java b/src/org/rascalmpl/values/parsetrees/ProductionAdapter.java index 069bd300d81..d66d2027a03 100644 --- a/src/org/rascalmpl/values/parsetrees/ProductionAdapter.java +++ b/src/org/rascalmpl/values/parsetrees/ProductionAdapter.java @@ -16,6 +16,7 @@ package org.rascalmpl.values.parsetrees; import io.usethesource.vallang.IConstructor; +import io.usethesource.vallang.IInteger; import io.usethesource.vallang.IList; import io.usethesource.vallang.IListWriter; import io.usethesource.vallang.INode; @@ -37,10 +38,15 @@ private ProductionAdapter() { * @return a constructor name if present or null otherwise */ public static String getConstructorName(IConstructor tree) { - IConstructor def = getDefined(tree); + if (isDefault(tree)) { + IConstructor def = getDefined(tree); - if (SymbolAdapter.isLabel(def)) { - return SymbolAdapter.getLabel(def); + if (SymbolAdapter.isLabel(def)) { + return SymbolAdapter.getLabel(def); + } + } + else if (isError(tree)) { + return "recovered"; } return null; @@ -206,4 +212,12 @@ public static boolean shouldFlatten(IConstructor surrounding, IConstructor neste } return false; } + + public static int getErrorDot(IConstructor prod) { + return ((IInteger) prod.get("dot")).intValue(); + } + + public static IConstructor getErrorProd(IConstructor prod) { + return (IConstructor) prod.get("prod"); + } } diff --git a/src/org/rascalmpl/values/parsetrees/TreeAdapter.java b/src/org/rascalmpl/values/parsetrees/TreeAdapter.java index 4ab329a2a92..2bf2c468590 100644 --- a/src/org/rascalmpl/values/parsetrees/TreeAdapter.java +++ b/src/org/rascalmpl/values/parsetrees/TreeAdapter.java @@ -24,6 +24,7 @@ import org.fusesource.jansi.Ansi.Color; import org.rascalmpl.exceptions.ImplementationError; import org.rascalmpl.interpreter.utils.LimitedResultWriter; +import org.rascalmpl.values.IRascalValueFactory; import org.rascalmpl.values.RascalValueFactory; import org.rascalmpl.values.ValueFactoryFactory; import org.rascalmpl.values.parsetrees.visitors.TreeVisitor; @@ -139,6 +140,9 @@ public static IConstructor getProduction(ITree tree) { /** * This function assumes that getLabeledField does not return null for the same parameters! */ + // TODO @PieterOlivier I guess we could extend this the way we also extended the getLabeledField. + // if the field is still on the parsed side of the dot then we're fine. Otherwise we could + // think about shifting the dot if we put in correct trees at the right places? public static ITree putLabeledField(ITree tree, String field, ITree repl) { if (isAppl(tree)) { IConstructor prod = TreeAdapter.getProduction(tree); @@ -190,6 +194,28 @@ else if (ProductionAdapter.isRegular(prod)) { return null; } } + else if (ProductionAdapter.isError(prod)) { + var eprod = ProductionAdapter.getErrorProd(prod); + int dot = ProductionAdapter.getErrorDot(prod); + int index = SymbolAdapter.indexOfLabel(ProductionAdapter.getSymbols(eprod), field); + IList args = getArgs(tree); + + if (index != -1) { + if (index < dot) { + // changing the normal part of the tree + return setArgs(tree, args.put(index, repl)); + } + else if (index == dot) { + // extending the accepted part of the tree by one field + eprod = prod.set("prod", IRascalValueFactory.getInstance().integer(dot + 1)); + return setProduction(setArgs(tree, args.append(repl)), eprod); + } + else { + // otherwise we return null which indicates the field does not exist. + return null; + } + } + } } return null; @@ -266,6 +292,27 @@ else if (ProductionAdapter.isRegular(prod)) { return null; } } + else if (ProductionAdapter.isError(prod)) { + int dot = ProductionAdapter.getErrorDot(prod); + IConstructor eprod = ProductionAdapter.getErrorProd(prod); + IList syms = ProductionAdapter.getSymbols(eprod); + int index = SymbolAdapter.indexOfLabel(syms, field); + + if (index != -1) { + IConstructor sym = (IConstructor) syms.get(index); + sym = SymbolAdapter.stripLabelsAndConditions(sym); + + if (dot <= index) { + // we have parsed the field so we can just return it. + // this is a likely scenario + return new FieldResult(sym, (ITree) tree.getArgs().get(index)); + } + else { + // we simply don't have that field yet. too bad. + return null; + } + } + } } return null;