From b9edb024881947a0da74ac088b7b1f4104de4bbd Mon Sep 17 00:00:00 2001 From: pjuftring Date: Mon, 21 Mar 2016 18:00:57 +0100 Subject: [PATCH 1/2] Add support for unsigned decimals --- ml-proto/spec/int.ml | 14 +++++++++++++- ml-proto/test/int_literals.wast | 6 ++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ml-proto/spec/int.ml b/ml-proto/spec/int.ml index 51a353ca9e..612cd81a10 100644 --- a/ml-proto/spec/int.ml +++ b/ml-proto/spec/int.ml @@ -208,7 +208,19 @@ 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 l = String.length x in + Rep.add + (Rep.mul + (Rep.of_string (String.sub x 0 (l - 1))) + (Rep.of_int 10)) + (Rep.of_string (String.sub x (l - 1) 1)) + in + try Rep.of_string x with + Failure _ -> unsigned_decimal x;; + let to_string = Rep.to_string let of_int = Rep.of_int diff --git a/ml-proto/test/int_literals.wast b/ml-proto/test/int_literals.wast index a60adb439d..34c0ea61a4 100644 --- a/ml-proto/test/int_literals.wast +++ b/ml-proto/test/int_literals.wast @@ -8,6 +8,7 @@ (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 $i64.test (result i64) (return (i64.const 0x0CABBA6E0ba66a6e))) (func $i64.umax (result i64) (return (i64.const 0xffffffffffffffff))) @@ -18,6 +19,7 @@ (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))) (export "i32.test" $i32.test) (export "i32.umax" $i32.umax) @@ -28,6 +30,7 @@ (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 "i64.test" $i64.test) (export "i64.umax" $i64.umax) @@ -38,6 +41,7 @@ (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) ) (assert_return (invoke "i32.test") (i32.const 195940365)) @@ -49,6 +53,7 @@ (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 "i64.test") (i64.const 913028331277281902)) (assert_return (invoke "i64.umax") (i64.const -1)) @@ -59,3 +64,4 @@ (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)) From 6e00599565025cc4326b90fb7a42c3f80a38411b Mon Sep 17 00:00:00 2001 From: pjuftring Date: Tue, 22 Mar 2016 18:16:24 +0100 Subject: [PATCH 2/2] Add overflow-check and allow '+' --- ml-proto/spec/int.ml | 24 ++++++++++++++++++++---- ml-proto/test/int_literals.wast | 6 ++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ml-proto/spec/int.ml b/ml-proto/spec/int.ml index 612cd81a10..18eebf54fe 100644 --- a/ml-proto/spec/int.ml +++ b/ml-proto/spec/int.ml @@ -211,15 +211,31 @@ struct (* 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) + then raise (Failure "int_to_string"); + let firstPart = Rep.of_string (String.sub x 0 (l - 1)) in + 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) + || (firstPart = (div_u Rep.minus_one ten) && secondPart > (rem_u Rep.minus_one ten)) + then raise (Failure "int_to_string"); Rep.add (Rep.mul - (Rep.of_string (String.sub x 0 (l - 1))) + firstPart (Rep.of_int 10)) - (Rep.of_string (String.sub x (l - 1) 1)) + secondPart in - try Rep.of_string x with - Failure _ -> unsigned_decimal x;; + 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 diff --git a/ml-proto/test/int_literals.wast b/ml-proto/test/int_literals.wast index 34c0ea61a4..bc545992dc 100644 --- a/ml-proto/test/int_literals.wast +++ b/ml-proto/test/int_literals.wast @@ -9,6 +9,7 @@ (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))) @@ -20,6 +21,7 @@ (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) @@ -31,6 +33,7 @@ (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) @@ -42,6 +45,7 @@ (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)) @@ -54,6 +58,7 @@ (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)) @@ -65,3 +70,4 @@ (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))