Function declarations
Quick examples:
function orElse
Maybe<a> ::= l::Maybe<a> r::Maybe<a>
{
return if l.isJust then l else r;
}
function performSubstitution
TypeExp ::= te::TypeExp s::Substitution
{
te.substitution = s;
return te.substituted;
}
Functions declarations give a name for the function, and a signature in the same format as productions, except that the left-hand side is not named. Functions must also contain a return statement.
Like the children of productions, function parameters may be supplied inherited attributes in the function body, and are considered implicitly decorated.
Passing undecorated types to a function, accessing an attribute, and getting errors about missing inherited attribute equations is a common mistake for new Silver programmers.
Sometimes the function should have taken a reference (Decorated Expr
) type instead of the undecorated (Expr
) type.
All parameters are passed lazily. There is currently no strictness annotation.
aspect function driver
_ ::= _ _ _
{
tasks <- [emitDocumentation(ast)];
}
Aspect functions are also possible, by prefixing the declaration with aspect
.
Aspect functions are forbidden from using return
, their purpose is only to influence the value of “collection production attributes” (which is not only a mouthful, but misnomer inside a function, too!)
Aspecting functions is discouraged. Future changes may deprecate this feature.
A more concise function declaration can often be used in cases where a function simply returns an expression. Examples:
fun foldr b ::= f::(b ::= a b) i::b l::[a] =
if null(l) then i else f(head(l), foldr(f, i, tail(l)));
fun lookup Eq a => Maybe<b> ::= lst::[(a, b)] key::a =
case lst of
[] -> nothing()
| h::t -> if fst(h) == key then just(snd(h)) else lookup (t, key)
end;
fun getName
attribute name i occurs on a =>
Integer ::= inst::Decorated a with i = inst.name;
These functions do not require a decoration context, which makes the concise function representation more efficient than ordinary functions. Functions of this style are simply treated as global named lambda expressions.