eelco-visser-compiler-const.../lab/8.html

659 lines
21 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="Eelco Visser">
<meta name="generator" content="Jekyll v3.8.5">
<title>Lab 8: Simple Transformation</title>
<!-- <base href="/2021"> -->
<!--link rel="canonical" href="https://getbootstrap.com/docs/4.3/examples/starter-template/"-->
<link rel="icon" href="../img/logo/pl_ico2_2B3_icon.ico" type="image/x-icon">
<!-- Bootstrap core CSS -->
<!--link href="https://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="../css/main.css" rel="stylesheet">
<link href="../css/borders-responsive.css" rel="stylesheet">
<link rel="stylesheet" href="../css/pl.css">
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="../index.html">
TU Delft | CS4200
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="../lectures/index.html" tabindex="-1" aria-disabled="true">Lectures</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../homework/index.html" tabindex="-1" aria-disabled="true">Homework</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../project/index.html" tabindex="-1" aria-disabled="true">Project</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../news/index.html" tabindex="-1" aria-disabled="true">News</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../blog/index.html" tabindex="-1" aria-disabled="true">Blog</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div class="mt-3 mb-3 pt-3 pb-3 text-dark border-top border-bottom border-grey">
<div class="text-dark font-weight-bold">
<h1>
Lab 8: Simple Transformation
</h1>
</div>
<div>
</div>
<div>
Project
</div>
<div>
November 12, 2021
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-9 border-lg-right border-grey">
<p>During this lab get to know Stratego by making the <a href="https://weblab.tudelft.nl/cs4200/2021-2022/assignment/88076/view">homework assignments for Week 1</a> either in Spoofax 3 or in WebLab.</p>
<!--
This lab is your first encounter with Stratego.
You add an outline view and a desugaring transformation to an initial editor provided by us.
### Objectives
1. Specify rewrite rules `to-outline-label` which map AST nodes to labels in an outline view. You should include:
* classes (class name and, if available, parent class name),
* fields (field name and type),
* methods (method name, parameter types, return type) and
* local variables (variable name and type).
2. Define rewrite rules `desugar` which desugar
* unary expressions into terms of the form `UnExp(op, exp)`,
* binary expressions into terms of the form `BinExp(op, exp1, exp2)` and
3. Integrate `desugar` into a strategy `desugar-all` which desugars subtrees in an AST.
For grading, it is required to comply with all constructor names, rule names, and strategy names literally.
<!-- ### Submission
You need to submit your ChocoPy project with a merge request against branch `assignment-3-submission` on GitLab.
The [Git documentation](/project/lab1d) explains how to file such a request. -->
<!-- ### Early Feedback
We provide early feedback for the correctness of your outline and desugarings.
This feedback is a score out of 90 points; the strategy choice (10 points) is graded manually.
You have 3 early feedback attempts. -->
<!--
### Preliminaries
#### GitLab Repository
We provide you with a template for this assignment.
See the [Git documentation](/2021/lab/1d) on how to check out this branch.
Make sure to read the `README.md` in the root of the repository, as it contains further instructions that are specific to this template.
#### Anatomy of a Spoofax Project
Until now, you mainly worked on files in the `syntax` folder of your project.
During this lab you will also edit files in the `trans` folder.
So, this is a good point to talk about the general structure of a Spoofax project.
Note: this general structure does not apply to the template we've given you for the project, considering it contains a compiled version of the front-end already.
First of all, every Spoofax project may be part of an Eclipse plug-in project.
This allows you to deploy your editor as a plugin using the Eclipse update site mechanism.
Users do not need to have Spoofax installed for using your editor.
The actual language definition is spread over three folders:
* `syntax` contains all syntax definition files, including the main file `chocopy.sdf3`.
* `trans` contains all transformation files, including the main file `chocopy.str`.
* `editor` contains editor service definition files, including the main file `Main.esv`.
In the `src-gen` folder, you will find files which were generated from your syntax definition.
For each file `<name>.sdf3`, there are generated files:
* `syntax/<name>.sdf`: an SDF2 definition which is equivalent to the SDF3 definition.
* `completions/<name>-cp.str`: abstract placeholder expansions for syntactic code completion derived from SDF3 templates.
* `completions/colorer/<name>-cc-esv.esv`: instructions to color placeholders for syntactic completions in gray.
* `pp/<name>-pp.str`: pretty-printing strategies derived from SDF3 templates.
* `signatures/<name>-sig.str`: signatures derived from SDF3 templates.
You can find more generated files in `src-gen` and `target/metaborg` folders:
* `src-gen/syntax/ChocoPy.def`: your complete syntax definition in SDF2.
* `src-gen/syntax/ChocoPy-Permissive.def`: a permissive version of the syntax definition, which supports error recovery.
* `target/metaborg/ChocoPy.tbl`: the parse table of your language.
* `src-gen/pp/ChocoPy-parenthesize.str`: strategies to add parentheses to an AST according to the priorities of your language.
* `target/metaborg/stratego.ctree` and/or `target/metaborg/stratego.jar`: compiled Stratego code of your language.
#### Initial Editor Project
We provide you with an initial ChocoPy project in the branch `milestone-3-template`.
This project is a common starting point for all of you.
It includes:
* A compiled version of a front-end ChocoPy project.
* corresponding signatures `reference/src-gen/signatures/*-sig.str`,
* pretty-printing definitions `reference/src-gen/pp/*-pp.str`, and a
* content-completion definitions `reference/src-gen/completion/*-cp.str` (errors in the completion files can be ignored).
During the building of the project the contents of `reference` will be copied over to `src-gen`.
So, when importing any module from the reference, you can just use the 'local' variant.
I.e. instead of importing `reference/src-gen/signatures/chocopy-sig`, please import `signatures/chocopy-sig`.
#### Signature
Signatures declare sorts and constructors for terms.
In Spoofax, terms are used to represent abstract syntax trees.
The corresponding signature is generated from the constructors in a syntax definition.
You can find the signature for ChocoPy in the files `reference/src-gen/signatures/*-sig.str`.
The signature was generated from a syntax definition, which itself is not included in the initial project.
If you write your own syntax definition, the generated signatures can be found in `src-gen/signatures/`.
### Outline View
#### Rewrite Rules
An outline view can be specified by rewrite rules `to-outline-label` in `trans/outline.str`.
These rules should rewrite AST nodes to their label in an outline view.
For example, the following rule rewrites a variable declaration to its name, which will be used as a label.
```
rules
to-outline-label: Var(t, v) -> v
```
On the left-hand side, the rule matches a variable declaration.
During the match, variables `t` and `v` are bound to actual terms.
On the right-hand side, the rule instantiates a label.
During the instantiation, variable `v` is replaced with the term it is bound to.
You can extend `to-outline-label` to provide labels for
* class declarations,
* field declarations and
* method declarations.
When you build the project and open a ChocoPy file, you will get an outline of this program in the outline view.
In case you do not see any outline view, you can select it in *Show View* from Eclipse's *Window* menu.
#### Naming Conventions
In Stratego, we use the following naming conventions:
* constructor and sort names: camel case, starting with an upper case (e.g. `Add`, `BinExp`)
* rule names, strategy names, variable names: lower case, multiple words separated by `-` (e.g. `e1`, `project-path`)
#### String Interpolation
In many cases, you want to provide more information than just the name.
For example, you might want to show not only a variable's name, but also it's type.
The following rule achieves this:
```
to-outline-label:
Var(t, v) -> label
where
t' := <pp-partial-ChocoPy-string> t
; label := <concat-strings> [v, ": ", t']
```
On its right-hand side, it produces a `label`, which is bound in the `where` clause.
First, the term bound to `t` is turned into a string bound to `t'` by applying a strategy `pp-partial-ChocoPy-string`.
This strategy is defined in `ChocoPy/trans/pp.str` and uses the pretty-printing rules generated from our SDF3 grammar for ChocoPy.
Next, the label is bound to the concatenation of
the string bound to `v`,
a constant string `": "`,
and the string bound to `t'`.
String concatenation is not very intuitive.
Instead, you can also use string interpolation:
```
to-outline-label:
Var(t, v) -> $[[v]: [t']]
where
t' := <pp-partial-ChocoPy-string> t
```
String interpolation allows you to combine text with variables.
Text is enclosed in `$[` and `]`, while variables inside the text are enclosed in `[` and `]`.
These variables need to be bound to strings.
You should provide the following information in your outline labels:
* class name and super class name
* field name and type
* method name, parameter types (not parameter names), return type
* variable name and type
For parameter types, you need to turn a list of parameters into a string.
You can do this with a recursive strategy:
```
pp-params: // empty parameter list
[] -> ...
pp-params: // single parameter
[TypedVar(p, t)] -> ...
pp-params: // at least two parameters
[TypedVar(p, t), param | params] -> ...
where
// do something on first parameter
...
// recursive call on remaining parameters
... := <pp-params> [param | params]
```
For grading, it is required to define a strategy `pp-params` that always rewrites a list of `TypedVar`s to a *string*.
{: .notice .notice-warning}
Your current outline view is missing a root node.
You can add a root node by providing a label for programs.
#### Annotations
In Stratego, terms can be annotated with additional information.
The Spoofax outline view uses annotations to determine the icon of a node.
You can specify the icon to use in an annotation:
```
to-outline-label:
Var(t, v) -> label{icon}
where
t' := <pp-partial-ChocoPy-string> t
; label := $[[v]: [t']]
; icon := "icons/var.gif"
```
We do not require you to use icons and you will not earn any points with them.
If you want to use them anyway, you should put the icons into the folder `icons`
and place a proper attribution or license file next to them.
#### Challenge
Challenges are meant to distinguish excellent solutions from good solutions.
Typically, they are less guided and require more investigation or higher programming skills.
{: .notice .notice-success}
1. Provide the file name as the root node label. In `outline.str`: import, command/control click and study `libspoofax/term/origin` for a suitable strategy.
2. Outline the main method as a subnode of the main class.
You need to change this strategy in the `outline.str` file:
```
outline := <custom-label-outline(to-outline-label, to-outline-node)> ast
```
Also import, command/control click, and investigate `libspoofax/editor/outline` for inspiration.
3. Use one of the library strategies for folding to implement `pp-params`. You can find various folding strategies in the [API docs](http://releases.strategoxt.org/docs/api/libstratego-lib/stable/docs/).
### Desugaring
A uniform representation of unary and binary expressions eases static analysis and code generation.
To get such a uniform representation, you need to desugar abstract syntax trees during the analysis phase.
#### Signature
Before you can implement a desugaring,
you need to define a signature for the uniform representation of expressions in `trans/desugar.str`:
1. Identify unary and binary expressions in ChocoPy.
A unary expression has one subexpression and an operator.
A binary expression has two subexpressions and an operator.
There are more than one kind of unary expressions and more than three kinds of binary expressions in ChocoPy.
2. Specify new constants for unary and binary operators in a signature.
Use `UnOp` and `BinOp` as types of these operators.
Again, you should use names based on the semantics of an operator, not on its syntax.
Reading an expression aloud might help you to find suitable constructor names.
3. Define constructors `UnExp` and `BinExp`,
which combine an operator and an expression (respectively two expressions) to an expression.
#### Rewrite Rules
The following rewrite rule defines a rule to desugar an addition:
```
rules
desugar: Add(e1, e2) -> BinExp(Plus(), e1, e2)
```
This rewrite rule is named `desugar`.
On the left-hand side, the rule matches an addition.
During the match, variables `e1` and `e2` are bound to actual terms.
On the right-hand side, the rule instantiates a binary expression (in a uniform representation).
During the instantiation, variables `e1` and `e2` are replaced with the terms they are bound to.
You can extend `desugar` to replace the different unary and binary expressions in the abstract syntax tree
with a uniform representation of these expressions.
Define a rewrite rule `desugar` in `trans/desugar.str` for every unary or binary operator,
which transforms the original expression into a uniform representation.
#### Editor Integration
To test your transformation, you need to define a builder.
This is done similar to the builder for pretty-printing.
First, import the `desugar` module (defined in `trans/desugar.str`) into the main `chocopy` module.
Then, add the following rewrite rule to `trans/chocopy.str`:
```
editor-desugar:
(_, _, ast, path, project-path) -> (filename, text)
where
filename := <guarantee-extension(|"desugared.aterm")> path ;
text := <desugar-all> ast
```
This rule follows Spoofax' convention for strategies which implement editor services.
On the left-hand site, it matches a tuple of
* the first two parts are ignored
* the `path` of the current file and
* the `project path`.
On the right-hand site, it instantiates a pair, consisting of a `filename` and the designated `text` of the file.
Both variables are bound in the `where` clause.
The file name is derived from the path of the current file,
while the content of the file is a desugared version of the selected AST node.
You also need to hook your strategy into the editor, making desugaring available in the *Syntax* menu.
You can do this in `editor/Syntax.esv` under the *Show Parsed AST* action:
```
action : "Show desugared syntax" = editor-desugar (source)
```
This rule defines
* a builder,
* its label in the *Syntax* menu, and
* its implementation strategy `editor-desugar`.
Annotations can be used for different variants of builders:
* `(openeditor)` from the Syntax menu ensures that a new editor window is opened for the result.
* Finally, `(source)` tells Spoofax to run the builder on an unanalysed (and also not desugared) AST.
Note that the `editor-desugar` rule uses `desugar-all`. You should implement this strategy as explained in the next section. Until you do, the menu option will not work.
{: .notice .notice-warning}
#### Strategies
Rewrite rules typically define local transformations inside an AST.
Rewrite rules with the same name define a strategy of this name.
Furthermore, strategies can be defined to orchestrate rewrite rules to complex transformations of complete ASTs.
A strategy consists of a name and a definition, which is typically a combination of strategy applications.
For example, the following strategy orchestrates local desugarings to a desugaring of complete ASTs:
```
strategies
desugar-all = innermost(desugar)
```
This strategy is named `desugar-all`.
It applies local `desugar` rules.
The application is guided by a generic traversal strategy `innermost`,
which tries to apply its parameter inside a tree, starting at the leaves (bottom-up, left-to-right).
Whenever an application is successful, the result is traversed again.
Same results can be achieved with different generic traversals.
You should try different traversals in `trans/desugar.str`:
* `desugar-all = innermost(desugar)`
* `desugar-all = topdown(desugar)`
* `desugar-all = topdown(try(desugar))`
* `desugar-all = bottomup(desugar)`
* `desugar-all = bottomup(try(desugar))`
* `desugar-all = alltd(desugar)`
Try to understand what is going on and decide for a suitable one.
You can use the library strategy `debug` to print the currently visited node.
For example, `innermost(debug; desugar)` will `debug` all nodes before it tries to `desugar` them.
As preparation for the exam, provide an explanation of
1. the choice you made,
2. why this choice is suitable for this project, and
3. why other choices would be less suitable.
Try changing the `editor-desugar` rule to use `desugar-all` instead of `desugar`. If you chose a suitable strategy, the builder should succeed even when no node is selected in the ChocoPy program.
-->
</div>
<div class="col-sm-12 col-md-12 col-lg-3 col-xl-3 " >
<div class="sticky-top top70 d-none d-lg-block d-xl-block">
<div class="pb4 mb3 border-bottom border-grey ">
<nav>
<ul class="pagination justify-content-left">
<li class="page-item">
<a class="page-link" href="../milestone/2.html">
&laquo;
</a>
</li>
<li class="page-item">
<a class="page-link" href="../project/index.html">
^
</a>
</li>
<li class="page-item">
<a class="page-link" href="9.html">&raquo;</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="border-top border-bottom border-grey mt-3 pt-3">
<nav>
<ul class="pagination justify-content-center">
<li class="page-item">
<a class="page-link" href="../milestone/2.html">
Previous
</a>
</li>
<li class="page-item">
<a class="page-link" href="9.html">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="../project/index.html">
Index
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>