* an end to oppression
@ 2008-11-14 22:29 Andy Wingo
0 siblings, 0 replies; only message in thread
From: Andy Wingo @ 2008-11-14 22:29 UTC (permalink / raw)
To: guile-devel
Hello,
Are you feeling oppressed because the misguided authors of Guile's
compiler did not see fit to include your crucially important
optimization pass, or did not add support for the passes needed in your
language? I though so. I can feel these things. Well suffer no more,
because Guile now has a fully generic compiler infrastructure.
What? You don't know what an FGCI is? Clearly you are not as up on the
literature as you pretend to be. Allow me to paste some code from the
newly shortened (system base compile):
(define *current-language* (make-fluid))
(define (current-language)
(or (fluid-ref *current-language*)
(begin (fluid-set! *current-language* (lookup-language 'scheme))
(current-language))))
Here we define some bits to set the current language, which defaults to
Scheme.
(define (compile-passes from to opts)
(let lp ((langs (or (lookup-compilation-order from to)
(error "no way to compile" (language-name from)
"to" (language-name to))))
(out '()))
(if (null? (cdr langs))
(reverse! out)
(lp (cdr langs)
(cons (assq-ref (language-compilers (car langs)) (cadr langs))
out)))))
This function computes the ordered list of functions to fold over the
source expression and environment. It's language-neutral.
(define (compile-fold passes exp env opts)
(if (null? passes)
exp
(receive (exp env) ((car passes) exp env opts)
(compile-fold (cdr passes) exp env opts))))
(define* (compile x #:key
(env #f)
(from (current-language))
(to value)
(opts '()))
(compile-fold (compile-passes from to opts)
x
env
opts))
As are these functions. The latter is the primary runtime compilation
interface, `compile-file' being the other one. Here's the bits about
looking up compilation passes, from (system base language):
(define (compute-compilation-order from to)
(let lp ((from from) (seen '()))
(cond ((eq? from to) (reverse! (cons from seen)))
((memq from seen) #f)
(else (or-map (lambda (lang) (lp lang (cons from seen)))
(map car (language-compilers from)))))))
(define (lookup-compilation-order from to)
(or (assoc-ref *compilation-cache* (cons from to))
(let ((order (compute-compilation-order from to)))
(set! *compilation-cache*
(acons (cons from to) order *compilation-cache*))
order)))
And to round out this exposition, here's the definition of the GHIL
language:
(define-language ghil
#:title "Guile High Intermediate Language (GHIL)"
#:version "0.3"
#:reader read
#:printer write-ghil
#:parser parse
#:compilers `((,glil . ,compile-il)))
The default target language is "value", which is a bit of a hack -- we
want to compile to objcode (a language), then turn that objcode into a
thunk and run the thunk. The latter operations are modeled as
translating a language of a static array of bytes (objcode) into Scheme
values -- thus a "compiler" from objcode to value.
Now that I think of it, there's a quine lurking here:
((lambda (x) ((compile x) x)) '(lambda (x) ((compile x) x)))
I feel like there's some further simplicity here, though perhaps not.
(Note that compile is equivalent to eval in this case.)
Happy hacking,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-11-14 22:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-14 22:29 an end to oppression Andy Wingo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).