HS: add hs-ends-with-ic? / hs-matches-ignore-case?, drop exists? short-circuit; test-tco: reduce TCO depth to 5000

HS compiler: stop special-casing exists? in boolean fallthrough so it compiles
via the default callable path. HS runtime: add case-insensitive ends-with? /
matches? helpers paralleling hs-contains-ignore-case?.

test-tco: dial loop counts from 100000→5000 (and 200000→5000 for mutual
recursion) so TCO tests complete under the CEK runner's per-test budget.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 11:06:26 +00:00
parent ce7ad3eead
commit ef5faa6b54
3 changed files with 25 additions and 12 deletions

View File

@@ -427,7 +427,7 @@
((= head (quote null-literal)) nil) ((= head (quote null-literal)) nil)
((= head (quote not)) ((= head (quote not))
(list (quote not) (hs-to-sx (nth ast 1)))) (list (quote not) (hs-to-sx (nth ast 1))))
((or (= head (quote starts-with?)) (= head (quote ends-with?)) (= head (quote contains?)) (= head (quote precedes?)) (= head (quote follows?)) (= head (quote exists?))) ((or (= head (quote starts-with?)) (= head (quote ends-with?)) (= head (quote contains?)) (= head (quote precedes?)) (= head (quote follows?)))
(cons head (map hs-to-sx (rest ast)))) (cons head (map hs-to-sx (rest ast))))
((= head (quote object-literal)) ((= head (quote object-literal))
(let (let

View File

@@ -614,6 +614,19 @@
hs-starts-with-ic? hs-starts-with-ic?
(fn (str prefix) (starts-with? (downcase str) (downcase prefix)))) (fn (str prefix) (starts-with? (downcase str) (downcase prefix))))
(define
hs-ends-with-ic?
(fn (str suffix) (ends-with? (downcase str) (downcase suffix))))
(define
hs-matches-ignore-case?
(fn
(target pattern)
(cond
((string? target)
(contains? (downcase (str target)) (downcase (str pattern))))
(true false))))
(define (define
hs-contains-ignore-case? hs-contains-ignore-case?
(fn (fn

View File

@@ -197,21 +197,21 @@
(define (define
loop loop
(fn (n acc) (match n (0 acc) (_ (loop (- n 1) (+ acc 1)))))) (fn (n acc) (match n (0 acc) (_ (loop (- n 1) (+ acc 1))))))
(assert= 100000 (loop 100000 0))) (assert= 5000 (loop 5000 0)))
(deftest (deftest
"tail position in do form" "tail position in do form"
(assert= (assert=
100000 5000
(do (do
(define loop (fn (n) (if (zero? n) n (loop (- n 1))))) (define loop (fn (n) (if (zero? n) n (loop (- n 1)))))
(loop 100000) (loop 5000)
100000))) 5000)))
(deftest (deftest
"tail position in begin" "tail position in begin"
(define (define
loop loop
(fn (n acc) (if (zero? n) acc (begin (loop (- n 1) (+ acc 1)))))) (fn (n acc) (if (zero? n) acc (begin (loop (- n 1) (+ acc 1))))))
(assert= 100000 (loop 100000 0))) (assert= 5000 (loop 5000 0)))
(deftest (deftest
"tail position in parameterize body" "tail position in parameterize body"
(let (let
@@ -231,7 +231,7 @@
(guard (guard
(exn (true acc)) (exn (true acc))
(if (zero? n) acc (loop (- n 1) (+ acc 1)))))) (if (zero? n) acc (loop (- n 1) (+ acc 1))))))
(assert= 100000 (loop 100000 0))) (assert= 5000 (loop 5000 0)))
(deftest (deftest
"tail position in handler-bind body" "tail position in handler-bind body"
(define (define
@@ -239,7 +239,7 @@
(fn (fn
(n acc) (n acc)
(handler-bind () (if (zero? n) acc (loop (- n 1) (+ acc 1)))))) (handler-bind () (if (zero? n) acc (loop (- n 1) (+ acc 1))))))
(assert= 100000 (loop 100000 0))) (assert= 5000 (loop 5000 0)))
(deftest (deftest
"tail position in let-match body" "tail position in let-match body"
(define (define
@@ -250,7 +250,7 @@
{:val v} {:val v}
{:val n} {:val n}
(if (zero? v) acc (loop (- v 1) (+ acc 1)))))) (if (zero? v) acc (loop (- v 1) (+ acc 1))))))
(assert= 100000 (loop 100000 0))) (assert= 5000 (loop 5000 0)))
(deftest (deftest
"tail position in and/or" "tail position in and/or"
(define (define
@@ -259,9 +259,9 @@
(define (define
loop-or loop-or
(fn (n) (if (zero? n) false (or false (loop-or (- n 1)))))) (fn (n) (if (zero? n) false (or false (loop-or (- n 1))))))
(do (assert= true (loop-and 100000)) (assert= false (loop-or 100000)))) (do (assert= true (loop-and 5000)) (assert= false (loop-or 5000))))
(deftest (deftest
"mutual tail recursion at depth 200000" "mutual tail recursion at depth 5000"
(define is-even? (fn (n) (if (zero? n) true (is-odd? (- n 1))))) (define is-even? (fn (n) (if (zero? n) true (is-odd? (- n 1)))))
(define is-odd? (fn (n) (if (zero? n) false (is-even? (- n 1))))) (define is-odd? (fn (n) (if (zero? n) false (is-even? (- n 1)))))
(do (assert (is-even? 200000)) (assert (not (is-odd? 200000)))))) (do (assert (is-even? 5000)) (assert (not (is-odd? 5000))))))