diff options
Diffstat (limited to 'module/language/scheme')
-rw-r--r-- | module/language/scheme/spec.scm | 54 | ||||
-rw-r--r-- | module/language/scheme/translate.scm | 277 |
2 files changed, 331 insertions, 0 deletions
diff --git a/module/language/scheme/spec.scm b/module/language/scheme/spec.scm new file mode 100644 index 000000000..d0281512b --- /dev/null +++ b/module/language/scheme/spec.scm @@ -0,0 +1,54 @@ +;;; Guile Scheme specification + +;; 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 (language scheme spec) + :use-module (language scheme translate) + :use-module (system base language) + :export (scheme)) + +;;; +;;; Reader +;;; + +(read-enable 'positions) + +;;; +;;; Compiler +;;; + +(define (compile port env . opts) + (do ((x (read port) (read port)) + (l '() (cons x l))) + ((eof-object? x) + (apply compile-in (cons 'begin (reverse! l)) env scheme opts)))) + +;;; +;;; Language definition +;;; + +(define-language scheme + :title "Guile Scheme" + :version "0.5" + :reader read + :translator translate + :printer write + :compiler compile + ) diff --git a/module/language/scheme/translate.scm b/module/language/scheme/translate.scm new file mode 100644 index 000000000..5b3585b08 --- /dev/null +++ b/module/language/scheme/translate.scm @@ -0,0 +1,277 @@ +;;; Guile Scheme specification + +;; 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 (language scheme translate) + :use-module (system base language) + :use-module (system il ghil) + :use-module (ice-9 match) + :use-module (ice-9 receive) + :export (translate)) + +(define (translate x e) + (call-with-ghil-environment (make-ghil-mod e) '() + (lambda (env vars) + (make-<ghil-lambda> env #f vars 0 (trans env #f x))))) + + +;;; +;;; Translator +;;; + +(define (trans e l x) + (cond ((pair? x) + (let ((y (macroexpand x))) + (if (eq? x y) + (trans-pair e (or (location x) l) (car x) (cdr x)) + (trans e l y)))) + ((symbol? x) (make-<ghil-ref> e l (ghil-lookup e x))) + (else (make-<ghil-quote> e l x)))) + +(define (trans-pair e l head tail) + (define (trans:x x) (trans e l x)) + (define (trans:pair x) (trans-pair e l (car x) (cdr x))) + (define (trans:body body) (trans-body e l body)) + (define (make:void) (make-<ghil-void> e l)) + (define (bad-syntax) + (syntax-error l (format #f "bad ~A" head) (cons head tail))) + (case head + ;; (void) + ((void) + (match tail + (() (make:void)) + (else (bad-syntax)))) + + ;; (quote OBJ) + ((quote) + (match tail + ((obj) (make-<ghil-quote> e l obj)) + (else (bad-syntax)))) + + ;; (quasiquote OBJ) + ((quasiquote) + (match tail + ((obj) (make-<ghil-quasiquote> e l (trans-quasiquote e l obj))) + (else (bad-syntax)))) + + ((define define-private) + (match tail + ;; (define NAME VAL) + (((? symbol? name) val) + (make-<ghil-define> e l (ghil-lookup e name) (trans:x val))) + + ;; (define (NAME FORMALS...) BODY...) + ((((? symbol? name) . formals) . body) + ;; -> (define NAME (lambda FORMALS BODY...)) + (let ((val (trans:x `(lambda ,formals ,@body)))) + (make-<ghil-define> e l (ghil-lookup e name) val))) + + (else (bad-syntax)))) + + ((set!) + (match tail + ;; (set! NAME VAL) + (((? symbol? name) val) + (make-<ghil-set> e l (ghil-lookup e name) (trans:x val))) + + ;; (set! (NAME ARGS...) VAL) + ((((? symbol? name) . args) val) + ;; -> ((setter NAME) ARGS... VAL) + (trans:pair `((setter ,name) (,@args ,val)))) + + (else (bad-syntax)))) + + ;; (if TEST THEN [ELSE]) + ((if) + (match tail + ((test then) + (make-<ghil-if> e l (trans:x test) (trans:x then) (make:void))) + ((test then else) + (make-<ghil-if> e l (trans:x test) (trans:x then) (trans:x else))) + (else (bad-syntax)))) + + ;; (and EXPS...) + ((and) + (make-<ghil-and> e l (map trans:x tail))) + + ;; (or EXPS...) + ((or) + (make-<ghil-or> e l (map trans:x tail))) + + ;; (begin EXPS...) + ((begin) + (make-<ghil-begin> e l (map trans:x tail))) + + ((let) + (match tail + ;; (let NAME ((SYM VAL) ...) BODY...) + (((? symbol? name) (((? symbol? sym) val) ...) body ...) + ;; -> (letrec ((NAME (lambda (SYM...) BODY...))) (NAME VAL...)) + (trans:pair `(letrec ((,name (lambda ,sym ,@body))) (,name ,@val)))) + + ;; (let () BODY...) + ((() body ...) + ;; NOTE: This differs from `begin' + (make-<ghil-begin> e l (list (trans:body body)))) + + ;; (let ((SYM VAL) ...) BODY...) + (((((? symbol? sym) val) ...) body ...) + (let ((vals (map trans:x val))) + (call-with-ghil-bindings e sym + (lambda (vars) + (make-<ghil-bind> e l vars vals (trans:body body)))))) + + (else (bad-syntax)))) + + ;; (let* ((SYM VAL) ...) BODY...) + ((let*) + (match tail + (((def ...) body ...) + (if (null? def) + (trans:pair `(let () ,@body)) + (trans:pair `(let (,(car def)) (let* ,(cdr def) ,@body))))) + (else (bad-syntax)))) + + ;; (letrec ((SYM VAL) ...) BODY...) + ((letrec) + (match tail + (((((? symbol? sym) val) ...) body ...) + (call-with-ghil-bindings e sym + (lambda (vars) + (let ((vals (map trans:x val))) + (make-<ghil-bind> e l vars vals (trans:body body)))))) + (else (bad-syntax)))) + + ;; (cond (CLAUSE BODY...) ...) + ((cond) + (match tail + (() (make:void)) + ((('else . body)) (trans:body body)) + (((test) . rest) (trans:pair `(or ,test (cond ,@rest)))) + (((test '=> proc) . rest) + (trans:pair `(let ((_t ,test)) (if _t (,proc _t) (cond ,@rest))))) + (((test . body) . rest) + (trans:pair `(if ,test (begin ,@body) (cond ,@rest)))) + (else (bad-syntax)))) + + ;; (case EXP ((KEY...) BODY...) ...) + ((case) + (match tail + ((exp . clauses) + (trans:pair + `(let ((_t ,exp)) + ,(let loop ((ls clauses)) + (cond ((null? ls) '(void)) + ((eq? (caar ls) 'else) `(begin ,@(cdar ls))) + (else `(if (memv _t ',(caar ls)) + (begin ,@(cdar ls)) + ,(loop (cdr ls))))))))) + (else (bad-syntax)))) + + ;; (do ((SYM VAL [UPDATE]) ...) (TEST RESULT...) BODY...) + ((do) + (let () + (define (next s x) (if (pair? x) (car x) s)) + (match tail + ((((sym init . update) ...) (test . result) body ...) + (trans:pair + `(letrec ((_l (lambda ,sym + (if ,test + (let () (void) ,@result) + (let () (void) ,@body + (_l ,@(map next sym update))))))) + (_l ,@init)))) + (else (bad-syntax))))) + + ;; (lambda FORMALS BODY...) + ((lambda) + (match tail + ((formals body ...) + (receive (syms rest) (parse-formals formals) + (call-with-ghil-environment e syms + (lambda (env vars) + (make-<ghil-lambda> env l vars rest (trans-body env l body)))))) + (else (bad-syntax)))) + + ((eval-case) + (let loop ((x tail)) + (match x + (() (make:void)) + ((('else . body)) (trans:pair `(begin ,@body))) + (((((? symbol? key) ...) body ...) rest ...) + (if (memq 'compile key) + (primitive-eval `(begin ,@(copy-tree body)))) + (if (memq 'load-toplevel key) + (trans:pair `(begin ,@body)) + (loop rest))) + (else (bad-syntax))))) + + (else + (make-<ghil-call> e l (trans:x head) (map trans:x tail))))) + +(define (trans-quasiquote e l x) + (cond ((not (pair? x)) x) + ((memq (car x) '(unquote unquote-splicing)) + (let ((l (location x))) + (match (cdr x) + ((obj) + (if (eq? (car x) 'unquote) + (make-<ghil-unquote> e l (trans e l obj)) + (make-<ghil-unquote-splicing> e l (trans e l obj)))) + (else (syntax-error l (format #f "bad ~A" (car x)) x))))) + (else (cons (trans-quasiquote e l (car x)) + (trans-quasiquote e l (cdr x)))))) + +(define (trans-body e l body) + (define (define->binding df) + (match (cdr df) + (((? symbol? name) val) (list name val)) + ((((? symbol? name) . formals) . body) + (list name `(lambda ,formals ,@body))) + (else (syntax-error (location df) "bad define" df)))) + ;; main + (let loop ((ls body) (ds '())) + (cond ((null? ls) (syntax-error l "bad body" body)) + ((and (pair? (car ls)) (eq? (caar ls) 'define)) + (loop (cdr ls) (cons (car ls) ds))) + (else + (if (null? ds) + (trans-pair e l 'begin ls) + (trans-pair e l 'letrec (cons (map define->binding ds) ls))))))) + +(define (parse-formals formals) + (cond + ;; (lambda x ...) + ((symbol? formals) (values (list formals) #t)) + ;; (lambda (x y z) ...) + ((list? formals) (values formals #f)) + ;; (lambda (x y . z) ...) + ((pair? formals) + (let loop ((l formals) (v '())) + (if (pair? l) + (loop (cdr l) (cons (car l) v)) + (values (reverse! (cons l v)) #t)))) + (else (syntax-error (location formals) "bad formals" formals)))) + +(define (location x) + (and (pair? x) + (let ((props (source-properties x))) + (and (not (null? props)) + (cons (assq-ref props 'line) (assq-ref props 'column)))))) |