From a8891836852f0b2f6f4e1bca5a46c3a899e3ce07 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 12 Oct 2024 14:02:06 -0700 Subject: Chapter 16: Constructors and Final fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com> Co-authored-by: tannal Co-authored-by: hadha Co-authored-by: Thalia Archibald Co-authored-by: RobertObkircher Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> --- docs/chapter16/16-grammar.md | 132 +++++++++++++++++++++++++++++++++++++++++++ docs/chapter16/Makefile | 12 ++++ docs/chapter16/README.md | 128 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 docs/chapter16/16-grammar.md create mode 100644 docs/chapter16/Makefile create mode 100644 docs/chapter16/README.md (limited to 'docs') diff --git a/docs/chapter16/16-grammar.md b/docs/chapter16/16-grammar.md new file mode 100644 index 00000000..7b611fbf --- /dev/null +++ b/docs/chapter16/16-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/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..a19c68db --- /dev/null +++ b/docs/chapter16/README.md @@ -0,0 +1,128 @@ +# Chapter 16: Constructors and Final fields + +# Table of Contents + +1. [Constructors](#constructors) +2. [Initialization code](#initialization-code) +3. [Final fields](#final-fields) +4. [Multiple Decls](#multiple-declarations-of-the-same-type) + +In this chapter, we add constructors and final fields. + +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 13](../chapter13/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 `final` and 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 and final 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; + // Newtons 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; +``` + +``` +struct Buffer { + if( arg < 0 || arg > 1000000 ) + return null; // Size out of bounds + u8[] buffer = new u8[arg]; +}; +return new Buffer; +``` + + +## Final fields + +Final fields are declared with a `!` before the name. +This decision is revisited in the next chapter. + +``` +int !x = 17; // Final field x +x = 3; // ERROR: cannot re-assign a final field +``` + +``` +struct Person { u8[]? !name; }; +return new Person { name = null; }; // OK: final name is assigned +``` + +``` +struct Point { int !x; int !y; int !z; }; +return new Point { x=arg; y=z; z=x; }; // ERROR: 'Point' is not fully initialized, field 'y' needs to be set in a constructor +``` + +``` +struct Point { int x; int y; int z; }; // Fields not-final, default to 0 +return new Point { x=arg; y=z; z=x; }; // Ok: x=arg, y=0, z=arg +``` + + +### 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 +``` + +``` +int !x=3,!y=5; // Two int variables declared, both are final and initialized +``` \ No newline at end of file -- cgit v1.2.3