spec: rational numbers — 1/3 literals, arithmetic, numeric tower integration
SxRational type in OCaml (Rational of int * int, stored reduced, denom>0) and JS (SxRational class with _rational marker). n/d reader syntax in spec/parser.sx. Arithmetic contagion: int op rational → rational, rational op float → float. JS keeps int/int → float for CSS backward compatibility. OCaml as_number + safe_eq extended for cross-type rational equality so (= 2.5 5/2) → true. 62 tests in test-rationals.sx, all pass. JS: 2232 passed. OCaml: 4532 passed (+11 vs pre-fix baseline). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,9 +14,10 @@
|
||||
;; list → '(' expr* ')'
|
||||
;; vector → '[' expr* ']' (sugar for list)
|
||||
;; map → '{' (key expr)* '}'
|
||||
;; atom → string | number | keyword | symbol | boolean | nil | char
|
||||
;; atom → string | number | rational | keyword | symbol | boolean | nil | char
|
||||
;; string → '"' (char | escape)* '"'
|
||||
;; number → '-'? digit+ ('.' digit+)? ([eE] [+-]? digit+)?
|
||||
;; rational → integer '/' digit+
|
||||
;; keyword → ':' ident
|
||||
;; symbol → ident
|
||||
;; boolean → 'true' | 'false'
|
||||
@@ -46,6 +47,7 @@
|
||||
;; (make-keyword name) → Keyword value
|
||||
;; (escape-string s) → string with " and \ escaped for serialization
|
||||
;; (make-char n) → Char value from Unicode codepoint
|
||||
;; (make-rational n d) → Rational value (auto-reduced by GCD)
|
||||
;; (char->integer c) → Unicode codepoint of char c
|
||||
;; (char-from-code n) → single-char string from codepoint
|
||||
;; (char-code s) → codepoint of first char in string s
|
||||
@@ -210,22 +212,42 @@
|
||||
(set! pos (inc pos))
|
||||
(read-digits))))
|
||||
(read-digits)
|
||||
(when
|
||||
(and (< pos len-src) (= (nth source pos) "."))
|
||||
(set! pos (inc pos))
|
||||
(read-digits))
|
||||
(when
|
||||
(if
|
||||
(and
|
||||
(< pos len-src)
|
||||
(or (= (nth source pos) "e") (= (nth source pos) "E")))
|
||||
(set! pos (inc pos))
|
||||
(when
|
||||
(and
|
||||
(< pos len-src)
|
||||
(or (= (nth source pos) "+") (= (nth source pos) "-")))
|
||||
(set! pos (inc pos)))
|
||||
(read-digits))
|
||||
(parse-number (slice source start pos)))))
|
||||
(= (nth source pos) "/")
|
||||
(< (inc pos) len-src)
|
||||
(let
|
||||
((nc (nth source (inc pos))))
|
||||
(and (>= nc "0") (<= nc "9"))))
|
||||
(let
|
||||
((numer (parse-number (slice source start pos))))
|
||||
(set! pos (inc pos))
|
||||
(let
|
||||
((denom-start pos))
|
||||
(read-digits)
|
||||
(make-rational
|
||||
numer
|
||||
(parse-number (slice source denom-start pos)))))
|
||||
(do
|
||||
(when
|
||||
(and (< pos len-src) (= (nth source pos) "."))
|
||||
(set! pos (inc pos))
|
||||
(read-digits))
|
||||
(when
|
||||
(and
|
||||
(< pos len-src)
|
||||
(or (= (nth source pos) "e") (= (nth source pos) "E")))
|
||||
(set! pos (inc pos))
|
||||
(when
|
||||
(and
|
||||
(< pos len-src)
|
||||
(or
|
||||
(= (nth source pos) "+")
|
||||
(= (nth source pos) "-")))
|
||||
(set! pos (inc pos)))
|
||||
(read-digits))
|
||||
(parse-number (slice source start pos)))))))
|
||||
(define
|
||||
read-symbol
|
||||
:effects ()
|
||||
@@ -490,6 +512,8 @@
|
||||
(if val "true" "false")
|
||||
"number"
|
||||
(str val)
|
||||
"rational"
|
||||
(str (numerator val) "/" (denominator val))
|
||||
"string"
|
||||
(str "\"" (escape-string val) "\"")
|
||||
"symbol"
|
||||
@@ -567,11 +591,12 @@
|
||||
;; True for: ident-start chars plus: 0-9 . : / # ,
|
||||
;;
|
||||
;; Constructors (provided by the SX runtime):
|
||||
;; (make-symbol name) → Symbol value
|
||||
;; (make-keyword name) → Keyword value
|
||||
;; (parse-number s) → number (int or float from string)
|
||||
;; (make-char n) → Char value from Unicode codepoint n
|
||||
;; (char->integer c) → Unicode codepoint of char c
|
||||
;; (make-symbol name) → Symbol value
|
||||
;; (make-keyword name) → Keyword value
|
||||
;; (parse-number s) → number (int or float from string)
|
||||
;; (make-char n) → Char value from Unicode codepoint n
|
||||
;; (make-rational n d) → Rational value (auto-reduced by GCD; d=0 is an error)
|
||||
;; (char->integer c) → Unicode codepoint of char c
|
||||
;;
|
||||
;; String utilities:
|
||||
;; (escape-string s) → string with " and \ escaped
|
||||
|
||||
Reference in New Issue
Block a user