From cc8f8153379c1ca071418d32e7e98129c9f6d5bb Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 4 Dec 2025 18:57:51 +0100 Subject: [PATCH] Describe the type system --- doc/language.adoc | 297 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) diff --git a/doc/language.adoc b/doc/language.adoc index 53b42e4..e6c5e7b 100644 --- a/doc/language.adoc +++ b/doc/language.adoc @@ -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" "." +```