Make test.sx self-executing: evaluators run it directly, no codegen
test.sx now defines deftest/defsuite as macros. Any host that provides 5 platform functions (try-call, report-pass, report-fail, push-suite, pop-suite) can evaluate the file directly — no bootstrap compilation step needed for JS. - Added defmacro for deftest (wraps body in thunk, catches via try-call) - Added defmacro for defsuite (push/pop suite context stack) - Created run.js: sx-browser.js evaluates test.sx directly (81/81 pass) - Created run.py: Python evaluator evaluates test.sx directly (81/81 pass) - Deleted bootstrap_test_js.py and generated test_sx_spec.js - Updated testing docs page to reflect self-executing architecture Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,58 +1,43 @@
|
||||
;; ==========================================================================
|
||||
;; test.sx — Self-hosting SX test framework
|
||||
;;
|
||||
;; Defines a minimal test framework in SX that bootstraps to every host.
|
||||
;; Tests are written in SX and verify SX semantics — the language tests
|
||||
;; itself. Bootstrap compilers emit native test runners from this spec.
|
||||
;;
|
||||
;; The framework uses only primitives already in primitives.sx:
|
||||
;; assert, equal?, type-of, str, list, len, error
|
||||
;;
|
||||
;; Usage:
|
||||
;; (defsuite "Suite name"
|
||||
;; (deftest "test name" (assert (equal? 1 1)))
|
||||
;; (deftest "another" (assert (= (+ 1 2) 3))))
|
||||
;; Defines a minimal test framework in SX that tests SX — the language
|
||||
;; proves its own correctness. The framework is self-executing: any host
|
||||
;; that provides 5 platform functions can evaluate this file directly.
|
||||
;;
|
||||
;; Platform functions required:
|
||||
;; (test-report suite-name results) → platform-specific output
|
||||
;; results is a list of {:name "..." :passed bool :error "..."|nil}
|
||||
;; try-call (thunk) → {:ok true} | {:ok false :error "msg"}
|
||||
;; report-pass (name) → platform-specific pass output
|
||||
;; report-fail (name error) → platform-specific fail output
|
||||
;; push-suite (name) → push suite name onto context stack
|
||||
;; pop-suite () → pop suite name from context stack
|
||||
;;
|
||||
;; Bootstrap compilers read this file and:
|
||||
;; 1. Emit the test runner infrastructure
|
||||
;; 2. Emit each test suite as native test cases
|
||||
;; 3. Wire up to the platform test framework (pytest, Jest, etc.)
|
||||
;; Usage:
|
||||
;; ;; Host injects platform functions into env, then:
|
||||
;; (eval-file "test.sx" env)
|
||||
;;
|
||||
;; The same test.sx runs on every host — Python, JavaScript, etc.
|
||||
;; ==========================================================================
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; 1. Test framework forms
|
||||
;; 1. Test framework macros
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; deftest and defsuite are declarative — bootstrap compilers parse them
|
||||
;; and emit native test functions. They are NOT runtime macros.
|
||||
;;
|
||||
;; (deftest "name" body ...)
|
||||
;; Declares a test case. Body expressions are evaluated sequentially.
|
||||
;; The test passes if no assertion fails (no error is raised).
|
||||
;; Uses `assert` primitive for assertions.
|
||||
;;
|
||||
;; (defsuite "name" test ...)
|
||||
;; Groups tests into a named suite. Suites can be nested.
|
||||
;; deftest and defsuite are macros that make test.sx directly executable.
|
||||
;; The host provides try-call (error catching), reporting, and suite
|
||||
;; context — everything else is pure SX.
|
||||
|
||||
;; (define-special-form "deftest"
|
||||
;; :syntax (deftest name body ...)
|
||||
;; :doc "Declare a test case. Name is a string literal.
|
||||
;; Body expressions are evaluated in a fresh env extended from
|
||||
;; the suite env. Test passes if all assertions succeed."
|
||||
;; :example '(deftest "addition" (assert (= (+ 1 2) 3))))
|
||||
;;
|
||||
;; (define-special-form "defsuite"
|
||||
;; :syntax (defsuite name tests ...)
|
||||
;; :doc "Declare a test suite. Name is a string. Tests are deftest forms
|
||||
;; or nested defsuite forms."
|
||||
;; :example '(defsuite "arithmetic"
|
||||
;; (deftest "add" (assert (= (+ 1 2) 3)))
|
||||
;; (deftest "sub" (assert (= (- 5 3) 2)))))
|
||||
(defmacro deftest (name &rest body)
|
||||
`(let ((result (try-call (fn () ,@body))))
|
||||
(if (get result "ok")
|
||||
(report-pass ,name)
|
||||
(report-fail ,name (get result "error")))))
|
||||
|
||||
(defmacro defsuite (name &rest items)
|
||||
`(do (push-suite ,name)
|
||||
,@items
|
||||
(pop-suite)))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -113,9 +98,9 @@
|
||||
|
||||
(define assert-throws
|
||||
(fn (thunk)
|
||||
;; Platform must implement try-catch or equivalent.
|
||||
;; Bootstrap compilers emit this as a native try/catch block.
|
||||
(platform-assert-throws thunk)))
|
||||
(let ((result (try-call thunk)))
|
||||
(assert (not (get result "ok"))
|
||||
"Expected an error to be thrown but none was"))))
|
||||
|
||||
|
||||
;; ==========================================================================
|
||||
|
||||
Reference in New Issue
Block a user