a415c247a384862d4ed8d226c9add079139feeba
[mes.git] / mes / module / mes / fluids.mes
1 ;;; -*-scheme-*-
2
3 ;;; GNU Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
5 ;;;
6 ;;; This file is part of GNU Mes.
7 ;;;
8 ;;; GNU Mes is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
12 ;;;
13 ;;; GNU Mes is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;;; GNU General Public License for more details.
17 ;;;
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;;; Code:
24
25 (mes-use-module (mes scm))
26
27
28 (define (sexp:define e a)
29   (if (atom? (car (cdr e))) (cons (car (cdr e))
30                                   (core:eval (car (cdr (cdr e))) a))
31       (cons (car (car (cdr e)))
32             (core:eval (cons (quote lambda)
33                              (cons (cdr (car (cdr e))) (cdr (cdr e)))) a))))
34
35 (define (f:env:define a+ a)
36   (set-cdr! a+ (cdr a))
37   (set-cdr! a a+)
38   ;;(set-cdr! (assq '*closure* a) a+)
39   )
40
41 (define (env:escape-closure a n)
42   (if (eq? (caar a) '*closure*) (if (= 0 n) a
43                                     (env:escape-closure (cdr a) (- n 1)))
44       (env:escape-closure (cdr a) n)))
45
46 (define-macro (module-define! name value a)
47   `(f:env:define (cons (sexp:define (cons 'define (cons ',name (cons ,value '()))) ,a) '()) (env:escape-closure ,a 1)))
48
49 (define-macro (make-fluid . default)
50   `(begin
51      ,(let ((fluid (symbol-append 'fluid: (gensym)))
52             (module (current-module)))
53         `(begin
54            (module-define! ,fluid
55                            (let ((v ,(and (pair? default) (car default))))
56                              (lambda ( . rest)
57                                (if (null? rest) v
58                                    (set! v (car rest))))) ',module)
59            ',fluid))))
60
61 (define (fluid-ref fluid)
62   (fluid))
63
64 (define (fluid-set! fluid value)
65   (fluid value))
66
67 (define-macro (fluid? fluid)
68   `(begin
69      (and (symbol? ,fluid)
70           (symbol-prefix? 'fluid: ,fluid))))
71
72 (define (with-fluid* fluid value thunk)
73   (let ((v (fluid)))
74     (fluid-set! fluid value)
75     (let ((r (thunk)))
76       (fluid-set! fluid v)
77       r)))
78
79 ;; (define-macro (with-fluids*-macro fluids values thunk)
80 ;;   `(begin
81 ;;      ,@(map (lambda (f v) (list 'set! f v)) fluids values)
82 ;;      (,thunk)))
83
84 ;; (define (with-fluids*-next fluids values thunk)
85 ;;   `(with-fluids*-macro ,fluids ,values ,thunk))
86
87 ;; (define (with-fluids* fluids values thunk)
88 ;;   (primitive-eval (with-fluids*-next fluids values thunk)))
89
90 (define-macro (with-fluids bindings . bodies)
91   (let ((syms (map gensym bindings)))
92     `(let ,(map (lambda (b s) `(,s (,b))) (map car bindings) syms)
93        ,@(map (lambda (o) `(fluid-set! ,(car o) ,(cadr o))) bindings)
94        (let ((r (begin ,@bodies)))
95          ,@(map (lambda (b s) `(fluid-set! ,b ,s)) (map car bindings) syms)
96          r))))
97
98 (define (dynamic-wind in-guard thunk out-guard)
99   (in-guard)
100   (let ((r (thunk)))
101     (out-guard)
102     r))