meta.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. ;;; Guile-GCC --- Guile extension to GCC. -*- coding: utf-8 -*-
  2. ;;; Copyright (C) 2012 Ludovic Courtès
  3. ;;;
  4. ;;; This file is part of Guile-GCC.
  5. ;;;
  6. ;;; Guile-GCC is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; Guile-GCC is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with Guile-GCC. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (meta)
  19. #:use-module (gcc)
  20. #:use-module (gcc cpp)
  21. #:use-module (srfi srfi-1)
  22. #:use-module (srfi srfi-26)
  23. #:use-module (system base compile)
  24. #:use-module (system base message))
  25. ;;;
  26. ;;; Meta-programming with interspersed Scheme code!
  27. ;;;
  28. (define %definitions
  29. ;; Map names to procedures.
  30. (make-hash-table))
  31. (define %user-module
  32. ;; Module where user code is run.
  33. (let ((m (make-fresh-user-module)))
  34. (module-use! m (resolve-interface '(gcc)))
  35. m))
  36. (define (handle-definition cpp)
  37. "Handle the `define' pragma."
  38. (let ((name (peek-token cpp 0))
  39. (arg (peek-token cpp 1)))
  40. (if (= CPP_NAME (token-type name))
  41. (if (= CPP_STRING (token-type arg))
  42. (let* ((loc (token-source-location name))
  43. (name (string->symbol (token-as-text cpp name)))
  44. (str (with-input-from-string (token-as-text cpp arg)
  45. read))
  46. (code (call-with-input-string str
  47. (lambda (port)
  48. (let ((loc (expand-location
  49. (token-source-location arg))))
  50. ;; XXX: This isn't great since `token-as-text'
  51. ;; returns a single string without newlines.
  52. (set-port-filename! port (location-file loc))
  53. (set-port-line! port (1- (location-line loc)))
  54. (set-port-column! port (1- (location-column loc)))
  55. (read port))))))
  56. (inform loc "seen definition of `~a'" name)
  57. (hashq-set! %definitions name
  58. (with-fluids ((*current-warning-prefix* ""))
  59. (compile code
  60. #:env %user-module
  61. #:opts %auto-compilation-options))))
  62. (error-at (token-source-location arg) "expected a code string"))
  63. (error-at (token-source-location name) "expected a name"))))
  64. (define (handle-invocation cpp)
  65. "Handle the `invoke' pragma."
  66. (let ((name (peek-token cpp 0)))
  67. (if (= CPP_NAME (token-type name))
  68. (let* ((proc-name (string->symbol (token-as-text cpp name)))
  69. (proc (hashq-ref %definitions proc-name #f)))
  70. (if (procedure? proc)
  71. (let* ((decl (compose lookup-name get-identifier
  72. (cut token-as-text cpp <>)))
  73. (args (unfold-right (lambda (i)
  74. (let ((t (peek-token cpp i)))
  75. (or (not t)
  76. (= CPP_EOF (token-type t))
  77. (= CPP_PRAGMA_EOL
  78. (token-type t)))))
  79. (lambda (i)
  80. (decl (peek-token cpp i)))
  81. 1+
  82. 1)))
  83. (inform (token-source-location name)
  84. "invoking `~a'" proc-name)
  85. (apply proc args))
  86. (error-at (token-source-location name)
  87. "~a: no procedure by that name" proc-name)))
  88. (error-at (token-source-location name)
  89. "expected a procedure name"))))
  90. (define (register-incredible-pragmas)
  91. (register-c-pragma "guile" "define" handle-definition)
  92. (register-c-pragma "guile" "invoke" handle-invocation))
  93. (register-callback "guile" PLUGIN_PRAGMAS register-incredible-pragmas)