Nested descendant pattern matches - rascal

I'm trying to find all method calls and the classes that contain them. If I understand correctly, pattern matches perform backtracking to match in all possible ways.
Take the following java code.
package main;
public class Main {
public static void main(String[] args) {
System.out.println("hello world");
System.out.println("hello again");
}
}
I'm loading the code with createAstsFromDirectory.
rascal>ast = createAstsFromDirectory(|home:///multiple-method-calls|, false);
I'm trying to find both calls to println. The following code matches once:
void findCalls(set[Declaration] ast)
{
visit(ast)
{
case \class(_,_,_,/\methodCall(_,_,str methodName,_)):
println("<methodName>");
}
}
rascal>findCalls(ast);
println
ok
This code matches four times:
void findCalls(set[Declaration] ast)
{
visit(ast)
{
case /\class(_,_,_,/\methodCall(_,_,str methodName,_)):
println("<methodName>");
}
}
rascal>findCalls(ast);
println
println
println
println
ok
How must the pattern look like to match exactly twice?
Related question, how to access the class name? When trying to access the class name I get an error message.
void findCalls(set[Declaration] ast)
{
visit(ast)
{
case /\class(str className,_,_,/\methodCall(_,_,str methodName,_)):
println("<className> <methodName>");
}
}
findCalls(ast);
Main println
|project://personal-prof/src/Assignment13Rules.rsc|(3177,9,<141,16>,<141,25>): Undeclared variable: className
It looks like the first match has className bound correctly to "Main", but the second one does not.

I think I would write this:
void findCalls(set[Declaration] ast) {
for(/class(_, _, _, /methodCall(_,_,str methodName,_)) <- ast) {
println("<methodName>");
}
}
The for loop goes for every class it can find, through every methodCall it can find inside and thus twice for the example you gave.
Your second try goes wrong and matches too often: if you nest a / at the top of the case of a visit, you visit every position in the tree once, and the traverse the entire sub-tree again including the root node again. So you would get each call twice.
Your first try goes wrong because the top-level of a case pattern of a visit does not back-track on itself, it finds the first match for the entire pattern and then stops. So the nested / is only matched once and then the body is executed.
In the for loop solution, the for-loop (unlike the visit) will try all possible matches until it stops, so that's the way to go. There is yet another solution closer to your original plan:
void findCalls(set[Declaration] ast) {
visit (ast) {
case class(_, _, _, body) :
for (/methodCall(_,_,str methodName,_) <- body) {
println("<methodName>");
}
}
}
This also works just like the for loop, it first finds all the classes one-by-one via the visit and then goes through all the nested matches via the for loop.
Finally you could also nest the visit itself to get the right answer:
void findCalls(set[Declaration] ast) {
visit (ast) {
case class(_, _, _, body) :
visit(body) {
case methodCall(_,_,str methodName,_): {
println("<methodName>");
}
}
}
}
WRT to the className thing, it appears that the combination of visit and top-level deep match on a case like so: case /<pattern> there is a bug in the Rasca interpreter with a loss of variable bindings in the deep pattern. So pls avoid that pattern (I don't think you need it), and if you feel like it, submit an issue report on github?
In the for-loop case, this will simply work as expected:
for(/class(str className, _, _, /methodCall(_,_,str methodName,_)) <- ast) {
println("<className>::<methodName>");
}

Related

Sharing Mono with the publish method doesn't work as expected

I have two service calls. The second one accepts a value that the first returns. I need to return the result of the first call only if the second succeeds. The following is my prototype implementation, however, the resulting mono is always empty. Please explain why it doesn't work and how to implement it the proper way.
#Test
public void testPublish() {
callToService1().publish(
mono -> mono.flatMap(resultOfCall1 -> callToService2(resultOfCall1))
.then(mono)
)
.map(Integer::valueOf)
.as(StepVerifier::create)
.expectNext(1)
.verifyComplete();
}
Mono<String> callToService1() {
return Mono.just("1");
}
Mono<Integer> callToService2(String value) {
// parameter that used in a call to service2
return Mono.empty();
}
Not sure why you used publish(Function). Sounds like your requirement would be fulfilled by a simple direct flatMap:
callToService1()
.flatMap(v1 -> callToService2(v1)
.thenReturn(v1)
);
if callToService2 throws or produces an onError, that error will be propagated to the main sequence, terminating it.
(edited below for requirement of emitting value from service1)
otherwise, inside the flatMap the callToService2 is completed then we ignore the result and emit the still in scope v1 value thanks to thenReturn (which also propagates onError if callToService2 emits onError)

forEach vs for in: Different Behavior When Calling a Method

I noticed that forEach and for in to produce different behavior. I have a list of RegExp and want to run hasMatch on each one. When iterating through the list using forEach, hasMatch never returns true. However, if I use for in, hasMatch returns true.
Sample code:
class Foo {
final str = "Hello";
final regexes = [new RegExp(r"(\w+)")];
String a() {
regexes.forEach((RegExp reg) {
if (reg.hasMatch(str)) {
return 'match';
}
});
return 'no match';
}
String b() {
for (RegExp reg in regexes) {
if (reg.hasMatch(str)) {
return 'match';
}
}
return 'no match';
}
}
void main() {
Foo foo = new Foo();
print(foo.a()); // prints "no match"
print(foo.b()); // prints "match"
}
(DartPad with the above sample code)
The only difference between the methods a and b is that a uses forEach and b uses for in, yet they produce different results. Why is this?
Although there is a prefer_foreach lint, that recommendation is specifically for cases where you can use it with a tear-off (a reference to an existing function). Effective Dart recommends against using Iterable.forEach with anything else, and there is a corresponding avoid_function_literals_in_foreach_calls lint to enforce it.
Except for those simple cases where the callback is a tear-off, Iterable.forEach is not any simpler than using a basic and more general for loop. There are more pitfalls using Iterable.forEach, and this is one of them.
Iterable.forEach is a function that takes a callback as an argument. Iterable.forEach is not a control structure, and the callback is an ordinary function. You therefore cannot use break to stop iterating early or use continue to skip to the next iteration.
A return statement in the callback returns from the callback, and the return value is ignored. The caller of Iterable.forEach will never receive the returned value and will never have an opportunity to propagate it. For example, in:
bool f(List<int> list) {
for (var i in list) {
if (i == 42) {
return true;
}
}
return false;
}
the return true statement returns from the function f and stops iteration. In contrast, with forEach:
bool g(List<int> list) {
list.forEach((i) {
if (i == 42) {
return true;
}
});
return false;
}
the return true statement returns from only the callback. The function g will not return until it completes all iterations and reaches the return false statement at the end. This perhaps is clearer as:
bool callback(int i) {
if (i == 42) {
return true;
}
}
bool g(List<int> list) {
list.forEach(callback);
return false;
}
which makes it more obvious that:
There is no way for callback to cause g to return true.
callback does not return a value along all paths.
(That's the problem you encountered.)
Iterable.forEach must not be used with asynchronous callbacks. Because any value returned by the callback is ignored, asynchronous callbacks can never be waited upon.
I should also point out that if you enable Dart's new null-safety features, which enable stricter type-checking, your forEach code will generate an error because it returns a value in a callback that is expected to have a void return value.
A notable case where Iterable.forEach can be simpler than a regular for loop is if the object you're iterating over might be null:
List<int>? nullableList;
nullableList?.forEach((e) => ...);
whereas a regular for loop would require an additional if check or doing:
List<int>? nullableList;
for (var e in nullableList ?? []) {
...
}
(In JavaScript, for-in has unintuitive pitfalls, so Array.forEach often is recommended instead. Perhaps that's why a lot of people seem to be conditioned to use a .forEach method over a built-in language construct. However, Dart does not share those pitfalls with JavaScript.)
đź‘‹ jamesdin! Everything you have shared about the limitations of forEach is correct however there's one part where you are wrong. In the code snippet showing the example of how you the return value from forEach is ignored, you have return true; inside the callback function for forEach which is not allowed as the callback has a return type of void and returning any other value from the callback is not allowed.
Although you have mentioned that returning a value from within the callback will result in an error, I'm just pointing at the code snippet.
Here's the signature for forEach
Also, some more pitfalls of forEach are:
One can't use break or continue statements.
One can't get access to the index of the item as opposed to using the regular for loop

Project Reactor + flatMap + Multiple onErrorComplete - Not working as expected

When multiple onErrorContinue added to the pipeline to handle specific type of exception thrown from flatMap, the exception handling is not working as expected.
The below code, I expect, the elements 1 to 6 should be dropped and element 7 to 10 should be consumed by the subscriber.
public class FlatMapOnErrorContinueExample {
public static void main(String[] args) {
Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.flatMap(number -> {
if (number <= 3) {
return Mono.error(new NumberLesserThanThree("Number is lesser than 3"));
} else if (number > 3 && number <= 6) {
return Mono.error(new NumberLesserThanSixButGretherThan3("Number is grether than 6"));
} else {
return Mono.just(number);
}
})
.onErrorContinue(NumberLesserThanThree.class,
(throwable, object) -> System.err.println("Exception: Dropping the element because it is lesser than 3"))
.onErrorContinue(NumberLesserThanSixButGretherThan3.class,
(throwable, object) -> System.err.println("Exception: Dropping the element because it is lesser than 6 but grether than 3"))
.onErrorContinue((throwable, object) ->
System.err.println("Exception: " + throwable.getMessage()))
.subscribe(number -> System.out.println("number is " + number),
error -> System.err.println("Exception in Subscription " + error.getMessage()));
}
public static class NumberLesserThanThree extends RuntimeException {
public NumberLesserThanThree(final String msg) {
super(msg);
}
}
public static class NumberLesserThanSixButGretherThan3 extends RuntimeException {
public NumberLesserThanSixButGretherThan3(final String msg) {
super(msg);
}
}
}
Here is the output what I am getting:
Exception: Dropping the element because it is lesser than 3
Exception: Dropping the element because it is lesser than 3
Exception: Dropping the element because it is lesser than 3
Exception in Subscription Number is grether than 6
Question: Why the 2nd onErrorContinue is not called but the exception send to subscriber?
Additional Note:
if i remove 1st and 2nd onErrorContinue, then all exception are handled by 3rd onErrorContinue. I could use this approach to receive all exception and check for the type of exception and proceed with handling. However, I would like to make it cleaner exception handling rather than adding if..else block.
How this question is different from Why does Thread.sleep() trigger the subscription to Flux.interval()?
1) This question about exception handling and the order of exception handling; The other question is about processing elements in parallel and making the main thread waiting for the all the element processing complete
3) This question dont have any concern about threading, even if add Thread.sleep(10000) after . subscribe, there is no change in behaviour.
This again comes down to the unusual behaviour of onErrorContinue. It breaks the rule in that it doesn't "catch" errors and then change the behaviour downstream as a result, it actually allows supporting operators to "look ahead" at it and behave accordingly, thus changing the result upstream.
This is weird, and leads to some behaviour that's not immediately obvious, such as is the case here. As far as I'm aware, all supporting operators only look ahead to the next onErrorContinue operator, rather than recursively searching ahead for all such operators. Instead, they will evaluate the predicate of the next onErrorContinue (in this case whether it's of a certain type), and then behave accordingly - either invoking the handler if the predicate returns true, or throwing the error downstream if not. (There's no case where it will then move onto the next onErrorContinue operator, then the next, until a predicate is matched.)
Clearly this is a contrived example - but because of these idiosyncrasies, I'd almost always recommend avoiding onErrorContinue. There's two "normal" ways that can happen where flatMap() is involved:
If flatMap() has an "inner reactive chain" in it, that is it calls another method or series of methods that return a publisher - then just use onErrorResume() at the end of the flatMap() call to handle those errors. You can chain onErrorResume() since it works with downstream, not upstream operators. This is by far the most common case.
If flatMap() is an imperative collection of if / else that's returning different publishers such as it is here and you want to / have to keep the imperative style, throw exceptions instead of using Mono.error(), and catch as appropriate, returning Mono.empty() in case of an error:
.flatMap(number -> {
try {
if (number <= 3) {
throw new NumberLessThanThree();
} else if (number <= 6) {
throw new NumberLessThanSixButGreaterThan3();
} else {
return Mono.just(number);
}
}
catch(NumberLessThanThree ex) {
//Handle it
return Mono.empty();
}
catch(NumberLessThanSixButGreaterThan3 ex) {
//As above
}
})
In general, using one of these two approaches will make it much easier to reason about what's going on.
(For the sake of completeness after reading the comments - this isn't anything to do with the reactive chain being unable to complete before the main thread exits.)

Have single line empty constructors, but braces on newline everywhere else

I am looking for a way to make clang-format allow single line empty constructors, but to put braces on the newline everywhere else.
Ideally I want to support these three cases all with one clang config.
Test::Test(const std::string &name) : name(name) {}
std::string Test::get_name()
{
return name;
}
void Test::blank()
{
}
Is there a way to special case constructors in anyway? Even being able to have empty functions on a single line the same as constructors would be acceptable. But putting short functions on a single line is not acceptable.
This doesn't solve all the issues, but it solves my main case.
AllowShortFunctionsOnASingleLine: InlineOnly
This will allow short functions in class definitions to be single line.
From https://clang.llvm.org/docs/ClangFormatStyleOptions.html
SFS_InlineOnly (in configuration: InlineOnly) Only merge functions defined inside a class. Same as “inline”, except it does not implies “empty”: i.e. top level empty functions are not merged either.
class Foo {
void f() { foo(); }
};
void f() {
foo();
}
void f() {
}
This combined with BreakBeforeBraces: Allman gives me the desired result.

Are parsers generated by FSYacc thread safe?

If I generate a parser using FSYacc will it be thread safe?
The only reason I ask is because the functions
Parsing.rhs_start_pos and Parsing.symbol_end_pos
don't appear to have any state passed into them, which would lead me to assume that they are getting the current NonTerminal/Symbols from a shared location, is this correct?
After reflecting the code I see that they are getting the postion from a static property
internal static IParseState parse_information
{
get
{
return parse_information;
}
set
{
parse_information = value;
}
}
Is this correct? If so what can I do about it?
Edit: I also see a static method called set_parse_state
public static void set_parse_state(IParseState x)
{
parse_information = x;
}
But that still wont solve my problem...
I really don't like to answer my own question, however since this could save someone else a world of grief someday I will.
It turns out that the functions provided in the parsing module are NOT thread safe.
What you can do however is access the parseState "variable", which is of type IParseState, in your nonterminal action.
For example (rough but work with me):
If you have a NonTerminal like
%token<string> NAME
%%
Person:
NAME NAME { $1 (* action *) }
The code that gets generated is:
(fun (parseState : Microsoft.FSharp.Text.Parsing.IParseState) ->
let _1 = (let data = parseState.GetInput(1) in
(Microsoft.FSharp.Core.Operators.unbox data : string)
) in
Microsoft.FSharp.Core.Operators.box((_1) : 'Person)
);
So you can interact with that parseState object in the same fashion.
%token<string> NAME
%%
Person:
NAME NAME { parseState.DoStuff(); }
The rhs_start_pos method basically does this:
let startPos,endPos = parseState.InputRange(n)
and the symbol_end_pos does this:
let startSymb,endSymb = parseState.ResultRange
I hope this helps

Resources