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
|
||||
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" "."
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user