;;; Copyright (C) 2023, 2025, 2025 Igalia, S.L.
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;;    http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

;;; Commentary:
;;;
;;; Prompt tests.
;;;
;;; Code:

(use-modules (srfi srfi-64)
             (test utils))

(test-begin "test-prompts")

(with-additional-imports ((except (hoot control)
                                  call-with-current-continuation
                                  call/cc)
                          (only (hoot numbers) 1+))
 (test-call "42" (lambda (f tag)
                   (call-with-prompt tag
                                     (lambda () (f))
                                     (lambda (k) #f)))
            (lambda () 42)
            "hey")

 (test-call "69" (lambda (f tag)
                   (call-with-prompt tag
                                     (lambda () (1+ (f tag)))
                                     (lambda (k v) v)))
            (lambda (tag) (abort-to-prompt tag 69))
            "hey")

 (test-call "69"
            (lambda (abort-to-prompt tag)
              (call-with-prompt tag
                                (lambda ()
                                  (dynamic-wind values
                                      (lambda () 42)
                                      (lambda () (abort-to-prompt tag 69))))
                                (lambda (k v) v)))
            abort-to-prompt "hey")
 (test-call "69"
            (lambda (abort-to-prompt tag)
              (call-with-prompt tag
                                (lambda ()
                                  (dynamic-wind values
                                      (lambda () (abort-to-prompt tag 42))
                                      (lambda () (abort-to-prompt tag 69))))
                                (lambda (k v) v)))
            abort-to-prompt "hey")

 (test-call "69" (lambda (f tag)
                   (call-with-prompt tag
                                     (lambda () (- (f tag)))
                                     (lambda (k v) (k (- -2 v)))))
            (lambda (tag) (abort-to-prompt tag 67))
            "hey")

 (test-call "4"
            (lambda ()
              (+ 1 (call/cc (lambda (k) (+ 2 (k 3)))))))

 (test-call "5"
            (lambda ()
              (+ 1 (% (+ 1 (call/cc (lambda (k) (+ 2 (k 3)))))))))

 (test-call "(1 2 3 4)"
            (lambda (tag-a tag-b tag-c head)
              (call-with-prompt tag-a
                (lambda ()
                  (call-with-prompt tag-b
                    (lambda ()
                      (call-with-prompt tag-c
                        (lambda ()
                          (list head
                                (abort-to-prompt tag-a)
                                (abort-to-prompt tag-b)
                                (abort-to-prompt tag-c)))
                        (lambda (k) (k 4))))
                    (lambda (k) (k 3))))
                (lambda (k) (k 2))))
            "a" "b" "c" 1)

 ;; Regression test for rewriting unwinds in join continuations in the
 ;; tailify pass.
 (test-call "42"
            (lambda (tag)
              (let lp ((thunk (lambda () (abort-to-prompt tag 42))))
                (call-with-prompt tag
                  thunk
                  (lambda (_k x)
                    (lp (lambda () x))))))
            "hey")

 ;; Regression test for unwind primcalls in a join point.
 (test-call "42"
            (lambda (tag)
              (let loop ((k (lambda () (abort-to-prompt tag 42))))
                (call-with-prompt tag
                  (lambda ()
                    (call-with-prompt tag
                      k
                      (lambda (k val)
                        (abort-to-prompt tag k val))))
                  (lambda (_k new-k val)
                    (loop (lambda () val))))))
            "hey"))

(test-end* "test-prompts")
