123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- ;;; Guile-GCC --- Guile extension to GCC. -*- coding: utf-8 -*-
- ;;; Copyright (C) 2012 Ludovic Courtès
- ;;;
- ;;; This file is part of Guile-GCC.
- ;;;
- ;;; Guile-GCC 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 3 of the License, or (at
- ;;; your option) any later version.
- ;;;
- ;;; Guile-GCC 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 Guile-GCC. If not, see <http://www.gnu.org/licenses/>.
- (define-module (meta)
- #:use-module (gcc)
- #:use-module (gcc cpp)
- #:use-module (srfi srfi-1)
- #:use-module (srfi srfi-26)
- #:use-module (system base compile)
- #:use-module (system base message))
- ;;;
- ;;; Meta-programming with interspersed Scheme code!
- ;;;
- (define %definitions
- ;; Map names to procedures.
- (make-hash-table))
- (define %user-module
- ;; Module where user code is run.
- (let ((m (make-fresh-user-module)))
- (module-use! m (resolve-interface '(gcc)))
- m))
- (define (handle-definition cpp)
- "Handle the `define' pragma."
- (let ((name (peek-token cpp 0))
- (arg (peek-token cpp 1)))
- (if (= CPP_NAME (token-type name))
- (if (= CPP_STRING (token-type arg))
- (let* ((loc (token-source-location name))
- (name (string->symbol (token-as-text cpp name)))
- (str (with-input-from-string (token-as-text cpp arg)
- read))
- (code (call-with-input-string str
- (lambda (port)
- (let ((loc (expand-location
- (token-source-location arg))))
- ;; XXX: This isn't great since `token-as-text'
- ;; returns a single string without newlines.
- (set-port-filename! port (location-file loc))
- (set-port-line! port (1- (location-line loc)))
- (set-port-column! port (1- (location-column loc)))
- (read port))))))
- (inform loc "seen definition of `~a'" name)
- (hashq-set! %definitions name
- (with-fluids ((*current-warning-prefix* ""))
- (compile code
- #:env %user-module
- #:opts %auto-compilation-options))))
- (error-at (token-source-location arg) "expected a code string"))
- (error-at (token-source-location name) "expected a name"))))
- (define (handle-invocation cpp)
- "Handle the `invoke' pragma."
- (let ((name (peek-token cpp 0)))
- (if (= CPP_NAME (token-type name))
- (let* ((proc-name (string->symbol (token-as-text cpp name)))
- (proc (hashq-ref %definitions proc-name #f)))
- (if (procedure? proc)
- (let* ((decl (compose lookup-name get-identifier
- (cut token-as-text cpp <>)))
- (args (unfold-right (lambda (i)
- (let ((t (peek-token cpp i)))
- (or (not t)
- (= CPP_EOF (token-type t))
- (= CPP_PRAGMA_EOL
- (token-type t)))))
- (lambda (i)
- (decl (peek-token cpp i)))
- 1+
- 1)))
- (inform (token-source-location name)
- "invoking `~a'" proc-name)
- (apply proc args))
- (error-at (token-source-location name)
- "~a: no procedure by that name" proc-name)))
- (error-at (token-source-location name)
- "expected a procedure name"))))
- (define (register-incredible-pragmas)
- (register-c-pragma "guile" "define" handle-definition)
- (register-c-pragma "guile" "invoke" handle-invocation))
- (register-callback "guile" PLUGIN_PRAGMAS register-incredible-pragmas)
|