spec: numeric tower primitives — integer?/float? predicates, contagion docs

Add integer? and float? to spec/primitives.sx predicates section.
Update number? doc and body (or-guard for integer? type).
Update / :returns to "float" (always inexact).
Update floor/ceil/truncate :returns to "integer", improve docs.
Update round doc (returns integer at ndigits=0).
Update exact?/inexact?/exact->inexact/inexact->exact docs and returns.
Update +/-/* docs to document float contagion rule.
Fix double-paren :params on truncate/exact?/inexact?/exact->inexact/inexact->exact.
4874 passed, 394 failed (baseline unchanged).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 12:31:01 +00:00
parent e3e767e434
commit 45ec553519

View File

@@ -43,35 +43,35 @@
"+" "+"
:params (&rest (args :as number)) :params (&rest (args :as number))
:returns "number" :returns "number"
:doc "Sum all arguments." :doc "Sum all arguments. Returns integer iff all args are exact integers (float contagion)."
:body (reduce (fn (a b) (native-add a b)) 0 args)) :body (reduce (fn (a b) (native-add a b)) 0 args))
(define-primitive (define-primitive
"-" "-"
:params ((a :as number) &rest (b :as number)) :params ((a :as number) &rest (b :as number))
:returns "number" :returns "number"
:doc "Subtract. Unary: negate. Binary: a - b." :doc "Subtract. Unary: negate. Binary: a - b. Float contagion: returns integer iff all args are integers."
:body (if (empty? b) (native-neg a) (native-sub a (first b)))) :body (if (empty? b) (native-neg a) (native-sub a (first b))))
(define-primitive (define-primitive
"*" "*"
:params (&rest (args :as number)) :params (&rest (args :as number))
:returns "number" :returns "number"
:doc "Multiply all arguments." :doc "Multiply all arguments. Float contagion: integer result iff all args are exact integers."
:body (reduce (fn (a b) (native-mul a b)) 1 args)) :body (reduce (fn (a b) (native-mul a b)) 1 args))
(define-primitive (define-primitive
"/" "/"
:params ((a :as number) (b :as number)) :params ((a :as number) (b :as number))
:returns "number" :returns "float"
:doc "Divide a by b." :doc "Divide a by b. Always returns inexact float."
:body (native-div a b)) :body (native-div a b))
(define-primitive (define-primitive
"mod" "mod"
:params ((a :as number) (b :as number)) :params ((a :as number) (b :as number))
:returns "number" :returns "number"
:doc "Modulo a % b." :doc "Modulo a % b. Returns integer iff both args are integers."
:body (native-mod a b)) :body (native-mod a b))
(define-primitive (define-primitive
@@ -108,26 +108,26 @@
(define-primitive (define-primitive
"floor" "floor"
:params ((x :as number)) :params ((x :as number))
:returns "number" :returns "integer"
:doc "Floor to integer.") :doc "Floor toward negative infinity — returns exact integer.")
(define-primitive (define-primitive
"ceil" "ceil"
:params ((x :as number)) :params ((x :as number))
:returns "number" :returns "integer"
:doc "Ceiling to integer.") :doc "Ceiling toward positive infinity — returns exact integer.")
(define-primitive (define-primitive
"round" "round"
:params ((x :as number) &rest (ndigits :as number)) :params ((x :as number) &rest (ndigits :as number))
:returns "number" :returns "number"
:doc "Round to ndigits decimal places (default 0).") :doc "Round to ndigits decimal places (default 0). Returns integer when ndigits is 0.")
(define-primitive (define-primitive
"truncate" "truncate"
:params (((x :as number))) :params ((x :as number))
:returns "number" :returns "integer"
:doc "Truncate toward zero.") :doc "Truncate toward zero — returns exact integer.")
(define-primitive (define-primitive
"remainder" "remainder"
@@ -143,30 +143,30 @@
(define-primitive (define-primitive
"exact?" "exact?"
:params (((x :as number))) :params ((x :as number))
:returns "boolean" :returns "boolean"
:doc "True if x is exact (integer-valued).") :doc "True if x is an exact integer (not an inexact float).")
(define-primitive (define-primitive
"inexact?" "inexact?"
:params (((x :as number))) :params ((x :as number))
:returns "boolean" :returns "boolean"
:doc "True if x is inexact (non-integer).") :doc "True if x is an inexact float (not an exact integer).")
;; -------------------------------------------------------------------------- ;; --------------------------------------------------------------------------
;; Core — Comparison ;; Core — Comparison
;; -------------------------------------------------------------------------- ;; --------------------------------------------------------------------------
(define-primitive (define-primitive
"exact->inexact" "exact->inexact"
:params (((x :as number))) :params ((x :as number))
:returns "number" :returns "float"
:doc "Convert exact to inexact (identity for float tower).") :doc "Convert exact integer to inexact float. Floats pass through unchanged.")
(define-primitive (define-primitive
"inexact->exact" "inexact->exact"
:params (((x :as number))) :params ((x :as number))
:returns "number" :returns "integer"
:doc "Convert inexact to nearest exact integer.") :doc "Convert inexact float to nearest exact integer (truncates). Integers pass through unchanged.")
(define-primitive (define-primitive
"make-vector" "make-vector"
@@ -374,8 +374,20 @@
"number?" "number?"
:params (x) :params (x)
:returns "boolean" :returns "boolean"
:doc "True if x is a number (int or float)." :doc "True if x is any number — exact integer or inexact float."
:body (= (type-of x) "number")) :body (or (= (type-of x) "number") (integer? x)))
(define-primitive
"integer?"
:params (x)
:returns "boolean"
:doc "True if x is an exact integer, or a float with no fractional part (e.g. 1.0).")
(define-primitive
"float?"
:params (x)
:returns "boolean"
:doc "True if x is an inexact float (Number type). Does not match exact integers.")
(define-primitive (define-primitive
"string?" "string?"