From 7096ba70c05eabfe96fd7e69d276b16ac1bd0bb9 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Thu, 8 Oct 2026 16:52:27 -0700 Subject: Support putting static data into ELF constant pool Mostly fcn inits in --- chapter25/module.md | 279 ---------------------------------------------------- 1 file changed, 279 deletions(-) delete mode 100644 chapter25/module.md (limited to 'chapter25/module.md') 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 ``) - - ---- -### 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 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; -``` - -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 "); -sys.io.p(ChildB.str); -``` - -File: `ChildA.smp` -``` -// for ChildA -sys.io.p("In ChildA "); -str str = "A"; -``` - -File: `ChildB.smp` -``` -// for ChildB -sys.io.p("In ChildB "); -str str = "B"; -``` - -Compile and run: -``` -> smp Parent.smp -In Parent -In ChildB -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 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 -- Anything it touches, gets recursively including e.g. A or B -- Parent completes. -- Nothing in a can refer to another *module*. -- Static functions *can* refer to another module, but then can be executed... - -Goal: deterministic within a module. - History: plenty of times I've had complex orders, and then discovered - some referred static-final-fields are not yet init'd when child uses. - SubGoal: deterministic *order*, Parent before Child, etc. - Issue: mid-Parent , refers to Child, so Child 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 can non-determistic init child. - "fcn = { -> rand ? A.fld : B.fld }" - Answer?: Parent *may not* direct or indirect refer to a child. - Example: `B b = new B; // Illegal ref to child in Parent.` - Example: `B? b = fcn(); fcn = { -> rand ? null : new B; } // Illegal call to fcn referring to B inside Parent ` - Example: `B? b; fcn = { -> new B; } // OK, no B. during Parent.` - -Goal: external linkage also enjoys the 1-shot init feature. - Answer?: extern call to 'Foo.foo()' first checks Foo. - has run, before calling `Foo.foo()`. Optional: Caller is - modified to bypass check after success. - \ No newline at end of file -- cgit v1.2.3