Skip to content

Commit

Permalink
Runtime improvements: use c3 linearization, etc.
Browse files Browse the repository at this point in the history
Use c3 linearization for the class precedence list.
Use the class precedence list for the slot index allocation.
Test and document it all.

Define defmutable in prelude.

Add a (dump-backtrace?) parameter to control backtrace printing.

Support build-manifest in the runtime.

Distinguish cases of "Bad syntax".

Regenerate the runtime bootstrap.

std/misc/rtd: add type=?

Integrate feedback from review.

Fix c3-test for destructive operations

More review feedback

Checkpointing progress with MOP refactoring
  • Loading branch information
fare committed Nov 28, 2023
1 parent a9ce89d commit 9070e65
Show file tree
Hide file tree
Showing 110 changed files with 36,477 additions and 32,905 deletions.
61 changes: 54 additions & 7 deletions doc/reference/dev/bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ summarized in a quotable one liner:
## The Long and Arduous History of Bootstrap

The first version of the Gerbil, let's call that the proto-Gerbil, was
The first version of the Gerbil, lets call that the proto-Gerbil, was
bootstrapped by vyzo a long time ago using a hand-written unhygienic
interpreter for the core language. Once that was done, vyzo wrote the
expander and the first version of the compiler, then the expander
Expand All @@ -41,7 +41,7 @@ Initially, the runtime was written in Gambit with a set of macros;
that was called `gx-gambc`. In the v0.18 release cycle, where Gerbil
became fully self hosted, all the traces have disappeared from the
source tree, as they are dead code. They still exist in the
repo's commit history if you want to do some historical research and
repos commit history if you want to do some historical research and
peek into the deep past to understand the evolution of Gerbil.


Expand Down Expand Up @@ -71,7 +71,7 @@ This can be accomplished with the following incantations in `$GERBIL_SRCDIR/src`

- To compile the bootstrap runtime:
```
gxc -d bootstrap -s -S -O gerbil/runtime/{gambit,system,util,loader,control,mop,error,thread,syntax,eval,repl,init}.ss gerbil/runtime.ss
gxc -d bootstrap -s -S -O gerbil/runtime/{gambit,util,system,loader,control,c3,mop,error,thread,syntax,eval,repl,init}.ss gerbil/runtime.ss
```

- To compile the bootstrap core prelude:
Expand All @@ -91,14 +91,61 @@ gxc -d bootstrap -s -S -O gerbil/expander/{common,stx,core,top,module,compile,ro

- To compile the bootstrap compiler:
```
gxc -d bootstrap -s -S -O gerbil/compiler/{base,compile,optimize-base,optimize-xform,optimize-top,optimize-spec,optimize-ann,optimize-call,optimize,driver,ssxi}.ss gerbil/compiler.ss
gxc -d bootstrap -s -S -O gerbil/compiler/{base,compile,optimize-base,optimize-xform,optimize-top,optimize-spec,optimize-ann,optimize-call,optimize,driver,ssxi}.ss gerbil/compiler.ss
```

- Finally, if you've made changes to it, you should also copy the core.ssxi.ss optimizer prelude:
- Finally, if youve made changes to it, you should also copy the core.ssxi.ss optimizer prelude:
```
cp gerbil/prelude/core.ssxi.ss bootstrap/gerbil
```

### Strictures on Modifying Parts of the Gerbil Bootstrap

***Every change to the Gerbil Bootstrap
must be API-compatible from one version to the next***:
both the old and new versions of Gerbil
(before and after recompiling the bootstrap) must be able to use them.

You *can* make API-incompatible changes from one version to another version,
but this must necessarily involve *several steps*
each of which will be API-compatible.

- First, you cannot make any backward-incompatible API change, such as
changing the calling convention of a function or macro e.g.
so you must use a symbol instead of a string,
or a 1-based index instead of a 0-based index, etc.
- You *could* modify a function to temporarily accept either a symbol or string
and do a conversion inside; but you obviously cannot determine whether
an user-provided index should be interpreted as 1-based or 0-based.
- The solution is to create a *new* API with *new* names that
must absolutely not clash with the old names.
Add a suffix or prefix such as `*`, `/2` or `%`, or take the opportunity
to give functions better and more systematic names.
- The *old* API will temporarily coexist with use the *new* API.
- When shared data structures are involved, the *old* API may have
to be translated in terms of the *new* API.
- The internal representations used by the new API may thus have to include
extra information needed by the old API that it doesn’t need,
or the new API may have to maintain two redundant representations together,
until after the old API is removed. This extra information
or redundant representation can be removed in a later phase.
- You can now bootstrap a next version that uses the new API,
while the old API remains available to the old version.
- In one or many iterations, you can make sure the old API is not used anywhere
anymore in Gerbil and its libraries.
- Only after you bootstrapped a version of Gerbil that does not at all
use the old API, you may wholly remove that old API:
this is now a backward-compatible change.
- If for some reason you really like the old name or hate the new name,
and “just” wanted to make an incompatible API change,
the name is made available anew after the old API was wholly removed
and a version that doesn’t use it has been bootstrapped into existence.
You may therefore start a new cycle of API changes as above to modify the API
to use this now-available-again name.

These strictures mean that you must stage your changes in multiple commits,
and regenerate the bootstrap compiler at each step.

### Debugging

If you have been making changes in the core system and building a new
Expand All @@ -124,7 +171,7 @@ will and supports serveral commands:
easily navigate code in emacs.
- `env` applies the arguments in the build environment.

So if you have made changes and want to rebuild gerbil, you don't have
So if you have made changes and want to rebuild gerbil, you dont have
to redo everything from scratch with `make`; you can simply build the
stage you want, and once you are satisfied you can move to the next
stage or push your branch so that CI does the job for you.
Expand Down Expand Up @@ -160,4 +207,4 @@ $ ./build.sh env gerbil test ./...
...
```

And that's it! Happy Hacking.
And thats it! Happy Hacking.
15 changes: 8 additions & 7 deletions doc/reference/gerbil/runtime/MOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,15 +305,16 @@ Converts *obj* to a list, which conses its type and to its fields.

## make-class-type
``` scheme
(make-class-type id super slots name plist ctor) -> type-descriptor
(make-class-type id name direct-supers direct-slots alist constructor) -> type-descriptor
id := symbol; the type id
super := list of type-descriptors or #f; super types
slots := list of symbols; class slot names
plist := alist; type properties
ctor := symbol or #f; id of constructor method
id := symbol; the unique type id
name := symbol; the possibly not unique source type name
direct-supers := list of type-descriptors or #f; super types
direct-slots := list of symbols; class slot names
alist := alist; type properties
constructor := symbol or #f; id of constructor method
plist elements:
alist elements:
(transparent: . boolean) ; controls whether the object is transparent
in equality and printing
(final: . boolean) ; controls whether the class if final
Expand Down
7 changes: 5 additions & 2 deletions doc/reference/std/debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ Returns true if the `thread`'s message queue is empty.
If the `tag` doesn't evaluate to `#f`, print the tag, then on separate lines
the source of each expression `expr1` to `exprN` (as by `write`)
followed by its single or multiple return values (as by `prn`).
When an expression is preceded by a quoted form (as in `'form`)
then that form is printed instead of the following expression
(which can help when the expression is large and uninformative to print).
Finally, return the values of the last expression `exprN`.

You can easily wrap an expression in a `DBG` form so as to print its value,
Expand All @@ -409,11 +412,11 @@ in some part of your code.
Example:
```scheme
> (define-values (x y z) (values 1 2 3))
> (* 10 (DBG foo: x (values [(+ x y) z] #t) (+ x y z)))
> (* 10 (DBG foo: x (values [(+ x y) z] #t) 'result (+ x y z)))
foo
x => 1
(values (@list (+ x y) z) #t) => [3 3] #t
(+ x y z) => 6
result => 6
60
```
In the above example the tag `foo` and the indented lines are printed by `DBG`,
Expand Down
18 changes: 17 additions & 1 deletion doc/reference/std/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,23 @@ displaying the exception with `display-exception`).
```

Invokes `thunk` with an exception handler that dumps the exception
stack trace with `dump-stack-trace!`.
stack trace with `dump-stack-trace!`
if `(dump-stack-trace?)` is true (the default).

### dump-stack-trace?
```scheme
(define dump-stack-trace? (make-parameter #t))
```
A parameter that controls whether `with-exception-stack-trace`
will actually dump a stack trace to standard error.

You can `(dump-stack-trace? #f)`
or locally `(parameterize ((dump-stack-trace? #f)) ...)`
to disable this stack trace dump,
in case you are building a program for end-users rather than for developers,
and want to control what limited error output they see.
Or you can re-enable them based on a debug flag at the CLI
in cases you want them to provide you with extra debugging information.

### dump-stack-trace!
```scheme
Expand Down
29 changes: 29 additions & 0 deletions doc/reference/std/misc/rtd.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,35 @@ type object.
```
:::

## type=?
``` scheme
(type=? typ1 type2) -> bool
typ1 := type object
typ2 := other type object
```

Returns true if the two type objects have the same `type-id`.
This is the preferred equality predicate for types.
`eq?` and `eqv?` should also work, but at present
`equal?` seems to be broken, by considering types as equal
that you would want to distinguish.

::: tip Examples:
``` scheme
> (defstruct a ())
> (defclass b ())
> (type-id a::t)
#:a::t45
> (type-id b::t)
#:b::t49
> (type=? a::t a::t)
#t
> (type=? a::t b::t)
#f
```
:::

## type-name
``` scheme
(type-name typ) -> type name | error
Expand Down
8 changes: 6 additions & 2 deletions src/bootstrap/gerbil/compiler/base__0.scm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(declare (block) (standard-bindings) (extended-bindings))
(begin
(define gerbil/compiler/base::timestamp 1697117338)
(define gerbil/compiler/base::timestamp 1701173525)
(begin
(define gxc#current-compile-symbol-table (make-parameter '#f))
(define gxc#current-compile-runtime-sections (make-parameter '#f))
Expand Down Expand Up @@ -82,7 +82,11 @@
(declare (not safe))
(##vector-set! _self596_ '2 __tmp5416)))
(error '"struct-instance-init!: too many arguments for struct"
_self596_))))
_self596_
'2
(let ()
(declare (not safe))
(##vector-length _self596_))))))
(let ()
(declare (not safe))
(bind-method! gxc#symbol-table::t ':init! gxc#symbol-table:::init! '#f))
Expand Down
11 changes: 7 additions & 4 deletions src/bootstrap/gerbil/compiler/base__1.scm
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
(declare (not safe))
(gx#raise-syntax-error
'#f
'"Bad syntax"
'"Bad syntax; invalid match target"
_g5372_))))
(_g51380_
(lambda (_g5380_)
Expand Down Expand Up @@ -153,7 +153,7 @@
(declare (not safe))
(gx#raise-syntax-error
'#f
'"Bad syntax"
'"Bad syntax; invalid match target"
_g156168_))))
(_g154233_
(lambda (_g156176_)
Expand Down Expand Up @@ -294,7 +294,7 @@
(declare (not safe))
(gx#raise-syntax-error
'#f
'"Bad syntax"
'"Bad syntax; invalid match target"
___stx53725373_)))))
(let ((___kont53755376_
(lambda (_L353_ _L355_)
Expand Down Expand Up @@ -488,7 +488,10 @@
(lambda (_g391400_)
(let ()
(declare (not safe))
(gx#raise-syntax-error '#f '"Bad syntax" _g391400_))))
(gx#raise-syntax-error
'#f
'"Bad syntax; invalid match target"
_g391400_))))
(_g389445_
(lambda (_g391408_)
(if (let () (declare (not safe)) (gx#stx-pair? _g391408_))
Expand Down
6 changes: 3 additions & 3 deletions src/bootstrap/gerbil/compiler/compile.ssi
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ namespace: gxc
(in: :gerbil/core <syntax-sugar>)
(spec:
(:gerbil/gambit)
(0 s32vector? 0 s32vector?)
(0 f32vector? 0 f32vector?)
(0 f64vector? 0 f64vector?)
(0 s64vector? 0 s64vector?)
(0 s8vector? 0 s8vector?)
(0 s32vector? 0 s32vector?)
(0 s16vector? 0 s16vector?)
(0 f64vector? 0 f64vector?)
(0 u64vector? 0 u64vector?)
(0 u32vector? 0 u32vector?)
(0 u16vector? 0 u16vector?)
(0 s16vector? 0 s16vector?)
(0 u8vector? 0 u8vector?)))
(%#export #t)
(%#define-runtime gambit-annotations gxc#gambit-annotations)
Expand Down
Loading

0 comments on commit 9070e65

Please sign in to comment.