Declaring Functions and Values
Grammar
val_bind ::= ["#[" attr "]"] ("def" | "let") (name | "(" symbol ")") type_param* pat* [":" type] "=" exp
| ["#[" attr "]"] ("def" | "let") pat symbol pat [":" type] "=" exp
Description
Functions and constants must be defined before they are used. A function declaration must specify the name, parameters, and body of the function:
def name params...: rettype = body
Type Inference
Hindley-Milner-style type inference is supported. A parameter may be given a type with the notation (name: type). Functions may not be recursive. The sizes of the arguments can be constrained - see Size Types.
Polymorphic Functions
A function can be polymorphic by using type parameters, in the same way as for Type Abbreviations:
def reverse [n] 't (xs: [n]t): [n]t = xs[::-1]
Type parameters for a function do not need to cover the types of all parameters. The type checker will add more if necessary. For example, the following is well typed:
def pair 'a (x: a) y = (x, y)
A new type variable will be invented for the parameter y.
Type Parameter Resolution
Shape and type parameters are not passed explicitly when calling functions, but are automatically derived. If an array value v is passed for a type parameter t, all other arguments passed of type t must have the same shape as v. For example, consider the following definition:
def pair 't (x: t) (y: t) = (x, y)
The application pair [1] [2,3] is ill-typed because the arrays have different shapes.
Aliasing Restrictions
To simplify the handling of in-place updates (see In-place Updates), the value returned by a function may not alias any global variables.
Let Bindings
let may not be used to define top-level bindings.
Shader Entry Points
Shader entry points are defined using the entry keyword with a #[vertex], #[fragment], or #[compute] attribute:
#[vertex]
entry vertex_main() #[builtin(position)] vec4f32 =
@[0.0, 0.0, 0.0, 1.0]
#[fragment]
entry fragment_main() #[location(0)] vec4f32 =
@[1.0, 0.0, 0.0, 1.0]
#[compute]
entry double(arr: []f32) []f32 = map(|x| x * 2.0, arr)
Entry Point Syntax:
- Parentheses are required, even for zero-argument entry points:
entry foo() ... - Parameters must be simple identifiers with explicit type annotations:
name: type - Pattern destructuring is not allowed in entry point parameters
- Return type is required and comes after the parameter list (no arrow)
When the Wyn program is compiled, any entry declaration in the single file passed directly to the Wyn compiler will be exposed as a shader entry point. Entry points in files accessed via import are not considered entry points, but can still be called as normal functions.
Entry Point Naming Restrictions:
The name of an entry point must not contain an apostrophe ('), even though that is normally permitted in Wyn identifiers.