Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 165 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Celerity

Loading...

Loading...

Language

Basic Concepts

Modules and Code Reuse

Types and Values

Optional Type Checking

Mutability and Freezing

Pattern Matching

Error Handling

Agents and Communication

Garbage Collection

Startup and Termination

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Special Types

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Value Expressions

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Operator Expressions

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Control Expressions

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Installation

Celerity can be installed as a in two ways:

To install Celerity globally, run dotnet tool install celerity -g. This will allow you to run the celerity CLI driver anywhere, assuming you have .

To install Celerity locally in a .NET-based project with a , omit the -g option. This will require you to run dotnet celerity from the project directory.

.NET tool
set up your PATH appropriately
tool manifest

Home

This is currently in-development vaporware.

Celerity is a programming language aiming for a good balance of productivity and scalability while being easily embeddable in host applications.

Celerity is expression-oriented, multi-paradigm, and features optional type checking. Some notable features are pattern matching, first-class functions with closures, opt-in mutability, explicit yet terse error propagation, concurrency based on lightweight agents, and non-suspending garbage collection.

Operators

operator ::= custom-operator |
             special-operator

Custom Operators

custom-operator ::= custom-additive-operator |
                    custom-multiplicative-operator |
                    custom-bitwise-operator |
                    custom-shift-operator
custom-additive-operator ::= [+-~] operator-part*
custom-multiplicative-operator ::= [*/%] operator-part*
custom-bitwise-operator ::= [&|^] operator-part*
custom-shift-operator ::= [><] operator-part*
operator-part ::= [+-~*/%&|^><]

Special Operators

special-operator ::= '=' |
                     '==' |
                     '!=' |
                     '>' |
                     '>=' |
                     '<' |
                     '<='

Identifiers

identifier ::= upper-identifier |
               lower-identifier |
               discard-identifier

Uppercase Identifier

upper-identifier ::= [A-Z] [0-9a-zA-Z]*

Lowercase Identifier

lower-identifier ::= [a-z] [_0-9a-z]*

Discard Identifier

discard-identifier ::= '_' [_0-9a-z]*

Special Identifiers

Binding Identifier

binding-identifier ::= discard-identifier |
                       code-identifier

Code Identifier

code-identifier ::= lower-identifier |
                    type-keyword

Punctuators

punctuator ::= '.' |
               '..' |
               ',' |
               ':' |
               '::' |
               ';' |
               '->' |
               '@' |
               '#' |
               '?' |
               '(' |
               ')' |
               '[' |
               ']' |
               '{' |
               '}'

Literals

literal ::= nil-literal |
            boolean-literal |
            integer-literal |
            real-literal |
            atom-literal |
            string-literal

Nil Literal

nil-literal ::= 'nil'

Boolean Literal

boolean-literal ::= 'true' |
                    'false'

Integer Literal

integer-literal ::= binary-integer-literal |
                    octal-integer-literal |
                    decimal-integer-literal |
                    hexadecimal-integer-literal
binary-integer-literal ::= '0' [bB] binary-digit ('_'* binary-digit)*
binary-digit ::= [0-1]
octal-integer-literal ::= '0' [oO] octal-digit ('_'* octal-digit)*
octal-digit ::= [0-7]
decimal-integer-literal ::= decimal-digit ('_'* decimal-digit)*
decimal-digit ::= [0-9]
hexadecimal-integer-literal ::= '0' [xX] hexadecimal-digit ('_'* hexadecimal-digit)*
hexadecimal-digit ::= [0-9a-fA-F]

Real Literal

real-literal ::= real-part '.' real-part ([eE] [+-]? real-part)?
real-part ::= decimal-digit ('_'* decimal-digit)*

Atom Literal

atom-literal ::= ':' (upper-identifier |
                      lower-identifier |
                      discard-identifier)

String Literal

string-literal ::= regular-string-literal |
                   verbatim-string-literal |
                   block-string-literal

Regular String Literal

regular-string-literal ::= '"' ([^#xa#xd#x85#x2028#x2029"\] |
                                regular-string-escape-sequence)* '"'
regular-string-escape-sequence ::= '\' (regular-string-escape-simple |
                                        regular-string-escape-unicode)
regular-string-escape-simple ::= [0aAbBeEfFnNrRtTvV"\]
regular-string-escape-unicode ::= [uU] hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit

Verbatim String Literal

verbatim-string-literal ::= '"""' '"'* [^#xa#xd#x85#x2028#x2029]+ '"""' '"'*

Block String Literal

block-string-literal ::= '"""' '"'* white-space* line-break block-string-line white-space* '"""' '"'*
block-string-line ::= [^#xa#xd#x85#x2028#x2029]* line-break

Attributes

attribute ::= '@' code-identifier literal

Declarations

declaration ::= attribute* (use-declaration |
                            type-declaration |
                            constant-declaration |
                            function-declaration |
                            test-declaration)

Type Declaration

type-declaration ::= ('pub' 'opaque'?)? 'type' lower-identifier type-parameter-list? '=' type ';'
type-parameter-list ::= '(' type-parameter (',' type-parameter)* ','? ')'
type-parameter ::= attribute* type-parameter-binding
type-parameter-binding ::= lower-identifier |
                           discard-identifier

Use Declaration

Constant Declaration

use-declaration ::= 'use' upper-identifier '=' module-path ';'
constant-declaration ::= 'pub'? 'const' code-identifier type-annotation? '=' expression ';'

Shebang Line

shebang-line ::= '#!' [^#xa#xd#x85#x2028#x2029]*

Function Declaration

function-declaration ::= 'pub'? (function-declaration-signature block-expression |
                                 'ext' function-declaration-signature ';')
function-declaration-signature ::= 'err'? 'fn' code-identifier function-parameter-list return-type-annotation?
function-parameter-list ::= '(' (function-parameter (',' function-parameter)* ','?)? ')'
function-parameter ::= attribute* function-parameter-binding type-annotation?
function-parameter-binding ::= binding-identifier

Any Type

any-type ::= 'any'

The type of any operation on a value typed as any is also any. A value of type any can be assigned to a location of any other type.

unk should generally be preferred over any wherever possible.

any is a special type that, like , allows any value. Unlike unk, however, any allows you to perform any operation on the value, even if the type checker would otherwise be able to prove that a given operation is incorrect.

unk

Keywords

keyword ::= regular-keyword |
            type-keyword |
            reserved-keyword

Regular Keywords

regular-keyword ::= 'and' |
                    'as' |
                    'assert' |
                    'break' |
                    'catch' |
                    'cond' |
                    'const' |
                    'defer' |
                    'else' |
                    'err' |
                    'ext' |
                    'false' |
                    'fn' |
                    'for' |
                    'if' |
                    'in' |
                    'let' |
                    'match' |
                    'meta' |
                    'mod' |
                    'mut' |
                    'next' |
                    'nil' |
                    'not' |
                    'opaque' |
                    'or' |
                    'pub' |
                    'raise' |
                    'rec' |
                    'recv' |
                    'ret' |
                    'tail' |
                    'test' |
                    'this' |
                    'true' |
                    'try' |
                    'type' |
                    'use' |
                    'while' |
                    'with'

Type Keywords

type-keyword ::= 'agent' |
                 'any' |
                 'atom' |
                 'bool' |
                 'handle' |
                 'int' |
                 'none' |
                 'real' |
                 'ref' |
                 'str' |
                 'unk'

Reserved Keywords

reserved-keyword ::= 'friend' |
                     'macro' |
                     'quote' |
                     'unquote' |
                     'yield'

Lexical Structure

input ::= shebang-line? token*
token ::= blank |
          comment |
          operator |
          punctuator |
          keyword |
          identifier |
          literal

Comments

comment ::= '//' [^#xa#xd#x85#x2028#x2029]*

Union Type

union-type ::= primary-type ('or' primary-type)*

Modules

Module Paths

module ::= attribute* 'mod' '{' declaration* '}'
module-path ::= upper-identifier ('::' upper-identifier)*

Literal Type

literal-type ::= nil-literal |
                 boolean-literal |
                 '-'? (integer-literal |
                       real-literal) |
                 atom-literal |
                 string-literal

Boolean Type

boolean-type ::= 'bool'

Atom Type

atom-type ::= 'atom'

Test Declaration

test-declaration ::= 'test' code-identifier block-expression

Reference Type

reference-type ::= 'ref'

Types

primary-type ::= nominal-type |
                 literal-type |
                 boolean-type |
                 integer-type |
                 real-type |
                 atom-type |
                 string-type |
                 reference-type |
                 handle-type |
                 module-type |
                 record-type |
                 error-type |
                 tuple-type |
                 array-type |
                 set-type |
                 map-type |
                 function-type |
                 agent-type
type ::= any-type |
         unknown-type |
         union-type |
         variable-type
type-annotation ::= ':' type

Return Types

return-type ::= regular-return-type |
                none-return-type
regular-return-type ::= type
none-return-type ::= 'none'
return-type-annotation ::= '->' return-type return-type-annotation-raise?
return-type-annotation-raise ::= 'raise' type

Variable Type

variable-type ::= 'type' lower-identifier variable-type-constraint?
variable-type-constraint ::= ':' union-type

Unknown Type

unknown-type ::= 'unk'

A value of type unk can only be assigned to a location of type unk or any.

unk is a special type that, like , allows any value. Unlike any, however, unk only allows a very limited set of operations which are safe on all values. In other words, unk is the type-safe counterpart to any.

any

Map Type

map-type ::= 'mut'? '#' '[' type ':' type ']'

Tuple Type

tuple-type ::= '(' type (',' type)+ ','? ')'

Blanks

blank ::= white-space |
          line-break

White Space

white-space ::= [#x9#xb#xc#x20#xa0#x1680#x#x2000-#x2009#x200a#x202f#x205f#x3000]

Line Break

line-break ::= [#xa#xd#x85#x2028#x2029]

Nominal Type

nominal-type ::= nominal-type-path? lower-identifier nominal-type-argument-list?
nominal-type-path ::= module-path '.'
nominal-type-argument-list ::= '(' nominal-type-argument (',' nominal-type-argument)* ','? ')'
nominal-type-argument ::= type

Integer Type

integer-type ::= 'int' integer-type-range?
integer-type-range ::= '(' (integer-type-range-bound '..' integer-type-range-bound? |
                            '..' integer-type-range-bound) ')'
integer-type-range-bound ::= '-'? integer-literal

Real Type

real-type ::= 'real'

Defer Statement

defer-statement ::= 'defer' expression ';'

defer statements are typically used to reliably clean up resources regardless of how control leaves a block expression.

Defers evaluation of (the body) until control leaves the enclosing . Multiple defer statements are evaluated in reverse lexical order.

expression
block expression

Let Statement

let-statement ::= 'let' pattern '=' expression ';'

Evaluates (the initializer) and matches it against . If the match fails, a panic occurs.

Any in pattern are available for the remainder of the enclosing . Any bindings in pattern that existed prior to the let statement are shadowed for the remainder of the enclosing block expression.

expression
pattern

String Type

string-type ::= 'str'
block expression

Expression Statement

expression-statement ::= (block-expression |
                          if-expression |
                          condition-expression |
                          match-expression |
                          receive-expression |
                          while-expression |
                          for-expression |
                          try-expression) ';'? | expression ';'

Expressions

Handle Type

Evaluates (the value). If the expression statement is the final statement of the enclosing , the value becomes the result of the block expression.

expression
block expression
expression ::= assignment-expression
prefix-expression ::= unary-expression |
                      primary-expression |
                      postfix-expression
primary-expression ::= parenthesized-expression |
                       block-expression |
                       this-expression |
                       meta-expression |
                       assert-expression |
                       identifier-expression |
                       literal-expression |
                       module-expression |
                       record-expression |
                       error-expression |
                       tuple-expression |
                       array-expression |
                       set-expression |
                       map-expression |
                       lambda-expression |
                       if-expression |
                       condition-expression |
                       match-expression |
                       receive-expression |
                       while-expression |
                       for-expression |
                       try-expression |
                       return-expression |
                       raise-expression |
                       next-expression |
                       break-expression
postfix-expression ::= primary-expression (field-expression |
                                           index-expression |
                                           call-expression |
                                           send-expression)*
handle-type ::= 'handle'

Literal Expression

literal-expression ::= literal

Record Type

record-type ::= 'rec' '{' (record-type-field (',' record-type-field)* ','?)? '}' record-type-meta?
record-type-meta ::= 'meta' type
record-type-field ::= 'mut'? code-identifier ':' type

Module Type

module-type ::= 'mod' '{' (module-type-field (',' module-type-field)* ','?)? '}'
module-type-field ::= code-identifier ':' type

Tuple Expression

tuple-expression ::= '(' expression (',' expression)+ ','? ')'

Array Type

array-type ::= 'mut'? '[' type ']'

Set Expression

set-expression ::= 'mut'? '#' '{' (expression (',' expression)* ','?)? '}'

Set Type

set-type ::= 'mut'? '#' '{' type '}'

Agent Type

agent-type ::= 'agent' agent-type-protocol?
agent-type-protocol ::= '{' agent-type-message (',' agent-type-message)* ','? '}'
agent-type-message ::= code-identifier agent-type-message-parameter-list
agent-type-message-parameter-list ::= '(' (agent-type-message-parameter (',' agent-type-message-parameter)* ','?)? ')'
agent-type-message-parameter ::= type

Function Type

function-type ::= 'fn' |
                  'err'? 'fn' function-type-signature?
function-type-signature ::= '(' function-type-parameter-list return-type-annotation ')'
function-type-parameter-list ::= '(' (function-type-parameter (',' function-type-parameter)* ','?)? ')'
function-type-parameter ::= attribute* type

Lambda Expression

lambda-expression ::= 'err'? 'fn' lambda-parameter-list '->' expression
lambda-parameter-list ::= '(' (lambda-parameter (',' lambda-parameter)* ','?)? ')'
lambda-parameter ::= attribute* lambda-parameter-binding
lambda-parameter-binding ::= binding-identifier

Additive Expressions

additive-expression ::= multiplicative-expression (custom-additive-operator multiplicative-expression)*

Module Expression

module-expression ::= module-path

Statements

statement ::= attribute* (let-statement |
                          defer-statement |
                          expression-statement)

If Expression

if-expression ::= 'if' expression block-expression if-expression-else?
if-expression-else ::= 'else' block-expression

The whole expression results in one of the following values, in order:

  1. The result of the then body.

  2. The result of the else body, if an if-expression-else is present.

Truthiness

Almost all values are considered truthy, with the following exceptions:

Evaluates the (the condition). If the result tests as , the first (the then body) is evaluated. Otherwise, if an if-expression-else clause is present, the second block-expression (the else body) is evaluated.

The .

The .

The .

expression
block-expression
truthy
nil value
nil value
false Boolean value

Multiplicative Expressions

multiplicative-expression ::= prefix-expression (custom-multiplicative-operator prefix-expression)*

Error Type

error-type ::= 'err' upper-identifier? '{' (error-type-field (',' error-type-field)* ','?)? '}'
error-type-field ::= 'mut'? code-identifier ':' type

Logical Expressions

logical-expression ::= relational-expression (('and' |
                                               'or') relational-expression)*

Error Expression

error-expression ::= 'err' upper-identifier error-expression-with? '{' (error-expression-field (',' error-expression-field)* ','?)? '}'
error-expression-with ::= 'with' expression
error-expression-field ::= 'mut'? code-identifier ':' expression

Condition Expression

condition-expression ::= 'cond' '{' condition-expression-arm (',' condition-expression-arm)* ','? '}'
condition-expression-arm ::= expression '->' expression

The whole expression results in the value of the evaluated body.

For each condition-expression-arm, in lexical order, evaluates the first (the condition). The first condition that tests as causes the associated second expression (the body) to be evaluated and the evaluation of arms to stop. If no body is evaluated during this process, a panic occurs.

expression
truthy

Array Expression

array-expression ::= 'mut'? '[' (expression (',' expression)* ','?)? ']'

Return Expression

return-expression ::= 'tail'? 'ret' expression

It is a semantic error for a ret expression to appear outside of an fn declaration or lambda expression. A ret expression cannot appear in the body of a defer statement, unless it is nested in a lambda expression.

A ret expression has no result value.

Evaluates (the result), explicitly returns result from the current or , and transfers control back to the caller.

Any that would go out of scope due to the control transfer are executed after evaluating result, but before returning it to the caller.

expression
fn declaration
lambda expression
defer statements

Match Expression

match-expression ::= 'match' expression '{' match-expression-arm (',' match-expression-arm)* ','? '}'
match-expression-arm ::= pattern match-expression-arm-guard? '->' expression
match-expression-arm-guard ::= 'if' expression

Unary Expressions

unary-expression ::= (custom-operator |
                      'not') prefix-expression

Receive Expression

receive-expression ::= 'recv' '{' receive-expression-arm (',' receive-expression-arm)* ','? '}' receive-expression-else?
receive-expression-arm ::= code-identifier receive-parameter-list receive-expression-arm-guard? '->' expression ','
receive-expression-arm-guard ::= 'if' expression
receive-expression-else ::= 'else' block-expression
receive-parameter-list ::= '(' (receive-parameter (',' receive-parameter)* ','?)? ')'
receive-parameter ::= pattern

Raise Expression

raise-expression ::= 'raise' expression

Bitwise Expressions

bitwise-expression ::= shift-expression (custom-bitwise-operator shift-expression)*

Break Expression

It is a semantic error for a break expression to appear outside of the loop body of a while expression or for expression. If a break expression appears in the body of a defer statement, it cannot bind to a while expression or for expression outside of the body.

A break expression has no result value.

Stops the evaluation of the enclosing or . In other words, a break expression is semantically equivalent to transferring control to just after the final statement of the loop body, and then performing no further iterations. If a break-expression-result is present, the (the result) becomes the result of the enclosing while expression or for expression.

Any that would go out of scope due to the control transfer are executed before stopping the loop.

break-expression ::= 'break' break-expression-result?
break-expression-result ::= 'as' expression
while expression
for expression
expression
defer statements

Shift Expressions

shift-expression ::= additive-expression (custom-shift-operator additive-expression)*

Block Expression

block-expression ::= '{' statement+ '}'

Relational Expressions

relational-expression ::= bitwise-expression (('==' |
                                               '!=' |
                                               '>' |
                                               '>=' |
                                               '<' |
                                               '<=') bitwise-expression)*

Meta Expression

meta-expression ::= 'meta' expression

Map Expression

map-expression ::= 'mut'? '#' '[' (map-expression-pair (',' map-expression-pair)* ','?)? ']'
map-expression-pair ::= expression ':' expression

Record Expression

record-expression ::= 'rec' record-expression-with? '{' (record-expression-field (',' record-expression-field)* ','?)? '}'
record-expression-with ::= 'with' expression
record-expression-meta ::= 'meta' expression
record-expression-field ::= 'mut'? code-identifier ':' expression

For Expression

for-expression ::= 'for' pattern 'in' expression block-expression for-expression-else?
for-expression-else ::= 'else' block-expression

Try Expression

try-expression ::= 'try' expression 'catch' '{' try-expression-arm (',' try-expression-arm)* ','? '}'
try-expression-arm ::= try-catch-pattern try-expression-arm-guard? '->' expression
try-expression-arm-guard ::= 'if' expression

While Expression

while-expression ::= 'while' expression block-expression while-expression-else?
while-expression-else ::= 'else' block-expression

The whole expression results in one of the following values, in order:

  1. The result of the loop body, if at least one iteration completes.

  2. The result of the else body, if a while-expression-else is present.

Evaluates the first (the loop body) repeatedly until the (the condition) no longer tests as . The condition is evaluated at the beginning of every iteration. If no iterations run and a while-expression-else is present, the second block-expression (the else body) is evaluated once.

The result of any within the loop body.

The .

break as expression
block-expression
expression
truthy
nil value

Identifier Expression

identifier-expression ::= code-identifier

Next Expression

next-expression ::= 'next'

It is a semantic error for a next expression to appear outside of the loop body of a while expression or for expression. If a next expression appears in the body of a defer statement, it cannot bind to a while expression or for expression outside of the body.

A next expression has no result value.

Skips the remaining portion of the loop body of the enclosing or and starts a new iteration. In other words, a next expression is semantically equivalent to transferring control to just after the final statement of the loop body.

Any that would go out of scope due to the control transfer are executed before the next loop iteration is started.

while expression
for expression
defer statements

Send Expression

send-expression ::= '->' code-identifier send-argument-list
send-argument-list ::= '(' (send-argument (',' send-argument)* ','?)? ')'
send-argument ::= expression

Parenthesized Expression

parenthesized-expression ::= '(' expression ')'

Assert Expression

assert-expression ::= 'assert' expression

The result of an assert expression is the value of the condition.

Evaluates (the condition). If the result does not test as , a panic occurs. An assert expression is always executed; it is not conditional on build flags or similar.

An assert expression is typically used in a to verify the outcome of a unit test, but it can also be used in regular code. The runtime system is allowed to optimize with the assumption that condition holds after the assert expression.

test declaration
expression
truthy

Assignment Expression

assignment-expression ::= logical-expression ('=' assignment-expression)*

This Expression

this-expression ::= 'this'

Field Expression

field-expression ::= '.' code-identifier

Index Expression

index-expression ::= index-argument-list
index-argument-list ::= '[' index-argument (',' index-argument)* ','? ']'
index-argument ::= expression

Call Expression

call-expression ::= call-argument-list '?'
call-argument-list ::= '(' (call-argument (',' call-argument)* ','?)? ')'
call-argument ::= expression
bindings