diff options
| author | Cliff Click <cliffc@acm.org> | 2025-05-10 08:59:31 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-05-10 08:59:31 -0700 |
| commit | 9112455cf661a2173edf11ef57e29935a1f4e9a8 (patch) | |
| tree | 8c03c43f67e403dacfb890a0ca10aa59b62e0e6e /chapter22 | |
| parent | 05afabd5152b06295e16c65b5a249229a4ead996 (diff) | |
| download | Simple-9112455cf661a2173edf11ef57e29935a1f4e9a8.tar.gz Simple-9112455cf661a2173edf11ef57e29935a1f4e9a8.zip | |
Update README.md
Diffstat (limited to 'chapter22')
| -rw-r--r-- | chapter22/README.md | 90 |
1 files changed, 75 insertions, 15 deletions
diff --git a/chapter22/README.md b/chapter22/README.md index c7ff50f6..7482fc70 100644 --- a/chapter22/README.md +++ b/chapter22/README.md @@ -1,8 +1,30 @@ # Chapter 22: A Hello, World! It's high time for strings and printing! In this chapter we look at what it -takes to make a basic string - not really a full fledged String class, that will -wait for another chapter. +takes to make a basic string - not really a full fledged String class, that +will wait for another chapter. + +```java +sys.io.p("Hello, World!"); +``` + +Yeah! A 1-liner `Hello, World`! + +Let's break it down. + +- `sys`: is Just A Variable Name. Like other variables, it is looked up in the + current scope... which looks completely empty. Every Simple program now starts + with the `sys` variable in-scope. `sys` itself a normal `struct` + and is defined in `src/main/java/com/seaofnodes/simple/sys/sys.smp`. +- `sys.io.p`: lookup the `io` field in `sys` struct, which yields the `sys.io` + struct; then a lookup of `p` (short for "print") in the `sys.io` struct. + This returns a function. +- `p("Hello, World!")`: call the function just loaded from the `p` field, with + `"Hello, World!"` as a string argument. +- `"Hello, World!"`: New syntax that yields a constant array of `u8` (chars). + The array is otherwise a normal range-checked array, with a leading `#` + length field. The array backing data eventually ends up in the *constant + pool*, and from there in an ELF file's RODATA section. You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter21) 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-chapter20...linear-chapter21) it to the previous chapter. @@ -26,12 +48,16 @@ struct Outer { Any final field set in the declaration (as opposed to the constructor) is automatically a "static" field - it is final for all instances, and does not need to be stored in each instances. Instead one copy is kept in a global -space (not really a *class* object yet) and loaded from there. +space (not really a *class* object yet) and loaded from there. In this example: -- Instances of the `Outer` class have a single `int` field `out`. -- Instances of the `Inner` class have a single `int` field `in`. -- There exists a `Outer.Inner.pi` field in a global space, with value `3.14`. +- Instances of the `Outer` struct have a single `int` field `out`. +- Instances of the `Inner` struct have a single `int` field `in`. +- There exists a `Outer.Inner.pi` field in a global space with value `3.14`. + +The `sys` struct is another example, with nested `libc` and `io` structs at +least. All the fields in these structs are all final, hence static. + ## FFI and I/O Calls @@ -52,9 +78,9 @@ name `write` has to be unique when linking. ## Auto-Import and the "sys." namespace -The `sys` import will eventually include libc bindings, and any default library -code including printing support, and probably collections. As of this chapter -it includes minimal libc bindings and an easy print: +The `sys` struct includes `libc` bindings, and any default library code +including e.g. printing support and collections. As of this chapter it +includes minimal libc bindings and an easy print: ```java // top-level default import @@ -97,16 +123,17 @@ You can now cast a pointer to an i64, although not the other way around. For arrays, this cast is to the array *base* skipping the `#` length field, and is suitable for passing to external "C" calls. For structs, this is just the -struct base. +struct base. This is used to pass a length-checked Simple array to the libc +`write` call in the above `sys.io.p` function. ## Arrays of Constants and Constant Arrays The Simple type system now supports the notion of a "constant array" - an array of fixed constants, stored in the ELF file in the RODATA section. Currently we -only support strings at the parser level: "Hello, World!" makes a `u8[13]` +only support strings at the parser level: `"Hello, World!"` makes a `u8[13]` array containing 13 ASCII bytes; like all arrays it has a length and will be -range-checked in the future. +range-checked at some point. A constant version of a non-constant array can be assigned using the `u8[~]` syntax. @@ -119,10 +146,10 @@ i32[] is = new i32[N]; for( int i=0; i<N; i++ ) is[i] = i*i; // Function "sum" can read but not write the array -val sum = { i32[~] is -> +val sum = { i32[~] nums -> // Notice the [~] signature marking nums as immutable int sum = 0; - for( int i=0; i<is#; i++ ) - sum += is[i]; + for( int i=0; i<nums#; i++ ) + sum += nums[i]; return sum; }; return sum(is); @@ -130,3 +157,36 @@ return sum(is); Note that this affects the deep contents of the array and not the array variable itself. + +## Quote Characters + +The form ``` `0` ``` makes a `u8` value with the ASCII character `0`. + +## Continuous Improvement + +In the rush to get executable code from +[Chapters 19](https://github.com/SeaOfNodes/Simple/tree/linear-chapter19), +[Chapters 20](https://github.com/SeaOfNodes/Simple/tree/linear-chapter20), and +[Chapters 21](https://github.com/SeaOfNodes/Simple/tree/linear-chapter21), we +wrote a lot of code in a hurry. That also means we wrote a lot of bugs (sad +face), and will be paying the price for a few chapters. In this chapter we +also found and fixed a number of bugs, here's a sample: + +- x86 encoding bugs: +- - `imul` with immediate forms and `setXX` had incorrect `REX` forms. +- - x86 `div` was taking `RAX,RDX` as the second *input* register; they are already + hardwired as the *first* input register. +- - Many x86 ops that kill `flags` did not state so in the port. +- - Short forms for some x86 ops (e.g. using the `inc` vs `add+1`) +- Global Code Motion `ScheduleLate` missed visiting values only visible around + loop backedges; also was adding extra dependence edges between loads and + stores with different aliasing. +- Inlining would reset the **idepth** (as expected) but then use the existing + `CallNode` and `FunNode` that are *folding* but not yet peep'd away - leading + to incorrect **idepth** calculations. + +Many more bugs got fixed, but this sample should give an idea of the continuous +improvements going on. These happen because we have finally reached a point +where we can aggressive test again - we are writing Real (Simple) Code (tm) and +running it... and crashing on these bugs. Compilers are big, complex, beasties +and some amount of bugs and bug fixing is to be expected. |
