From 863a6ed0ad723e06c76f392d4fb3a5f6bd22863c Mon Sep 17 00:00:00 2001 From: Jun Kawasaki Date: Tue, 6 Oct 2026 13:01:11 +0900 Subject: docs: add Japanese translations for all chapters --- chapter25/module.ja.md | 275 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 chapter25/module.ja.md (limited to 'chapter25/module.ja.md') diff --git a/chapter25/module.ja.md b/chapter25/module.ja.md new file mode 100644 index 00000000..2746ad1e --- /dev/null +++ b/chapter25/module.ja.md @@ -0,0 +1,275 @@ +# Simple のモジュール + +[English](module.md) | 日本語 + +この文書は [Modules for Simple](module.md) の日本語訳です。原文はモジュールの設計案です。 + +目標: + +- 有効なプログラムを1行で書けるようにする(チュートリアルや初心者の導入を簡単にする)。 + - 最小限の手間でコンパイルして実行する。 +- 分割コンパイル、名前空間、外部ライブラリを扱う。 + - ELF など、リンク可能・実行可能な形式へコンパイルする。 +- フィールドやクラスを簡単に非公開にする。 +- 出力ファイルを、既存の .o/.exe/lib/dll の仕組みと互換にする。 +- `#include` や `import` 用のファイルを不要にする。 +- モジュールごとに構造・ファイルシステムの階層を持たせる。 + - 複数のファイルで1つのモジュールを構成することも考えられる。 + - モジュール内で簡単に名前空間を使う。 + - 親ファイルまたは入れ子のファイルに、入れ子の名前を置く。 +- クラス初期化子について次を保証する。 + - 正確に1回だけ実行する。 + - 最初にアクセスされた時点で遅延実行する。 + - 最初のインスタンスが作られる前、またはその時点までに完了する。 + - `` 内の特別な原型インスタンス(golden instance)は例外として認める。 + +--- +### 目標:最小限の手間で有効な1行プログラムを書く + +現在の作業ディレクトリの名前から、モジュールとクラス `hello` を作ります。 +追加の引数なしでコンパイルすると、リンクと実行も行います。 + +ファイル:`hello.smp` +``` +sys.io.p("Hello World!"); +``` + +コンパイルして実行します。 +``` +> smp hello.smp +Hello World! +``` + +モジュール名とクラス名は、ファイル名から取り出した `hello` です。 +メモリ内でコンパイルし、`exec` で実行します。ファイルは作りません。 +これは、その場でコンパイルして実行するためだけのモードです。 + +--- +### 目標:分割コンパイル + +コンパイル時に出力先のビルドディレクトリを指定すると、`.o` ファイルを得られます。 +出力先ディレクトリの構造はソースと一致し、場所は自由に選べます。 + +前と同様に、コンパイルのコマンドでモジュール名を指定していないため、 +`Pet` がモジュールにもクラスにもなります。 + +ファイル:Pet.smp +``` +// Class initializer is any code outside a struct declaration +// and is guaranteed to run-once on first touch. + +// static fields listed here: +int default_leggies = 4; + +// A default (no argument) is code inside struct with same name as the +// file; this is the same behavior as field initializers for Java, although +// any code is allowed, not just expressions. + +struct Pet { + str name; + int leggies = default_leggies; +} + +float yet_another_static_field; +``` + +`build/` ディレクトリ内の `Pet.o` へコンパイルします。 +``` +> smp Pet.smp -o build/ +> ls build +Pet.o +``` + +--- +### 目標:入れ子の名前空間 + +`myRepo` 内のファイル名から、モジュールとクラス `Pet` を作ります。 +入れ子のクラス `Pet.Vet` も作ります。これらを別のモジュール `Owner` から使います。 + +ディレクトリ:`~/myRepo/` +``` +~/myRepo/ + Pet.smp + build/ + +~/otherRepo/ + Owner.smp +``` + +ファイル:`myRepo/Pet.smp` +``` +int default_leggies = 4; + +struct Pet { + str name; + int leggies = default_leggies; +} + +// Nested class Vet inside of file Pet +struct Vet { + str name; + str address; + long credit_card_num; +} +``` + +ファイル:`otherRepo/Owner.smp` +``` +Pet dog = Pet{name="Fido"}; +Pet snake = Pet{name="slither", leggies = 0; }; +Pet.Vet vet = Pet.Vet{name="Linda"; address="101 Main St"; credit_card_num=1234}; + +sys.io.p("I took "+dog.name+" to "+vet.name+"\n"); +``` + +`build/` ディレクトリ内の `Pet.o` へコンパイルします。 +コマンドで別のモジュールのルートを指定していないため、`Pet` がモジュールであり、クラスでもあります。 +`Pet` がモジュールなので、`Vet` はモジュール `Pet` 内のクラスです。 + +``` +> smp Pet.smp -o build/ +> ls build +Pet.o +``` + +`Pet` と `Pet.Vet` のコードは、同じ `Pet.o` ファイルに入ります。 + +自由変数 `Pet` と `Pet.Vet` を解決するために `Pet` のリポジトリを指定して、 +`Owner.smp` をコンパイルし、実行します。 + +``` +> smp Owner.smp -lib ~/myRepo/build +I took Fido to Linda +``` + +--- +### 目標:入れ子のファイル内の入れ子の名前空間 + +前の例と同じですが、ファイルを入れ子にします。 + +``` +~/myRepo + Pet.smp + Pet/ + Vet.smp + build/ + Pet.o + Pet/ + Vet.o + +~/otherRepo + Owner.smp +``` + +ファイル:Pet.smp +``` +int default_leggies = 4; + +struct Pet { + str name; + int leggies = default_leggies; +} +``` + +ファイル:Pet/Vet.smp +``` +// Nested class Vet inside of directory Pet +struct Vet { + str name; + str address; + long credit_card_num; +} +``` + +`Owner.smp` をコンパイルし、実行します。 +``` +> smp Owner.smp -lib ~/myRepo/build +I took Fido to Linda +``` + +--- +### 目標:クラス初期化子の遅延実行 + +``` +Parent.smp +Parent/ + ChildA.smp + ChildB.smp +``` + +ファイル:`Parent.smp` +``` +sys.io.p("In Parent "); +sys.io.p(ChildB.str); +``` + +ファイル:`ChildA.smp` +``` +// for ChildA +sys.io.p("In ChildA "); +str str = "A"; +``` + +ファイル:`ChildB.smp` +``` +// for ChildB +sys.io.p("In ChildB "); +str str = "B"; +``` + +コンパイルして実行します。 +``` +> smp Parent.smp +In Parent +In ChildB +B + +``` + +### 目標:簡単な非公開フィールド + +名前の先頭にアンダースコアを付けると、フィールドやクラスが非公開になります。 + +### 目標:C コンパイラのドライバに似た構文 + +``` +Simple --cpu x86_64_v2 --abi Win64 --norun -o lib/lib/sys_x86_64_v2_win64.o src/main/smp/sys.smp +``` + +モジュールを指定していないため、最上位のファイルがモジュール `sys` になります。 +モジュールディレクトリも指定していないため、ファイル名のディレクトリ部分 `src/main/smp` になります。 +ビルドディレクトリを指定していないため、出力ファイルのディレクトリ部分 `lib/` になります。 +出力ファイル名の既定値は `smp.o` ですが、ここでは別名を指定しています。 + +ある `` は別の `` を参照でき、最初のアクセス時に実行されます。 +設計上、子より先に親へアクセスする必要があります。ただし、子 A は子 B を参照できます。 +Parent.B へのアクセスは、次を意味します。 + +- 最初に Parent にアクセスし、`` を開始する。 +- そこからアクセスするものにも、A や B を含め、再帰的に `` を実行する。 +- Parent の処理が完了する。 +- `` 内では別の*モジュール*を参照できない。 +- 静的関数は別のモジュールを参照*できる*が、その場合、実行される可能性がある……。 + +目標:モジュール内の `` を決定的にする。 + +- 背景:複雑な `` の順序のせいで、子が使う時点で参照先の static final フィールドがまだ初期化されていないことが、何度もあった。 +- 副目標:親が子より先になるなど、`` の*順序*を決定的にする。 + - 問題:Parent の `` の途中で Child を参照すると、Parent が完了する前に Child の `` が走る。 + - 部分的な回答:親が先で「親は子を知っている」ため、これはよい。 + - 追加の問題:モジュールをまたぐと成り立たない。あるモジュールは別のモジュールの親ではない。 + - 問題:`` 中に呼び出す Parent の関数が、非決定的に子を初期化できる。 + - `fcn = { -> rand ? A.fld : B.fld }` +- 回答案:Parent の `` は、直接にも間接にも子を参照しては*ならない*。 +- 例:`B b = new B; // Illegal ref to child in Parent.` + — Parent の初期化子から子への不正な参照。 +- 例:`B? b = fcn(); fcn = { -> rand ? null : new B; } // Illegal call to fcn referring to B inside Parent ` + — Parent の初期化子内で B を参照する関数への不正な呼び出し。 +- 例:`B? b; fcn = { -> new B; } // OK, no B. during Parent.` + — Parent の初期化中に B の初期化子を実行しないため、これは許される。 + +目標:外部とのリンクでも、1回限りの初期化機能を使えるようにする。 + +回答案:外部から `Foo.foo()` を呼ぶときは、まず `Foo.` が実行済みであることを確認してから、 +`Foo.foo()` を呼び出す。任意の最適化として、成功後は呼び出し元を変更し、 +`` の確認を省略する。 -- cgit v1.2.3