Git Product home page Git Product logo

usethesource / rascal Goto Github PK

View Code? Open in Web Editor NEW
389.0 27.0 79.0 1.02 GB

The implementation of the Rascal meta-programming language (including interpreter, type checker, parser generator, compiler and JVM based run-time system)

Home Page: http://www.rascal-mpl.org

License: Other

HTML 0.01% Java 72.25% Python 0.01% TeX 0.01% C 5.06% Ruby 0.01% Rascal 19.06% RouterOS Script 3.60%
language static-analysis parser-generator pattern-matching source-to-source code-generation reverse-engineering domain-specific-language term-rewriting relational-algebra

rascal's Introduction

Rascal - Metaprogramming Language

Build and Deploy

This is the core implementation of the Rascal meta-programming language. It contains the interpreter, the parser generator, the parser run-time, the (documented) standard library, and the Rascal language reference documentation.

Other relevant repositories:

Please visit http://www.rascal-mpl.org for all information regarding Rascal.

For questions use the rascal tag on StackOverflow.

rascal's People

Contributors

aanastasiou avatar anastassija avatar anyahelene avatar arnoldlankamp avatar ashimshahi avatar balland avatar basten avatar davylandman avatar dependabot[bot] avatar ferryriet avatar grammarware avatar jeroenpeeters avatar jjwtimmer avatar joppekroon avatar joukestoel avatar jurgenvinju avatar jvdb avatar keepertje avatar lmove avatar magielbruntink avatar mahills avatar maveme avatar meersdavy avatar migod avatar msteindorfer avatar paulklint avatar pinoval avatar rodinaarssen avatar tvdstorm avatar wietsevenema avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rascal's Issues

textfield does not trigger redraw

This code from the documentation does not work. If you replace the textfield by a button, it does work:

public bool intInput(str s){
    return /^[0-9]+$/ := s;
}

public Figure higher(){
    int H = 100;
    return vcat( [ textfield("<H>", void(str s){H = toInt(s);}, intInput),
                   box(width(100), vresizable(false), vsize(num(){return H;}), fillColor("red"))
                 ], shrink(0.5), resizable(false));
}

Change of "rascal_eclipse" to "rascal-eclipse" breaks new project creation

Changing the plugin name for the "rascal_eclipse" project to "rascal-eclipse" breaks new project creation, since it refers to a "rascal_eclipse.rascal_nature" which no longer exists. Two questions:

  • Is there a reason this change was made?
  • Will this have an impact on existing projects? So far it doesn't seem like it is, I'm not sure if there are any corner cases we just aren't aware of, though, where this would be a problem.

Patterns for Rascal applications to simplify use and deployment

For automated build/general deployment scenarios, I think it would make sense to have the following capabilities in Rascal:

  1. Generate a jar that contains a Rascal project and all its dependencies.
  2. Have Rascal projects be maven-enabled, i.e. come with a pom.xml that allows fully automatic execution for inclusion in automated builds.

This can be done per-project, but perhaps it is possible to define some patterns and include some glue code to make it easy to achieve this automatically. The things I would like to see then are:

  1. A standardized commandline interface for the generated jars.
  2. A standardized interface for calling Rascal code from maven or other automated builds.

The low-level code around this I believe to be relatively small (some commandline handling, mapping arguments to pdb types, a rascal-maven-plugin that creates an Evaluator and calls a function), but to standardize this, I would propose to create something such as registerContributions in Plugin.rsc, only independent of Eclipse and related to common Rascal applications.

To this end, I have identified two common applications in Rascal:

  1. Code generator (compiler)
  2. Source code (static) analysis tool

Both receive the following inputs:

  1. Rascal root.
  2. Input path/set/pattern.
  3. Input type (e.g. language).
  4. Output path/set/pattern.
  5. Output type (e.g. language).
  6. Optionally, some additional configuring arguments.

They are different in that a code generator will generate source code (and in the context of maven, would execute in the generate-sources phase) and a source code analysis tool will generate reports (and in the context of maven, would execute in the process-sources phase).

So my proposal is to add something like Execute.rsc (I haven't thought about the name yet, there are probably better ideas) in the root next to Plugin.rsc, that does not have a dependency on Eclipse and where a project can register its code generator(s) and/or static analyzer(s).

comparable numbers

The given rascal design for numbers

  • In Rascal we have ints, reals and rationals and they are currently of incomparable types and have a common super-type called num.
  • The == and <=,>=,< and > operators should work on any combination of numbers, where == implements an equivalence relation and <= is a total ordering on the numbers.

Problems

  • == and the <= operators do not implement an equivalence relation and a total ordering. The implementation is unfinished in this respect
  • the hashCode/equals (Java) contract is not satisfied by the current implementation. This breaks some of our random tests, such as size({x,toReal(x)} == 1; The problem is that even though 1r1 == 1 the hashcode of the rational is different from the hashcode of the integer.

Solutions

  • try and fix the implementations of equals and hashCode until this works. This will be slow because it requires on-the-fly transformation between representations, only to get the right hashcode.
  • unify the numbers in a vertical hierarchy int <: rat <: real and pick a canonical representation for all numbers such that they will have the same representation if they are equal.

Corrolaries

A hierarchy int <: rat <: real has consequences for printed values and for overloading of operators.

  • 1.345 will be printed as 265r200
  • we have to introduce a div operator to disambiguate real division from integer division
  • all numbers will have precision and scale, i.e. the integer 12345 will have precision 5. what is the precision of a rational? what is the scale?
  • this breaks existing rascal code big-time
  • this represents a lot of work
  • this makes a maximally shared representation feasible
  • this removes the need for a separate isEqual method as we have now in the PDB implementation, given we resolve another issue (with annotations).

Random datetime generator generates impossible date times

Random datetime generator generates impossible date times.
See:

 $0717-08-13T11:27:32.966+0100 == $0717-08-13T11:27:32.966+0100   (true)

which is the result of this.getValue() == that.getValue()

However

2:-84743155947034 == -39521136747034 (false)
which is the result of this.getValue().getInstant() == that.getValue().getInstant())

Step over single statement body jumps out of for loop

In a for loop like this, while stepping through the code, if the cursor is on the println() and you choose "step over", it jumps out of the for loop even if there are more elements to consider:

public int f() {
  for (i <- [1..10]) 
    println(i);

  return 20 * 9;
}

Generate Typed AST hierarchy

Based on a table of all the operators and their overloaded argument types, we should generate sub-classes of the static AST hierarchy. For each specific combination of operator and argument types there will be on sub-class of the operator class.

Make UTF-8 default for new rascal projects?

I am thinking of making sure new rascal projects are UTF-8, to make it easier to exchange files between users (since eclipse defaults to the OS codepage)..

So my proposal, when we create a rascal project, set the project default charset (which overrides the global eclipse setting).

Change would be:

diff --git a/src/org/rascalmpl/eclipse/wizards/RascalProjectWizard.java b/src/org/rascalmpl/eclipse/wizards/RascalProjectWizard.java
index fe963f7..aee1777 100644
--- a/src/org/rascalmpl/eclipse/wizards/RascalProjectWizard.java
+++ b/src/org/rascalmpl/eclipse/wizards/RascalProjectWizard.java
@@ -66,7 +66,7 @@
                        IBundleProjectDescription plugin = service.getDescription(project);
                        //plugin.setBundleName(project.getName());
                        plugin.setBundleName(project.getName().replaceAll("[^a-zA-Z0-9_]", "_"));
-                       
+                       project.setDefaultCharset("UTF-8", monitor); // now let's just force new rascal projects to be UTF-8.
                        initializeProjectAsRascalProject(project, monitor, service, plugin);
                        initializeProjectAsJavaProject(project);
                        ConsoleFactory.getInstance().launchConsole(project, ILaunchManager.DEBUG_MODE);

mouseOver does not work in graph Figure

The following code prints "B" once while layouting the graph, then mouseOver has no effect after that:

public void draw()
{
    nodes = [box(id("A"), fillColor("red"),mouseOver(classDepInfo("A","B"))),
             box(id("B"), fillColor("yellow")),
             box(id("C"), fillColor("blue")),
             box(id("D"), fillColor("green")),
             box(id("E"), fillColor("orange"))];

    edges = [edge("A","B", toArrow(triangle(10))),
             edge("A","C", toArrow(triangle(10))),
             edge("B","C", toArrow(triangle(10))),
             edge("A","D", toArrow(triangle(10))),
             edge("C","D", toArrow(triangle(10))),
             edge("B","D", toArrow(triangle(10))),
             edge("E","D", toArrow(triangle(10))),
             edge("E","B", toArrow(triangle(10))),
             edge("C","E", toArrow(triangle(10)))];

    render(graph(nodes,edges,gap(25),std(size(25)),hint("layered")));
}

public Figure classDepInfo (str name, str fullname)
{
    println(fullname);
    return box(text("<name>\n<fullname>"), gap(20), right(), resizable(false));
}

(thanks to @PKlijn)

Unexplained exception in JDT importer, could be related to Java7

I found it hard to reproduce this exception that several students have run into:

Java("org/eclipse/jdt/core/dom/UnionType")

    org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDTImporter.addMethodBody(JDTImporter.java:476)
    org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDTImporter.importBindingInfo(JDTImporter.java:356)
    org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDTImporter.preVisit(JDTImporter.java:214)
    org.eclipse.jdt.core.dom.ASTVisitor.preVisit2(ASTVisitor.java:167)
    org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2480)
    org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2553)
    org.eclipse.jdt.core.dom.TypeDeclaration.accept0(TypeDeclaration.java:484)
    org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2482)
    org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java:2553)
    org.eclipse.jdt.core.dom.CompilationUnit.accept0(CompilationUnit.java:219)
    org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2482)
    org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDTImporter.visitCompilationUnit(JDTImporter.java:210)
    org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDTImporter.importFacts(JDTImporter.java:162)
    org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDT.extractClass(JDT.java:104)
    sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
    somewhere in: extractResource
    somewhere in: extractResources
    somewhere in: extractResource
    somewhere in: extractResources
    somewhere in: extractResource
    somewhere in: extractProject
    somewhere in: getSubTypeInformation
    somewhere in: main
    somewhere in: $shell$

So far I've been able to observe that:

  • each instance of the problem related to use of Java 7
  • it was all on Windows machines (could be coincidental)

UTF-8 without byte order mark, extractClass and readFile

If a Java file is stored with the "UTF-8 without byte order mark", lang::java::jdt::JDT::extractClass parses the file as ANSI but IO::readFile parses the file as UTF-8. If the file contains characters like é, í, etc. this causes problems.

For an example, all method body's are loaded separately using extractClass and readFile. extractClass contains the start and end of the method in the Rascal loc format, which can be loaded with the readFile function. If the file is stored in UTF-8 without byte order mark and contains special characters like é, the positions returned from extractClass aren't correct any more. Pieces of the loaded string representation of the method are chopped off.

A method of reproducing the problem is included here. To reproduce the bug, call reproduce() on Reproduce.rsc. It will load the methods separately and print them. It can then been seen that the start of the returnsFalse method is missing.

The problem occurs on Windows, although I'm not sure if it occurs on other operating systems as well.

"Comparison method violates its general contract!" exception when sorting ints with List::sort

sort([3,4,3,17,5,1,3,3,4,3,6,3,4,3,9,7,9,3,2,50,3,88,4,35,3,3,5,8,4,18,3,1]);

This generates a Java exception:

|std:///List.rsc|(24584,35,<1202,11>,<1202,46>): Java("Comparison method violates its general contract!")
    java.util.TimSort.mergeHi(TimSort.java:868)
    java.util.TimSort.mergeAt(TimSort.java:485)
    java.util.TimSort.mergeCollapse(TimSort.java:410)
    java.util.TimSort.sort(TimSort.java:214)
    java.util.TimSort.sort(TimSort.java:173)
    java.util.Arrays.sort(Arrays.java:659)
    org.rascalmpl.library.Prelude.sort(Prelude.java:1195)
    sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
    somewhere in: sort
    somewhere in: $shell$

I can't figure out why it crashes on this particular input, especially because sort(reverse[3,4,3,17,5,1,3,3,4,3,6,3,4,3,9,7,9,3,2,50,3,88,4,35,3,3,5,8,4,18,3,1])); works just fine. The ordering of the elements seems to be important because of this, but I can't figure out a pattern what could cause this behavior.

PDB API .is<...>Type on VoidType should not answer "true" for everything

void is everything, ok, but due to void saying is<...> for everything there are subtle bugs to be found around the lub and isSubTypeOf implementations. It may cost some extra code in the Rascal implementations, but changing this semantics would benefit the stability of the code overall. isVoidType should only return true if the type is literally 'void'. The same goes for alias type and constructor type (alias types forward to the aliased type at the moment, and constructor types are also saying node type).

arbSeed return type is wrong

In the module util::Math, the arbSeed function is defined as follows:

public java real arbSeed(int seed);

However, when called, it does not return anything:

rascal>s = arbSeed(12123);
ok

rascal>s
|stdin:///|(0,1,<1,0>,<1,1>): Uninitialized variable: s

This makes perfectly good sense, since I don't know what seeding a random number generator should return.

Suggested solution: change the return type of arbSeed from real to void.

`r[i]?{} += {1}` breaks

There is a type-check error in r[i]?{} += {1}, since you can not add elements to set[void]

People work around this as follows:

set[int] init = {};
r[i]?init += {1};

Unclear intention of testMap (lang::rascal::tests::Equality)

This test case only passed due to a bug in the fast and shared implementation of PDB. x <= x + y on maps is internally handled as x isSubMap (x join y).

If x and y contain entries with the same keys, the entries of y will supersede the entries of x in the joined map. Thus, x must not be a sub map of x + y, if both both maps contain entries with equal keys, but y must be a sup map.

With that regards I don't understand the comment of @jurgenvinju // maps are ordered as sets of tuples. Can somebody clarify and also fix the test with regards how it was intended to work?

I'll also open an issue at PDB values for the bug in the fast and shared implementation that first hand allowed the test pass.

Not understandable error message when adding tuple elements to relations using `+=`

This code (thanks to Peter Klijn) triggers the following message:

map[int cc, rel[loc method, int length] method] returnValue = ();
returnValue[cc]?init += <methodLocation, (methodLocation.end.line - methodLocation.begin.line)>;

triggers:

insert into collection not supported on value and tuple[loc,int]

The fix is:

returnValue[cc]?init += {<methodLocation, (methodLocation.end.line - methodLocation.begin.line)>};

Keyword Parameters

Keyword Parameters

Abstract

In order to better support embedded DSLs (for prettyprinting, visualization, type-checking, …) we have two options:

  • Support full-fledged syntactic extensibility.
  • Add some more flexibility to our data notation so that embedded DSLs that follow the interpreter pattern (i.e., the DSL is actually a data value that is evaluated by a user-defined interpreter) can be reasonably supported.

Here we explore the second alternative.

Current situation

For constructors and function declarations the following parameters mechanisms are supported:

  • Positional parameters: “standard” formal parameters like int x, but also patterns.
  • Variable list of parameters (at the last parameter position): int x …

We have experience with two libraries that use extensive lists of options and settings:

  • Box has many options (indentation, token color, font, etc) all with a default value.
  • This is also the case for the Figure library.

One also sees this in, for instance, chart libraries where many options (title, subtitle, x-label, y-label, etc.) have a default value that can be overridden by the caller. It is mandatory that we provide a usable solution for this.

Another data point is that we use data constructors often to model abstract data, while the order of the model elements are irrelevant:

  • UML2 or FAMIX like meta-models, such as data Class = class(str name, set[Field] fields, set[Method] methods)

Proposal

Notably missing are

  • Keyword parameters: these parameters have a name, may be used in arbitrary order and (may) have a default value.
  • Optional arguments.

Let’s study how Python solves this. In Python formal parameters can be

  • Named, positional parameters optionally followed by a default value. A parameter without a default value is a _required parameter, the others are _optional.
  • Formal parameter *x denotes a variable length parameter (in a function call *x transforms a list into positional parameters)
  • Formal parameter **x denotes a variable map of name/value pairs (in a function call **x transforms a map into positional parameters).

In Python function calls can have positional arguments that match the order of the formal parameters, keyword arguments of the form kwarg=val, or a mixture of both. Here are examples (from the same website):

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"

accepts one required argument (voltage) and three optional arguments (state, action, and type). This function can be called in any of the following ways:

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

but all the following calls would be invalid:

parrot()                     # required argument missing
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
parrot(110, voltage=220)     # duplicate value for the same argument
parrot(actor='John Cleese')  # unknown keyword argument

The following rules apply:

  • Required arguments need to be present.
  • Required arguments come first and maybe followed by keyword arguments.
  • Required arguments may also be given as keyword argument.
  • An argument may only be bound once.
  • A keyword argument should have a known keyword.

Python has more mechanisms such as splicing in a list as positional parameters (see * above) and passing a dictionary of key/value pairs (see ** above), but this is less likely to work in our typed setting.

Keyword arguments for Rascal

The proposal is to implement the main parts of Python’s keyword arguments. The reasons are as follows:

  • It solves the problem of functions with extensive options and settings.
  • The order of the formal parameters is completely determined. This is convenient for ADTs like parse trees.
  • At the call site arguments (even positional ones) may occur in any order if keywords are used.
  • This approach eliminates the need to introduce a separate record type; they are subsumed by the proposed approach.

Example: Figure library

In the Figure library the function ellipse is a figure defined by two constructors:

data Figure  = ellipse(list[FProperty] props)
             | ellipse(Figure inner, list[FProperty] props) | ... ;

in other words an ellipse only gets a list of properties or an inner figure and
a list of properties. FProperty is also a data type with many constructors including:

data FProperty = … | shrink(real f) |  fillColor(str c) | …;

These are examples:

b1 = ellipse(shrink(0.8), fillColor("green"));
b0 = ellipse(b1, size(150,50), fillColor("lightGray"));

Reformulation 1: repeat keyword parameters

Given this data declaration:

data Figure  = ellipse(Figure inner=emptyFigure(), real shrink = 1.0, str fillColor = “white”, 
                                                   str lineColor = “black”, ...)

The examples can be formulated as:

b1 = ellipse(shrink=0.8, fillColor="green");
b0 = ellipse(inner=b1, size= <150,50>, fillColor="lightGray");

At the call site this solution is perfect but it is not at the data declaration site since we have to repeat the keyword parameters for each constructor and this is bad from a maintenance perspective.

Reformulation 2

Given these data declarations:

data FProperty = props(..., real shrink = 1.0, str fillColor = “white”, 
                                               str lineColor = “black”, …);

data Figure  = ellipse(Figure inner=emptyFigure(), FProperty props = props())

The examples can be formulated as:

b1 = ellipse(props=props(shrink=0.8, fillColor="green"));
b0 = ellipse(inner=b1, props=props(size=<150,50>, fillColor="lightGray"));

At the call site this solution is bearable but not very nice since we need to add all these props keywords. At the declaration site, the props arguments has to be repeated for every constructor.

Reformulation 3 (with proposal)

What we need is a mechanism to either add keyword parameters to all constructors of a datatype or to splice in the keywords of another constructor. The first approach looks like this:

data Figure(..., real shrink = 1.0, str fillColor = “white”, str lineColor = “black”, ...)
     = ellipse(Figure inner=emptyFigure())  | ...;

Here the keyword parameters following the datatype name (Figure) are added to each constructor of Figure,

The second alternative looks like this:

data FProperty = props(..., real shrink = 1.0, str fillColor = “white”, 
                                               str lineColor = “black”, ...);

data Figure  = ellipse(Figure inner=emptyFigure(), **props)
             | ... ;

Here the keyword parameters of another constructor (props) are spliced into the constructor declaration.

With both solutions the examples can be formulated as desired:

b1 = ellipse(shrink=0.8, fillColor="green");
b0 = ellipse(inner=b1, size= <150,50>, fillColor="lightGray");

The proposal is to use the first approach:

  • In data declarations, the name of the datatype maybe followed by a list of keyword parameters.
  • This list can be extended in subsequent declarations, i.,e,
    data Figure(str lineStyle = “dotted”); adds a keyword parameter to an existing ADT.
  • The keywords in this list are added automatically to each constructor of the ADT.
  • Per constructor, specific keywords can be defined.

Implications for the Rascal Implementation

Syntax

The syntax needs to be adapted in three places:

  • Function declaration
  • Data declaration.
  • Constructor declaration
  • Function call.
  • Pattern matching

For function and constructor declarations, each formal parameter may now optionally be followed by “= Expr”. The data declaration is extended to allow declaring keyword parameters shared by all constructors.

Program Data base (PDB)

Default values have to be added to ADTs.

  • When printing ADT values, arguments are printed in order and keyword parameters with a value equal to their default value are suppressed.
  • Keyword parameters have to be added to abstract INodes as well
  • Keyword parameters have to be added to IConstructors.
  • The ConstructorType has to be extended with types for the keyword parameters.

Interpretation of call expression

The interpretation of calls has to be extended as follows:

  • The function name determines the set of actual functions to be called.
  • The values of all (positional and keyword) parameters are computed.
  • The function to be called from the set of functions is determined as follows:
    ** Reorder the parameter so that positional parameters that are referred to by name are placed in their proper position.
    ** Match the actual values of positional parameters with the corresponding formal postional parameters.
    ** Determine if the function supports all the used keyword names.
  • If this yields a unique choice then called the selected function and
    ** Bind positional formal parameters to the corresponding actual parameter value.
    ** Bind keyword formal parameters to the actual values that are given as actual keyword arguments.
    ** Bind the remaining formal keyword parameters to their default value.

Pattern Matching

The matching of abstract patterns has to be adapted to perform a similar search as sketched for calls.

Also, pattern matching must be extended to be able to ignore keyword parameters. This is slightly different from the calls semantics, where the default values will be used. Here we want to ignore the values of keyword parameters when the parameters are not named in the pattern. This allows later to use keyword parameters instead of annotations.

Potential Benefits

In addition to a much more versatile parameter mechanism, keyword parameters can also play the role of annotations and even make annotations obsolete. This can have _large benefits for achieving maximal sharing_. However, this depends on the interpretation of pattern matching. The keyword parameters must be ignorable.

Potential Pitfalls

  • The proposed solution places an extra burden on the call overhead and pattern matching.
  • The proposed “common” keyword parameters and the way to add keyword parameters introduces a form of inheritance. Is it sufficient for our needs?
  • Ignoring keyword parameters by default while pattern matching is kind of special and may be surprising.

Alternative solutions

  • Use annotations to get attach optional values to ADT values.
  • Introduce a record type (which has named, unordered, fields).

add heuristic to generate robustness specifications

a robustness specification is a map from productions to continuation characters. All productions that are list elements, separated lists separators could be robust with their follow sets as continuation characters as a heuristic to make parser robust more easily. It's an experiment to do.

ambidexter can not display ambiguity anymore

Just run ambidexter on a grammar that has an ambiguity:

org.eclipse.imp.pdb.facts.exceptions.UnexpectedTypeException: Expected Symbol, but got node at org.eclipse.imp.pdb.facts.io.StandardTextReader.readValue(StandardTextReader.java:130) at org.eclipse.imp.pdb.facts.io.StandardTextReader.read(StandardTextReader.java:88) at org.rascalmpl.eclipse.ambidexter.ReportView.ambiguousString(ReportView.java:119) at nl.cwi.sen1.AmbiDexter.derivgen.ParallelDerivationGenerator.ambiguity(ParallelDerivationGenerator.java:216) at nl.cwi.sen1.AmbiDexter.derivgen.ScannerlessDerivGen2$Worker2.go(ScannerlessDerivGen2.java:139) at nl.cwi.sen1.AmbiDexter.derivgen.ParallelDerivationGenerator.detect(ParallelDerivationGenerator.java:150) at nl.cwi.sen1.AmbiDexter.derivgen.ScannerlessDerivGen2.detect(ScannerlessDerivGen2.java:51) at nl.cwi.sen1.AmbiDexter.derivgen.ParallelDerivationGenerator.detectAmbiguities(ParallelDerivationGenerator.java:107) at nl.cwi.sen1.AmbiDexter.Main.doDerivationGeneration(Main.java:475) at nl.cwi.sen1.AmbiDexter.Main.checkGrammar(Main.java:267) at org.rascalmpl.eclipse.ambidexter.ReportView$AmbiDexterJob.run(ReportView.java:255) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

replace annotation facility by pattern matching modulo keyword parameters

The idea is to remove the whole annotations feature and replace it by keyword parameters.

  • keyword parameters can be ignore at construction and pattern matching time, because they have default values
  • we need to think about what overloading between functions and constructors means if they have different keyword parameters but are otherwise the same
  • keyword parameters do not imply transparent equality between nodes that have different values for the parameters. Different values means different identity. This allows us to simplify the equals/hashcode story for pdb nodes.
  • node should have keyword parameters as well, albeit untyped, such that node can remain a common supertype for all abstract data-types.
  • e.g. data Tree = appl(Production prod, list[Tree] args, loc src=|null:///|)

The rascal grammar seems to leak through

For example if you take the rule:
syntax Name = "first" "last";
The input string "first last" doesn't parse, because the Name non-terminal is defined as being lexical in the Rascal grammar. Somehow this property leaks through to the generated object parser.

Improved handling of numeric precision

I have made changes to PDB and Rascal to improve handling of precision:

  1. The precision can now be controlled with "setPrecision" (it returns the previous precision).
  2. The precision of individual numbers can be controlled with "precision" (it returns a number with given precision).
  3. The precision of all numeric computations is now limited to the precision that is set.
  4. I have set the default precision at 10 (was 50). Maybe it should be set even lower.

All-in-all this will speed-up computations with moderate precision.

Visiting an ADT and using an incorrect matching causes java.lang.reflect.InvocationTargetExceptio

The stacktrace:

rascal>import null;
nullorg.rascalmpl.interpreter.asserts.ImplementationError: Unexpected error in Rascal interpreter: Unexpected error in AST construction: java.lang.reflect.InvocationTargetException caused by null(internal error) somewhere in: $shell$
org.rascalmpl.interpreter.asserts.ImplementationError: Unexpected error in Rascal interpreter: Unexpected error in AST construction: java.lang.reflect.InvocationTargetException caused by null
    at org.rascalmpl.parser.ASTBuilder.unexpectedError(ASTBuilder.java:829)
    at org.rascalmpl.parser.ASTBuilder.callMakerMethod(ASTBuilder.java:915)
    at org.rascalmpl.parser.ASTBuilder.callMakerMethod(ASTBuilder.java:863)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:332)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:321)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildList(ASTBuilder.java:252)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:298)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:321)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:321)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:321)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildList(ASTBuilder.java:252)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:298)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildContextFreeNode(ASTBuilder.java:321)
    at org.rascalmpl.parser.ASTBuilder.buildValue(ASTBuilder.java:231)
    at org.rascalmpl.parser.ASTBuilder.buildSort(ASTBuilder.java:180)
    at org.rascalmpl.parser.ASTBuilder.buildModule(ASTBuilder.java:133)
    at org.rascalmpl.interpreter.Evaluator.loadModule(Evaluator.java:1501)
    at org.rascalmpl.interpreter.Evaluator.evalRascalModule(Evaluator.java:1571)
    at org.rascalmpl.semantics.dynamic.Import.importModule(Import.java:289)
    at org.rascalmpl.semantics.dynamic.Import$Default.interpret(Import.java:248)
    at org.rascalmpl.semantics.dynamic.Command$Import.interpret(Command.java:75)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:1007)
    at org.rascalmpl.interpreter.Evaluator.eval(Evaluator.java:967)
    at org.rascalmpl.eclipse.console.RascalScriptInterpreter.execCommand(RascalScriptInterpreter.java:432)
    at org.rascalmpl.eclipse.console.RascalScriptInterpreter.run(RascalScriptInterpreter.java:236)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedConstructorAccessor132.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
    at org.rascalmpl.parser.ASTBuilder.callMakerMethod(ASTBuilder.java:900)
    ... 31 more
Caused by: java.lang.UnsupportedOperationException
    at org.rascalmpl.ast.PatternWithAction.getPattern(PatternWithAction.java:37)
    at org.rascalmpl.interpreter.utils.Cases.isConcreteSyntaxPattern(Cases.java:75)
    at org.rascalmpl.interpreter.utils.Cases.precompute(Cases.java:35)
    at org.rascalmpl.semantics.dynamic.Visit$DefaultStrategy.<init>(Visit.java:43)
    ... 35 more

rascal>main();
|stdin:///|(0,4,<1,0>,<1,4>): Undeclared variable, function or constructor: main

rascal>

With the following file:

module null

import IO;
import lines;
import lang::java::jdt::Java;
import lang::java::jdt::JDT;
import lang::java::jdt::JavaADT;
import util::ValueUI;
import Node;
import List;


private void parseUnit(str name, loc l, AstNode body) {
    println("Method: <name>, <l>");

    visit(body) {
        case a: AstNode:
            if(isControlStructure(a)) {
                println("<a>");
            }
    }
}

private bool isControlStructure(AstNode x) {
    return x is assignment ||
    x is methodInvocation;
}

public void main() {
    P = |project://helloworld|;
    asts = createAstsFromProject(P);

    for(x <- asts) {
        visit(x) {
            case m: methodDeclaration(_, _, _, _, str name, _, _, some(body)): parseUnit(name, m@location, body);
        }   
    }   
}

Rascal in a Sandbox

Goal

For various ideas (tutor/rascal on the web, automatic judging of results) we want to have a sandbox for Rascal. This page describes our proposal for creating this mode for rascal.

We aim for a low-maintenance solution with minimal impact on our current system.

Setting (attack vector)

The external user is allowed to submit Rascal expressions, Rascal files or non-executable data files.
A timeout can be used to limit the possibility of a DOS.
Data files can be used in two ways:

  1. The submitted Rascal program can read example data that is part of the Rascal library. It is convenient to have some standard data sets available.
  2. The submitter can add his/her own data.

Proposed solution

Our solution is threefold.

  1. Disable the @java annotations on non- library functions. (eg., white list the library functions).
  2. Blacklist insecure Rascal functions (such as util::ShellExec).
  3. Whitelist locations which can be resolved for either reading or writing.

Implementation

An evaluator is either started in sandbox mode or not, from a Rascal program this cannot be changed. The descriptions below describe the cases when an evaluator is started in sandbox mode.

Disabling @java annotations on non-library functions

During import of a module, we check in case of a @java annotation if the current module is on a white listed path (containing the library paths).

Blacklisting insecure Rascal functions

We introduce a new annotation @insecure (or a better name?) which is checked during overload resolution, and if it is called in sandbox mode, we raise a security exception.

Whitelist locations which can be resolved

The Location resolvers are extended such that when they create an InputStream or an OutputStream they call our own SandboxInputStreams or SandboxOutputStream instead. These will check if you try to read or write outside your current path or the loaded eclipse projects.

So our question to you is, are we forgetting an attack vector or is this a secure sandbox?

ambiguity in expression

it + ((folder(id, _) := c) ? id : {}) is not ambiguous, but it + (folder(id, _) := c ? id : {}) is ambiguous (less brackets)

classcast exception on ADT* in pattern matching

The codesnippet parses, but generates an internal error at the Foo*.

module ModFoo

import IO;

data Foo = foo();

public void tryMe() {
    t1 = [foo(), foo(), foo()];

    switch (t1) {
        case Foo* x : println("yes: <x>");
    }
}

Accessing deploying "snakeyaml" library dependency separately.

The snakeyaml library is currently hardwired included in the build binary of Rascal. This increases the size of of the Rascal built and forces people, who update Rascal, to always re-download the snakeyaml with Rascal, even if the library didn't change.

Proposal for solution:

  • Finding a p2 that contains snakeyaml, to avoid dealing with the dependency at our own. Redeploying the library at our update site.
  • Downloading / copying the library, which would leaf the burden on us. Redeploying the library at our update site.

github issues for Rascal sub projects

github issues are currently not enabled for all sub projects, e.g. rascal-eclipse or AmbiDexter.

Are we going to enable github issues for these projects as well? If not, what is the alternative? Creating issues in the Rascal project also if they refer to problems in sub projects?

toMap is broken, or equality on nodes

rascal>{<k,"K">,<h,"H">}
rel[Y, str]: {
  <t()[
    @p=100
  ],"H">,
  <t()[
    @p=4
  ],"K">
}

rascal>toMap({<k,"K">,<h,"H">})
map[Y, set[str]]: (t()[
    @p=4
  ]:{"H"})

rascal>import Relation;
ok

rascal>index({<k,"K">,<h,"H">})
map[Y, set[str]]: (t()[
    @p=100
  ]:{"K"})

rascal>r = {<k,"K">,<h,"H">};
rel[Y, str]: {
  <t()[
    @p=100
  ],"H">,
  <t()[
    @p=4
  ],"K">
}

rascal>( k:r[k] | k <- t)
|stdin:///|(16,1,<1,16>,<1,17>): Y () is not enumerable

rascal>( k:r[k] | k <- r)
|stdin:///|(16,1,<1,16>,<1,17>): Expected tuple[Y,str], but got Y

rascal>( k:r[k] | <k,_> <- r)
map[Y, set[str]]: (t()[
    @p=4
  ]:{"K","H"})

rascal>

allow . notation for function calls and remove builtin fields for locations

  • We {c,sh}ould allow x.f as sugar for f(x), and x.f(y) for f(x,y) etc.
  • Also, we could allow x.m as sugar for m[x], where m is map
  • and, while we are at it, also x.r for r[x] where r is a relation

The issue is that we currently have a number of operations on locations such as l.ls which are inconsistent with the rest of the library.

LazyRelation must implement the inherited abstract method IRelation.select(String...)

When starting to create a set of AstNodes from the rascal project, an error is thrown regarding an unimplemented method in LazyRelation:

rascal>import bugs::LazyRelationInCreateAstsFromProject;
ok

rascal>main();
|eclipse-std:///lang/java/jdt/JDT.rsc|(6969,1,<221,23>,<221,24>): "Error(s) in compilation unit: The type LazyRelation must implement the inherited abstract method IRelation.select(String...)"
    /src/org/rascalmpl/library/experiments/resource/results/buffers/LazyRelation.java:15,0
    somewhere in: public org.eclipse.imp.pdb.facts.IValue org.rascalmpl.eclipse.library.lang.java.jdt.internal.JDT.createAstFromFile(org.eclipse.imp.pdb.facts.ISourceLocation,org.rascalmpl.interpreter.IEvaluatorContext)
    somewhere in: createAstsFromProject
    somewhere in: main
    somewhere in: $shell$

The code to trigger this:

import lang::java::jdt::JDT;

public void main() {
    // Rascal is the rascal project from cwi-swat @ git
    proj = |project://rascal|;

    asts = createAstsFromProject(proj);
}

Rascal Boolean::fromString Missing return statement.

rascal>fromString("true"); 
bool: true
rascal>fromString("false");  
bool: false
rascal>fromString("linux");
|std:///Boolean.rsc|(1043,234,<50,0>,<63,1>): Missing return statement

The implementation (src/org/rascalmpl/library/Boolean.rsc) has the exception commented out:

//  throw s + " is not \"true\" or \"false\";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.