Decorate and new
Quick examples:
decorate expr with { env = emptyEnv(); }
decorate expr with {}
decorate expr with { inh = value; env = top.env; }
just(new(expr))
See Decorated vs Undecorated for an explanation of what Decorated
means.
The following syntax will decorate an undecorated tree:
decorate expression with { inherited attribute = expression; ... }
The initial expression is expected to be undecorated. Each inherited attribute should occur on the type of the initial expression.
Example:
decorate expr with { env = [pair("x", 1), pair("y", 2)]; }
will decorate an undecorated expression with an environment binding two variables.
decorate folder with { input = ["Hello", "world"]; }.output
will decorate a value called
folder
with the inherited attributeinput
, then demand the synthesized attributeoutput
from the resulting decorated node.
new
is the inverse operation of decorate
.
It will take an explictly decorated valued (e.g. of type Decorated Expr
) and produce the undecorate valued (e.g. of type Expr
).
The following syntax will undecorate a decorated tree:
new(expression)
Any nonterminal-typed child of a production has both a decorated and undecorate value, and type inference will automatically select the appropriate one.
It’s generally unnecessary to use these expressions on such a child, unless a different decoration of a child is required than the usual one happening in that production.
(In such cases, it’s still likely you should use a local
instead of decorate
.)
Use of decorate
and new
generally only happens when doing slightly interesting things with let
and pattern matching or tree-rewriting.
You will often be guided by type errors in such cases.