Type System
Type System
Type System
In Letlang, values are not assigned a single type. Instead, each type determines which values it contains.
For example:
42
is an int
, a number
, and the singleton type 42
"hello"
is a string
and the singleton type "hello"
We can consider a type definition to be some kind of function which returns
true
or false
wether the value belongs to that type.
The Letlang runtime MUST provide the following types:
bool
which contains the values true
and false
int
which contains every 64-bits floating-point number with the fractional part equal to 0number
which contains every 64-bits floating-point numberstring
which contains every UTF-8 encoded stringsatom
which contains every atomNB: An atom is a developer-defined symbol, for example:
@ok
,@error
,@hello_world
.
Additionally, the Letlang runtime MUST provide the following types:
pid
representing Letlang process identifiersfile
representing file descriptorssocket
representing socket descriptorsThose types MUST NOT be forgeable by the developer, only the Letlang runtime should be able to create values of those types.
Literal values MUST match the following syntax:
Rule: literal
Rule: literal_bool
Rule: literal_number
Rule: literal_string
Rule: literal_atom
literal
= literal_bool
/ literal_number
/ literal_string
/ literal_atom
literal_bool
= "true"
/ "false"
literal_number
= "0b" "_"* [01] [_01]*
/ "0o" "_"* [0-7] ["_" 0-7]*
/ [0-9][_0-9]*
/ "0x" "_"* [0-9a-fA-F][_0-9a-fA-F]*
/ (([0-9]+ "."? [0-9]*) / ("." [0-9]+)) (([eE][+-]?)? [0-9]+)?
literal_string
= "\"" ([^"] / "\\\"")* "\""
literal_atom
= "@" ( ("'" ([^'] / "\\'")+ "'") / ([_a-zA-Z][_a-zA-Z0-9]*))
The Letlang runtime MUST provide the following container types:
list<T>
, a generic type representing a list whose elements are of type T
,
for example: [1, 2, 3]
is a list<int>
(int, string)
contains values such as (42, "hello")
{foo: string}
contains values such as {foo: "bar"}
The Letlang runtime MUST NOT provide a tuple
or struct
type containing
“every tuples” or “every structures”.
Every value MUST be its own singleton type, for example:
42
is a singleton type containing only the value 42
"foo"
is a singleton type containing only the value "foo"
(@ok, 42)
is a singleton type containing only the value (@ok, 42)
The Letlang runtime MUST allow types to be combined using |
(or), &
(and) and/or !
(not).
For example:
int | string
is a type containing all integers and all strings!int
is a type containing all values, except integersnumber & !int
is a type containing all numbers except integersThis can be used to define tagged enumerations, such as:
(@ok, int) | (@error, string)
, similar to Rust’s Result type@none | (@some, int)
, similar to Rust’s Option typeEvery function is a value whose type is its signature, for example:
func foo(bar: string) -> @ok { ... }
belongs to the type func[(string) -> @ok]
func add(a: int, b: int) -> int { ... }
belongs to the type func[(int, int) -> int]
A type reference is defined using the following syntax:
Rule: typeref
Rule: typeref_val
Rule: typeref_name
Rule: typeref_struct
Rule: typeref_struct_member
Rule: typeref_tuple
Rule: typeref_func
Rule: typeref_oneof
Rule: typeref_allof
Rule: typeref_not
Rule: identifier
typeref
= typeref_val
/ typeref_name
/ typeref_struct
/ typeref_tuple
/ typeref_func
/ typeref_oneof
/ typeref_allof
/ typeref_not
typeref_val
= literal
typeref_name
= name:identifier
type_params:("<" identifier ("," identifier)* ","? ">")?
typeref_struct
= "{" members:(typeref_struct_member ("," typeref_struct_member)* ","?)? "}"
typeref_struct_member
= field:identifier ":" type:typeref
typeref_tuple
= "(" members:(typeref ("," typeref)* ","?)? ")"
typeref_func
= "func" "[" "(" params:(typeref ("," typeref)* ","?)? ")" "->" return_type:typeref "]"
typeref_oneof
= typeref "|" typeref
typeref_allof
= typeref "&" typeref
typeref_not
= "!" typeref
identifier
= [_a-zA-Z][_0-9a-zA-Z]*
A custom type is defined using a class
:
The type’s predicate (if present) MUST return a bool
.
The class
is defined using the following syntax:
Rule: class_decl_statement
Rule: proposition
class_decl_statement
= "pub"? "class" name:identifier
type_params:("<" identifier ("," identifier)* ","? ">")?
"(" cons_param:(variable:identifier ":" typename:typeref) ")"
(";" / predicate:("{" proposition+ "}"))
proposition
= proposition_let
/ proposition_expr
NB:
proposition_let
andproposition_expr
rules will be defined later.
The value of the last proposition of the class’s predicate evaluates to is the return value of the predicate.
Example:
module example;
class even(n: int) {
n % 2 = 0;
}
class odd(n: int & !even);
The Letlang runtime MUST perform type checking at the function’s boundaries:
The Letlang runtime MUST perform type checking when binding a value to a variable.
The Letlang runtime MUST perform type checking when requested manually by the developer.