Functions
Linking declaration
calling-convention ::= label
format ::= identifier
link ::= link [s] calling-convention
Functions can have a calling-convention parameter: the names and types of
the possible values are for future times (and platform specific)
Placement rules
placement ::= inline
| generic
generic-type ::= @ identifier
Generic code uses identifiers with an '@' prefix to indicate the placeholder
types.
Code use
code-use ::= terminal
| co_routine
| generator
| volatile
| constant
| synchronized
| weak
- terminal
- Function will never return, it should only have
'my' parameters, and no further code after its call is allowed
- co_routine
- Function can only be used by resume.
It can not have any parameters.
- generator
- Function can use yield
- volatile
- Function changes some basic (global) property.
No code may be moved from before <-> after its call by the optimizer.
- const
- Function changes nothing except its arguments, and
also gives a identical result for constant arguments. NB: print functions are
never constant. These functions, when called with constant arguments, may be
resolved at compile time.
- synchronized
- Only one active instance of the function may
exists. This is done inside the function itself, so the parameter
evaluation and the call itself are not protected. Synchronized
implies volatile
- weak
- Function need not be available. Parameter evaluation
(including side effects) is not done when the function is not
available. Note that weak function do certain magick; see
TODO.
Parameter
pass ::= copy | take | use
| borrow | share
| give | present
- copy
- (In) Pass by value, a new value is made, the function gets the ownership
- take [my]
- (In) Pass by reference, the function gets the ownership
- borrow [your]
- (In/Out) Pass by reference, function does not get the ownership
- THEIR
- (In/Out) Pass by value - return (for example RPC calls)
- share [our]
- (In/Out) Pass a shared variable by reference
- use
- (In) This is the odd one out. Actually use indicates that it is
either passed as borrow or as copy, but it has to be constant!
The compiler/interpreter can decide which method to choose.
Nota Bene: you can (and should) not use ==, or any other feature
which is based on the identity of the parameter.-
- give
- (Out) Return by reference, the caller gets the ownership
Return (out) value. Actually space for this paremeter is allocated by the
caller, and a reference to this space is passed to the function. Except
when the optimizer decides otherwise (TODO) like using registers
- present
- (Out) Return a shared variable
- mandatory
- The default value: this parameter has to be there
- automatic
- If this parameter is not present, a variable of this type is quietly
created in the 'nearest' with block in scope.
Note that a 'that automatic' parameter can be used as hidden
iterator
Also note that a 'return automatic' parameter is effectively an
optional return value
- repeated
- The type of this parameter is silently promoted to 'const []' of
its original type, and all calling params of the same type are aggregated into
that array.
Note that you can use the compound structure if you have 2+ repeated
parameter of identical type.
define function foo(my repeated integer a, my repeated integer b);
my int i,j,k,l;
foo(i,j,k,l); # a.length()==3 (i,j,k), b.length()==1 (l)
foo((i,j),(k,l)); # a.length()==2 (i,j), b.length()==2 (k,l)
parameter ::= [presence] [pass change] [check] type
Shortcut: If there is no passing method and no change field then
'some const' is silently inserted.
Constraints
fn-constraint ::= restriction-x
| requirement
| ensure-guarantee
| invariant-x
Contract
parameter-list ::= list-start [parameters] list-end
function ::= function
end-function ::= end [[s] function [s identifier]
function-contract ::= function identifier [s] parameter-list [[s] sep fn-constraint]...
...