Skip to content

Add support for unsigned decimals #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion ml-proto/spec/int.ml
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,35 @@ struct
let ge_s x y = x >= y
let ge_u x y = cmp_u x (>=) y

let of_string = Rep.of_string
(* to_string supports unsigned decimals *)
let of_string x =
let unsigned_decimal x =
let ten = Rep.of_int 10 in
let l = String.length x in
(* First overflow-check via String.length *)
if l > (if Rep.bitwidth = 32 then 10 else 20)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this effectively hard-codes that we only instantiate with 32 and 64 bit. It would be more modular to have a generic criterium, e.g. bitwidth / 3.

then raise (Failure "int_to_string");
let firstPart = Rep.of_string (String.sub x 0 (l - 1)) in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: Ocaml prefers snake_casing

let secondPart = Rep.of_string (String.sub x (l - 1) 1) in
(* Negativity-check *)
if firstPart < Rep.zero
then raise (Failure "int_to_string");
(* Second overflow-check *)
if firstPart > (div_u Rep.minus_one ten)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: redundant parens around the div_u (same below)

|| (firstPart = (div_u Rep.minus_one ten) && secondPart > (rem_u Rep.minus_one ten))
then raise (Failure "int_to_string");
Rep.add
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can we put this on one line? Also, you can shorten to Rep.(add (mul ...) ...)

(Rep.mul
firstPart
(Rep.of_int 10))
secondPart
in
let l = String.length x in
(* OCaml doesn't like '+' in front of numbers, while host/lexer.mll allows it *)
let number_sans_plus = if String.get x 0 = '+' then String.sub x 1 (l - 1) else x in
try Rep.of_string number_sans_plus with
Failure _ -> unsigned_decimal number_sans_plus;;

let to_string = Rep.to_string

let of_int = Rep.of_int
Expand Down
12 changes: 12 additions & 0 deletions ml-proto/test/int_literals.wast
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
(func $i32.inc_smin (result i32) (return (i32.add (i32.const -0x80000000) (i32.const 1))))
(func $i32.neg_zero (result i32) (return (i32.const -0x0)))
(func $i32.not_octal (result i32) (return (i32.const 010)))
(func $i32.unsigned_decimal (result i32) (return (i32.const 4294967295)))
(func $i32.plus_sign (result i32) (return (i32.const +42)))

(func $i64.test (result i64) (return (i64.const 0x0CABBA6E0ba66a6e)))
(func $i64.umax (result i64) (return (i64.const 0xffffffffffffffff)))
Expand All @@ -18,6 +20,8 @@
(func $i64.inc_smin (result i64) (return (i64.add (i64.const -0x8000000000000000) (i64.const 1))))
(func $i64.neg_zero (result i64) (return (i64.const -0x0)))
(func $i64.not_octal (result i64) (return (i64.const 010)))
(func $i64.unsigned_decimal (result i64) (return (i64.const 18446744073709551615)))
(func $i64.plus_sign (result i64) (return (i64.const +42)))

(export "i32.test" $i32.test)
(export "i32.umax" $i32.umax)
Expand All @@ -28,6 +32,8 @@
(export "i32.inc_smin" $i32.inc_smin)
(export "i32.neg_zero" $i32.neg_zero)
(export "i32.not_octal" $i32.not_octal)
(export "i32.unsigned_decimal" $i32.unsigned_decimal)
(export "i32.plus_sign" $i32.plus_sign)

(export "i64.test" $i64.test)
(export "i64.umax" $i64.umax)
Expand All @@ -38,6 +44,8 @@
(export "i64.inc_smin" $i64.inc_smin)
(export "i64.neg_zero" $i64.neg_zero)
(export "i64.not_octal" $i64.not_octal)
(export "i64.unsigned_decimal" $i64.unsigned_decimal)
(export "i64.plus_sign" $i64.plus_sign)
)

(assert_return (invoke "i32.test") (i32.const 195940365))
Expand All @@ -49,6 +57,8 @@
(assert_return (invoke "i32.inc_smin") (i32.const -2147483647))
(assert_return (invoke "i32.neg_zero") (i32.const 0))
(assert_return (invoke "i32.not_octal") (i32.const 10))
(assert_return (invoke "i32.unsigned_decimal") (i32.const -1))
(assert_return (invoke "i32.plus_sign") (i32.const 42))

(assert_return (invoke "i64.test") (i64.const 913028331277281902))
(assert_return (invoke "i64.umax") (i64.const -1))
Expand All @@ -59,3 +69,5 @@
(assert_return (invoke "i64.inc_smin") (i64.const -9223372036854775807))
(assert_return (invoke "i64.neg_zero") (i64.const 0))
(assert_return (invoke "i64.not_octal") (i64.const 10))
(assert_return (invoke "i64.unsigned_decimal") (i64.const -1))
(assert_return (invoke "i64.plus_sign") (i64.const 42))