#! /bin/sh
# -*-scheme-*-
exec ${MES-bin/mes} --no-auto-compile -L ${0%/*} -L module -C module -e '(tests closure)' -s "$0" "$@"
!#

;;; -*-scheme-*-

;;; GNU Mes --- Maxwell Equations of Software
;;; Copyright © 2016,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Mes.
;;;
;;; GNU Mes 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.
;;;
;;; GNU Mes 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 GNU Mes.  If not, see <http://www.gnu.org/licenses/>.

(define-module (tests closure)
  #:use-module (mes mes-0)
  #:use-module (mes test))

(mes-use-module (mes test))

(pass-if "first dummy" #t)
(pass-if-not "second dummy" #f)

(define b 0)
(define x (lambda () b))
(define (x) b)
(pass-if-equal "closure" 0 (x))
(display "===>") (display (x)) (newline)
(define (c b)
  (x))
(pass-if "closure 2" (seq? (c 1) 0))

(define (x)
  (define b 1)
  (define (y) b)
  (set! b 0)
  (list b
        (let ((b 2))
          (y))))

(pass-if "closure 3" (sequal? (x) '(0 0)))

(pass-if "closure 4 "
  (seq? (let ()
          (let ((count (let ((counter 0))
                         (lambda ()
                           counter))))
            (count)))
        0))

(pass-if "closure 5 "
         (seq?
          (let ()
            (define name? 2)
            (define (foo)
              (define name? 0)
              (lambda () name?))
            ((foo)))
          0))

(pass-if "closure 6 "
         (seq?
          (let ()
            (define foo
              (lambda ()
                (define name? symbol?)
                (lambda ()
                  (name? 'boo))))
            ((foo)))
               #t))

(define-macro (foo? q+q)
  #t)
(foo? 'cons)
(pass-if-equal "closure 7" #f (defined? 'q+q))

(let ((x 0))
  (pass-if-equal "closure 8" #f (not (defined? 'x))))

((lambda ()
   (define sc-expand #f)
   ((lambda (g38)
      (set! sc-expand
            ((lambda ()
               (lambda ()
                 (list g38))))))
    "noexpand")
   (pass-if "closure 9" (sc-expand))))

(pass-if "closure is procedure"
             (procedure? (lambda () #t)))

(pass-if-not "closure is not a pair"
             (pair? (lambda () #t)))

(define shared
  (let ((x 0))
    (lambda () (set! x (+ 1 x)) x)))
(define-macro (share)
  (list 'begin
        (list 'shared)))

(pass-if-equal "shared variable macro access"
    2
  (begin
    (share)
    (shared)))

(result 'report)
