diff options
Diffstat (limited to 'docs/chapter16')
| -rw-r--r-- | docs/chapter16/16-grammar.ja.md | 136 | ||||
| -rw-r--r-- | docs/chapter16/16-grammar.md | 132 | ||||
| -rw-r--r-- | docs/chapter16/Makefile | 12 | ||||
| -rw-r--r-- | docs/chapter16/README.ja.md | 107 | ||||
| -rw-r--r-- | docs/chapter16/README.md | 133 |
5 files changed, 520 insertions, 0 deletions
diff --git a/docs/chapter16/16-grammar.ja.md b/docs/chapter16/16-grammar.ja.md new file mode 100644 index 00000000..6bf57f0c --- /dev/null +++ b/docs/chapter16/16-grammar.ja.md @@ -0,0 +1,136 @@ +# 第16章の文法 + +[English](16-grammar.md) | 日本語 + +この文書は [原文](16-grammar.md) の日本語訳です。 + +[第16章に戻る](README.ja.md) + +```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/16-grammar.md b/docs/chapter16/16-grammar.md new file mode 100644 index 00000000..f86e7269 --- /dev/null +++ b/docs/chapter16/16-grammar.md @@ -0,0 +1,132 @@ +# Grammar for Chapter 16 + +English | [日本語](16-grammar.ja.md) + +```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.ja.md b/docs/chapter16/README.ja.md new file mode 100644 index 00000000..e6b1f2d3 --- /dev/null +++ b/docs/chapter16/README.ja.md @@ -0,0 +1,107 @@ +# 第16章: コンストラクタ + +[English](README.md) | 日本語 + +[前: 第15章](../chapter15/README.ja.md) | +[次: 第17a章](../chapter17a/README.ja.md) + +この文書は [原文](README.md) の日本語訳です。 + +# 目次 + +1. [コンストラクタ](#コンストラクタ) +2. [初期化コード](#初期化コード) +3. [複数の宣言](#同じ型の複数の宣言) +4. [コンストラクタを通るメモリ](#コンストラクタを通るメモリ) + +この章では、フィールドのデフォルト値とコンストラクタブロックを追加します。第17a章では、これらのコンストラクタで初期化する、固定の束縛と読み取り専用のアクセスを追加します。 + +[linear](https://github.com/SeaOfNodes/Simple/tree/linear) ブランチの線形の Git リビジョン履歴で[この章](https://github.com/SeaOfNodes/Simple/tree/linear-chapter16)を読むことや、前章との[差分](https://github.com/SeaOfNodes/Simple/compare/linear-chapter15...linear-chapter16)を見ることもできます。 + +## コンストラクタ + +[第12章](../chapter12/README.ja.md)の参照には、null を許容しないフィールドが常に `null` から始まるという大きな問題があります。この章ではそれを修正し、null を許容しないフィールドの初期化に*コンストラクタ*構文を要求します。 + +フィールドの初期化には3つの方法があります。 + +1. 許容するフィールドには、デフォルトのゼロ/null 初期化を使います。特別な構文は不要です。 + +``` +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. 型の宣言で初期値を指定できます。それ以降の割り当てはこの値から始まります。 + +``` +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. 割り当てで初期値を指定できます。 + +``` +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 +``` + +null を許容しないフィールドは、最初に使用する前、かつ割り当ての終了前に、*必ず*初期化しなければなりません。宣言でも割り当てでも初期化できます。初期化でデフォルト値を与えることはできますが、デフォルト値から始まるわけではありません。 + +``` +struct Person { u8[] name; }; +return new Person; // ERROR: 'Person' is not fully initialized, field 'name' needs to be set in a constructor +``` + +## 初期化コード + +パーサーは、型の宣言と割り当てのどちらにも、完全な Block 文をパースすることを許します。`while` ループや `return` を含め、任意の量のコードが合法です。 + +``` +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; +``` + +別の例です。 + +``` +struct Buffer { + if( arg < 0 || arg > 1000000 ) + return null; // Size out of bounds + u8[] buffer = new u8[arg]; +}; +return new Buffer; +``` + +### 同じ型の複数の宣言 + +この章では新たに、ほかの言語でよく見られる、同じ型の複数の宣言も許します。 + +``` +int x,y; // Two int variables declared +struct Point { int x,y,z; }; // Three fields declared +``` + +## コンストラクタを通るメモリ + +[第11章](../chapter11/README.ja.md)の遅延的なメモリ分割は、コンストラクタを通して続きます。パーサーは、スカラー変数と並んで1つの `$mem` 変数を追跡します。分岐とループは BulkMemPhi でその束縛を合流し、フィールドアクセスは必要に応じて精密な MemPhi を分離します。宣言型の変数レコードは ScopeNode にあります。パーサーに別個のメモリエイリアステーブルはありません。 + +コンストラクタは割り当て前にフィールド値を計算します。本体の読み出し、書き込み、ループは、通常のコードと同じ `$mem` 束縛を更新します。その後 New は `{ctrl, $mem, size, field values...}` を取り、`{ptr, $mem}` を生成します。入力メモリは構造体のエイリアスを含む部分 MemMerge で、出力メモリも同じエイリアスを覆います。メモリ全体の MemMerge は無関係なスライスを保持します。配列も同じ配置を使い、長さとデフォルトの要素値を初期化入力として供給します。 + +自身の New からの Load は、対応する初期化入力を使えます。エイリアスの内容は、初期値の型と古いオブジェクトからの流入内容を組み合わせるため、新しいオブジェクトが既存オブジェクトの事実や作用を消すことはありません。ロードが迂回するのは、別のものと証明された割り当てだけです。スケジューリングは、読み出しを後続の書き込みより前に順序付ける際、部分的な集約をたどります。 + +1つの割り当てメモリ結果を共有することで、Store を New に畳み込む処理はより保守的になります。既存の単独使用のチェックが、覆うすべてのエイリアスのユーザーを見るようになるためです。以前の別々のメモリ射影なら定数畳み込みできたところに、フィールドの Load が残ることがあります。Phi のくくり出しも、単純な1段階の Load 安全性チェックを維持します。 diff --git a/docs/chapter16/README.md b/docs/chapter16/README.md new file mode 100644 index 00000000..a9d9422d --- /dev/null +++ b/docs/chapter16/README.md @@ -0,0 +1,133 @@ +# Chapter 16: Constructors + +English | [日本語](README.ja.md) + +[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. |
