summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/chapter17/17-grammar.md132
-rw-r--r--docs/chapter17/Makefile12
-rw-r--r--docs/chapter17/README.md136
3 files changed, 280 insertions, 0 deletions
diff --git a/docs/chapter17/17-grammar.md b/docs/chapter17/17-grammar.md
new file mode 100644
index 00000000..7b611fbf
--- /dev/null
+++ b/docs/chapter17/17-grammar.md
@@ -0,0 +1,132 @@
+# Grammar for Chapter 16
+
+```antlrv4
+grammar SimpleLanguage;
+
+program : block EOF ;
+
+block : statement+ ;
+
+
+statement
+ : '{' block '}'
+ | returnStatement
+ | ifStatement
+ | whileStatement
+ | breakStatement
+ | continueStatement
+ | metaStatement
+ | structDeclaration
+ | expressionStatement
+ ;
+
+
+returnStatement : 'return' expression ';' ;
+
+ifStatement : 'if' '(' expression ')' statement ('else' statement)? ;
+
+whileStatement : 'while' '(' expression ')' statement ;
+
+breakStatement : 'break' ';' ;
+
+continueStatement : 'continue' ';' ;
+
+metaStatement : '#showGraph' ';' ;
+
+structDeclaration : 'struct' IDENTIFIER '{' block '}' ;
+
+expressionStatement
+ : type IDENTIFIER ';'
+ | type IDENTIFIER '=' expression ';'
+ | IDENTIFIER '=' expression ';'
+ | expression
+ ;
+
+PRIMTYPE
+ : 'int'
+ | 'i8'
+ | 'i16'
+ | 'i32'
+ | 'i64'
+ | 'u8'
+ | 'u16'
+ | 'u32'
+ | 'flt'
+ | 'f32'
+ | 'f64'
+ | 'bool'
+ ;
+
+type
+ : PRIMTYPE
+ | typeName '?'?
+ | typeName nestedArray+
+ ;
+
+nestedArray : '?'? '[]'* ;
+
+typeName : IDENTIFIER ;
+
+
+expression : bitWiseExpression ;
+
+bitWiseExpression
+ : comparisonExpression ( '&' | '|' | '^' ) comparisonExpression)*
+ ;
+
+comparisonExpression
+ : shiftExpression (('==' | '!='| '>'| '<'| '>='| '<=') shiftExpression)*
+ ;
+
+shiftExpression
+ : additiveExpression ( '<<' | '>>>' | '>>' ) additiveExpression)*
+ ;
+
+additiveExpression
+ : multiplicativeExpression (('+' | '-') multiplicativeExpression)*
+ ;
+
+multiplicativeExpression
+ : unaryExpression (('*' | '/') unaryExpression)*
+ ;
+
+unaryExpression
+ : ('-') unaryExpression
+ | '!' unaryExpression
+ | primaryExpression postAssign
+ ;
+
+primaryExpression
+ : INTEGER_LITERAL
+ | FLOAT_LITERAL
+ | '(' expression ')'
+ | 'true'
+ | 'false'
+ | 'null'
+ | newExpression
+ | IDENTIFIER
+ ;
+
+newExpression
+ : 'new' IDENTIFIER [ '{' block '}' ]
+ | 'new' IDENTIFIER '[' expression ']'
+ ;
+
+postAssign : postFix [ '=' expression ] | [ '#' ];
+
+postFix
+ : '.' IDENTIFIER postFix
+ | '[' expression ']' postFix
+ ;
+
+
+IDENTIFIER : NON_DIGIT (NON_DIGIT | DIGIT)* ;
+
+INTEGER_LITERAL
+ : [1-9]DIGIT*
+ | [0]
+ ;
+
+NON_DIGIT: [a-zA-Z_];
+DIGIT: [0-9];
+```
diff --git a/docs/chapter17/Makefile b/docs/chapter17/Makefile
new file mode 100644
index 00000000..12659b8f
--- /dev/null
+++ b/docs/chapter17/Makefile
@@ -0,0 +1,12 @@
+GV := $(wildcard *.gv)
+SVG := $(patsubst %.gv,%.svg,$(GV))
+
+.PHONY: all
+all: $(SVG)
+
+%.svg: %.gv
+ dot -Tsvg $< > $@
+
+.PHONY: clean
+clean:
+ @rm -f $(SVG)
diff --git a/docs/chapter17/README.md b/docs/chapter17/README.md
new file mode 100644
index 00000000..f6216398
--- /dev/null
+++ b/docs/chapter17/README.md
@@ -0,0 +1,136 @@
+# Chapter 17: Syntax Sugar
+
+
+## Pre/Post-increment
+
+Allow `arg++` and `arg--` with the usual meanings; the value is updated and the
+expression is the pre-update value. Greedy match is used so `arg---arg` parses
+as `(arg--)-arg`.
+
+Also allows `s.fld++` and `ary[idx]++`, and their `--` variants.
+
+Allow pre-increment for identifiers only, for now: `--pc`.
+
+
+## Operator assignment
+
+Along the same lines as post-increment, we now allow `op=` assignment
+with semantics similar to other languages.
+
+`x += y`
+
+
+## var & val
+
+`var` can be used in the `type` position to indicate a "variable" (mutable
+value), whose type will be inferred from the required initalizing expression.
+
+`val` is the same as `var`, except it is a "value" (not mutable).
+
+The inferred value is the `glb` of the peephole type, which means `var` and
+`val` will not infer types like `u8` or `f32`, instead inferring `int` and
+`flt` respectively. Reference types will always infer as nullable, so e.g.
+
+`var s = new S;`
+
+infers as
+
+`S s? = new S;`
+
+
+## Mutability
+
+Typed primitive fields are always mutable. Typed reference fields without an
+initializer must be mutable to get a value. Initialized reference variables
+are immutable by default and can be made mutable with a leading `!`. `var` and
+`val` keep their current sense and can be used to make any field mutable or
+immutable. Fields are always mutable during construction, but will become
+immutable at the end of either constructor.
+
+`int x; x=3; x++; // OK, primitive so mutable`
+
+`int x =3; x++; // Ok, primitive so mutable, despite initializer`
+
+Assume in the next examples this struct exists:
+`struct S { int x; };`
+
+Then:
+
+`S s; s = new S ; s.x++; // OK, no initializer so s.x is mutable`
+
+`S s; s = new S{x=3}; s.x++; // OK, no initializer so s.x is mutable`
+
+`S s = new S ; s.x++; // Error, initializer so s.x is immutable`
+
+`S s = new S{x=3}; s.x++; // Error, initializer so s.x is immutable`
+
+Leading `!` makes mutable:
+
+`S !s = new S; s.x++; // Ok, has '!' so mutable`
+
+'var' is variable:
+
+`var s = new S; s.x++; // Ok, has var so mutable`
+
+'val' is a "value": not mutable through this reference, but may be mutable
+through other references.
+
+`val s = new S; s.x++; // Error, val so s.x is immutable`
+
+
+
+### Reference variables with an initializer are deeply immutable
+
+Initialized reference variables are deeply immutable, but a mutable version of the same
+reference can exist. This works for `val` and normal type declarations: `val s
+= new S;` and `S s = new S` both make `s` an immutable reference to a `struct S`.
+
+```cpp
+struct Bar { int x; }
+Bar !bar = new Bar;
+bar.x = 3; // Ok, bar is mutable
+
+struct Foo { Bar !bar; int y; }
+Foo !foo = new Foo;
+foo.bar = barl // Ok bar is mutable
+foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable
+
+val xfoo = foo; // Throw away mutability
+xfoo.bar.x++; // Error, cannot mutate through xfoo
+
+print(xfoo.bar.x); // Ok to read through xfoo, prints 4
+foo.bar.x++; // Bumps to 5
+print(xfoo.bar.x); // Ok to read through xfoo, prints 5
+```
+
+## Trinary
+
+Allow `pred ? e_true : e_false`. Also allow `pred ? e_true`, where the false result
+is the zero type version of the true result.
+
+
+## For Loops
+
+Allow C/C++ style `for` loops:
+
+`for( init; test; next ) body`
+
+Example:
+
+```cpp
+int sum=0;
+for( int i=0; i<arg; i++ )
+ sum += i;
+return sum;
+```
+
+Any of `init`, `test` and `next` can be empty. `init` allows for declaration
+of a new variable, with scope limited to the `for` expression.
+
+```cpp
+int sum=0;
+for( int i=0; i<arg; i++ )
+ sum += i;
+return i; // ERROR: Undefined name 'i'
+```
+