Skip to content

Commit

Permalink
Have lambda list parsing instructions push instead of set
Browse files Browse the repository at this point in the history
This makes compile-with-lambda-list significantly less worse, as
now we don't have to do weird crap like reserve indices without
binding them to variables to compile default forms. It also saves
a few extraneous locals when binding specials, for what little
that's worth.

bind-required-args still sets. I'm not sure if it should. It is
the one part of the argument parsing that could genuinely be
implemented as a single simple memcpy, but even then, it's broken
up by any special required parameters.
  • Loading branch information
Bike committed Jul 19, 2024
1 parent a2c2055 commit 51cd4ae
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 369 deletions.
6 changes: 5 additions & 1 deletion FASL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ After the last instruction is executed, the FASL has been fully loaded. Any rema

# Changelog

## 0.14 (pending)
## 0.15 (pending)

* `listify-rest-args` pushes to the stack again. `bind-optional-args` and `parse-key-args` do as well. (This makes compilation a little easier and cleaner.)

## 0.14

* `listify-rest-args` now assigns directly to a local rather than pushing to the stack.
* New `encell` instruction for a common lexical variable cell making operation.
Expand Down
27 changes: 14 additions & 13 deletions MACHINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,28 +235,28 @@ Set the first `nreq` locals to be the first `nreq` arguments.

### bind-optional-args #x10 (nreq misc) (nopt misc)

Set the `nopt` locals beginning at `nreq` to be the arguments beginning at `nreq`. If there are not enough arguments, the remaining locals are set to an "unsupplied" value with no meaning except to `jump-if-supplied`.
Push the `nopt` arguments beginning at `nreq` to the stack. If there are not enough arguments, an "unsupplied" value with no meaning except to `jump-if-supplied` is pushed instead.

```lisp
(loop for i from nreq
do (setf (aref LOCALS i)
(if (< (length ARGUMENTS) i)
(loop for i from nreq below (+ nreq nopt)
do (push (if (< (length ARGUMENTS) i)
(aref ARGUMENTS i)
+UNSUPPLIED+)))
+UNSUPPLIED+)
STACK))
```

### listify-rest-args #x11 (nfixed misc)

Construct a list out of all the arguments beginning at `nfixed`, and assign it to the `nfixed`th local.
Construct a list out of all the arguments beginning at `nfixed`, and push it to the stack.

```lisp
(setf (aref LOCALS nfixed) (nthcdr nfixed ARGUMENTS))
(push (nthcdr nfixed ARGUMENTS) STACK)
```


## parse-key-args #x13 (nfixed misc) (key-count-info misc) (keys keys) (base misc)
## parse-key-args #x13 (nfixed misc) (key-count-info misc) (keys keys)

The low 7 (or 15, for `long parse-key-args`) bits of `key-count-info` are a count of keywords, call it `nkeys`. There are `nkeys` literals beginning at `keys` that are keys. Interpret the arguments beginning with `nfixed` as a keyword plist, and assign the locals beginning at `base` to the corresponding keywords. If any of these locals do not have an entry in the arguments plist, they are set to an "unsupplied" value with no meaning except to `jump-if-supplied`.
The low 7 (or 15, for `long parse-key-args`) bits of `key-count-info` are a count of keywords, call it `nkeys`. There are `nkeys` literals beginning at `keys` that are keys. Interpret the arguments beginning with `nfixed` as a keyword plist, and push them to the stack in the order of the corresponding keywords. If any of these do not have an entry in the arguments plist, an "unsupplied" value with no meaning except to `jump-if-supplied` is pushed instead.

If the length of the argument plist is odd, signal a program error. If the high bit of `key-count-info` is unset, and there are keywords in the argument plist that are not part of `keys`, signal a program error.

Expand All @@ -267,7 +267,7 @@ If the length of the argument plist is odd, signal a program error. If the high
(keywords (subseq LITERALS keys (+ keys nkeys))))
(unless (evenp (length plist)) (error 'program-error ...))
(loop for i from base for kw in keywords
do (setf (aref LOCALS i) (getf plist kw +UNSUPPLIED+)))
do (push (getf plist kw +UNSUPPLIED+) STACK))
(unless (or aokp (all-known-keywords-p plist keywords))
(error 'program-error ...)))
```
Expand All @@ -288,12 +288,13 @@ Pop a value from the stack. If it is not `cl:nil`, jump to the label.
(when (pop STACK) (incf IP label))
```

### jump-if-supplied-{8,16} #x1a #x1b (base misc) (dest label)
### jump-if-supplied-{8,16} #x1a #x1b (dest label)

If the `base`th local is anything but the distinguished unsupplied value, jump to the label.
Pop a value. If it is anything but the distinguished unsupplied value, push it back, then jump to the label.

```lisp
(unless (eq (pop STACK) +UNSUPPLIED+) (incf IP label))
(let ((value (pop STACK)))
(unless (eq value +UNSUPPLIED+) (push value STACK) (incf IP label)))
```

### check-arg-count-<= #x1c (nargs misc)
Expand Down
2 changes: 1 addition & 1 deletion compile-file/preliminaries.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
;;; The versioning encompasses both the FASL format itself as well as the
;;; bytecode in modules. Changes to bytecode should get a version bump too.
(defparameter *major-version* 0)
(defparameter *minor-version* 14)
(defparameter *minor-version* 15)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
Expand Down
Loading

0 comments on commit 51cd4ae

Please sign in to comment.