2001-04-01 05:03:41 +00:00
|
|
|
|
;;; Guile VM specific syntaxes and utilities
|
|
|
|
|
|
|
2009-08-05 21:25:35 +02:00
|
|
|
|
;; Copyright (C) 2001, 2009 Free Software Foundation, Inc
|
2001-04-01 05:03:41 +00:00
|
|
|
|
|
2009-07-15 22:46:54 +02:00
|
|
|
|
;;; This library is free software; you can redistribute it and/or
|
|
|
|
|
|
;;; modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
|
;;; License as published by the Free Software Foundation; either
|
|
|
|
|
|
;;; version 3 of the License, or (at your option) any later version.
|
|
|
|
|
|
;;;
|
|
|
|
|
|
;;; This library is distributed in the hope that it will be useful,
|
|
|
|
|
|
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
|
;;; Lesser General Public License for more details.
|
|
|
|
|
|
;;;
|
|
|
|
|
|
;;; You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
|
;;; License along with this library; if not, write to the Free Software
|
|
|
|
|
|
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
2001-04-01 05:03:41 +00:00
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
|
|
(define-module (system base syntax)
|
2008-09-09 06:56:06 +02:00
|
|
|
|
#:export (%compute-initargs)
|
2009-02-13 00:01:47 +01:00
|
|
|
|
#:export-syntax (define-type define-record define-record/keywords
|
2009-02-27 12:36:58 +01:00
|
|
|
|
record-case transform-record))
|
2001-04-01 05:03:41 +00:00
|
|
|
|
|
2009-02-27 10:44:47 +01:00
|
|
|
|
(define (symbol-trim-both sym pred)
|
|
|
|
|
|
(string->symbol (string-trim-both (symbol->string sym) pred)))
|
|
|
|
|
|
(define (trim-brackets sym)
|
|
|
|
|
|
(symbol-trim-both sym (list->char-set '(#\< #\>))))
|
|
|
|
|
|
|
2001-04-01 05:03:41 +00:00
|
|
|
|
|
|
|
|
|
|
;;;
|
2001-04-22 02:13:48 +00:00
|
|
|
|
;;; Type
|
|
|
|
|
|
;;;
|
|
|
|
|
|
|
2008-10-24 11:09:43 +02:00
|
|
|
|
(define-macro (define-type name . rest)
|
add parsers and unparser for ghil; ,language ghil works now
* module/system/repl/common.scm (repl-print): Slightly refine the meaning
of "language-printer": a language printer prints an expression of a
language, not the result of evaluation. `write' prints values.
* module/language/ghil/spec.scm (ghil): Define a language printer, and a
translator for turning s-expressions (not scheme, mind you) into GHIL.
* module/language/scheme/translate.scm (quote, quasiquote): Add some
#:keyword action, so that we can (quote #:keywords).
* module/system/base/language.scm (<language>):
* module/system/base/compile.scm (read-file-in): Don't require that a
language have a read-file; instead error when read-file is called.
(compile-passes, compile-in): Refactor to call a helper method to turn
the language + set of options into a set of compiler passes.
* module/system/base/syntax.scm (define-type): Allow the type to be a
list, with the car being the name and the cdr being keyword options.
Interpret #:printer as a printer, and pass it down to...
(define-record): Here.
* module/system/il/ghil.scm (print-ghil, <ghil>): New printer for GHIL,
yay!
(parse-ghil, unparse-ghil): New lovely functions. Will document them in
the manual.
2008-11-11 22:52:24 +01:00
|
|
|
|
(let ((name (if (pair? name) (car name) name))
|
|
|
|
|
|
(opts (if (pair? name) (cdr name) '())))
|
2009-02-27 10:44:47 +01:00
|
|
|
|
(let ((printer (kw-arg-ref opts #:printer))
|
|
|
|
|
|
(common-slots (or (kw-arg-ref opts #:common-slots) '())))
|
nifty generic compiler infrastructure -- no more hardcoded passes
* module/system/base/language.scm (<language>): Rework so that instead of
hardcoding passes in the language, we define compilers that translate
from one language to another. Add `parser' to the language fields, a
bit of a hack but useful for languages with s-expression external
representations but with record internal representations.
(define-language, *compilation-cache*, invalidate-compilation-cache!)
(compute-compilation-order, lookup-compilation-order): Add an algorithm
that does a depth-first search for a translation path from a source
language to a target language, caching the result in a lookup table.
* module/language/scheme/spec.scm:
* module/language/ghil/spec.scm: Update to the new language format.
* module/language/glil/spec.scm: Add a language specification for GLIL,
with a compiler to objcode. Also there are parsers and printers, for
repl usage, but for some reason this doesn't work yet.
* module/language/objcode/spec.scm: Define a language specification for
object code. There is some sleight of hand here, in the "compiler" to
values; but there is method behind the madness, because this way we
higher levels can pass environments (a module + externals pair) to
objcode->program.
* module/language/value/spec.scm: Define a language specification for
values. There is something intellectually dishonest about this, but it
does serve its purpose as a foundation for the language hierarchy.
* configure.in:
* module/language/Makefile.am
* module/language/ghil/Makefile.am
* module/language/glil/Makefile.am
* module/language/objcode/Makefile.am
* module/language/value/Makefile.am:
Autotomfoolery for the ghil, glil, objcode, and value languages.
* module/language/scheme/translate.scm (translate): Import the bits that
understand `compile-time-environment' here, and pass on the relevant
portions of the environment to the next compiler pass.
* module/system/base/compile.scm (current-language): New procedure, refs
the current language fluid, or lazily sets it to scheme.
(call-once, call-with-output-file/atomic): Refactor these bits to use
with-throw-handler. No functional change.
(compile-file, compile-and-load, compile-passes, compile-fold)
(compile): Refactor the public interface of the compiler to be generic
and simple. Uses `lookup-compilation-order' to find a path from the
source language to the target language.
* module/system/base/syntax.scm (define-type): Adapt to changes in
define-record.
(define-record): Instead of expecting all slots in the first form,
expect them in the body, and let the first form hold the options.
* module/system/il/compile.scm (compile): Adapt to the compilation pass
API (three in and two out).
* module/system/il/ghil.scm (<ghil-var>, <ghil-env>)
(<ghil-toplevel-env>): Adapt to define-record changes.
* module/system/il/glil.scm (<glil-vars>): Adapt to define-record
changes.
(<glil>, print-glil): Add a GLIL record printer that uses unparse.
(parse-glil, unparse-glil): Update unparse (formerly known as pprint),
and write a parse function.
* module/system/repl/common.scm (<repl>): Adapt to define-record changes.
(repl-parse): New function, parses the read form using the current
language. Something of a hack.
(repl-compile): Adapt to changes in `compile'.
(repl-eval): Fix up the does-the-language-have-a-compiler check for
changes in <language>.
* module/system/repl/repl.scm (start-repl): Parse the form before eval.
* module/system/repl/command.scm (describe): Parse.
(compile): Be more generic.
(compile-file): Adapt to changes in compile-file.
(disassemble, time, profile, trace): Parse.
* module/system/vm/debug.scm:
* module/system/vm/assemble.scm: Adapt to define-record changes.
* module/language/scheme/translate.scm (receive): Fix an important bug
that gave `receive' letrec semantics instead of let semantics. Whoops!
2008-11-14 22:42:31 +01:00
|
|
|
|
`(begin ,@(map (lambda (def)
|
|
|
|
|
|
`(define-record ,(if printer
|
|
|
|
|
|
`(,(car def) ,printer)
|
|
|
|
|
|
(car def))
|
2009-02-27 10:44:47 +01:00
|
|
|
|
,@common-slots
|
nifty generic compiler infrastructure -- no more hardcoded passes
* module/system/base/language.scm (<language>): Rework so that instead of
hardcoding passes in the language, we define compilers that translate
from one language to another. Add `parser' to the language fields, a
bit of a hack but useful for languages with s-expression external
representations but with record internal representations.
(define-language, *compilation-cache*, invalidate-compilation-cache!)
(compute-compilation-order, lookup-compilation-order): Add an algorithm
that does a depth-first search for a translation path from a source
language to a target language, caching the result in a lookup table.
* module/language/scheme/spec.scm:
* module/language/ghil/spec.scm: Update to the new language format.
* module/language/glil/spec.scm: Add a language specification for GLIL,
with a compiler to objcode. Also there are parsers and printers, for
repl usage, but for some reason this doesn't work yet.
* module/language/objcode/spec.scm: Define a language specification for
object code. There is some sleight of hand here, in the "compiler" to
values; but there is method behind the madness, because this way we
higher levels can pass environments (a module + externals pair) to
objcode->program.
* module/language/value/spec.scm: Define a language specification for
values. There is something intellectually dishonest about this, but it
does serve its purpose as a foundation for the language hierarchy.
* configure.in:
* module/language/Makefile.am
* module/language/ghil/Makefile.am
* module/language/glil/Makefile.am
* module/language/objcode/Makefile.am
* module/language/value/Makefile.am:
Autotomfoolery for the ghil, glil, objcode, and value languages.
* module/language/scheme/translate.scm (translate): Import the bits that
understand `compile-time-environment' here, and pass on the relevant
portions of the environment to the next compiler pass.
* module/system/base/compile.scm (current-language): New procedure, refs
the current language fluid, or lazily sets it to scheme.
(call-once, call-with-output-file/atomic): Refactor these bits to use
with-throw-handler. No functional change.
(compile-file, compile-and-load, compile-passes, compile-fold)
(compile): Refactor the public interface of the compiler to be generic
and simple. Uses `lookup-compilation-order' to find a path from the
source language to the target language.
* module/system/base/syntax.scm (define-type): Adapt to changes in
define-record.
(define-record): Instead of expecting all slots in the first form,
expect them in the body, and let the first form hold the options.
* module/system/il/compile.scm (compile): Adapt to the compilation pass
API (three in and two out).
* module/system/il/ghil.scm (<ghil-var>, <ghil-env>)
(<ghil-toplevel-env>): Adapt to define-record changes.
* module/system/il/glil.scm (<glil-vars>): Adapt to define-record
changes.
(<glil>, print-glil): Add a GLIL record printer that uses unparse.
(parse-glil, unparse-glil): Update unparse (formerly known as pprint),
and write a parse function.
* module/system/repl/common.scm (<repl>): Adapt to define-record changes.
(repl-parse): New function, parses the read form using the current
language. Something of a hack.
(repl-compile): Adapt to changes in `compile'.
(repl-eval): Fix up the does-the-language-have-a-compiler check for
changes in <language>.
* module/system/repl/repl.scm (start-repl): Parse the form before eval.
* module/system/repl/command.scm (describe): Parse.
(compile): Be more generic.
(compile-file): Adapt to changes in compile-file.
(disassemble, time, profile, trace): Parse.
* module/system/vm/debug.scm:
* module/system/vm/assemble.scm: Adapt to define-record changes.
* module/language/scheme/translate.scm (receive): Fix an important bug
that gave `receive' letrec semantics instead of let semantics. Whoops!
2008-11-14 22:42:31 +01:00
|
|
|
|
,@(cdr def)))
|
2009-02-27 10:44:47 +01:00
|
|
|
|
rest)
|
|
|
|
|
|
,@(map (lambda (common-slot i)
|
2009-02-27 10:56:15 +01:00
|
|
|
|
`(define ,(symbol-append (trim-brackets name)
|
|
|
|
|
|
'- common-slot)
|
|
|
|
|
|
(make-procedure-with-setter
|
|
|
|
|
|
(lambda (x) (struct-ref x ,i))
|
|
|
|
|
|
(lambda (x v) (struct-set! x ,i v)))))
|
2009-02-27 10:44:47 +01:00
|
|
|
|
common-slots (iota (length common-slots)))))))
|
2008-10-24 11:09:43 +02:00
|
|
|
|
|
2001-04-22 02:13:48 +00:00
|
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
|
;;; Record
|
|
|
|
|
|
;;;
|
|
|
|
|
|
|
nifty generic compiler infrastructure -- no more hardcoded passes
* module/system/base/language.scm (<language>): Rework so that instead of
hardcoding passes in the language, we define compilers that translate
from one language to another. Add `parser' to the language fields, a
bit of a hack but useful for languages with s-expression external
representations but with record internal representations.
(define-language, *compilation-cache*, invalidate-compilation-cache!)
(compute-compilation-order, lookup-compilation-order): Add an algorithm
that does a depth-first search for a translation path from a source
language to a target language, caching the result in a lookup table.
* module/language/scheme/spec.scm:
* module/language/ghil/spec.scm: Update to the new language format.
* module/language/glil/spec.scm: Add a language specification for GLIL,
with a compiler to objcode. Also there are parsers and printers, for
repl usage, but for some reason this doesn't work yet.
* module/language/objcode/spec.scm: Define a language specification for
object code. There is some sleight of hand here, in the "compiler" to
values; but there is method behind the madness, because this way we
higher levels can pass environments (a module + externals pair) to
objcode->program.
* module/language/value/spec.scm: Define a language specification for
values. There is something intellectually dishonest about this, but it
does serve its purpose as a foundation for the language hierarchy.
* configure.in:
* module/language/Makefile.am
* module/language/ghil/Makefile.am
* module/language/glil/Makefile.am
* module/language/objcode/Makefile.am
* module/language/value/Makefile.am:
Autotomfoolery for the ghil, glil, objcode, and value languages.
* module/language/scheme/translate.scm (translate): Import the bits that
understand `compile-time-environment' here, and pass on the relevant
portions of the environment to the next compiler pass.
* module/system/base/compile.scm (current-language): New procedure, refs
the current language fluid, or lazily sets it to scheme.
(call-once, call-with-output-file/atomic): Refactor these bits to use
with-throw-handler. No functional change.
(compile-file, compile-and-load, compile-passes, compile-fold)
(compile): Refactor the public interface of the compiler to be generic
and simple. Uses `lookup-compilation-order' to find a path from the
source language to the target language.
* module/system/base/syntax.scm (define-type): Adapt to changes in
define-record.
(define-record): Instead of expecting all slots in the first form,
expect them in the body, and let the first form hold the options.
* module/system/il/compile.scm (compile): Adapt to the compilation pass
API (three in and two out).
* module/system/il/ghil.scm (<ghil-var>, <ghil-env>)
(<ghil-toplevel-env>): Adapt to define-record changes.
* module/system/il/glil.scm (<glil-vars>): Adapt to define-record
changes.
(<glil>, print-glil): Add a GLIL record printer that uses unparse.
(parse-glil, unparse-glil): Update unparse (formerly known as pprint),
and write a parse function.
* module/system/repl/common.scm (<repl>): Adapt to define-record changes.
(repl-parse): New function, parses the read form using the current
language. Something of a hack.
(repl-compile): Adapt to changes in `compile'.
(repl-eval): Fix up the does-the-language-have-a-compiler check for
changes in <language>.
* module/system/repl/repl.scm (start-repl): Parse the form before eval.
* module/system/repl/command.scm (describe): Parse.
(compile): Be more generic.
(compile-file): Adapt to changes in compile-file.
(disassemble, time, profile, trace): Parse.
* module/system/vm/debug.scm:
* module/system/vm/assemble.scm: Adapt to define-record changes.
* module/language/scheme/translate.scm (receive): Fix an important bug
that gave `receive' letrec semantics instead of let semantics. Whoops!
2008-11-14 22:42:31 +01:00
|
|
|
|
(define-macro (define-record name-form . slots)
|
2009-02-13 00:01:47 +01:00
|
|
|
|
(let* ((name (if (pair? name-form) (car name-form) name-form))
|
|
|
|
|
|
(printer (and (pair? name-form) (cadr name-form)))
|
|
|
|
|
|
(slot-names (map (lambda (slot) (if (pair? slot) (car slot) slot))
|
|
|
|
|
|
slots))
|
2009-02-27 10:44:47 +01:00
|
|
|
|
(stem (trim-brackets name)))
|
2009-02-13 00:01:47 +01:00
|
|
|
|
`(begin
|
|
|
|
|
|
(define ,name (make-record-type ,(symbol->string name) ',slot-names
|
|
|
|
|
|
,@(if printer (list printer) '())))
|
|
|
|
|
|
,(let* ((reqs (let lp ((slots slots))
|
|
|
|
|
|
(if (or (null? slots) (not (symbol? (car slots))))
|
|
|
|
|
|
'()
|
|
|
|
|
|
(cons (car slots) (lp (cdr slots))))))
|
|
|
|
|
|
(opts (list-tail slots (length reqs)))
|
|
|
|
|
|
(tail (gensym)))
|
|
|
|
|
|
`(define (,(symbol-append 'make- stem) ,@reqs . ,tail)
|
|
|
|
|
|
(let ,(map (lambda (o)
|
|
|
|
|
|
`(,(car o) (cond ((null? ,tail) ,(cadr o))
|
|
|
|
|
|
(else (let ((_x (car ,tail)))
|
|
|
|
|
|
(set! ,tail (cdr ,tail))
|
|
|
|
|
|
_x)))))
|
|
|
|
|
|
opts)
|
|
|
|
|
|
(make-struct ,name 0 ,@slot-names))))
|
|
|
|
|
|
(define ,(symbol-append stem '?) (record-predicate ,name))
|
|
|
|
|
|
,@(map (lambda (sname)
|
|
|
|
|
|
`(define ,(symbol-append stem '- sname)
|
|
|
|
|
|
(make-procedure-with-setter
|
|
|
|
|
|
(record-accessor ,name ',sname)
|
|
|
|
|
|
(record-modifier ,name ',sname))))
|
|
|
|
|
|
slot-names))))
|
|
|
|
|
|
|
|
|
|
|
|
;; like the former, but accepting keyword arguments in addition to
|
|
|
|
|
|
;; optional arguments
|
|
|
|
|
|
(define-macro (define-record/keywords name-form . slots)
|
nifty generic compiler infrastructure -- no more hardcoded passes
* module/system/base/language.scm (<language>): Rework so that instead of
hardcoding passes in the language, we define compilers that translate
from one language to another. Add `parser' to the language fields, a
bit of a hack but useful for languages with s-expression external
representations but with record internal representations.
(define-language, *compilation-cache*, invalidate-compilation-cache!)
(compute-compilation-order, lookup-compilation-order): Add an algorithm
that does a depth-first search for a translation path from a source
language to a target language, caching the result in a lookup table.
* module/language/scheme/spec.scm:
* module/language/ghil/spec.scm: Update to the new language format.
* module/language/glil/spec.scm: Add a language specification for GLIL,
with a compiler to objcode. Also there are parsers and printers, for
repl usage, but for some reason this doesn't work yet.
* module/language/objcode/spec.scm: Define a language specification for
object code. There is some sleight of hand here, in the "compiler" to
values; but there is method behind the madness, because this way we
higher levels can pass environments (a module + externals pair) to
objcode->program.
* module/language/value/spec.scm: Define a language specification for
values. There is something intellectually dishonest about this, but it
does serve its purpose as a foundation for the language hierarchy.
* configure.in:
* module/language/Makefile.am
* module/language/ghil/Makefile.am
* module/language/glil/Makefile.am
* module/language/objcode/Makefile.am
* module/language/value/Makefile.am:
Autotomfoolery for the ghil, glil, objcode, and value languages.
* module/language/scheme/translate.scm (translate): Import the bits that
understand `compile-time-environment' here, and pass on the relevant
portions of the environment to the next compiler pass.
* module/system/base/compile.scm (current-language): New procedure, refs
the current language fluid, or lazily sets it to scheme.
(call-once, call-with-output-file/atomic): Refactor these bits to use
with-throw-handler. No functional change.
(compile-file, compile-and-load, compile-passes, compile-fold)
(compile): Refactor the public interface of the compiler to be generic
and simple. Uses `lookup-compilation-order' to find a path from the
source language to the target language.
* module/system/base/syntax.scm (define-type): Adapt to changes in
define-record.
(define-record): Instead of expecting all slots in the first form,
expect them in the body, and let the first form hold the options.
* module/system/il/compile.scm (compile): Adapt to the compilation pass
API (three in and two out).
* module/system/il/ghil.scm (<ghil-var>, <ghil-env>)
(<ghil-toplevel-env>): Adapt to define-record changes.
* module/system/il/glil.scm (<glil-vars>): Adapt to define-record
changes.
(<glil>, print-glil): Add a GLIL record printer that uses unparse.
(parse-glil, unparse-glil): Update unparse (formerly known as pprint),
and write a parse function.
* module/system/repl/common.scm (<repl>): Adapt to define-record changes.
(repl-parse): New function, parses the read form using the current
language. Something of a hack.
(repl-compile): Adapt to changes in `compile'.
(repl-eval): Fix up the does-the-language-have-a-compiler check for
changes in <language>.
* module/system/repl/repl.scm (start-repl): Parse the form before eval.
* module/system/repl/command.scm (describe): Parse.
(compile): Be more generic.
(compile-file): Adapt to changes in compile-file.
(disassemble, time, profile, trace): Parse.
* module/system/vm/debug.scm:
* module/system/vm/assemble.scm: Adapt to define-record changes.
* module/language/scheme/translate.scm (receive): Fix an important bug
that gave `receive' letrec semantics instead of let semantics. Whoops!
2008-11-14 22:42:31 +01:00
|
|
|
|
(let* ((name (if (pair? name-form) (car name-form) name-form))
|
|
|
|
|
|
(printer (and (pair? name-form) (cadr name-form)))
|
2008-05-04 17:25:13 +02:00
|
|
|
|
(slot-names (map (lambda (slot) (if (pair? slot) (car slot) slot))
|
|
|
|
|
|
slots))
|
2009-02-27 12:36:58 +01:00
|
|
|
|
(stem (trim-brackets name)))
|
2001-04-22 02:13:48 +00:00
|
|
|
|
`(begin
|
add parsers and unparser for ghil; ,language ghil works now
* module/system/repl/common.scm (repl-print): Slightly refine the meaning
of "language-printer": a language printer prints an expression of a
language, not the result of evaluation. `write' prints values.
* module/language/ghil/spec.scm (ghil): Define a language printer, and a
translator for turning s-expressions (not scheme, mind you) into GHIL.
* module/language/scheme/translate.scm (quote, quasiquote): Add some
#:keyword action, so that we can (quote #:keywords).
* module/system/base/language.scm (<language>):
* module/system/base/compile.scm (read-file-in): Don't require that a
language have a read-file; instead error when read-file is called.
(compile-passes, compile-in): Refactor to call a helper method to turn
the language + set of options into a set of compiler passes.
* module/system/base/syntax.scm (define-type): Allow the type to be a
list, with the car being the name and the cdr being keyword options.
Interpret #:printer as a printer, and pass it down to...
(define-record): Here.
* module/system/il/ghil.scm (print-ghil, <ghil>): New printer for GHIL,
yay!
(parse-ghil, unparse-ghil): New lovely functions. Will document them in
the manual.
2008-11-11 22:52:24 +01:00
|
|
|
|
(define ,name (make-record-type ,(symbol->string name) ',slot-names
|
nifty generic compiler infrastructure -- no more hardcoded passes
* module/system/base/language.scm (<language>): Rework so that instead of
hardcoding passes in the language, we define compilers that translate
from one language to another. Add `parser' to the language fields, a
bit of a hack but useful for languages with s-expression external
representations but with record internal representations.
(define-language, *compilation-cache*, invalidate-compilation-cache!)
(compute-compilation-order, lookup-compilation-order): Add an algorithm
that does a depth-first search for a translation path from a source
language to a target language, caching the result in a lookup table.
* module/language/scheme/spec.scm:
* module/language/ghil/spec.scm: Update to the new language format.
* module/language/glil/spec.scm: Add a language specification for GLIL,
with a compiler to objcode. Also there are parsers and printers, for
repl usage, but for some reason this doesn't work yet.
* module/language/objcode/spec.scm: Define a language specification for
object code. There is some sleight of hand here, in the "compiler" to
values; but there is method behind the madness, because this way we
higher levels can pass environments (a module + externals pair) to
objcode->program.
* module/language/value/spec.scm: Define a language specification for
values. There is something intellectually dishonest about this, but it
does serve its purpose as a foundation for the language hierarchy.
* configure.in:
* module/language/Makefile.am
* module/language/ghil/Makefile.am
* module/language/glil/Makefile.am
* module/language/objcode/Makefile.am
* module/language/value/Makefile.am:
Autotomfoolery for the ghil, glil, objcode, and value languages.
* module/language/scheme/translate.scm (translate): Import the bits that
understand `compile-time-environment' here, and pass on the relevant
portions of the environment to the next compiler pass.
* module/system/base/compile.scm (current-language): New procedure, refs
the current language fluid, or lazily sets it to scheme.
(call-once, call-with-output-file/atomic): Refactor these bits to use
with-throw-handler. No functional change.
(compile-file, compile-and-load, compile-passes, compile-fold)
(compile): Refactor the public interface of the compiler to be generic
and simple. Uses `lookup-compilation-order' to find a path from the
source language to the target language.
* module/system/base/syntax.scm (define-type): Adapt to changes in
define-record.
(define-record): Instead of expecting all slots in the first form,
expect them in the body, and let the first form hold the options.
* module/system/il/compile.scm (compile): Adapt to the compilation pass
API (three in and two out).
* module/system/il/ghil.scm (<ghil-var>, <ghil-env>)
(<ghil-toplevel-env>): Adapt to define-record changes.
* module/system/il/glil.scm (<glil-vars>): Adapt to define-record
changes.
(<glil>, print-glil): Add a GLIL record printer that uses unparse.
(parse-glil, unparse-glil): Update unparse (formerly known as pprint),
and write a parse function.
* module/system/repl/common.scm (<repl>): Adapt to define-record changes.
(repl-parse): New function, parses the read form using the current
language. Something of a hack.
(repl-compile): Adapt to changes in `compile'.
(repl-eval): Fix up the does-the-language-have-a-compiler check for
changes in <language>.
* module/system/repl/repl.scm (start-repl): Parse the form before eval.
* module/system/repl/command.scm (describe): Parse.
(compile): Be more generic.
(compile-file): Adapt to changes in compile-file.
(disassemble, time, profile, trace): Parse.
* module/system/vm/debug.scm:
* module/system/vm/assemble.scm: Adapt to define-record changes.
* module/language/scheme/translate.scm (receive): Fix an important bug
that gave `receive' letrec semantics instead of let semantics. Whoops!
2008-11-14 22:42:31 +01:00
|
|
|
|
,@(if printer (list printer) '())))
|
2008-05-03 18:32:46 +02:00
|
|
|
|
(define ,(symbol-append 'make- stem)
|
|
|
|
|
|
(let ((slots (list ,@(map (lambda (slot)
|
|
|
|
|
|
(if (pair? slot)
|
|
|
|
|
|
`(cons ',(car slot) ,(cadr slot))
|
|
|
|
|
|
`',slot))
|
fix else in cond, letrec env corruption, syntax.scm compile, define-module side effects
* module/language/scheme/translate.scm (primitive-syntax-table):
Translate the `else' clause of a cond as (begin ...). We used to use
trans-body, which processes internal defines, which are not legal
syntax here.
* module/system/base/syntax.scm (define-record): Unfortunately, we can't
unquote in the actual procedure for `%compute-initargs', because that
doesn't work with compilation. So reference %compute-initargs by name,
and export it.
* module/system/il/ghil.scm (apopq!): Gaaaaar. The order of the arguments
to assq-remove! was reversed, which was the badness, causing corruption
to the env after calling call-with-ghil-bindings. Grrrrrr.
(fix-ghil-mod!, ghil-lookup, ghil-define): As amply commented in the
code, deal with compile-time side effects to the current module by
lazily noticing and patching up the compile-time environment. A hacky
solution until such a time as we special-case something for
`define-module'.
2008-05-15 18:48:22 +02:00
|
|
|
|
slots)))
|
|
|
|
|
|
(constructor (record-constructor ,name)))
|
2008-05-03 18:32:46 +02:00
|
|
|
|
(lambda args
|
fix else in cond, letrec env corruption, syntax.scm compile, define-module side effects
* module/language/scheme/translate.scm (primitive-syntax-table):
Translate the `else' clause of a cond as (begin ...). We used to use
trans-body, which processes internal defines, which are not legal
syntax here.
* module/system/base/syntax.scm (define-record): Unfortunately, we can't
unquote in the actual procedure for `%compute-initargs', because that
doesn't work with compilation. So reference %compute-initargs by name,
and export it.
* module/system/il/ghil.scm (apopq!): Gaaaaar. The order of the arguments
to assq-remove! was reversed, which was the badness, causing corruption
to the env after calling call-with-ghil-bindings. Grrrrrr.
(fix-ghil-mod!, ghil-lookup, ghil-define): As amply commented in the
code, deal with compile-time side effects to the current module by
lazily noticing and patching up the compile-time environment. A hacky
solution until such a time as we special-case something for
`define-module'.
2008-05-15 18:48:22 +02:00
|
|
|
|
(apply constructor (%compute-initargs args slots)))))
|
2008-05-15 18:57:33 +02:00
|
|
|
|
(define ,(symbol-append stem '?) (record-predicate ,name))
|
2008-05-04 17:25:13 +02:00
|
|
|
|
,@(map (lambda (sname)
|
|
|
|
|
|
`(define ,(symbol-append stem '- sname)
|
2008-05-15 18:57:33 +02:00
|
|
|
|
(make-procedure-with-setter
|
|
|
|
|
|
(record-accessor ,name ',sname)
|
|
|
|
|
|
(record-modifier ,name ',sname))))
|
2008-05-04 17:25:13 +02:00
|
|
|
|
slot-names))))
|
|
|
|
|
|
|
|
|
|
|
|
(define (%compute-initargs args slots)
|
|
|
|
|
|
(define (finish out)
|
2008-05-03 18:32:46 +02:00
|
|
|
|
(map (lambda (slot)
|
|
|
|
|
|
(let ((name (if (pair? slot) (car slot) slot)))
|
2008-05-04 17:25:13 +02:00
|
|
|
|
(cond ((assq name out) => cdr)
|
|
|
|
|
|
((pair? slot) (cdr slot))
|
|
|
|
|
|
(else (error "unbound slot" args slots name)))))
|
2008-05-03 18:32:46 +02:00
|
|
|
|
slots))
|
|
|
|
|
|
(let lp ((in args) (positional slots) (out '()))
|
|
|
|
|
|
(cond
|
|
|
|
|
|
((null? in)
|
2008-05-04 17:25:13 +02:00
|
|
|
|
(finish out))
|
2008-05-03 18:32:46 +02:00
|
|
|
|
((keyword? (car in))
|
|
|
|
|
|
(let ((sym (keyword->symbol (car in))))
|
|
|
|
|
|
(cond
|
|
|
|
|
|
((and (not (memq sym slots))
|
|
|
|
|
|
(not (assq sym (filter pair? slots))))
|
|
|
|
|
|
(error "unknown slot" sym))
|
|
|
|
|
|
((assq sym out) (error "slot already set" sym out))
|
|
|
|
|
|
(else (lp (cddr in) '() (acons sym (cadr in) out))))))
|
|
|
|
|
|
((null? positional)
|
|
|
|
|
|
(error "too many initargs" args slots))
|
|
|
|
|
|
(else
|
|
|
|
|
|
(lp (cdr in) (cdr positional)
|
recompiling with compile environments, fluid languages, cleanups
* ice-9/boot-9.scm (compile-time-environment): Remove definition from
boot-9 -- instead, autoload it and `compile' from (system base
compile).
* libguile/objcodes.h:
* libguile/objcodes.c (scm_objcode_to_program): Add an optional argument,
`external', the external list to set on the returned program.
* libguile/vm-i-system.c (externals): New instruction, returns the
external list. Only used by (compile-time-environment).
* libguile/vm.c (scm_load_compiled_with_vm): Adapt to
scm_objcode_to_program change.
* module/language/scheme/translate.scm (translate): Actually pay
attention to the environment passed as an argument.
(custom-transformer-table): Expand out (compile-time-environment) to
something that can be passed to `compile'.
* module/system/base/compile.scm (*current-language*): Instead of
hard-coding `scheme' in various places, use a current language fluid,
initialized to `scheme'.
(compile-file, load-source-file): Adapt to *current-language*.
(load-source-file): Ada
(scheme-eval): Removed, no one used this.
(compiled-file-name): Don't hard-code "scm" and "go"; instead use the
%load-extensions and %load-compiled-extensions.
(cenv-module, cenv-ghil-env, cenv-externals): Some accessors for
compile-time environments.
(compile-time-environment): Here we define (compile-time-environment)
to something that will return #f; the compiler however produces
different code as noted above.
(compile): New function, compiles an expression into a thunk, then runs
the thunk to get the value. Useful for procedures. The optional second
argument can be either a module or a compile-time-environment; in the
latter case, we can recompile even with lexical bindings.
(compile-in): If the env specifies a module, set that module for the
duration of the compilation.
* module/system/base/syntax.scm (%compute-initargs): Fix a bug where the
default value for a field would always replace a user-supplied value.
Whoops.
* module/system/il/ghil.scm (ghil-env-dereify): New function, takes the
result of ghil-env-reify and turns it back into a GHIL environment.
* scripts/compile (compile): Remove some of the tricky error handling, as
the library procedures handle this for us.
* test-suite/tests/compiler.test: Add a test for the dynamic compilation
bits.
2008-10-30 10:57:36 +01:00
|
|
|
|
(let ((slot (car positional)))
|
|
|
|
|
|
(acons (if (pair? slot) (car slot) slot)
|
|
|
|
|
|
(car in)
|
|
|
|
|
|
out)))))))
|
2001-04-22 02:13:48 +00:00
|
|
|
|
|
2009-02-11 22:08:04 +01:00
|
|
|
|
;; So, dear reader. It is pleasant indeed around this fire or at this
|
|
|
|
|
|
;; cafe or in this room, is it not? I think so too.
|
|
|
|
|
|
;;
|
|
|
|
|
|
;; This macro used to generate code that looked like this:
|
|
|
|
|
|
;;
|
|
|
|
|
|
;; `(((record-predicate ,record-type) ,r)
|
|
|
|
|
|
;; (let ,(map (lambda (slot)
|
|
|
|
|
|
;; (if (pair? slot)
|
|
|
|
|
|
;; `(,(car slot) ((record-accessor ,record-type ',(cadr slot)) ,r))
|
|
|
|
|
|
;; `(,slot ((record-accessor ,record-type ',slot) ,r))))
|
|
|
|
|
|
;; slots)
|
|
|
|
|
|
;; ,@body)))))
|
|
|
|
|
|
;;
|
|
|
|
|
|
;; But this was a hot spot, so computing all those predicates and
|
|
|
|
|
|
;; accessors all the time was getting expensive, so we did a terrible
|
|
|
|
|
|
;; thing: we decided that since above we're already defining accessors
|
|
|
|
|
|
;; and predicates with computed names, we might as well just rely on that fact here.
|
|
|
|
|
|
;;
|
|
|
|
|
|
;; It's a bit nasty, I agree. But it is fast.
|
|
|
|
|
|
;;
|
|
|
|
|
|
;;scheme@(guile-user)> (with-statprof #:hz 1000 #:full-stacks? #t (resolve-module '(oop goops)))% cumulative self
|
|
|
|
|
|
;; time seconds seconds name
|
|
|
|
|
|
;; 8.82 0.03 0.01 glil->assembly
|
|
|
|
|
|
;; 8.82 0.01 0.01 record-type-fields
|
|
|
|
|
|
;; 5.88 0.01 0.01 %compute-initargs
|
|
|
|
|
|
;; 5.88 0.01 0.01 list-index
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-08-05 21:25:35 +02:00
|
|
|
|
;;; So ugly... but I am too ignorant to know how to make it better.
|
|
|
|
|
|
(define-syntax record-case
|
|
|
|
|
|
(lambda (x)
|
|
|
|
|
|
(syntax-case x ()
|
|
|
|
|
|
((_ record clause ...)
|
|
|
|
|
|
(let ((r (syntax r))
|
|
|
|
|
|
(rtd (syntax rtd)))
|
|
|
|
|
|
(define (process-clause tag fields exprs)
|
|
|
|
|
|
(let ((infix (trim-brackets (syntax->datum tag))))
|
|
|
|
|
|
(with-syntax ((tag tag)
|
|
|
|
|
|
(((f . accessor) ...)
|
|
|
|
|
|
(let lp ((fields fields))
|
|
|
|
|
|
(syntax-case fields ()
|
|
|
|
|
|
(() (syntax ()))
|
|
|
|
|
|
(((v0 f0) f1 ...)
|
|
|
|
|
|
(acons (syntax v0)
|
|
|
|
|
|
(datum->syntax x
|
|
|
|
|
|
(symbol-append infix '- (syntax->datum
|
|
|
|
|
|
(syntax f0))))
|
|
|
|
|
|
(lp (syntax (f1 ...)))))
|
|
|
|
|
|
((f0 f1 ...)
|
|
|
|
|
|
(acons (syntax f0)
|
|
|
|
|
|
(datum->syntax x
|
|
|
|
|
|
(symbol-append infix '- (syntax->datum
|
|
|
|
|
|
(syntax f0))))
|
|
|
|
|
|
(lp (syntax (f1 ...))))))))
|
|
|
|
|
|
((e0 e1 ...)
|
|
|
|
|
|
(syntax-case exprs ()
|
|
|
|
|
|
(() (syntax (#t)))
|
|
|
|
|
|
((e0 e1 ...) (syntax (e0 e1 ...))))))
|
|
|
|
|
|
(syntax
|
|
|
|
|
|
((eq? rtd tag)
|
|
|
|
|
|
(let ((f (accessor r))
|
|
|
|
|
|
...)
|
|
|
|
|
|
e0 e1 ...))))))
|
|
|
|
|
|
(with-syntax
|
|
|
|
|
|
((r r)
|
|
|
|
|
|
(rtd rtd)
|
|
|
|
|
|
((processed ...)
|
|
|
|
|
|
(let lp ((clauses (syntax (clause ...)))
|
|
|
|
|
|
(out '()))
|
|
|
|
|
|
(syntax-case clauses (else)
|
|
|
|
|
|
(()
|
|
|
|
|
|
(reverse! (cons (syntax
|
|
|
|
|
|
(else (error "unhandled record" r)))
|
|
|
|
|
|
out)))
|
|
|
|
|
|
(((else e0 e1 ...))
|
|
|
|
|
|
(reverse! (cons (syntax (else e0 e1 ...)) out)))
|
|
|
|
|
|
(((else e0 e1 ...) . rest)
|
|
|
|
|
|
(syntax-violation 'record-case
|
|
|
|
|
|
"bad else clause placement"
|
|
|
|
|
|
(syntax x)
|
|
|
|
|
|
(syntax (else e0 e1 ...))))
|
|
|
|
|
|
((((<foo> f0 ...) e0 ...) . rest)
|
|
|
|
|
|
(lp (syntax rest)
|
|
|
|
|
|
(cons (process-clause (syntax <foo>)
|
|
|
|
|
|
(syntax (f0 ...))
|
|
|
|
|
|
(syntax (e0 ...)))
|
|
|
|
|
|
out)))))))
|
|
|
|
|
|
(syntax
|
|
|
|
|
|
(let* ((r record)
|
|
|
|
|
|
(rtd (struct-vtable r)))
|
|
|
|
|
|
(cond processed ...)))))))))
|
|
|
|
|
|
|
2009-02-27 12:36:58 +01:00
|
|
|
|
|
|
|
|
|
|
;; Here we take the terrorism to another level. Nasty, but the client
|
|
|
|
|
|
;; code looks good.
|
|
|
|
|
|
|
|
|
|
|
|
(define-macro (transform-record type-and-common record . clauses)
|
|
|
|
|
|
(let ((r (gensym))
|
|
|
|
|
|
(rtd (gensym))
|
|
|
|
|
|
(type-stem (trim-brackets (car type-and-common))))
|
|
|
|
|
|
(define (make-stem s)
|
|
|
|
|
|
(symbol-append type-stem '- s))
|
|
|
|
|
|
(define (further-predicates x record-stem slots)
|
|
|
|
|
|
(define (access slot)
|
|
|
|
|
|
`(,(symbol-append (make-stem record-stem) '- slot) ,x))
|
|
|
|
|
|
(let lp ((in slots) (out '()))
|
|
|
|
|
|
(cond ((null? in) out)
|
|
|
|
|
|
((pair? (car in))
|
|
|
|
|
|
(let ((slot (caar in))
|
|
|
|
|
|
(arg (cadar in)))
|
|
|
|
|
|
(cond ((symbol? arg)
|
|
|
|
|
|
(lp (cdr in) out))
|
|
|
|
|
|
((pair? arg)
|
|
|
|
|
|
(lp (cdr in)
|
|
|
|
|
|
(append (further-predicates (access slot)
|
|
|
|
|
|
(car arg)
|
|
|
|
|
|
(cdr arg))
|
|
|
|
|
|
out)))
|
|
|
|
|
|
(else (lp (cdr in) (cons `(eq? ,(access slot) ',arg)
|
|
|
|
|
|
out))))))
|
|
|
|
|
|
(else (lp (cdr in) out)))))
|
|
|
|
|
|
(define (let-clauses x record-stem slots)
|
|
|
|
|
|
(define (access slot)
|
|
|
|
|
|
`(,(symbol-append (make-stem record-stem) '- slot) ,x))
|
|
|
|
|
|
(let lp ((in slots) (out '()))
|
|
|
|
|
|
(cond ((null? in) out)
|
|
|
|
|
|
((pair? (car in))
|
|
|
|
|
|
(let ((slot (caar in))
|
|
|
|
|
|
(arg (cadar in)))
|
|
|
|
|
|
(cond ((symbol? arg)
|
|
|
|
|
|
(lp (cdr in)
|
|
|
|
|
|
(cons `(,arg ,(access slot)) out)))
|
|
|
|
|
|
((pair? arg)
|
|
|
|
|
|
(lp (cdr in)
|
|
|
|
|
|
(append (let-clauses (access slot)
|
|
|
|
|
|
(car arg)
|
|
|
|
|
|
(cdr arg))
|
|
|
|
|
|
out)))
|
|
|
|
|
|
(else
|
|
|
|
|
|
(lp (cdr in) out)))))
|
|
|
|
|
|
(else
|
|
|
|
|
|
(lp (cdr in)
|
|
|
|
|
|
(cons `(,(car in) ,(access (car in))) out))))))
|
2009-02-27 13:24:38 +01:00
|
|
|
|
(define (transform-expr x)
|
|
|
|
|
|
(cond ((not (pair? x)) x)
|
|
|
|
|
|
((eq? (car x) '->)
|
|
|
|
|
|
(if (= (length x) 2)
|
|
|
|
|
|
(let ((form (cadr x)))
|
|
|
|
|
|
`(,(symbol-append 'make- (make-stem (car form)))
|
|
|
|
|
|
,@(cdr type-and-common)
|
|
|
|
|
|
,@(map (lambda (y)
|
|
|
|
|
|
(if (and (pair? y) (eq? (car y) 'unquote))
|
|
|
|
|
|
(transform-expr (cadr y))
|
|
|
|
|
|
y))
|
|
|
|
|
|
(cdr form))))
|
|
|
|
|
|
(error "bad -> form" x)))
|
|
|
|
|
|
(else (cons (car x) (map transform-expr (cdr x))))))
|
2009-02-27 12:36:58 +01:00
|
|
|
|
(define (process-clause clause)
|
|
|
|
|
|
(if (eq? (car clause) 'else)
|
|
|
|
|
|
clause
|
|
|
|
|
|
(let ((stem (caar clause))
|
|
|
|
|
|
(slots (cdar clause))
|
|
|
|
|
|
(body (cdr clause)))
|
|
|
|
|
|
(let ((record-type (symbol-append '< (make-stem stem) '>)))
|
|
|
|
|
|
`((and (eq? ,rtd ,record-type)
|
|
|
|
|
|
,@(reverse (further-predicates r stem slots)))
|
2009-02-27 13:37:35 +01:00
|
|
|
|
(let ,(reverse (let-clauses r stem slots))
|
2009-02-27 13:24:38 +01:00
|
|
|
|
,@(if (pair? body)
|
|
|
|
|
|
(map transform-expr body)
|
|
|
|
|
|
'((if #f #f)))))))))
|
2009-02-27 12:36:58 +01:00
|
|
|
|
`(let* ((,r ,record)
|
2009-02-27 13:37:35 +01:00
|
|
|
|
(,rtd (struct-vtable ,r))
|
|
|
|
|
|
,@(map (lambda (slot)
|
|
|
|
|
|
`(,slot (,(make-stem slot) ,r)))
|
|
|
|
|
|
(cdr type-and-common)))
|
2009-02-27 12:36:58 +01:00
|
|
|
|
(cond ,@(let ((clauses (map process-clause clauses)))
|
|
|
|
|
|
(if (assq 'else clauses)
|
|
|
|
|
|
clauses
|
|
|
|
|
|
(append clauses `((else (error "unhandled record" ,r))))))))))
|