Tuesday, July 28, 2015

Accessing Clafer Models Programmatically

by Michał Antkiewicz, updated for Clafer 0.4.3

Since we ourselves translate Clafer into many output formats and use many different programming languages in the various tools (Haskell, Java, JavaScript), we developed ways of accessing the compiler's intermediate representation (IR), which represents fully-resolved information about Clafer models. This way, the compiler does all the hard work and the downstream tools can access the model conveniently.

Of course, the best way to access the IR is to call the compiler directly from Haskell via the API. The IR is a tree data structure defined in Intclafer.hs. The abstract syntax is defined (automatically generated from the grammar) in Absclafer.hs. After parsing, which creates the abstract syntax tree (AST), the compiler desugars the AST into the IR. The IR is then used as the basis of subsequent analyses (e.g., name, inheritance, and type resolution, and scope analysis), and it is rewritten to contain the results of these analyses. Finally, a number of generators can be invoked to produce the various outputs, such as, Alloy code, HTML rendering, or Graph rendering in GraphViz DOT language.

The various generators are located in the Generator folder. Some generators are simple (like Html.hs), some produce output such that the traceability information is preserved (Alloy.hs). Some generators are driven by the abstract syntax, like the HTML one which needs to preserve the original model layout, some are driven by the IR, like the Alloy one, which is more concerned about the semantics than the syntax.

The second best way to access the IR is to use the JSON output. Running the compiler with --mode=json model.cfr produces a file model.json. The JSON representation is an automatic serialization of the IR datatypes from Intclafer.hs and it contains full information about the model known to the compiler at the end of the compilation. This representation is used by the web tools 0.4.0.

The third best way to access the IR is to use the JavaScript output. Running the compiler with --mode=choco model.cfr produces a file model.js. The JavaScript representation is very compact and very convenient to work with. The project chocosolver, then defines Java classes for both the AST and the IR and evaluates the JavaScript to instantiate these classes (see the method JavascriptShell.load).

Finally, a parser can be generated directly using BNFC. We are using a customized BNFC to generate the Haskell implementation from Clafer grammar, but it can also be used to generate implementation for C, C++, C#, Java, and OCaml. This way is not recommended as it requires reimplementing all processing done by the compiler.

No comments:

Post a Comment