Describe the type system

This commit is contained in:
2025-12-04 18:57:51 +01:00
parent 8eb87757a0
commit cc8f815337

View File

@@ -8,3 +8,300 @@ Elna is a simple, imperative, low-level programming language.
It is intendet to accompany other languages in the areas, where a high-level
language doesn't fit well. It is also supposed to be an intermediate
representation for a such high-level hypothetical programming language.
== Expressions
The expression `@r.field` includes 3 expressions:
1. Variable expression `r`.
2. Field access `(r).field`.
3. Address taking `@(r.field)`.
The expression is evaluated in the above order. The postfix expressions
like field access have higher precedence than prefix operators.
=== Binary expressions
.Operator precedence
|===
|Precedence |Operator |Description
|1 |* / % |Multiplication, division and remainder.
|2 |+ - |Addition and subtraction.
|3 |<< >> |Left and right shifts.
|4 |= <> > < <= >=| Relational operators.
|5 |or xor &| Logical operators.
|===
=== Unary expressions
Unary expressions are expressions with a prefix operator followed by one
operand.
`@` (*at sign*) takes the address of its operand. The operand expression should be
addressable.
`-` (*minus*) negates a numeric value.
`~` (*tilde*) applied on a boolean acts as logical not. Applied on a numeric as
bitwise not.
== Conditional statements
== Loop statements
== Type system
```
type = array-type | pointer-type | record-type | enumeration-type
| procedure-type | identifier.
```
=== Primitive types
* Pointer
* Word
* Int
* Bool
* String
* Char
=== Pointer types
```
pointer-type = "^" type.
```
Example:
```
program;
var
x: Int;
y: ^Int;
begin
y := @x;
y^ := 0
end.
```
=== Static array
```
array-type = "[" expression "]" type.
```
Example:
```
program;
var
array: [3]Int := [1, 2, 3];
begin
array[1] := array[2]
end.
```
=== Procedure types
```
procedure-heading = "proc" identifier-definition
"(" [field {"," field}] ")" return-declaration.
block = constant-part variable-part statement-part "end".
procedure-declaration = procedure-heading ";" (block | "extern").
return-declaration = ["->" "!" | "->" type].
procedure-type = "proc" "(" [types] ")" return-declaration.
```
Example:
```
program;
var
a: proc(Int) -> Int;
proc f(x: Int) -> Int;
end;
begin
a := f;
a(0)
end.
```
=== Records
```
field = identifier ":" type.
record-type = "record" ["(" identifier ")"] [field {";" field}] "end".
```
Example:
```
program;
type
T = record
x: Int
end;
U = record(T)
y: Int;
z: Int
end;
var
u: U;
begin
u := U(0, 1, 2);
u.x := 3
end.
```
=== Enumerations
```
enumeration-type = "(" identifier {"," identifier} ")".
```
Example:
```
program;
type
E = (one, two, three);
var
e: E;
begin
e := E.one
end.
```
=== Type operations
=== Cast
```
cast = "cast" "(" expression ":" type ")".
```
The type of an object can be reinterpreted with a cast expression:
`cast(object: Type)`.
=== Traits
```
trait-identifier = "#" identifier.
trait = trait-identifier "(" [types] ")".
```
Traits allow to query some information about the types, like their size or
field offset or alignment. Calling a trait looks like a procedure call but
traits names start with a `#` and their arguments are type expressions and
not value expressions.
Supported compiler traits:
- `#size(T)` queries type size.
- `#align(T)` queries type alignment.
- `#offset(T, F)` queries the offset of the field `F` in the record `T`.
== Appendix
=== Syntax
```
letter = "A" | "B" | … | "Z" | "a" | "b" | … | "z" | "_".
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".
character = ? a printable character ?.
hex-digit = digit | "A" | "B" | … | "F" | "a" | "b" | … | "f".
binary-digit = "0" | "1".
identifier = letter {letter | digit}.
identifier-definition = identifier ["*"].
trait-identifier = "#" identifier.
integer-literal = digit {digit}.
word-literal = integer-literal "u"
| "0" ("X" | "x") hex-digit {hex-digit}
| "0" ("B" | "b") binary-digit {binary-digit}.
real-literal = digit {digit} "." digit {digit}.
string-literal = """ {character} """.
character-literal = "'" {character} "'".
literal = integer-literal | word-literal | real-literal
| string-literal | character-literal
| "true" | "false" | "nil".
trait = trait-identifier "(" [types] ")".
cast = "cast" "(" expression ":" type ")".
procedure-call = designator "(" [expressions] ")".
relation-operator = "=" | "<>" | "<" | ">" | "<=" | ">=".
multiplication-operator = "*" | "/" | "%".
addition-operator = "+" | "-".
shift-operator = "<<" | ">>".
unary-operator = "@" | "~" | "-".
selector = "[" expression "]" | "." identifier | "^".
case = expressions ":" optional-statements.
designator = reference selector | identifier.
reference = literal | designator | trait | cast | procedure-call
| "(" expression ")".
factor = unary-operator factor | reference.
term = factor {multiplication-operator factor}.
simple-expression = term {addition-operator term}.
comparand = simple-expression {shift-operator simple-expression}.
relation = comparand {relation-operator comparand}.
operand = relation {"&" relation}.
expression = operand {("or" | "xor") operand}.
expressions = expression {"," expression}.
identifier-definitions = identifier-definition {"," identifier-definition}.
types = type {"," type}.
required-statements = statement {";" statement}.
optional-statements = [required-statements].
return-declaration = ["->" "!" | "->" type].
field = identifier ":" type.
array-type = "[" expression "]" type.
pointer-type = "^" type.
record-type = "record" ["(" identifier ")"] [field {";" field}] "end".
enumeration-type = "(" identifier {"," identifier} ")".
procedure-type = "proc" "(" [types] ")" return-declaration.
type = array-type | pointer-type | record-type | enumeration-type
| procedure-type | identifier.
assignment = designator ":=" expression.
if-statement = "if" expression "then" optional-statements
{"elsif" expression "then" optional-statements}
["else" optional-statements] "end".
while-statement = "while" expression "do" optional-statements
{"elsif" expression "do" optional-statements} "end".
defer-statement = "defer" optional-statements "end".
case-statement = "case" expression "of" case {"|" case}
["else" optional-statements] "end".
label-declaration = "." identifier.
goto-statement = "goto" identifier.
statement = assignment | procedure-call | defer-statement
| label-declaration | goto-statement |
| while-statement | if-statement | case-statement.
statement-part = ["begin" required-statements | "return" expression
| "begin" required-statements ";" "return" expression].
constant-declaration = identifier-definition ":=" expression.
constant-part = ["const" {constant-declaration ";"}].
variable-declaration = identifier-definitions ":" type
[":=" (expression | "extern")].
variable-part = ["var" {variable-declaration ";"}].
type_declaration = identifier-definition "=" type.
type-part ["type" {type-declaration ";"}].
import-declaration = identifier {"." identifier}.
import-part = ["import" {import_declarations ";"}].
procedure-heading = "proc" identifier-definition
"(" [field {"," field}] ")" return-declaration.
block = constant-part variable-part statement-part "end".
procedure-declaration = procedure-heading ";" (block | "extern").
declaration-sequence = import-part
constant-part type-part variable-part {procedure-declaration ";"}.
program = "program" ";" declaration-sequence statement-part "end" "."
| "module" ";" declaration-sequence "end" "."
```