summaryrefslogtreecommitdiff
path: root/chapter25/module.md
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-08 16:52:27 -0700
committerCliff Click <cliffc@acm.org>2026-10-08 16:52:27 -0700
commit7096ba70c05eabfe96fd7e69d276b16ac1bd0bb9 (patch)
treebda5cb52577488cb61544c671afa5080297d0381 /chapter25/module.md
parent87a75c83b75480e65147a4d425fddd14a05df4d9 (diff)
downloadSimple-main.tar.gz
Simple-main.zip
Support putting static data into ELF constant poolmain
Mostly fcn inits in <clinit>
Diffstat (limited to 'chapter25/module.md')
-rw-r--r--chapter25/module.md279
1 files changed, 0 insertions, 279 deletions
diff --git a/chapter25/module.md b/chapter25/module.md
deleted file mode 100644
index 4cd801e7..00000000
--- a/chapter25/module.md
+++ /dev/null
@@ -1,279 +0,0 @@
-
-# Modules for Simple
-
-English | [日本語](module.ja.md)
-
-Goals:
-- 1-liner valid program (for easy tutorial/newbie starts)
-- - Compile and run with minimal effort
-- Separate compilation and namespaces; external libs
-- - Compile to ELF or other linkable/executable format
-- Easy private fields & classes
-- Output files are compatible with existing .o/.exe/lib/dll infrastructure
-- No `#include` or `import` files
-- Structure / file system heirarchy per module
-- - Perhaps many files make a module
-- - easy namespaces within a module
-- - Nested names in parent file or nested file
-- Class initializers guarenteed:
-- - execute exactly once
-- - lazily on first touch
-- - complete on or before first instances are made
-- - - (an exception is allowed for a golden instance in `<clinit>`)
-
-
----
-### Goal: Valid 1-liner, minimal effort
-
-This makes a module and a class `hello` out of the current working directory
-name. Compiling without more arguments also links and executes.
-
-File: `hello.smp`
-```
-sys.io.p("Hello World!");
-```
-
-Compile and run:
-```
-> smp hello.smp
-Hello World!
-```
-
-Module and class name is `hello` extracted from file name, compiled in memory
-and `exec'd`. No files made, this is strictly a run and gun mode.
-
-
----
-### Goal: separate compilation
-
-Name a build directory target during compilation to get `.o` files.
-The build target directory structure will match the source, and
-can be placed anywhere.
-
-As before, since no module name is mentioned on the compile line, `Pet` becomes
-both the module and a class.
-
-File: Pet.smp
-```
-// Class initializer <clinit> 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) <init> 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;
-```
-
-Compile to `Pet.o` in the `build/` directory:
-```
-> smp Pet.smp -o build/
-> ls build
-Pet.o
-```
-
-
----
-### Goal: nested namespaces
-
-This makes a module and class `Pet` based on the file name in `myRepo`. It
-also makes a nested class `Pet.Vet`. These are used from a different module
-`Owner`.
-
-
-Directory: `~/myRepo/`
-```
-~/myRepo/
- Pet.smp
- build/
-
-~/otherRepo/
- Owner.smp
-```
-
-File: `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;
-}
-```
-
-File: `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");
-```
-
-Compile to `Pet.o` in the `build/` directory; since the compile line does not
-mention some other module root, `Pet` must be the module (and is also a class).
-Since `Pet` is the module, `Vet` is a class within the module `Pet`.
-
-```
-> smp Pet.smp -o build/
-> ls build
-Pet.o
-```
-
-The code for both `Pet` and `Pet.Vet` are in the same `Pet.o` file.
-
-Compile and run `Owner.smp`, specifying the `Pet` repo to satisfy the free
-variables `Pet` and `Pet.Vet`.
-
-```
-> smp Owner.smp -lib ~/myRepo/build
-I took Fido to Linda
-```
-
----
-### Goal: nested namespace in a nested file
-
-Same as the last example but with nested files:
-
-```
-~/myRepo
- Pet.smp
- Pet/
- Vet.smp
- build/
- Pet.o
- Pet/
- Vet.o
-
-~/otherRepo
- Owner.smp
-```
-
-
-File: Pet.smp
-```
-int default_leggies = 4;
-
-struct Pet {
- str name;
- int leggies = default_leggies;
-}
-```
-
-File: Pet/Vet.smp
-```
-// Nested class Vet inside of directory Pet
-struct Vet {
- str name;
- str address;
- long credit_card_num;
-}
-```
-
-Compile and run `Owner.smp`:
-```
-> smp Owner.smp -lib ~/myRepo/build
-I took Fido to Linda
-```
-
-
----
-### Goal: Class Initializers are Lazy
-
-```
-Parent.smp
-Parent/
- ChildA.smp
- ChildB.smp
-```
-
-File: `Parent.smp`
-```
-sys.io.p("In Parent <clinit>");
-sys.io.p(ChildB.str);
-```
-
-File: `ChildA.smp`
-```
-// <clinit> for ChildA
-sys.io.p("In ChildA <clinit>");
-str str = "A";
-```
-
-File: `ChildB.smp`
-```
-// <clinit> for ChildB
-sys.io.p("In ChildB <clinit>");
-str str = "B";
-```
-
-Compile and run:
-```
-> smp Parent.smp
-In Parent <clinit>
-In ChildB <clinit>
-B
-
-```
-
-### Goal: Easy private fields
-
-Leading underscore makes field or class private.
-
-### Goal: similar to C compiler driver syntax
-
-```
-Simple --cpu x86_64_v2 --abi Win64 --norun -o lib/lib/sys_x86_64_v2_win64.o src/main/smp/sys.smp
-```
-
-Module not mentioned, so top-level file is module: `sys`
-Module directory not mentioned, so is prefix of file name `src/main/smp`.
-Build dir not mentioned, so is prefix of output file: `lib/`
-Output file is default `smp.o`, here renamed.
-
-
-
-One <clinit> can refer to another, and will be executed as first touched.
-Parents must be touched before children by design.
-However a child A can refer to a child B.
-Touching Parent.B means
-- Parent is touched first, and begins <clinit>
-- Anything it touches, gets recursively <clinit> including e.g. A or B
-- Parent completes.
-- Nothing in a <clinit> can refer to another *module*.
-- Static functions *can* refer to another module, but then can be executed...
-
-Goal: deterministic <clinit> within a module.
- History: plenty of times I've had complex <clinit> orders, and then discovered
- some referred static-final-fields are not yet init'd when child uses.
- SubGoal: deterministic <clinit> *order*, Parent before Child, etc.
- Issue: mid-Parent <clinit>, refers to Child, so Child <clinit> before Parent completes.
- SubAnswer: Since parent first, and "parent knows child", this is OK.
- SubIssue: this does not work across modules; one module is not a parent of another
- Issue: Parent fcns called during <clinit> can non-determistic init child.
- "fcn = { -> rand ? A.fld : B.fld }"
- Answer?: Parent <clinit> *may not* direct or indirect refer to a child.
- Example: `B b = new B; // Illegal ref to child in Parent.<clinit>`
- Example: `B? b = fcn(); fcn = { -> rand ? null : new B; } // Illegal call to fcn referring to B inside Parent <clinit>`
- Example: `B? b; fcn = { -> new B; } // OK, no B.<clinit> during Parent.<clinit>`
-
-Goal: external linkage also enjoys the 1-shot init feature.
- Answer?: extern call to 'Foo.foo()' first checks Foo.<clinit>
- has run, before calling `Foo.foo()`. Optional: Caller is
- modified to bypass <clinit> check after success.
- \ No newline at end of file