summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-05-10 08:59:31 -0700
committerCliff Click <cliffc@acm.org>2025-05-10 08:59:31 -0700
commit9112455cf661a2173edf11ef57e29935a1f4e9a8 (patch)
tree8c03c43f67e403dacfb890a0ca10aa59b62e0e6e
parent05afabd5152b06295e16c65b5a249229a4ead996 (diff)
downloadSimple-9112455cf661a2173edf11ef57e29935a1f4e9a8.tar.gz
Simple-9112455cf661a2173edf11ef57e29935a1f4e9a8.zip
Update README.md
-rw-r--r--chapter22/README.md90
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.