Describe the type system
This commit is contained in:
@@ -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
|
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
|
language doesn't fit well. It is also supposed to be an intermediate
|
||||||
representation for a such high-level hypothetical programming language.
|
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" "."
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user