* 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.
120 lines
4.5 KiB
Scheme
120 lines
4.5 KiB
Scheme
;;; Guile VM specific syntaxes and utilities
|
||
|
||
;; Copyright (C) 2001 Free Software Foundation, Inc
|
||
|
||
;; This program is free software; you can redistribute it and/or modify
|
||
;; it under the terms of the GNU General Public License as published by
|
||
;; the Free Software Foundation; either version 2, or (at your option)
|
||
;; any later version
|
||
;;
|
||
;; This program 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 General Public License for more details
|
||
;;
|
||
;; You should have received a copy of the GNU General Public License
|
||
;; along with this program; see the file COPYING. If not, write to
|
||
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||
;; Boston, MA 02111-1307, USA
|
||
|
||
;;; Code:
|
||
|
||
(define-module (system base syntax)
|
||
#:export (%compute-initargs)
|
||
#:export-syntax (define-type define-record record-case))
|
||
|
||
|
||
;;;
|
||
;;; Type
|
||
;;;
|
||
|
||
(define-macro (define-type name . rest)
|
||
(let ((name (if (pair? name) (car name) name))
|
||
(opts (if (pair? name) (cdr name) '())))
|
||
(let ((printer (kw-arg-ref opts #:printer)))
|
||
`(begin ,@(map (lambda (def) `(define-record ,def
|
||
,@(if printer (list printer) '())))
|
||
rest)))))
|
||
|
||
|
||
;;;
|
||
;;; Record
|
||
;;;
|
||
|
||
(define (symbol-trim-both sym pred)
|
||
(string->symbol (string-trim-both (symbol->string sym) pred)))
|
||
|
||
(define-macro (define-record def . printer)
|
||
(let* ((name (car def)) (slots (cdr def))
|
||
(slot-names (map (lambda (slot) (if (pair? slot) (car slot) slot))
|
||
slots))
|
||
(stem (symbol-trim-both name (list->char-set '(#\< #\>)))))
|
||
`(begin
|
||
(define ,name (make-record-type ,(symbol->string name) ',slot-names
|
||
,@printer))
|
||
(define ,(symbol-append 'make- stem)
|
||
(let ((slots (list ,@(map (lambda (slot)
|
||
(if (pair? slot)
|
||
`(cons ',(car slot) ,(cadr slot))
|
||
`',slot))
|
||
slots)))
|
||
(constructor (record-constructor ,name)))
|
||
(lambda args
|
||
(apply constructor (%compute-initargs args slots)))))
|
||
(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))))
|
||
|
||
(define (%compute-initargs args slots)
|
||
(define (finish out)
|
||
(map (lambda (slot)
|
||
(let ((name (if (pair? slot) (car slot) slot)))
|
||
(cond ((assq name out) => cdr)
|
||
((pair? slot) (cdr slot))
|
||
(else (error "unbound slot" args slots name)))))
|
||
slots))
|
||
(let lp ((in args) (positional slots) (out '()))
|
||
(cond
|
||
((null? in)
|
||
(finish out))
|
||
((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)
|
||
(let ((slot (car positional)))
|
||
(acons (if (pair? slot) (car slot) slot)
|
||
(car in)
|
||
out)))))))
|
||
|
||
(define-macro (record-case record . clauses)
|
||
(let ((r (gensym)))
|
||
(define (process-clause clause)
|
||
(if (eq? (car clause) 'else)
|
||
clause
|
||
(let ((record-type (caar clause))
|
||
(slots (cdar clause))
|
||
(body (cdr clause)))
|
||
`(((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)))))
|
||
`(let ((,r ,record))
|
||
(cond ,@(let ((clauses (map process-clause clauses)))
|
||
(if (assq 'else clauses)
|
||
clauses
|
||
(append clauses `((else (error "unhandled record" ,r))))))))))
|