diff --git a/.vscode/launch.json b/.vscode/launch.json index ec4586fd25d..aa506d012ad 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -32,6 +32,15 @@ "projectName": "rascal", "vmArgs": "-Xss80m -Xmx2g -ea" }, + { + "type": "java", + "name": "Launch RascalShell Tutor", + "request": "launch", + "mainClass": "org.rascalmpl.shell.RascalShell", + "projectName": "rascal", + "cwd" : "${workspaceFolder}/../rascal-tutor", + "vmArgs": "-Xss80m -Xmx2g -ea" + }, { "type": "java", "name": "Attach RascalShell", @@ -40,6 +49,14 @@ "hostName": "localhost", "port": 9001 }, + { + "type": "java", + "name": "Attach Mvn Rascal", + "request": "attach", + "projectName": "rascal-maven-plugin", + "hostName": "localhost", + "port": 8000 + }, { "type": "java", "name": "Attach Rascal LSP Terminal", diff --git a/pom.xml b/pom.xml index 53e3e0672c0..398d5ccc9f1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.rascalmpl rascal - 0.35.0-RC2-SNAPSHOT + 0.35.0-RC8-SNAPSHOT jar @@ -32,7 +32,7 @@ org.rascalmpl.shell.RascalShell 2 11 - 0.22.0-RC2 + 0.25.0-RC2-SNAPSHOT @@ -116,7 +116,7 @@ org.rascalmpl rascal-maven-plugin - ${rascal-maven.version} + 0.25.0-RC1 true ${project.build.outputDirectory} @@ -156,7 +156,7 @@ package - + @@ -366,7 +366,7 @@ io.usethesource vallang - 1.0.0-RC3 + 1.0.0-RC11 org.ow2.asm diff --git a/src/org/rascalmpl/interpreter/DefaultTestResultListener.java b/src/org/rascalmpl/interpreter/DefaultTestResultListener.java index d588ab41cb1..fab6d6bed70 100644 --- a/src/org/rascalmpl/interpreter/DefaultTestResultListener.java +++ b/src/org/rascalmpl/interpreter/DefaultTestResultListener.java @@ -13,14 +13,11 @@ *******************************************************************************/ package org.rascalmpl.interpreter; -import java.io.IOException; import java.io.PrintWriter; -import org.rascalmpl.exceptions.Throw; import org.rascalmpl.repl.ReplTextWriter; import io.usethesource.vallang.ISourceLocation; -import io.usethesource.vallang.io.StandardTextWriter; public class DefaultTestResultListener implements ITestResultListener{ private PrintWriter err; @@ -119,19 +116,7 @@ else if (t != null) { err.println(); } err.println("error: " + test + " @ " + ReplTextWriter.valueToString(loc)); - err.println("\t" + t.getMessage()); - - if (t instanceof Throw) { - try { - ((Throw) t).getTrace().prettyPrintedString(err, new StandardTextWriter(true)); - } - catch (IOException e) { - // should not happen - } - } - else { - t.printStackTrace(err); - } + err.println(message); } else { failures++; diff --git a/src/org/rascalmpl/interpreter/TestEvaluator.java b/src/org/rascalmpl/interpreter/TestEvaluator.java index 47da78a248c..c555402e864 100644 --- a/src/org/rascalmpl/interpreter/TestEvaluator.java +++ b/src/org/rascalmpl/interpreter/TestEvaluator.java @@ -20,12 +20,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Random; import org.rascalmpl.interpreter.env.ModuleEnvironment; import org.rascalmpl.interpreter.result.AbstractFunction; import org.rascalmpl.test.infrastructure.QuickCheck; import org.rascalmpl.test.infrastructure.QuickCheck.TestResult; +import org.rascalmpl.test.infrastructure.QuickCheck.UnExpectedExceptionThrownResult; import io.usethesource.vallang.IBool; import io.usethesource.vallang.IString; @@ -117,7 +119,8 @@ private void runTests(ModuleEnvironment env, List tests) { } } catch (Throwable e) { - return new TestResult(false, e); + // TODO: add bound type parameters + return new UnExpectedExceptionThrownResult(test.getEnv().getName() + "::" + test.getName(), actuals, Map.of(), args, e); } }, env.getRoot().getStore(), tries, maxDepth, maxWidth); @@ -137,6 +140,7 @@ private void runTests(ModuleEnvironment env, List tests) { catch(Throwable e){ testResultListener.report(false, test.getName(), test.getAst().getLocation(), e.getMessage(), e); } + eval.getOutPrinter().flush(); eval.getErrorPrinter().flush(); } diff --git a/src/org/rascalmpl/library/List.rsc b/src/org/rascalmpl/library/List.rsc index 26a03040a1d..e8c86ba18df 100644 --- a/src/org/rascalmpl/library/List.rsc +++ b/src/org/rascalmpl/library/List.rsc @@ -19,7 +19,6 @@ module List import Exception; import Map; -import IO; @synopsis{Concatenate a list of lists.} diff --git a/src/org/rascalmpl/library/Location.rsc b/src/org/rascalmpl/library/Location.rsc index f47e63eb360..1da26a7ec69 100644 --- a/src/org/rascalmpl/library/Location.rsc +++ b/src/org/rascalmpl/library/Location.rsc @@ -77,13 +77,17 @@ Strict containment between two locations `inner` and `outer` holds when } bool isStrictlyContainedIn(loc inner, loc outer){ + if(inner == outer){ + return false; + } if(isSameFile(inner, outer)){ if(inner.offset?){ - return outer.offset? ==> ( inner.offset == outer.offset && inner.offset + inner.length < outer.offset + outer.length - || inner.offset > outer.offset && inner.offset + inner.length <= outer.offset + outer.length - ); - } else { - return inner.offset > 0 && !outer.offset?; + if(outer.offset?){ + return inner.offset == outer.offset && inner.offset + inner.length < outer.offset + outer.length + || inner.offset > outer.offset && inner.offset + inner.length <= outer.offset + outer.length; + } else { + return inner.offset > 0; + } } } return false; @@ -102,7 +106,11 @@ Containment between two locations `inner` and `outer` holds when bool isContainedIn(loc inner, loc outer){ if(isSameFile(inner, outer)){ if(inner.offset?){ - return outer.offset? ==> (inner.offset >= outer.offset && inner.offset + inner.length <= outer.offset + outer.length); + if(outer.offset?){ + return (inner.offset >= outer.offset && inner.offset + inner.length <= outer.offset + outer.length); + } else { + return true; + } } else { return !outer.offset?; } diff --git a/src/org/rascalmpl/library/Map.rsc b/src/org/rascalmpl/library/Map.rsc index c88045522cb..4512649e89f 100644 --- a/src/org/rascalmpl/library/Map.rsc +++ b/src/org/rascalmpl/library/Map.rsc @@ -157,7 +157,7 @@ int incr(int x) { return x + 1; } mapper(("apple": 1, "pear": 2, "orange": 3), prefix, incr); ``` } -public map[&K, &V] mapper(map[&K, &V] M, &L (&K) F, &W (&V) G) +public map[&L, &W] mapper(map[&K, &V] M, &L (&K) F, &W (&V) G) = (F(key) : G(M[key]) | &K key <- M); diff --git a/src/org/rascalmpl/library/Prelude.java b/src/org/rascalmpl/library/Prelude.java index 999ee0f41a0..409bb0f93f0 100644 --- a/src/org/rascalmpl/library/Prelude.java +++ b/src/org/rascalmpl/library/Prelude.java @@ -1341,8 +1341,8 @@ private void writeFileEnc(ISourceLocation sloc, IString charset, IList V, boolea else if (elem.getType().isSubtypeOf(RascalValueFactory.Tree)) { TreeAdapter.yield((IConstructor) elem, out); } - else{ - out.append(elem.toString()); + else { + new StandardTextWriter().write(elem, out); } } if (postfix != null) { diff --git a/src/org/rascalmpl/library/Set.rsc b/src/org/rascalmpl/library/Set.rsc index 39c8066445a..10e0f819cdd 100644 --- a/src/org/rascalmpl/library/Set.rsc +++ b/src/org/rascalmpl/library/Set.rsc @@ -276,7 +276,13 @@ public default (&T <:num) sum({(&T <: num) e, *(&T <: num) r}) @synopsis{Pick an arbitrary element from a set.} @description{ +This _randomly_ picks one element from a set, unless the set is empty. +:::warning +Use ((getSingleFrom)) if you want the element from a singleton set. ((getOneFrom)) will silently +continue even if there are more element present, which can be a serious threat to the validity of your +analysis algorithm (arbitrary data is not considered). +::: } @examples{ ```rascal-shell @@ -287,6 +293,16 @@ getOneFrom({"elephant", "zebra", "snake"}); getOneFrom({"elephant", "zebra", "snake"}); ``` } +@benefits{ +* Random sampling can be an effective test input selection strategy. +} +@pitfalls{ +* The name ((getOneFrom)) does not convey randomness. +* ((getOneFrom)) drops all the other elements. +If you are sure there is only one element and you need it, then use ((getSingleFrom)). It will fail fast if your assumption is wrong. +* If you need more then one element, then repeatedly calling ((getOneFrom)) will be expensive. Have a look at ((util::Sampling)) for more effective +sampling utilities. +} @javaClass{org.rascalmpl.library.Prelude} public java &T getOneFrom(set[&T] st); @@ -294,15 +310,45 @@ public java &T getOneFrom(set[&T] st); @synopsis{Get "first" element from a set.} @description{ Get "first" element of a set. Of course, sets are unordered and do not have a first element. -However, we may assume that sets are internally ordered in some way and this ordering is reproducible. +However, we could assume that sets are internally ordered in some way and this ordering is reproducible (it's deterministic up to hashing collisions). Applying `getFirstFrom` on the same set will always returns the same element. + +:::warning +Use ((getSingleFrom)) if you want the element from a singleton set. ((getFirstFrom)) will silently +continue even if there are more element present, which can be a serious threat to the validity of your +analysis algorithm (arbitrary data is not considered). +::: } @benefits{ This function helps to make set-based code more deterministic, for instance, for testing purposes. } +@pitfalls{ +* The deterministic order is _undefined_. This means it may be stable between runs, but not between releases of Rascal. +* There are much better ways to iterate over the elements of a set: + * Use the `<-` enumerator operator in a `for` loop or a comprehension. + * Use list matching +* ((getFirstFrom)) drops all the other elements + * If you are sure there is only one element and you need it, then use ((getSingleFrom)). It will fail fast if your assumption is wrong. +} @javaClass{org.rascalmpl.library.Prelude} public java &T getFirstFrom(set[&T] st); +@synopsis{Get the only element from a singleton set.} +@description{ +Get the only element of a singleton set. This fails with a ((CallFailed)) exception when the set is not a singleton. +} +@benefits{ +* ((getSingleFrom)) fails _fast_ if the assumption (parameter `st` is a singleton) is not met. +* If a binary relation `r` is injective (i.e. it models a function where each key only has one value) then all projections `r[key]` should produce singleton values: `{v}`. +Using ((getSingleFrom)) to get the element out makes sure we fail fast in case our assumptions were wrong, or they have changed. +* Never use ((getFirstFrom)) or ((takeOneFrom)) if you can use ((getSingleFrom)). +} +@pitfalls{ +* ((CallFailed)) exceptions are sometimes hard to diagnose. Look at the stack trace to see that it was ((getSingleFrom)) +that caused it, and then look at the parameter of ((CallFailed)) to see that the set was not a singleton. +} +public &T getSingleFrom(set[&T] st) = getFirstFrom(st) when size(st) == 1; + // TODO temporary? replacement due to unexplained behaviour of compiler //public &T getFirstFrom({&T f, *&T _}) = f; //public &T getFirstFrom(set[&T] _:{}) { throw EmptySet(); } diff --git a/src/org/rascalmpl/library/lang/java/m3/Core.rsc b/src/org/rascalmpl/library/lang/java/m3/Core.rsc index 08e21e84d13..fe871c1b9ad 100644 --- a/src/org/rascalmpl/library/lang/java/m3/Core.rsc +++ b/src/org/rascalmpl/library/lang/java/m3/Core.rsc @@ -115,7 +115,7 @@ java M3 createM3FromString(loc fileName, str contents, bool errorRecovery = fals java M3 createM3FromJarClass(loc jarClass, list[loc] classPath = []); @javaClass{org.rascalmpl.library.lang.java.m3.internal.EclipseJavaCompiler} -java M3 createM3FromSingleClass(loc jarClass, str className); +java M3 createM3FromSingleClass(loc jarClass, str className, list[loc] classPath = []); @javaClass{org.rascalmpl.library.lang.java.m3.internal.EclipseJavaCompiler} java M3 createM3FromJarFile(loc jarLoc, list[loc] classPath = []); diff --git a/src/org/rascalmpl/library/lang/java/m3/internal/EclipseJavaCompiler.java b/src/org/rascalmpl/library/lang/java/m3/internal/EclipseJavaCompiler.java index e01e61451f3..f044df7c7b9 100644 --- a/src/org/rascalmpl/library/lang/java/m3/internal/EclipseJavaCompiler.java +++ b/src/org/rascalmpl/library/lang/java/m3/internal/EclipseJavaCompiler.java @@ -67,9 +67,9 @@ public IValue createM3FromJarClass(ISourceLocation jarLoc, IList classPath) { return createM3FromJarClass(jarLoc, classPath, getM3Store()); } - public IValue createM3FromSingleClass(ISourceLocation classLoc, IString className) { + public IValue createM3FromSingleClass(ISourceLocation classLoc, IString className, IList classpath) { JarConverter converter = new JarConverter(getM3Store(), new HashMap<>()); - converter.convertJarFile(classLoc, ((IString) className).getValue()); + converter.convertJarFile(classLoc, ((IString) className).getValue(), classpath); return converter.getModel(false); } diff --git a/src/org/rascalmpl/library/lang/java/m3/internal/JarConverter.java b/src/org/rascalmpl/library/lang/java/m3/internal/JarConverter.java index 0061d3ee329..d0e59ad8a55 100644 --- a/src/org/rascalmpl/library/lang/java/m3/internal/JarConverter.java +++ b/src/org/rascalmpl/library/lang/java/m3/internal/JarConverter.java @@ -132,9 +132,9 @@ public void convertJar(ISourceLocation jar, IList classPath) { * @param classFile * @param className */ - public void convertJarFile(ISourceLocation classFile, String className) { + public void convertJarFile(ISourceLocation classFile, String className, IList classpath) { loc = classFile; - createSingleClassM3(className); + createSingleClassM3(className, classpath); } /** @@ -172,7 +172,11 @@ private void createM3() { * and parent packages is triggered. * @param className */ - private void createSingleClassM3(String className) { + private void createSingleClassM3(String className, IList classpath) { + if (resolver == null) { + resolver = new ASMNodeResolver(loc, classpath, typeStore); + } + String compUnit = className; ClassReader classReader = resolver.buildClassReader(className); diff --git a/src/org/rascalmpl/library/lang/rascal/tests/basic/Sets.rsc b/src/org/rascalmpl/library/lang/rascal/tests/basic/Sets.rsc index 380af2b0340..38e220533bc 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/basic/Sets.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/basic/Sets.rsc @@ -121,6 +121,22 @@ test bool tst_takeOneFrom(set[int] S) { return x in S && x notin S2 && size(S2) == size(S) - 1 && S2 < S; } +test bool tst_getSingleFrom(set[int] S) { + if ({e} := S) { + return getSingleFrom(S) == e; + } + return true; +} + +test bool tst_getSingleFromExample(str input) { + return getSingleFrom({input}) == input; +} + +@expected{CallFailed} +test bool tst_getSingleFromMore(str input, int i) { + getSingleFrom({input, i}); +} + test bool tst_toList(set[int] S) = isEmpty(S) || size(S) == size(toList(S)) && all(x <- S, x in toList(S)); test bool tst_toMap(rel[int, int] S) = isEmpty(S) || domain(S) == domain(toMap(S)) && range(S) == {*toMap(S)[k] | k <- toMap(S)}; diff --git a/src/org/rascalmpl/library/lang/rascal/tests/concrete/Issue1913.rsc b/src/org/rascalmpl/library/lang/rascal/tests/concrete/Issue1913.rsc new file mode 100644 index 00000000000..4690092aa75 --- /dev/null +++ b/src/org/rascalmpl/library/lang/rascal/tests/concrete/Issue1913.rsc @@ -0,0 +1,23 @@ +module lang::rascal::tests::concrete::Issue1913 + +extend lang::std::Layout; +import IO; + +syntax As = "begin" A* as "end"; + +syntax A = "a" | "b"; + +test bool issue1913() { + A* bs = (As)`begin b a b end`.as; + + As prog = (As)`begin b a a end`; + + prog = visit (prog) { + case (As)`begin b end` + => (As)`begin end` + } + + println(prog); + // don't loose a space + return "" == "begin b a b a a end"; +} \ No newline at end of file diff --git a/src/org/rascalmpl/library/util/Reflective.java b/src/org/rascalmpl/library/util/Reflective.java index 70c821fa58e..98f50a5a981 100644 --- a/src/org/rascalmpl/library/util/Reflective.java +++ b/src/org/rascalmpl/library/util/Reflective.java @@ -433,6 +433,10 @@ public IInteger getFingerprintNode(INode nd){ return values.integer(ToplevelType.getFingerprintNode(nd)); } + public IInteger getHashCode(IValue v) { + return values.integer(v.hashCode()); + } + public void throwNullPointerException() { throw new NullPointerException(); } diff --git a/src/org/rascalmpl/library/util/Reflective.rsc b/src/org/rascalmpl/library/util/Reflective.rsc index f86ec6058fa..2955befe5d0 100644 --- a/src/org/rascalmpl/library/util/Reflective.rsc +++ b/src/org/rascalmpl/library/util/Reflective.rsc @@ -287,6 +287,17 @@ public java int getFingerprint(value val, int arity, bool concretePatterns); @javaClass{org.rascalmpl.library.util.Reflective} public java int getFingerprintNode(node nd); +@synopsis{Get the internal hash code of a value. For the benefit of debugging the Rascal implementation.} +@description{ +This function is useless for Rascal programmer's as it is a part of the under-the-hood implementation of values. +You can use a value directly as a lookup key. The internal data-structures probably use this hashCode for +optimal lookups in `O(log(size))`. + +We use this function to diagnose possible performance issues caused by hash collisions. +} +@javaClass{org.rascalmpl.library.util.Reflective} +public java int getHashCode(value v); + @synopsis{Throw a raw Java NullPointerException, to help simulate an unexpected exception in test scenarios} @javaClass{org.rascalmpl.library.util.Reflective} java void throwNullPointerException(); diff --git a/src/org/rascalmpl/library/vis/Charts.rsc b/src/org/rascalmpl/library/vis/Charts.rsc index 9c2e5cfc2e0..6d6944aa922 100644 --- a/src/org/rascalmpl/library/vis/Charts.rsc +++ b/src/org/rascalmpl/library/vis/Charts.rsc @@ -85,29 +85,29 @@ Content scatterChart(list[str] labels, rel[num x,num y] values ..., str title="S * the radius is in raw pixels rather than scaled to the chart's axis } Content bubbleChart(lrel[num x,num y, num r] v, str title="Scatterplot", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(title, v), \type=bubble(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(title, v), \type=bubble(), title=title, colorMode=colorMode, legend=false)); Content bubbleChart(list[str] labels, lrel[num x,num y, num r] values ..., str title="Scatterplots", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(labels, values), \type=scatter(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=scatter(), title=title, colorMode=colorMode, legend=true)); Content bubbleChart(rel[num x,num y, num r] v, str title="Scatterplot", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(title, v), \type=scatter(), title=title, colorMode=colorMode)); - + = content(title, chartServer(chartData(title, v), \type=scatter(), title=title, colorMode=colorMode, legend=false)); + Content bubbleChart(list[str] labels, rel[num x,num y, num r] values ..., str title="Scatterplots", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(labels, values), \type=scatter(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=scatter(), title=title, colorMode=colorMode, legend=true)); @synopsis{A bar chart from labeled numbers} Content barChart(rel[str label, num val] values, str title="Bar Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\bar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\bar(), title=title, colorMode=colorMode, legend=false)); Content barChart(lrel[str label, num val] values, str title="Bar Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\bar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\bar(), title=title, colorMode=colorMode, legend=true)); Content barChart(list[str] labels, rel[str label, num val] values..., str title="Bar Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\bar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\bar(), title=title, colorMode=colorMode, legend=false)); Content barChart(list[str] labels, lrel[str label, num val] values..., str title="Bar Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\bar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\bar(), title=title, colorMode=colorMode, legend=true)); @synopsis{A line chart from labeled numbers} Content lineChart(rel[str label, num val] values, str title="Line Chart", ChartAutoColorMode colorMode=\dataset()) @@ -117,62 +117,62 @@ Content lineChart(lrel[str label, num val] values, str title="Line Chart", Chart = content(title, chartServer(chartData(values), \type=\line(), title=title, colorMode=colorMode, legend=false)); Content lineChart(list[str] labels, rel[str label, num val] values..., str title="Line Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\line(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\line(), title=title, colorMode=colorMode, legend=true)); Content lineChart(list[str] labels, lrel[str label, num val] values..., str title="Line Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\line(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\line(), title=title, colorMode=colorMode, legend=true)); @synopsis{A polar area chart from labeled numbers} Content polarAreaChart(rel[str label, num val] values, str title="Polar Area Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\polarArea(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\polarArea(), title=title, colorMode=colorMode, legend=false)); Content polarAreaChart(lrel[str label, num val] values, str title="Polar Area Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\polarArea(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\polarArea(), title=title, colorMode=colorMode, legend=false)); Content polarAreaChart(list[str] labels, rel[str label, num val] values..., str title="Polar Area Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\polarArea(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\polarArea(), title=title, colorMode=colorMode, legend=true)); Content polarAreaChart(list[str] labels, lrel[str label, num val] values..., str title="Polar Area Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\polarArea(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\polarArea(), title=title, colorMode=colorMode, legend=true)); @synopsis{A radar chart from labeled numbers} Content radarChart(rel[str label, num val] values, str title="Radar Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\radar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\radar(), title=title, colorMode=colorMode, legend=true)); Content radarChart(lrel[str label, num val] values, str title="Radar Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\radar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\radar(), title=title, colorMode=colorMode, legend=true)); Content radarChart(list[str] labels, rel[str label, num val] values..., str title="Radar Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\radar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\radar(), title=title, colorMode=colorMode, legend=true)); Content radarChart(list[str] labels, lrel[str label, num val] values..., str title="Radar Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\radar(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\radar(), title=title, colorMode=colorMode, legend=true)); @synopsis{A pie chart from labeled numbers} Content pieChart(rel[str label, num val] values, str title="Pie Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\pie(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\pie(), title=title, colorMode=colorMode, legend=true)); Content pieChart(lrel[str label, num val] values, str title="Pie Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\pie(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\pie(), title=title, colorMode=colorMode, legend=true)); Content pieChart(list[str] labels, rel[str label, num val] values..., str title="Pie Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\pie(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\pie(), title=title, colorMode=colorMode, legend=true)); Content pieChart(list[str] labels, lrel[str label, num val] values..., str title="Pie Chart", ChartAutoColorMode colorMode=\dataset()) - = content(title, chartServer(chartData(labels, values), \type=\pie(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\pie(), title=title, colorMode=colorMode, legend=true)); @synopsis{A dougnut chart from labeled numbers} Content doughnutChart(rel[str label, num val] values, str title="Doughnut Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\doughnut(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\doughnut(), title=title, colorMode=colorMode, legend=true)); Content doughnutChart(lrel[str label, num val] values, str title="Doughnut Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(values), \type=\doughnut(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(values), \type=\doughnut(), title=title, colorMode=colorMode, legend=true)); Content doughnutChart(list[str] labels, rel[str label, num val] values..., str title="Doughnut Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(labels, values), \type=\doughnut(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\doughnut(), title=title, colorMode=colorMode, legend=true)); Content doughnutChart(list[str] labels, lrel[str label, num val] values..., str title="Doughnut Chart", ChartAutoColorMode colorMode=\data()) - = content(title, chartServer(chartData(labels, values), \type=\doughnut(), title=title, colorMode=colorMode)); + = content(title, chartServer(chartData(labels, values), \type=\doughnut(), title=title, colorMode=colorMode, legend=true)); @synopsys{ converts plain data sources into chart.js datasets @@ -182,6 +182,11 @@ ChartDataSet chartDataSet(str label, rel[num x, num y] r) label=label ); +ChartDataSet chartDataSet(str label, map[num x, num y] r) + = chartDataSet([point(x,r[x]) | x <- r], + label=label + ); + ChartDataSet chartDataSet(str label, rel[num x, num y, num rad] r) = chartDataSet([point(x,y,r=rad) | <- r], label=label @@ -206,7 +211,15 @@ ChartData chartData(rel[str label, num val] v) datasets=[ chartDataSet([n | <_, n> <- v]) ] - ); + ); + +ChartData chartData(map[str label, num val] v) + = chartData( + labels=[l | l <- v], + datasets=[ + chartDataSet([v[l] | l <- v]) + ] + ); ChartData chartData(lrel[str label, num val] v) = chartData( @@ -273,6 +286,13 @@ ChartData chartData(str label, lrel[num x, num y] values) ] ); +ChartData chartData(str label, map[num x, num y] values) + = chartData( + datasets=[ + chartDataSet(label, values) + ] + ); + ChartData chartData(str label, lrel[num x, num y, num r] values) = chartData( datasets=[ @@ -396,7 +416,7 @@ A chart has a typical default layout that we can reuse for all kinds of chart ty provides the template and immediately instantiates the client and the server to start displaying the chart in a browser. } -Response(Request) chartServer(ChartData theData, ChartType \type=\bar(), str title="Chart", ChartAutoColorMode colorMode=\data(), bool legend=false, bool animations=false) +Response(Request) chartServer(ChartData theData, ChartType \type=\bar(), str title="Chart", ChartAutoColorMode colorMode=\data(), bool legend=true, bool animations=false) = chartServer( chart( \type=\type, diff --git a/src/org/rascalmpl/repl/BaseREPL.java b/src/org/rascalmpl/repl/BaseREPL.java index 4540685a344..0f9e66f64d6 100755 --- a/src/org/rascalmpl/repl/BaseREPL.java +++ b/src/org/rascalmpl/repl/BaseREPL.java @@ -19,7 +19,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import org.fusesource.jansi.Ansi; -import org.fusesource.jansi.Ansi.Color; import org.rascalmpl.ideservices.IDEServices; import org.rascalmpl.library.util.PathConfig; @@ -274,7 +273,7 @@ protected void stackTraceRequested() { } private String previousPrompt = ""; - public static final String PRETTY_PROMPT_PREFIX = Ansi.ansi().reset().bold().fg(Color.BLACK).toString(); + public static final String PRETTY_PROMPT_PREFIX = Ansi.ansi().reset().bold().toString(); public static final String PRETTY_PROMPT_POSTFIX = Ansi.ansi().boldOff().reset().toString(); protected void updatePrompt() { diff --git a/src/org/rascalmpl/semantics/dynamic/Tree.java b/src/org/rascalmpl/semantics/dynamic/Tree.java index f69f8c750c5..d1bf20785f9 100644 --- a/src/org/rascalmpl/semantics/dynamic/Tree.java +++ b/src/org/rascalmpl/semantics/dynamic/Tree.java @@ -302,6 +302,7 @@ private IList flatten(IList args) { if (nestedArgs.length() > 0) { appendPreviousSeparators(args, result, delta, i, previousWasEmpty); result.appendAll(nestedArgs); + previousWasEmpty = false; } else { previousWasEmpty = true; diff --git a/src/org/rascalmpl/test/infrastructure/QuickCheck.java b/src/org/rascalmpl/test/infrastructure/QuickCheck.java index 25ba7105bd1..0b9fbd1167b 100644 --- a/src/org/rascalmpl/test/infrastructure/QuickCheck.java +++ b/src/org/rascalmpl/test/infrastructure/QuickCheck.java @@ -12,6 +12,7 @@ */ package org.rascalmpl.test.infrastructure; +import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; @@ -25,6 +26,7 @@ import io.usethesource.vallang.IString; import io.usethesource.vallang.IValue; import io.usethesource.vallang.IValueFactory; +import io.usethesource.vallang.io.StandardTextWriter; import io.usethesource.vallang.type.Type; import io.usethesource.vallang.type.TypeStore; @@ -196,7 +198,7 @@ public void writeMessage(PrintWriter out) { } } - public class UnExpectedExceptionThrownResult extends TestFailedResult { + public static class UnExpectedExceptionThrownResult extends TestFailedResult { public UnExpectedExceptionThrownResult(String functionName, Type[] actualTypes, Map tpbindings, IValue[] values, Throwable thrownException) { @@ -210,16 +212,21 @@ public void writeMessage(PrintWriter out) { out.println("Exception:"); if (thrownException instanceof Throw) { out.println(((Throw)thrownException).getMessage()); + try { + ((Throw) thrownException).getTrace().prettyPrintedString(out, new StandardTextWriter(true)); + } + catch (IOException e) { + // should not happen + } } else { - out.println(thrownException.toString()); + // out.println(thrownException.toString()); thrownException.printStackTrace(out); } } - } - public class ExceptionNotThrownResult extends TestFailedResult { + public static class ExceptionNotThrownResult extends TestFailedResult { public ExceptionNotThrownResult(String functionName, Type[] actualTypes, Map tpbindings, IValue[] values, String expected) { super(functionName, "test did not throw '" + expected + "' exception", actualTypes, tpbindings, values); diff --git a/src/org/rascalmpl/uri/classloaders/SourceLocationClassLoader.java b/src/org/rascalmpl/uri/classloaders/SourceLocationClassLoader.java index 5459bba761e..307ba73b23b 100644 --- a/src/org/rascalmpl/uri/classloaders/SourceLocationClassLoader.java +++ b/src/org/rascalmpl/uri/classloaders/SourceLocationClassLoader.java @@ -160,10 +160,23 @@ public URL getResource(String name) { public Enumeration getResources(String name) throws IOException { List result = new ArrayList<>(path.size()); + for (ClassLoader l : path) { - Enumeration e = l.getResources(name); - while (e.hasMoreElements()) { - result.add(e.nextElement()); + SearchItem item = new SearchItem(l, name); + + if (stack.contains(item)) { + continue; + } + try { + stack.push(item); + + Enumeration e = l.getResources(name); + while (e.hasMoreElements()) { + result.add(e.nextElement()); + } + } + finally { + stack.pop(); } }