;;; Guile High Intermediate Language ;; 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 il ghil) :use-syntax (system base syntax) :use-module (ice-9 match) :use-module (ice-9 regex) :export ( ? -1 -2 ? -1 -2 -3 ? -1 -2 -3 ? -1 -2 -3 ? -1 -2 -3 ? -1 -2 -3 ? -1 -2 -3 -4 ? -1 -2 -3 -4 ? -1 -2 -3 -4 -5 ? -1 -2 -3 ? -1 -2 -3 ? -1 -2 -3 ? -1 -2 -3 -4 -5 ? -1 -2 -3 -4 -5 ? -1 -2 -3 -4 ? -1 -2 -3 -4 )) ;;; ;;; Parse tree ;;; (define-type (| ;; Objects ( env loc) ( env loc obj) ( env loc exp) ( env loc exp) ( env loc exp) ;; Variables ( env loc var) ( env loc var val) ( env loc var val) ;; Controls ( env loc test then else) ( env loc exps) ( env loc exps) ( env loc exps) ( env loc vars vals body) ( env loc vars rest body) ( env loc proc args) ( env loc inline args))) (define-public ghil-env %slot-1) (define-public ghil-loc %slot-2) ;;; ;;; Procedures ;;; (define *core-primitives* '(@void @quote @define @set! @if @begin @let @letrec @lambda)) (define *macro-module* (resolve-module '(system il macros))) (define-public (ghil-primitive-macro? x) (and (module-defined? *macro-module* x) (procedure? (module-ref *macro-module* x)))) (define (ghil-macro-expander x) (module-ref *macro-module* x)) (define (ghil-primitive? x) (or (memq x *core-primitives*) (ghil-primitive-macro? x))) ;;; ;;; Variables ;;; (define-record ( env name kind (type #f) (value #f) (index #f))) (define-public (make-ghil-var env name kind) ( :env env :name name :kind kind)) ;;; ;;; Modules ;;; (define-record ( module (table '()) (imports '()))) (define-public (make-ghil-mod module) ( :module module)) ;;; ;;; Environments ;;; (define-record ( mod parent (table '()) (variables '()))) (define-public (make-ghil-env e) (match e (($ ) ( :mod e :parent e)) (($ m) ( :mod m :parent e)))) (define (ghil-env-toplevel? e) (eq? e.mod e.parent)) (define (ghil-env-ref env sym) (assq-ref env.table sym)) (define-public (ghil-env-add! env var) (set! env.table (acons var.name var env.table)) (set! env.variables (cons var env.variables))) (define (ghil-env-remove! env var) (set! env.table (assq-remove! env.table var.name))) ;;; ;;; Public interface ;;; (define-public (ghil-lookup env sym) (or (ghil-env-ref env sym) (let loop ((e env.parent)) (cond ((? e) (or (assq-ref e.table sym) (let ((var (make-ghil-var #f sym 'module))) (set! e.table (acons sym var e.table)) var))) ((ghil-env-ref e sym) => (lambda (var) (set! var.kind 'external) var)) (else (loop e.parent)))))) (define-public (call-with-ghil-environment e syms func) (let* ((e (make-ghil-env e)) (vars (map (lambda (s) (let ((v (make-ghil-var e s 'argument))) (ghil-env-add! e v) v)) syms))) (func e vars))) (define-public (call-with-ghil-bindings e syms func) (let* ((vars (map (lambda (s) (let ((v (make-ghil-var e s 'local))) (ghil-env-add! e v) v)) syms)) (ret (func vars))) (for-each (lambda (v) (ghil-env-remove! e v)) vars) ret)) ;;; ;;; Parser ;;; ;;; (define-public (parse-ghil x e) ;;; (parse `(@lambda () ,x) (make-ghil-mod e))) ;;; ;;; (define (parse x e) ;;; (cond ((pair? x) (parse-pair x e)) ;;; ((symbol? x) ;;; (let ((str (symbol->string x))) ;;; (case (string-ref str 0) ;;; ((#\@) (error "Invalid use of IL primitive" x)) ;;; ((#\:) (let ((sym (string->symbol (substring str 1)))) ;;; ( (symbol->keyword sym)))) ;;; (else ( e (ghil-lookup e x)))))) ;;; (else ( x)))) ;;; ;;; (define (map-parse x e) ;;; (map (lambda (x) (parse x e)) x)) ;;; ;;; (define (parse-pair x e) ;;; (let ((head (car x)) (tail (cdr x))) ;;; (if (and (symbol? head) (eq? (string-ref (symbol->string head) 0) #\@)) ;;; (if (ghil-primitive-macro? head) ;;; (parse (apply (ghil-macro-expander head) tail) e) ;;; (parse-primitive head tail e)) ;;; ( e (parse head e) (map-parse tail e))))) ;;; ;;; (define (parse-primitive prim args e) ;;; (case prim ;;; ;; (@ IDENTIFIER) ;;; ((@) ;;; (match args ;;; (() ;;; ( e (make-ghil-var '@ '@ 'module))) ;;; ((identifier) ;;; (receive (module name) (identifier-split identifier) ;;; ( e (make-ghil-var module name 'module)))))) ;;; ;;; ;; (@@ OP ARGS...) ;;; ((@@) ;;; (match args ;;; ((op . args) ;;; ( op (map-parse args e))))) ;;; ;;; ;; (@void) ;;; ((@void) ;;; (match args ;;; (() ()))) ;;; ;;; ;; (@quote OBJ) ;;; ((@quote) ;;; (match args ;;; ((obj) ;;; ( obj)))) ;;; ;;; ;; (@define NAME VAL) ;;; ((@define) ;;; (match args ;;; ((name val) ;;; (let ((v (ghil-lookup e name))) ;;; ( e v (parse val e)))))) ;;; ;;; ;; (@set! NAME VAL) ;;; ((@set!) ;;; (match args ;;; ((name val) ;;; (let ((v (ghil-lookup e name))) ;;; ( e v (parse val e)))))) ;;; ;;; ;; (@if TEST THEN [ELSE]) ;;; ((@if) ;;; (match args ;;; ((test then) ;;; ( (parse test e) (parse then e) ())) ;;; ((test then else) ;;; ( (parse test e) (parse then e) (parse else e))))) ;;; ;;; ;; (@begin BODY...) ;;; ((@begin) ;;; (parse-body args e)) ;;; ;;; ;; (@let ((SYM INIT)...) BODY...) ;;; ((@let) ;;; (match args ;;; ((((sym init) ...) body ...) ;;; (let* ((vals (map-parse init e)) ;;; (vars (map (lambda (s) ;;; (let ((v (make-ghil-var e s 'local))) ;;; (ghil-env-add! e v) v)) ;;; sym)) ;;; (body (parse-body body e))) ;;; (for-each (lambda (v) (ghil-env-remove! e v)) vars) ;;; ( e vars vals body))))) ;;; ;;; ;; (@letrec ((SYM INIT)...) BODY...) ;;; ((@letrec) ;;; (match args ;;; ((((sym init) ...) body ...) ;;; (let* ((vars (map (lambda (s) ;;; (let ((v (make-ghil-var e s 'local))) ;;; (ghil-env-add! e v) v)) ;;; sym)) ;;; (vals (map-parse init e)) ;;; (body (parse-body body e))) ;;; (for-each (lambda (v) (ghil-env-remove! e v)) vars) ;;; ( e vars vals body))))) ;;; ;;; ;; (@lambda FORMALS BODY...) ;;; ((@lambda) ;;; (match args ;;; ((formals . body) ;;; (receive (syms rest) (parse-formals formals) ;;; (let* ((e (make-ghil-env e)) ;;; (vars (map (lambda (s) ;;; (let ((v (make-ghil-var e s 'argument))) ;;; (ghil-env-add! e v) v)) ;;; syms))) ;;; ( e vars rest (parse-body body e))))))) ;;; ;;; ;; (@eval-case CLAUSE...) ;;; ((@eval-case) ;;; (let loop ((clauses args)) ;;; (cond ((null? clauses) ()) ;;; ((or (eq? (caar clauses) '@else) ;;; (and (memq 'load-toplevel (caar clauses)) ;;; (ghil-env-toplevel? e))) ;;; (parse-body (cdar clauses) e)) ;;; (else ;;; (loop (cdr clauses)))))) ;;; ;;; (else (error "Unknown primitive:" prim)))) ;;; ;;; (define (parse-body x e) ;;; ( (map-parse x e))) ;;; ;;; (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 (error "Invalid formals:" formals)))) ;;; ;;; (define (identifier-split identifier) ;;; (let ((m (string-match "::([^:]*)$" (symbol->string identifier)))) ;;; (if m ;;; (values (string->symbol (match:prefix m)) ;;; (string->symbol (match:substring m 1))) ;;; (values #f identifier))))