Juno Frontend
Syntax
Throughout the description of syntax, we use the convention that any text contained within a pair of angle-brackets with no space (such as ) denotes a placeholder. In particular, we use the following placeholders
- name: an identifier, which must begin with a letter and the other characters may be letters, numbers, or underscores
- qualified name: a sequence of identifiers separated by
::
- top levels: a number of top-level constructs; where the top-level constructs are those defined below as Modules, Constants, Types, and Functions
- type: a type name
- expr: an expression
Additionally, text contained within a pair of square brackets without space (such as [this]) denotes an optional part of the syntax
Modules
Modules can be imported using
use <qualified-name>;
In this context, the qualified name may also end with ::*
to indicate that all names in some package should be imported into the current scope.
To define a new module within an existing file, use
[pub] mod <name> { <top-levels> }
where the optional pub indicates whether the module is exported when this file is used by another program.
Constants
Constant values can be declared as
[pub] const <name> [: <type>] = <expr>;
Constant values must be able to be completely evaluated at compile time and therefore do not allow function calls, but all other expression forms, with the exception of those involving arrays, are supported.
Types
Type declarations have the form
[pub] type <name> [< <type-variables> >] = <type-def>
where <type-variables>
are a comma separated list of names and kinds expressed as <name> : <kind>
where the kinds are type
, usize
, number
, and integer
.
The kind type
indicates that the associated variable is some type; this is the standard type variables that are present in many languages.
The kind usize
indicates that the variable is a dynamic constant, and can therefore be used as a dimension for arrays as well as being used in expressions.
The kinds number
and integer
indicate that the associated variable is a type but must be a numeric type or integer type, respectively; this allows us to express computation such as matrix multiplication which can be applied to any numeric type while still ensuring that this parametric function will be well-typed for all types it can be applied to (in contrast to C++ where type errors can arise when a function is instantiated).
In addition, the kind can be omitted after a variable to instead create a list of variables followed by a kind, such as x, y, z : usize
, in which case all preceding variables after the last kind are given the specified kind (here usize
).