3 ;; Copyright (C) 2014 <Dmitry Bogatov <KAction@gnu.org>>
5 ;; Author: <Dmitry Bogatov <KAction@gnu.org>>
7 ;; This program is free software; you can redistribute it and/or
8 ;; modify it under the terms of the GNU General Public License
9 ;; as published by the Free Software Foundation; either version 3
10 ;; of the License, or (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ;; This module defines functions to operate on syntax objects similar
22 ;; to common function operations saving referential transparency.
25 (define-module (syntax functional))
27 (use-modules (srfi srfi-1))
28 (use-modules (ice-9 match))
29 (use-modules (ice-9 control))
31 (define-syntax sealed (const #'#f))
33 (let ((thales-module (resolve-module '(thales seal) #:ensure #f)))
35 (module-define! (current-module) 'sealed
36 (module-ref thales-module 'sealed))
38 "Module (thales seal) is not available."
39 "GNU Thales based testing is disabled."))))
44 (#'() *!* syntax-error))
46 (define-public (s-car x)
51 (#'(foo bar) *#* (bar))
54 (define-public (s-cdr x)
60 (#'x #'y #'z *!* wrong-number-of-args))
62 (define-public (s-cons x y)
65 (define-public (s-xcons x y)
75 (define-public (s-fold fn init list1 . more)
76 ;; One more line to make explicit in signature
77 ;; that at least one list must be present.
78 (let ((lists (cons list1 more)))
79 (if (any s-null? lists)
81 (let* ((vals (map s-car lists))
82 (tails (map s-cdr lists))
83 (args `(,@vals ,init)))
84 (apply s-fold fn (apply fn args) tails)))))
86 (define-public (s-fold-right fn init list1 . more)
87 ;; One more line to make explicit in signature
88 ;; that at least one list must be present.
89 (let ((lists (cons list1 more)))
90 (if (any s-null? lists)
92 (let ((vals (map s-car lists))
93 (tails (map s-cdr lists)))
94 (apply fn `(,@vals ,(apply s-fold-right fn init tails)))))))
99 (#'foo #'bar *#* (foo bar)))
101 (define-public (s-list . args)
102 (s-fold-right s-cons #'() args))
105 (#'(foo bar) *#* (bar foo)))
107 (define-public (s-reverse x)
108 (s-fold s-cons #'() x))
110 (sealed s-map-in-order
111 (s-car #'((foo bar) (qq quaz)) *#* (foo qq)))
113 (define-public (s-map-in-order f list1 . more)
114 (s-reverse (apply s-fold
116 ((args ... acc) (s-cons (apply f args) acc)))
119 (define-public s-map s-map-in-order)
122 (identifier? #'(foo (bar oo)) *#* (foo)))
124 (define-public (s-filter p list)
128 (let ((filtered-tail (s-filter p #'cdr)))
130 (s-cons #'car filtered-tail)
134 (#f #'foo #'bar *#* (begin foo bar)))
136 (define-public (s-begin . args)
137 (define (significant? x)
138 (and x (not (eq? x *unspecified*))))
139 (s-cons #'begin (s-filter significant? args)))
142 ;; FIXME: Write seals.
143 (define-public (s->if-datum pred? list)
146 (define datum (syntax->datum x))
147 (xcons acc (if (pred? datum) datum x)))