summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-10-12 14:02:06 -0700
committerCliff Click <cliffc@acm.org>2026-10-04 13:30:41 -0700
commit63fe16fa2ea123b8ce2f976662b0a6d09f352868 (patch)
tree9faf4cfd8c3c2ed24b44faf02a95c0e9e755b31b /docs
parenteab779cdd6453215354725b114442e221fa48c3d (diff)
downloadSimple-63fe16fa2ea123b8ce2f976662b0a6d09f352868.tar.gz
Simple-63fe16fa2ea123b8ce2f976662b0a6d09f352868.zip
Chapter 16: Constructors
Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com> Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: tannal <tannal2409@gmail.com> Co-authored-by: hadha <helsgithub15@gmail.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Thalia Archibald <thalia@archibald.dev> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: RobertObkircher <robert.obkircher@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs')
-rw-r--r--docs/chapter16/16-grammar.md130
-rw-r--r--docs/chapter16/Makefile12
-rw-r--r--docs/chapter16/README.md131
3 files changed, 273 insertions, 0 deletions
diff --git a/docs/chapter16/16-grammar.md b/docs/chapter16/16-grammar.md
new file mode 100644
index 00000000..7da725e9
--- /dev/null
+++ b/docs/chapter16/16-grammar.md
@@ -0,0 +1,130 @@
+# Grammar for Chapter 16
+
+```antlrv4
+grammar SimpleLanguage;
+
+program : block EOF ;
+
+block : statement+ ;
+
+
+statement
+ : '{' block '}'
+ | returnStatement
+ | ifStatement
+ | whileStatement
+ | breakStatement
+ | continueStatement
+ | structDeclaration
+ | expressionStatement
+ ;
+
+
+returnStatement : 'return' expression ';' ;
+
+ifStatement : 'if' '(' expression ')' statement ('else' statement)? ;
+
+whileStatement : 'while' '(' expression ')' statement ;
+
+breakStatement : 'break' ';' ;
+
+continueStatement : 'continue' ';' ;
+
+
+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/chapter16/Makefile b/docs/chapter16/Makefile
new file mode 100644
index 00000000..12659b8f
--- /dev/null
+++ b/docs/chapter16/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/chapter16/README.md b/docs/chapter16/README.md
new file mode 100644
index 00000000..c55de47f
--- /dev/null
+++ b/docs/chapter16/README.md
@@ -0,0 +1,131 @@
+# Chapter 16: Constructors
+
+[Previous: Chapter 15](../chapter15/README.md) |
+[Next: Chapter 17a](../chapter17a/README.md)
+
+# Table of Contents
+
+1. [Constructors](#constructors)
+2. [Initialization code](#initialization-code)
+3. [Multiple Decls](#multiple-declarations-of-the-same-type)
+4. [Memory through constructors](#memory-through-constructors)
+
+This chapter adds field defaults and constructor blocks. Chapter 17a will add
+fixed bindings and read-only access, using these constructors to initialize them.
+
+You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter16) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter15...linear-chapter16) it to the previous chapter.
+
+## Constructors
+
+A big problem with the [Chapter 12](../chapter12/README.md) refs is that
+not-null fields always start out `null`. This is fixed in this chapter, where
+a *constructor* syntax is required to initialize not-null fields.
+
+Fields are initialized in three ways:
+
+1. A default zero/null initialization for fields that allow it. No special
+ syntax is required.
+```
+int x; // x is initialized to 0
+struct Ref { Ref? ptr; }; // Instances of Ref will have ptr initialized to null
+return new Ref.ptr; // Returns a null
+```
+
+2. The type declaration can specify an initial value. Later allocations will
+ start with this value.
+```
+int x = 5; // x is initialized to 5
+struct Point { int x=1; int y=1; }; // Point x and y will start as 1, not 0
+return new Point.x; // Returns a 1
+```
+
+3. The allocation can specify an initial value.
+
+```
+struct Point { int x=1; int y=1; }; // Point x and y will start as 1, not 0
+return new Point { x=3; }.x; // Returns a 3
+```
+
+Not-null fields *must* be initialized before first use and before the
+end of the allocation. They can be initialized in either the declaration or
+allocation. They do not start with the default value, although the
+initialization can be to the default.
+
+```
+struct Person { u8[] name; };
+return new Person; // ERROR: 'Person' is not fully initialized, field 'name' needs to be set in a constructor
+```
+
+
+## Initialization code
+
+The parser allows a full Block statement to be parsed in either the type
+declaration or the allocation. Any amount of code is legal, including
+`while` loops and `return`s.
+
+```
+struct Square {
+ flt side = arg;
+ flt diag = arg*arg/2;
+ // Newton's approximation to the square root, computed in a constructor.
+ // The actual allocation will copy in this result as the initial
+ // value for 'diag'.
+ while( 1 ) {
+ // The next-guess variable "next" is not a field in Square,
+ // because it does not appear at the top level
+ flt next = (side/diag + diag)/2;
+ if( next == diag ) break;
+ diag = next;
+ }
+};
+return new Square;
+```
+
+Another example:
+
+```
+struct Buffer {
+ if( arg < 0 || arg > 1000000 )
+ return null; // Size out of bounds
+ u8[] buffer = new u8[arg];
+};
+return new Buffer;
+```
+
+
+### Multiple declarations of the same type
+
+Also new this chapter is allowing multiple declarations with the same type, as
+is commonly seen in other languages:
+
+```
+int x,y; // Two int variables declared
+struct Point { int x,y,z; }; // Three fields declared
+```
+
+## Memory through constructors
+
+The lazy memory partitioning from [Chapter 11](../chapter11/README.md) continues
+through constructors. The parser tracks one `$mem` variable alongside its scalar
+variables. Branches and loops merge that binding with BulkMemPhi; field access
+splits out precise MemPhis when needed. The variable records for declared types live in ScopeNode. There is no separate parser table of memory aliases.
+
+A constructor computes its field values before the allocation. Reads, writes,
+and loops in its body update the same `$mem` binding as ordinary code. New then
+takes `{ctrl, $mem, size, field values...}` and produces `{ptr, $mem}`. The input
+memory is a partial MemMerge containing the struct's aliases; the output memory
+covers those same aliases. A whole-memory MemMerge preserves unrelated slices.
+Arrays use the same layout, supplying their length and default element value as
+initializer inputs.
+
+A Load from its own New can use the matching initializer input. Alias contents
+combine the initializer's type with incoming contents from older objects, so a
+new object does not erase facts or effects for existing objects. Loads bypass
+only allocations proven to be distinct. Scheduling follows partial aggregates
+when establishing read-before-write order.
+
+Sharing one allocation memory result makes Store-to-New folding more
+conservative: the existing sole-use check now sees users of every covered
+alias. This can leave a field Load where separate memory projections previously
+allowed a constant fold. Phi factoring also retains the simple one-step Load
+safety check.