107 lines
4.3 KiB
Plaintext
107 lines
4.3 KiB
Plaintext
;;;; The evidence for lib/js.ml's integer decisions, run by the survey.
|
|
;;;;
|
|
;;;; JavaScript has one number type and it is a double. Flan has eight integer
|
|
;;;; types and they wrap. Every line below is a place where the two disagree
|
|
;;;; unless the backend normalises, and the survey diffs this program's output
|
|
;;;; against the LLVM build's byte for byte — so a wrong answer here is a
|
|
;;;; DIFFER and not a discussion.
|
|
;;;;
|
|
;;;; Everything goes through a global rather than a literal, for the reason
|
|
;;;; arith.flan gives: a literal operand is exactly what a constant folder
|
|
;;;; removes, and a folded program does not contain the code being tested.
|
|
|
|
(defonce i8hi i8 127)
|
|
(defonce i16hi i16 32767)
|
|
(defonce i32hi i32 2147483647)
|
|
(defonce u8hi u8 255)
|
|
(defonce u16hi u16 65535)
|
|
(defonce u32hi u32 4294967295)
|
|
(defonce i64hi i64 9223372036854775807)
|
|
(defonce u64zero u64 0)
|
|
|
|
(defonce one8 i8 1)
|
|
(defonce one16 i16 1)
|
|
(defonce one32 i32 1)
|
|
(defonce oneu8 u8 1)
|
|
(defonce oneu16 u16 1)
|
|
(defonce oneu32 u32 1)
|
|
(defonce one64 i64 1)
|
|
(defonce oneu64 u64 1)
|
|
|
|
(defonce big32 i32 123456789)
|
|
(defonce big64 i64 1234567890123)
|
|
(defonce three i32 3)
|
|
(defonce three64 i64 3)
|
|
(defonce seven i32 7)
|
|
(defonce negsev i32 -7)
|
|
(defonce shift i32 33)
|
|
(defonce shift8 i8 9)
|
|
(defonce f32one f32 1.0)
|
|
(defonce f32big f32 16777217.0)
|
|
|
|
(defn main [] i32
|
|
;; ── Wrapping at every width ──────────────────────────────────────
|
|
;; The top of the type plus one. A JS number would answer 128, 32768,
|
|
;; 2147483648, 256, 65536, 4294967296 and never wrap at all.
|
|
(println (+ i8hi one8))
|
|
(println (+ i16hi one16))
|
|
(println (+ i32hi one32))
|
|
(println (+ u8hi oneu8))
|
|
(println (+ u16hi oneu16))
|
|
(println (+ u32hi oneu32))
|
|
(println (+ i64hi one64))
|
|
(println (- u64zero oneu64)) ; the top of u64, which no literal spells
|
|
|
|
;; A multiply whose exact product passes 2^53, where a * b in JS is not
|
|
;; exact and Math.imul is. 123456789 * 123456789 = 15241578750190521, which
|
|
;; is above 2^53, so a double rounds it before the truncation can happen.
|
|
(println (* big32 big32))
|
|
(println (* big64 big64))
|
|
|
|
;; ── Truncating division, and the sign of a remainder ─────────────
|
|
;; C truncates toward zero and so does JS's %, but (a / b) | 0 is only the
|
|
;; same answer below 2^31, which is why the backend uses Math.trunc.
|
|
(println (/ seven three))
|
|
(println (/ negsev three))
|
|
(println (% seven three))
|
|
(println (% negsev three))
|
|
(println (/ big64 three64))
|
|
|
|
;; ── Shifts, with the count masked to the operand's width ─────────
|
|
;; 33 is not a legal shift count for a 32-bit type, and the checker only
|
|
;; rejects a *literal* out of range, so this is the computed case emit.ml
|
|
;; masks and this backend has to mask too. JS masks a 32-bit shift itself
|
|
;; and has no 8- or 16-bit shift at all, which is why the mask is written
|
|
;; out rather than relied on.
|
|
(println (<< one32 shift))
|
|
(println (<< one8 shift8))
|
|
(println (>> i32hi one32))
|
|
(println (>> (- (i32 0) i32hi) one32)) ; arithmetic: signed stays signed
|
|
(println (>> u32hi oneu32)) ; logical: unsigned stays unsigned
|
|
(println (<< one64 (i64 65)))
|
|
|
|
;; ── Bitwise over an unsigned 32-bit value ────────────────────────
|
|
;; JS bitwise operators produce a *signed* 32-bit result, so every one of
|
|
;; these needs the >>> 0 back.
|
|
(println (bit-and u32hi u32hi))
|
|
(println (bit-or u32hi oneu32))
|
|
(println (bit-xor u32hi oneu32))
|
|
|
|
;; ── f32 is not a double ──────────────────────────────────────────
|
|
;; 16777217 is the first integer a float cannot hold, so this prints
|
|
;; 16777216 under a real f32 and 16777218 under a double.
|
|
(println (+ f32big f32one))
|
|
(println (/ (f32 1.0) (f32 3.0)))
|
|
(println (/ (f64 1.0) (f64 3.0)))
|
|
|
|
;; ── The conversions, both ways ───────────────────────────────────
|
|
(println (i8 i32hi))
|
|
(println (u8 (- (i32 0) one32)))
|
|
(println (i32 i64hi))
|
|
(println (i64 big32))
|
|
(println (u64 i64hi))
|
|
(println (f64 i64hi))
|
|
(println (i32 (f64 2.9)))
|
|
(println (i32 (f64 -2.9)))
|
|
0)
|