Metadata

Sometimes we need a way to associate some extra information to a specific named binding and have it be visible whenever we refer to that name. The most common reason for this is documentation comments. When we write some documentation for a binding we would like this documentation to be visible whenever someone uses that binding.

For this reason gluon runs a "metadata" pass on all code in which "metadata" (such as documentation comments) gets statically propagated throughout the code.

/// Adds one to the argument `x`
let add1 x = x + 1

/// Adds two to the argument `x`
let add2 x = x + 2

add1 // Looking up the metadata of this variable yields the documentation of `add1`

// It can't be statically determined which branch the `if` takes (since constant folding do not
// take place). Thus `addN` do not get any metadata from either `add1` or `add2`
let addN = if True then add1 else add2
addN

Attributes

In addtion to documentation comments gluon also has a special notion of attributes that get propagated in the same manner. These are specified using the following syntax.

Attribute : #[ AttributeContents ]

AttributeContents :
      #[ IDENTIFIER ]
    | #[ IDENTIFIER ( TOKENS* ) ]

#[infix(..)]

#[infix(<left|right>, <NON-NEGATIVE INTEGER>)]

The #[infix] attribute is used to specified the fixity and precedence of infix operators. This lets us specify that multiplication binds tighter that addition.

#[infix(left, 6)]
let (+) ?num : [Num a] -> a -> a -> a = num.(+)
#[infix(left, 7)]
let (*) ?num : [Num a] -> a -> a -> a = num.(*)

#[implicit]

#[implicit]

The #[implicit] attribute is used to mark value bindings or type bindings as usable for implicit resolution. If specified on a value binding then only that specific binding can be used on implicit resolution. If specified on a type binding then all bindings that has that type can be used in implicit resolution.

// Can be used as an implicit argument
#[implicit]
let binding : MyType = ..

#[implicit]
type Eq a = { (==) : a -> a -> Bool }

// Can be used as an implicit argument
let eq_Int : Eq Int = ..

#[derive(..)]

#[derive(IDENTIFIER)]

The #[derive(..)] attribute can be used on type bindings to generate implementations for some traits. Currently only Eq and Show can be derived and only non-recursive and self-recursive types are supported (mutually recursive types do not work for the moment).

#[derive(Eq, Show)]
type Tree a = | Tip a | Branch (Tree a) (Tree a)

let tree = Branch (Tip 1) (Branch (Tip 2) (Tip 3))

let tree_str = show tree // "Branch (Tip 1) (Branch (Tip 2) (Tip 3))"
tree == Tip 1 // False

#[doc(hidden)]

#[doc(hidden)]

The #[doc(hidden)] attribute hides the binding, omitting it from generated documentation.