summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/language.adoc297
1 files changed, 297 insertions, 0 deletions
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" "."
+```