I'm trying to write a summarizer for my DSL in order to display error messages in the console. I've been following the example with the Pico language and was able to successfully create a parser and get syntax highlighting for my language. I tried to copy and simplify the Pico summarizer as much as possible in order to make it work for my language, but to no success so far.
Here's a small part of the grammar for my language:
start syntax Deployment = deployment: Hardware+ hardwares;
syntax Hardware = hardware: "hardware" String name "{" Service* services "}";
And here's the current state of the Language module:
set[LanguageService] depContributions() = {
parsing(parser(#start[Deployment])),
analysis(summarizer, providesDocumentation = false, providesDefinitions = false, providesReferences = false, providesImplementations = false)
};
int produceLSP() {
registerLanguage(
language(
pathConfig(srcs=[|project://deployment-manager/src/main/rascal|]),
"DeploymentManager",
{"dep"},
"Language",
"depContributions"
)
);
return 0;
}
Summary summarizer(loc l, start[Deployment] input) {
rel[str, loc] result = {<"<var.name>", var.src> | /Hardware var := input};
return summary(l,
messages = {<src, error("<id> exists", src)> | <id, src> <- result}
);
}
When I open a DSL program, I get the following error message:
Parsing failed: CallFailed
at: |project://deployment-manager/src/main/rascal/Language.rsc|(443,5,<19,139>,<19,144>)
The line the error message points to is the analysis line in depContributions().
I would greatly appreciate it if someone could help me out!
1 Answer 1
Ah yes, this can be tricky at first. But later you might appreciate the extensible overloading feature of Rascal functions :-) For now, this overloading feature is messing up your code, as follows:
The
analysisfunction fails to apply, because one of its arguments does not fit the formal type parameter. When a function fails to apply in Rascal you get aCallFailedexception.The reason is that the first argument
summarizerdoes not have a type that matchesSummary (loc _origin, Tree _input)The reason for that is that the function
summarizeris overloaded in the current context. There is your definition of type:Summary (loc l, start[Deployment] input)-which perfectly fits by the way. But there is also this other one, imported fromutil::LanguageServer:LanguageService summarizer(Summarizer summarizer, ...). Together these two functions with the same name are merged into one, with the typevalue(the "least upper bound type" of the two function types) because they do not have the same amount of parameters.valueis not a subtype ofSummary (loc, Tree)and soanalysisfails to apply.
The fix for this is easy. Just rename summarizer to mySummarizer and supply that function to the analysis language service. That way it will not be overloaded anymore and keep its original type, and thus match with the first formal parameter of analysis.
10 Comments
summarizer function. However, I still do not see any error messages. I would expect to see test_machine exists for example. Is the cause something in the definition of my syntax? Also is there a way of debugging the functions applied to registerLanguage?import ParseTree;), d = parse(#start[Deployment], |file:///something.dep|), and you call mySummarizer(|file:///something.dep|, d)mySummary.messages you can see what the messages are like. The location URI's are hyperlinks, so you can jump to the source of each error message to check if it's right.rel[str, loc] result = {<"<var.name>", var.src> | /Hardware var := input}; into its own function, so you can test it separately. It looks good to me, BTW.mySummarizer works and I can see the error message that I expect in my REPL when I call mySummarizer from there. However, I still do not see them in VSCode. I'm expecting the error message to show up in the Problems section of the bottom panel. Is that what the expected outcome should be? I know that produceLSP() works because I see correct terminal output and syntax highlighting.