command
#
A command declaration introduces a new global command in the application. It has many different syntaxes depending on which features of the command one is using, and the name of the command.
Signatures#
Signatures define the name of the command, and can be postfix, prefix, binary, keyword, or self-less keyword.
Postfix commands#
A postfix command _ name
can be defined with:
command Requirement name do
// Implementation
end
Or:
command Requirement name = Expression;
Cast commands#
A cast command _ as Type
can be defined with:
command Requirement as type-name do
// Implementation
end
The right hole of this command is always going to be a specific type, and it’s not possible to bind that to any variable.
Binary commands#
A binary command _ + _
can be defined with:
command Requirement + Requirement do
// Implementation
end
Or:
command Requirement + Requirement = Expression;
The following is the complete list of valid binary names:
_ <- _
(store);_ and _
;_ or _
;_ === _
(equals);_ =/= _
(not equals);_ > _
(greater than);_ >= _
(greater or equal to);_ < _
(less than);_ <= _
(less or equal to);_ + _
(plus);_ - _
(minus);_ * _
(times);_ / _
(divided by);_ % _
(remainder of a division);_ ** _
(power);_ ++ _
(juxtaposition, concatenation);
Prefix commands#
A prefix command not _
can be defined with:
command not Requirement do
// Implementation
end
Or:
command not Requirement = Expression;
The following is the complete list of valid prefix names:
not _
;
Keyword commands#
A keyword command _ and: _ then: _
can be defined with:
command Requirement and: Requirement then: Requirement do
// Implementation
end
Or:
command Requirement and: Requirement then: Requirement =
Expression;
Self-less keyword commands#
A self-less keyword command and: _ then: _
can be defined with:
command and: Requirement then: Requirement do
// Implementation
end
Or:
command and: Requirement then: Requirement =
Expression;
Requirements#
Requirements define how a command can be triggered. They can either be left out (no requirements exist to prevent the command from triggering), or can be based on types and traits.
Ignored requirements#
An ignored requirement uses the _
(underscore) syntax:
command _ name do
// Implementation
end
Variable requirements#
A variable requirement is simply a variable name, such as Variable
:
command Variable name do
// Implementation
end
Type requirements#
A requirement that the value is of type good
has syntax:
command (Requirement is good) name do
// Implementation
end
Trait requirements#
A requirement that the value has a trait trait-a
, and trait-b
has
syntax:
command (Requirement has trait-a, trait-b) name do
// Implementation
end
Type and trait requirements#
Combined type and trait requirements has the syntax:
command (Requirement is good has trait-a, trait-b) name do
// Implementation
end
Contracts#
Contracts define conditions that must be true before the execution of the command (pre-conditions), and after the execution of the command (post-conditions).
Pre-conditions#
A pre-condition is introduced by the requires
keyword, and contains
any number of name :: Expression
contracts:
command Variable name
requires
first-condition :: Variable > 0,
second-condition :: Variable < 30
do
// Implementation
end
Post-conditions#
A post-condition is introduced by the ensures
keyword, and contains
any number of name :: Expression
contracts. It can use the return
value:
command Variable name
ensures
first-condition :: Variable < return,
second-condition :: return < 100
do
// Implementation
end
Test blocks#
A test block is a convenience for writing example-based tests for the command. It has the following syntax:
command Variable name do
// Implementation
test
assert 5 name === 10;
end
Documentation comment#
Commands may have a preceding documentation comment with the syntax:
/// This is a documentation comment
/// And it spans
/// Multiple lines
///
command _ name do
// Implementation
end
Example#
command (Items is list) separated-list do
condition
when Items is-empty => "";
when Items count === 1 => "[Items first]";
when Items count === 2 => "[Items at: 1], and [Items at: 2]";
otherwise do
"[Items first], [Items rest separated-list]";
end
end
test
assert [] separated-list flatten-into-plain-text === "";
assert ["a", "b"] separated-list flatten-into-plain-text === "a, and b";
end