129 lines
7.5 KiB
Racket
129 lines
7.5 KiB
Racket
#lang racket/base
|
|
|
|
(require racket/string
|
|
"../main.rkt"
|
|
"jsmaker-executors.rkt"
|
|
"jsmaker-test-framework.rkt")
|
|
|
|
(define direct-and (js/expression (and (> x 10) (< x 15))))
|
|
(unless (string=? direct-and "((x > 10) && (x < 15))")
|
|
(error 'jsmaker-regression "expected direct && generation, got: ~a" direct-and))
|
|
|
|
(define direct-or (js/expression (or (< x 10) (> x 20))))
|
|
(unless (string=? direct-or "((x < 10) || (x > 20))")
|
|
(error 'jsmaker-regression "expected direct || generation, got: ~a" direct-or))
|
|
|
|
(define direct-chain (js/expression (< x y 10)))
|
|
(unless (string=? direct-chain "((x < y) && (y < 10))")
|
|
(error 'jsmaker-regression "expected direct pairwise comparison, got: ~a" direct-chain))
|
|
|
|
(define effectful-chain (js/expression (< x (f y) 10)))
|
|
(unless (regexp-match? #rx"__cmp" effectful-chain)
|
|
(error 'jsmaker-regression "effectful chained comparison should use temporaries, got: ~a" effectful-chain))
|
|
|
|
(define simple-let-star
|
|
(js (let* ((x 10)
|
|
(y (+ x x)))
|
|
(return y))))
|
|
|
|
(define with-handlers-rest-lambda-program
|
|
(js (with-handlers ([exn? (λ args (displayln args))])
|
|
(/ 10 0))))
|
|
(unless (regexp-match? #rx"\\(function\\(\\.\\.\\.args\\)" with-handlers-rest-lambda-program)
|
|
(error 'jsmaker-regression
|
|
"with-handlers rest-lambda handler should be parenthesized in callee position, got: ~a"
|
|
with-handlers-rest-lambda-program))
|
|
(unless (not (regexp-match? #rx"catch[^{]*\\{\\n function\\(" with-handlers-rest-lambda-program))
|
|
(error 'jsmaker-regression
|
|
"with-handlers emitted a function declaration in statement position, got: ~a"
|
|
with-handlers-rest-lambda-program))
|
|
(unless (regexp-match? #rx"let x = 10;" simple-let-star)
|
|
(error 'jsmaker-regression "simple let* should emit direct let for x, got: ~a" simple-let-star))
|
|
(unless (regexp-match? #rx"let y = .*x.*x.*;" simple-let-star)
|
|
(error 'jsmaker-regression "simple let* should emit direct dependent let for y, got: ~a" simple-let-star))
|
|
(unless (not (regexp-match? #rx"__let_star_value" simple-let-star))
|
|
(error 'jsmaker-regression "simple let* should not use tempvars, got: ~a" simple-let-star))
|
|
|
|
(define tests
|
|
(list
|
|
(js-expression-test 'if-zero (js/expression (if 0 1 2)) "1")
|
|
(js-expression-test 'if-false (js/expression (if #f 1 2)) "2")
|
|
(js-expression-test 'and-false (js/expression (and #f 5)) "false")
|
|
(js-expression-test 'and-zero (js/expression (and 0 5)) "5")
|
|
(js-expression-test 'or-empty-string (js/expression (or "" 5)) "\"\"")
|
|
(js-expression-test 'direct-and-boolean (format "((x) => ~a)(12)" direct-and) "true")
|
|
(js-expression-test 'direct-or-boolean (format "((x) => ~a)(5)" direct-or) "true")
|
|
(js-expression-test 'chain-lt (js/expression (< 1 2 3)) "true")
|
|
(js-expression-test 'chain-lt-false (js/expression (< 1 3 2)) "false")
|
|
(js-expression-test 'let-expr (js/expression (let ([x 2] [y 3]) (+ x y))) "5")
|
|
(js-expression-test 'let-star-sequential-binding (js/expression (let* ([x 10] [y (+ x x)]) y)) "20")
|
|
(js-expression-test 'let-star-dependent-shadowing (js/expression (let ([x 4]) (let* ([x x] [y x]) (+ x y)))) "8")
|
|
(js-expression-test 'named-let (js/expression (let loop ([i 0] [s 0]) (if (< i 5) (loop (+ i 1) (+ s i)) s))) "10")
|
|
(js-expression-test 'for-list (js/expression (for/list ([x (in-range 5)] #:when (odd? x)) (* x x))) "[1,9]")
|
|
(js-expression-test 'for-fold (js/expression (for/fold ([s 0]) ([x (in-list (list 1 2 3))]) (+ x s))) "6")
|
|
(js-expression-test 'map-filter (js/expression (filter (lambda (x) (> x 2)) (map (lambda (x) (+ x 1)) (list 1 2 3)))) "[3,4]")
|
|
(js-expression-test 'hash-ref (js/expression (hash-ref (hash 'a 1 'b 2) 'b)) "2")
|
|
(js-expression-test 'compile-time-eval-var
|
|
(let ((x 10)
|
|
(y 20))
|
|
(js/expression (let ((a (eval (* x y))))
|
|
(+ a a))))
|
|
"400")
|
|
(js-expression-test 'compile-time-eval-number
|
|
(js/expression (eval (+ 1 2)))
|
|
"3")
|
|
(js-expression-test 'compile-time-eval-data
|
|
(js/expression (array (eval (list 1 2 3))
|
|
(eval (string-append "a" "b"))))
|
|
"[[1,2,3],\"ab\"]")
|
|
(let ([x 10]
|
|
[y 20])
|
|
(js-expression-test 'runtime-eval-lexical-let
|
|
(js/expression (let ([a (eval (* x y))]) (* a a)))
|
|
"40000"))
|
|
(js-expression-test 'substring (js/expression (substring "abcdef" 1 4)) "\"bcd\"")
|
|
(js-expression-test 'equal-list (js/expression (equal? (list 1 2) (list 1 2))) "true")
|
|
(js-expression-test 'cond-test-only (js/expression (cond [0] [else 2])) "0")
|
|
(js-expression-test 'cond-arrow (js/expression (cond [(+ 1 2) => (lambda (x) (+ x 10))] [else 0])) "13")
|
|
(js-expression-test 'cond-false-arrow (js/expression (cond [#f => (lambda (x) (+ x 10))] [else 7])) "7")
|
|
(js-expression-test 'rest-lambda (js/expression ((lambda xs (length xs)) 1 2 3)) "3")
|
|
(js-expression-test 'dotted-lambda (js/expression ((lambda (a . xs) (+ a (length xs))) 10 20 30)) "12")
|
|
(js-expression-test 'let-values-one (js/expression (let-values ([(x) 5]) (+ x 1))) "6")
|
|
(js-expression-test 'let-values-many (js/expression (let-values ([(x y) (values 2 3)]) (+ x y))) "5")
|
|
(js-expression-test 'let-tdz (js/expression (let ([x 4]) (let ([x x]) (+ x 1)))) "5")
|
|
(js-expression-test 'let-star-tdz (js/expression (let ([x 4]) (let* ([x x] [y x]) (+ x y)))) "8")
|
|
(js-expression-test 'division-normal
|
|
(js/expression (/ 20 2 2))
|
|
"5")
|
|
(js-expression-test 'with-handlers-division-by-zero
|
|
(js/expression (with-handlers ([exn? (lambda args (string-append "caught:" (exn-message (car args))))])
|
|
(/ 10 0)))
|
|
"\"caught:division by zero\"")
|
|
(js-expression-test 'with-handlers-generic-exn
|
|
(js/expression (with-handlers ([exn? (lambda (e) (string-append "caught:" (exn-message e)))])
|
|
(error "boom")))
|
|
"\"caught:boom\"")
|
|
(js-expression-test 'with-handlers-no-error
|
|
(js/expression (with-handlers ([exn? (lambda (e) 99)])
|
|
(+ 20 22)))
|
|
"42")
|
|
(js-expression-test 'gregor-prefix-date-string
|
|
(js/expression (date->string (foo:date 2026 5 25)))
|
|
"\"2026-05-25\"")
|
|
(js-expression-test 'gregor-prefix-time-string
|
|
(js/expression (time->string (bar:time 8 9 10)))
|
|
"\"08:09:10\"")
|
|
(js-expression-test 'gregor-prefix-moment-fields
|
|
(js/expression (list (baz:->year (baz:parse-moment "2026-05-25T08:09:10" "yyyy-MM-dd'T'HH:mm:ss"))
|
|
(baz:->month (baz:parse-moment "2026-05-25T08:09:10"))
|
|
(baz:->day (baz:parse-moment "2026-05-25T08:09:10"))))
|
|
"[2026,5,25]")
|
|
(js-expression-test 'gregor-js-date-conversion
|
|
(js/expression (list (q:->year (js-date->datetime (q:->js-date (q:date 2026 5 25))))
|
|
(q:date? (q:date 2026 5 25))
|
|
(q:moment? (q:moment 2026 5 25 8 9 10))))
|
|
"[2026,true,true]")))
|
|
|
|
(define engine (find-js-engine))
|
|
(run-jsmaker-regression 'jsmaker-core-regression tests "/tmp/jsmaker-core-regression.js" #:engine engine)
|