Setting up the TypePal type checker on Eclipse IDE - rascal

After implementing a type checker in Rascal using TypePal, how do I hook it up to the Eclipse IDE? Any resources or repositories to the solution to this problem would be appreciated, Thanks.

in Eclipse search path of the Rascal Navigator view in your project you will find the rascal_eclipse library which contains a good example: demo::lang::Pico::Plugin
in this module you see how to register a language with Eclipse:
registerLanguage("Pico Language", "pico", parsePico); where parsePico is a function reference. Pass your own parameters here. The registerLanguage function comes from util::IDE.
now you can open files with the "IMP editor" in Eclipse and they will use your parser and show syntax highlighting.
next up is registering other effects with the IDE. The library function to call is registerAnnotator. You pass it a function that takes a parse tree for your language and annotates it with error messages:
the messages may be distributed over the tree, using #message or
using a list of #messages at the top of the tree
the error messages will be added as annotations in the editor and registered with the Problem View automatically.
So you have to wire the output of TypePal into the annotator function yourself. Which should be a one-liner.
Alternatively, running type-checks can also be useful after a "save" action. In this case you can register another type of contribition (also in the Pico demo), called builder: builder(set[Message] ((&T<:Tree) tree) messages), and register that with the registerContributions function.
The Message ADT is the same for the annotator and the builder. Both have the effect of adding editor annotations and problems in the view.
Here is some example code taken from an older open-source DSL project called "Bird", https://github.com/SWAT-engineering/bird:
Tree checkBird(Tree input){
model = birdTModelFromTree(input, pathConf = config(input#\loc)); // your function that collects & solves
types = getFacts(model);
return input[#messages={*getMessages(model)}]
[#hyperlinks=getUseDef(model)]
[#docs=(l:"<prettyPrintAType(types[l])>" | l <- types)]
;
}
birdTModelFromTree calls collectAndSolve from TypePal and returns the TModel
getMessage comes from TypePal's Utilities and extracts a list[Message] from the TModel that can be directly communicated to Eclipse via the #messages annotation.
The entire checkBird function is registered as an annotator using the util::IDE function registerAnnotator.
This code hasn't been used for a while, so if you run into trouble, please contact again?

Related

What does "Building tree for null using TinyBuilder" mean with Saxon extension function and using -t option?

With my Saxon extension function code I have the log messages:
> java -cp ./saxon-he-10.2.jar:./ net.sf.saxon.Transform -t -init:MyInitializer -xsl:./exttest.xsl -o:./out.xml -it:initialtemplate
Saxon-HE 10.2J from Saxonica
Java version 14.0.2
Stylesheet compilation time: 305.437652ms
Processing (no source document) initial template = initialtemplate
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for null using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 0.850325ms
Tree size: 3 nodes, 0 characters, 0 attributes
Execution time: 29.965658ms
Memory used: 14Mb
It is not clear to me wether Building tree for null using class net.sf.saxon.tree.tiny.TinyBuilder means that there is something wrong with my code https://gitlab.com/ms452206/socode20200915 and how to avoid it.
It's a poor message and I will improve it; the "null" would be the base URI (or systemId) of the document if it had one. The fact that the document has no known base URI could be a predictor of trouble downstream, since some things rely on a document having a known base URI; but it's not an error in itself.
It's most likely to happen if you build a document using a JAXP Source object whose systemId property is null. Which is what you have done when you wrote:
new StreamSource(new StringReader("<foo/>"))
This is likely to cause failures only if the document contains relative URIs (for example in external entity references or href or xml:base attributes), which is not the case with your simple XML document.

Is there support for predefined macros in DART

Does DART support predefined macros such as:
__LINE__
or
__FUNCTION__
The reason for asking is that the transformer DART2JS makes the console log not useful as all the logs shows: js_primitives.dart:30
[update BasE]
When using the transformer dart2js, print("hello world"); will result in:
JS('void', r'console.log(#)', "hello world);
to be invoked from function: printString(String string)
residing in the library dart2js._js_primitives
This results that the console.log message always contains the same line number over and over again wherever in the DART code a print(); is used. (As console.log will add automatically the filename and line-number to the console display of the wrapper function residing in dart2js._js_primitives)
As the current implementation of adding file-name and line-number to the console.log message is useless, it would have been nice if there would be another method that allows to display additional information.
As example, print("hello world" __FUNCTION__ __LINE__); would result in additional debug information that can be more useful.
You could use
void main() {
print(StackTrace.current);
}
to get better information about the source of the error
DartPad example
You can also run your code in a custom zone and define a custom print method for that zone. See also https://api.dartlang.org/stable/1.24.3/dart-async/Zone/print.html
Seems what you are looking for is source maps that dart2js creates, that contain the information needed to recreate line numbers in original dart files, from the javascript locations.

"attempt to call global 'tonumber' (a nil value)" in Lua, embedded (in VLC)

I use VLC media player 1.1.9 on Ubuntu 11.04. I'm trying to experiment with lua extensions for VLC; so I've added the file test.lua in ~/.local/share/vlc/lua/extensions/, which has only these two lines:
fps="25.000"
frame_duration=1/tonumber(fps)
When I run vlc with verbose output for debugging, I get (edited to split on multiple lines:):
$ vlc --verbose 2
...
[0xa213874] lua generic warning: Error loading script
~/.local/share/vlc/lua/extensions/test.lua:
.../.local/share/vlc/lua/extensions/test.lua:2:
attempt to call global 'tonumber' (a nil value)
...
Now, as far as I know, tonumber as function is part of Lua5.1 proper (Lua 5.1 Reference Manual: tonumber) - and on my system:
$ locate --regex 'lua.*so.*' | head -4
/usr/lib/libipelua.so.7.0.10
/usr/lib/liblua5.1.so
/usr/lib/liblua5.1.so.0
/usr/lib/liblua5.1.so.0.0.0
... apparently I do have Lua 5.1 installed.
So, why do I get an error on using tonumber here - and how can I use this (and other) standard functions in a VLC lua extension properly?
Documentation is sparse for VLC Lua extensions to say the least but I did find an example in the github vlc repository here: https://github.com/videolan/vlc/blob/master/share/lua/extensions/VLSub.lua
Judging from that example it appears you need to supply some basic event functions for your addon for VLC to call into when certain events happen. Some of the obvious callback handlers I've noticed:
descriptor, this should return a table that contains fields describing your addon.
activate, this seems to get called when you activate it from view menubar.
deactivate, called when you deactivate the addon from view menubar.
plus a couple of other functions like close and input_change which you can guess what they're for.
From my brief testing done on VLC 2.0.8 under Win7 it appears VLC loads the lua extension using an empty sandbox environment. This is likely the reason you're getting nil for tonumber and I'm betting none of the other standard lua functions are accessible either when you try to perform computation at this global scope.
However, if I move that code into one of the event handling functions then all those standard functions are accessible again. For example:
function descriptor()
return
{
title = "Test Ext";
version = "0.1";
author = "";
shortdesc = "Testing Lua Extension";
capabilities = {};
description = "VLC Hello Test Addon";
}
end
function activate()
print "test activating"
local fps = tonumber "25.000"
local frame_duration = 1 / fps
print(frame_duration)
return true
end
-- ...
That prints out what you would expect in the console debug log. Now the documentation (what little there is) doesn't mention any of this but what's probably happening here is VLC is injecting the standard lua functions and vlc api table into the sandboxed environment when any of these event handlers get called. But during the extension loading phase, it is done in an empty sandbox environment which explains why all those lua function calls end up being nil when you try to use it at the outter most scope.
I recommend cloning the VLC source tree from github and then performing a grep on the C source that's embedding lua to see what VLC is really doing behind the scenes. Most of the relevant code will likely be here: https://github.com/videolan/vlc/tree/master/modules/lua
Probably some extension script installed in your system overwrites the function and the Lua interpreter instance is shared between all extension scripts, so you end up not being able to call the function if that script is called before yours.
As a quick workaround, Lua being dynamically typed, you can still do things like:
1 / "25.000"
and the string will be coerced to a number.
Alternatively, you can define a tonumber equivalent like:
string_to_num = function(s) return s + 0 end
This again relies on dynamic typing.

FAKE Fsc task is writing build products to wrong directory

I'm just learning F#, and setting up a FAKE build harness for a hello-world-like application. (Though the phrase "Hell world" does occasionally come to mind... :-) I'm using a Mac and emacs (generally trying to avoid GUI IDEs by preference).
After a bit of fiddling about with documentation, here's how I'm invoking the F# compiler via FAKE:
let buildDir = #"./build-app/" // Where application build products go
Target "CompileApp" (fun _ -> // Compile application source code
!! #"src/app/**/*.fs" // Look for F# source files
|> Seq.toList // Convert FileIncludes to string list
|> Fsc (fun p -> // which is what the Fsc task wants
{p with //
FscTarget = Exe //
Platform = AnyCpu //
Output = (buildDir + "hello-fsharp.exe") }) // *** Writing to . instead of buildDir?
) //
That uses !! to make a FileIncludes of all the sources in the usual way, then uses Seq.toList to change that to a string list of filenames, which is then handed off to the Fsc task. Simple enough, and it even seems to work:
...
Starting Target: CompileApp (==> SetVersions)
FSC with args:[|"-o"; "./build-app/hello-fsharp.exe"; "--target:exe"; "--platform:anycpu";
"/Users/sgr/Documents/laboratory/hello-fsharp/src/app/hello-fsharp.fs"|]
Finished Target: CompileApp
...
However, despite what the console output above says, the actual build products go to the top-level directory, not the build directory. The message above looks like the -o argument is being passed to the compiler with an appropriate filename, but the executable gets put in . instead of ./build-app/.
So, 2 questions:
Is this a reasonable way to be invoking the F# compiler in a FAKE build harness?
What am I misunderstanding that is causing the build products to go to the wrong place?
This, or a very similar problem, was reported in FAKE issue #521 and seems to have been fixed in FAKE pull request #601, which see.
Explanation of the Problem
As is apparently well-known to everyone but me, the F# compiler as implemented in FSharp.Compiler.Service has a practice of skipping its first argument. See FSharp.Compiler.Service/tests/service/FscTests.fs around line 127, where we see the following nicely informative comment:
// fsc parser skips the first argument by default;
// perhaps this shouldn't happen in library code.
Whether it should or should not happen, it's what does happen. Since the -o came first in the arguments generated by FscHelper, it was dutifully ignored (along with its argument, apparently). Thus the assembly went to the default place, not the place specified.
Solutions
The temporary workaround was to specify --out:destinationFile in the OtherParams field of the FscParams setter in addition to the Output field; the latter is the sacrificial lamb to be ignored while the former gets the job done.
The longer term solution is to fix the arguments generated by FscHelper to have an extra throwaway argument at the front; then these 2 problems will annihilate in a puff of greasy black smoke. (It's kind of balletic in its beauty, when you think about it.) This is exactly what was just merged into the master by #forki23:
// Always prepend "fsc.exe" since fsc compiler skips the first argument
let optsArr = Array.append [|"fsc.exe"|] optsArr
So that solution should be in the newest version of FAKE (3.11.0).
The answers to my 2 questions are thus:
Yes, this appears to be a reasonable way to invoke the F# compiler.
I didn't misunderstand anything; it was just a bug and a fix is in the pipeline.
More to the point: the actual misunderstanding was that I should have checked the FAKE issues and pull requests to see if anybody else had reported this sort of thing, and that's what I'll do next time.

F#'s "Hello, world" with 2 fs files

I come from C# background to F#. So far I wrote simple programs and spent a lot of time in F# interactive.
I'm stuck creating a VS F# project with two .fs files.
Sample code:
// part 1: functions
let rec gcd (a : uint64) (b : uint64) =
if b = 0UL then a
else gcd b (a % b)
// part 2: main()
let a, b = (13UL, 15UL)
do printfn "gcd of %d %d = %d" a b (gcd a b)
I'd like to have two .fs files, namely, Alg.fs and Program.fs, so that Program.fs would contain the code I'm working and Alg.fs having algorithms.
Taken steps:
I've created the two files. Compiler gave an error: Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'
I've inserted module Program and module Alg. The complied program executes only the code from Alg.fs completely ignoring Program.fs...
I'm using F# 2.0 in Visual Studio 2010.
P.S. I've googled and checked some posts, and read documentation on modules and saw relative questions before asking.
Sounds like this is an order-of-files-in-the-project issue. The last file is the entry point ("main method"), sounds like you have Alg.fs last, and you need Program.fs last. You can re-order them via the right-click context menu in VS Solution Explorer.
There are at least three separate things that need to be looked at here:
As mentioned by #Brian, the order of source control files is also the compile order. This matters in F# where type inference is heavily used. Make sure Alg.fs comes before Program.fs in your Visual Studio file list (try this: select Program.fs and hit Alt+Down Arrow until it's at the bottom).
Since Alg.fs and Program.fs are now in modules, you need to actually open the Alg module in Program to get access to its bindings (open Alg), or add the [<AutoOpen>] attribute on Alg.
As #Daniel says, the last problem could be the definition of the entry point to the program. You need either an [<EntryPoint>] attribute on a top level binding that is also the last function in the last file. Alternatively, this defaults to the last binding in the last file anyway, just make sure it has the right signature (see Daniel's link).

Resources