;;; Guile Low Intermediate Language ;; Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc. ;;;; 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 ;;; Code: (define-module (language glil) #:use-module (system base syntax) #:use-module (system base pmatch) #:use-module ((srfi srfi-1) #:select (fold)) #:export ( make-glil-program glil-program? glil-program-meta glil-program-body make-glil-std-prelude glil-std-prelude? glil-std-prelude-nreq glil-std-prelude-nlocs glil-std-prelude-else-label make-glil-opt-prelude glil-opt-prelude? glil-opt-prelude-nreq glil-opt-prelude-nopt glil-opt-prelude-rest glil-opt-prelude-nlocs glil-opt-prelude-else-label make-glil-kw-prelude glil-kw-prelude? glil-kw-prelude-nreq glil-kw-prelude-nopt glil-kw-prelude-kw glil-kw-prelude-allow-other-keys? glil-kw-prelude-rest glil-kw-prelude-nlocs glil-kw-prelude-else-label make-glil-bind glil-bind? glil-bind-vars make-glil-mv-bind glil-mv-bind? glil-mv-bind-vars glil-mv-bind-rest make-glil-unbind glil-unbind? make-glil-source glil-source? glil-source-props make-glil-void glil-void? make-glil-const glil-const? glil-const-obj make-glil-lexical glil-lexical? glil-lexical-local? glil-lexical-boxed? glil-lexical-op glil-lexical-index make-glil-toplevel glil-toplevel? glil-toplevel-op glil-toplevel-name make-glil-module glil-module? glil-module-op glil-module-mod glil-module-name glil-module-public? make-glil-label glil-label? glil-label-label make-glil-branch glil-branch? glil-branch-inst glil-branch-label make-glil-call glil-call? glil-call-inst glil-call-nargs make-glil-mv-call glil-mv-call? glil-mv-call-nargs glil-mv-call-ra make-glil-prompt glil-prompt? glil-prompt-label glil-prompt-escape-only? parse-glil unparse-glil)) (define (print-glil x port) (format port "#" (unparse-glil x))) (define-type ( #:printer print-glil) ;; Meta operations ( meta body) ( nreq nlocs else-label) ( nreq nopt rest nlocs else-label) ( nreq nopt rest kw allow-other-keys? nlocs else-label) ( vars) ( vars rest) () ( props) ;; Objects () ( obj) ;; Variables ( local? boxed? op index) ( op name) ( op mod name public?) ;; Controls ( label) ( inst label) ( inst nargs) ( nargs ra) ( label escape-only?)) (define (parse-glil x) (pmatch x ((program ,meta . ,body) (make-glil-program meta (map parse-glil body))) ((std-prelude ,nreq ,nlocs ,else-label) (make-glil-std-prelude nreq nlocs else-label)) ((opt-prelude ,nreq ,nopt ,rest ,nlocs ,else-label) (make-glil-opt-prelude nreq nopt rest nlocs else-label)) ((kw-prelude ,nreq ,nopt ,rest ,kw ,allow-other-keys? ,nlocs ,else-label) (make-glil-kw-prelude nreq nopt rest kw allow-other-keys? nlocs else-label)) ((bind . ,vars) (make-glil-bind vars)) ((mv-bind ,vars ,rest) (make-glil-mv-bind vars rest)) ((unbind) (make-glil-unbind)) ((source ,props) (make-glil-source props)) ((void) (make-glil-void)) ((const ,obj) (make-glil-const obj)) ((lexical ,local? ,boxed? ,op ,index) (make-glil-lexical local? boxed? op index)) ((toplevel ,op ,name) (make-glil-toplevel op name)) ((module public ,op ,mod ,name) (make-glil-module op mod name #t)) ((module private ,op ,mod ,name) (make-glil-module op mod name #f)) ((label ,label) (make-glil-label label)) ((branch ,inst ,label) (make-glil-branch inst label)) ((call ,inst ,nargs) (make-glil-call inst nargs)) ((mv-call ,nargs ,ra) (make-glil-mv-call nargs ra)) ((prompt ,label ,escape-only?) (make-glil-prompt label escape-only?)) (else (error "invalid glil" x)))) (define (unparse-glil glil) (record-case glil ;; meta (( meta body) `(program ,meta ,@(map unparse-glil body))) (( nreq nlocs else-label) `(std-prelude ,nreq ,nlocs ,else-label)) (( nreq nopt rest nlocs else-label) `(opt-prelude ,nreq ,nopt ,rest ,nlocs ,else-label)) (( nreq nopt rest kw allow-other-keys? nlocs else-label) `(kw-prelude ,nreq ,nopt ,rest ,kw ,allow-other-keys? ,nlocs ,else-label)) (( vars) `(bind ,@vars)) (( vars rest) `(mv-bind ,vars ,rest)) (() `(unbind)) (( props) `(source ,props)) ;; constants (() `(void)) (( obj) `(const ,obj)) ;; variables (( local? boxed? op index) `(lexical ,local? ,boxed? ,op ,index)) (( op name) `(toplevel ,op ,name)) (( op mod name public?) `(module ,(if public? 'public 'private) ,op ,mod ,name)) ;; controls (( label) `(label ,label)) (( inst label) `(branch ,inst ,label)) (( inst nargs) `(call ,inst ,nargs)) (( nargs ra) `(mv-call ,nargs ,ra)) (( label escape-only?) `(prompt ,label escape-only?))))