Skip to content

Commit 102f8dd

Browse files
authored
Merge pull request #110 from ocaml-wasm/float_of_string
Stricter float_of_string
2 parents 15bea92 + 48c22c6 commit 102f8dd

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

compiler/tests-jsoo/test_floats.ml

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,38 @@ let%expect_test "log2" =
177177
p 1024.0;
178178
[%expect {| 10.000000 |}]
179179

180+
let print' f = try print (f ()) with e -> print_endline (Printexc.to_string e)
181+
180182
let%expect_test "of_string" =
181183
let x = "0x1.1" in
182-
print (float_of_string x);
184+
print' (fun () -> float_of_string x);
183185
[%expect {| 1.062500 |}];
184186
let x = "0x1.1p-1" in
185-
print (float_of_string x);
186-
[%expect {| 0.531250 |}]
187+
print' (fun () -> float_of_string x);
188+
[%expect {| 0.531250 |}];
189+
let x = " 0x1.1" in
190+
print' (fun () -> float_of_string x);
191+
[%expect {| 1.062500 |}];
192+
let x = " 0x1.1 " in
193+
print' (fun () -> float_of_string x);
194+
[%expect {| Failure("float_of_string") |}];
195+
let x = "0x1.1 p-1" in
196+
print' (fun () -> float_of_string x);
197+
[%expect {| Failure("float_of_string") |}]
198+
199+
let%expect_test "of_string" =
200+
let x = "3.14" in
201+
print' (fun () -> float_of_string x);
202+
[%expect {| 3.140000 |}];
203+
let x = " 3.14" in
204+
print' (fun () -> float_of_string x);
205+
[%expect {| 3.140000 |}];
206+
let x = "3. 14" in
207+
print' (fun () -> float_of_string x);
208+
[%expect {| Failure("float_of_string") |}];
209+
let x = "3.1 4" in
210+
print' (fun () -> float_of_string x);
211+
[%expect {| Failure("float_of_string") |}];
212+
let x = "3.14 " in
213+
print' (fun () -> float_of_string x);
214+
[%expect {| Failure("float_of_string") |}]

runtime/ieee_754.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,13 +567,16 @@ function caml_format_float(fmt, x) {
567567
//Requires: caml_failwith, caml_jsbytes_of_string
568568
function caml_float_of_string(s) {
569569
var res;
570+
var r_float = /^ *[-+]?(?:\d*\.?\d+|\d+\.?\d*)(?:[eE][-+]?\d+)?$/;
570571
s = caml_jsbytes_of_string(s);
571572
res = +s;
572-
if (s.length > 0 && res === res) return res;
573+
//Fast path
574+
if (!Number.isNaN(res) && r_float.test(s)) return res;
573575
s = s.replace(/_/g, "");
574576
res = +s;
575-
if ((s.length > 0 && res === res) || /^[+-]?nan$/i.test(s)) return res;
576-
var m = /^ *([+-]?)0x([0-9a-f]+)\.?([0-9a-f]*)(p([+-]?[0-9]+))?/i.exec(s);
577+
if ((!Number.isNaN(res) && r_float.test(s)) || /^[+-]?nan$/i.test(s))
578+
return res;
579+
var m = /^ *([+-]?)0x([0-9a-f]+)\.?([0-9a-f]*)(p([+-]?[0-9]+))?$/i.exec(s);
577580
// 1 2 3 5
578581
if (m) {
579582
var m3 = m[3].replace(/0+$/, "");

runtime/wasm/float.wat

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,12 @@
483483
(array.new_data $string $float_of_string (i32.const 0) (i32.const 15)))
484484
(f64.const 0))
485485

486+
(func $on_whitespace (param $s (ref $string)) (param $i i32) (result i32)
487+
(local $c i32)
488+
(local.set $c (array.get_u $string (local.get $s) (local.get $i)))
489+
(i32.or (i32.eq (local.get $c) (i32.const 32)) ;; ' '
490+
(i32.le_u (i32.sub (local.get $c) (i32.const 9)) (i32.const 4))))
491+
486492
(func (export "caml_float_of_string") (param (ref eq)) (result (ref eq))
487493
(local $s (ref $string)) (local $len i32) (local $i i32) (local $j i32)
488494
(local $s' (ref $string))
@@ -525,13 +531,15 @@
525531
(loop $skip_spaces
526532
(if (i32.lt_u (local.get $i) (local.get $len))
527533
(then
528-
(if (i32.eq (i32.const 32) ;; ' '
529-
(array.get_u $string (local.get $s) (local.get $i)))
534+
(if (call $on_whitespace (local.get $s) (local.get $i))
530535
(then
531536
(local.set $i (i32.add (local.get $i) (i32.const 1)))
532537
(br $skip_spaces))))))
533538
(block $error
534539
(br_if $error (i32.eq (local.get $i) (local.get $len)))
540+
(br_if $error
541+
(call $on_whitespace
542+
(local.get $s) (i32.sub (local.get $len) (i32.const 1))))
535543
(local.set $c (array.get_u $string (local.get $s) (i32.const 0)))
536544
(if (i32.eq (local.get $c) (i32.const 45)) ;; '-'
537545
(then

0 commit comments

Comments
 (0)