Rewrite the compiler
A few days ago I found a bug in the compiler that I decided merited basically an
entire rewrite of it.
This was long overdue. The compiler kind of grew organically and unhealthily
over time as I wrapped my head around how the whole WAM is structured, and now
that I understand a lot more I can do things right.
This new implementation is a lot "flatter" than the old one. It makes use of
CLOS classes and generic methods to un-nest a lot of the crap that was
previously happening in bigass `labels` blocks. This is a lot easier to read
and understand because you can take things a piece at a time.
Unfortunately, it's currently a lot slower than the old one. But at least it's
*correct*, and now I can start taking a look at optimizing the performance with
a cleaner base to start from.
Notes/ideas for the near future:
* Switch to structs instead of CLOS classes for all the bits and bobs in the
compilation process.
* Inline hot functions in the compilation process.
* Type hint the fucking compiler already. I've put this off for far too long.
* Move the compiler to its own package for easier profiling and to maintain my
shreds of sanity.
* Look into that generic-function-inlining library thing I saw on Reddit...
* Remove the last vestiges of `match` and kill the dependency on optima.
author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 07 Jun 2016 14:49:20 +0000 |
parents |
e244881864f7 |
children |
792dfa2f9120 |
(in-package #:bones.wam)
(deftype cell ()
`(unsigned-byte ,+cell-width+))
(deftype cell-tag ()
`(unsigned-byte ,+cell-tag-width+))
(deftype cell-value ()
`(unsigned-byte ,+cell-value-width+))
(deftype store-index ()
`(integer 0 ,(1- +store-limit+)))
(deftype heap-index ()
`(integer ,+heap-start+ ,(1- +store-limit+)))
(deftype stack-index ()
`(integer ,+stack-start+ ,(1- +stack-end+)))
(deftype trail-index ()
`(integer 0 ,(1- +trail-limit+)))
(deftype register-index ()
`(integer 0 ,(1- +register-count+)))
(deftype functor-index ()
`(integer 0 ,(1- +functor-limit+)))
(deftype arity ()
`(integer 0 ,+maximum-arity+))
(deftype functor ()
'(cons symbol arity))
(deftype code-word ()
`(unsigned-byte ,+code-word-size+))
(deftype code-index ()
;; either an address or the sentinel
`(integer 0 ,(1- +code-limit+)))
(deftype opcode ()
'(integer 0 33))
(deftype stack-frame-size ()
`(integer 4 ,+stack-frame-size-limit+))
(deftype stack-choice-size ()
;; TODO: is this actually right? check on frame size limit vs choice point
;; size limit...
`(integer 7 ,+stack-frame-size-limit+))
(deftype stack-frame-argcount ()
'arity)
(deftype continuation-pointer ()
'code-index)
(deftype environment-pointer ()
'stack-index)
(deftype backtrack-pointer ()
'stack-index)
(deftype stack-frame-word ()
'(or
environment-pointer ; CE
continuation-pointer ; CP
stack-frame-argcount ; N
cell)) ; Yn
(deftype stack-choice-word ()
'(or
environment-pointer ; CE
backtrack-pointer ; B
continuation-pointer ; CP, BP
stack-frame-argcount ; N
trail-index ; TR
heap-index ; H
cell)) ; An
(deftype stack-word ()
'(or stack-frame-word stack-choice-word))
;;;; Sanity Checks
;;; The values on the WAM stack are a bit of a messy situation. The WAM store
;;; is defined as an array of cells, but certain things on the stack aren't
;;; actually cells (e.g. the stored continuation pointer).
;;;
;;; This shouldn't be a problem (aside from being ugly) as long as our `cell`
;;; type is big enough to hold the values of these non-cell things. So let's
;;; just make sure that's the case...
(defun sanity-check-stack-type (type)
(assert (subtypep type 'cell) ()
"Type ~A is too large to fit into a cell!"
type)
(values))
(sanity-check-stack-type 'stack-frame-argcount)
(sanity-check-stack-type 'environment-pointer)
(sanity-check-stack-type 'continuation-pointer)
(sanity-check-stack-type 'backtrack-pointer)
(sanity-check-stack-type 'trail-index)
(sanity-check-stack-type 'stack-word)