Skip to content

Commit ba50f92

Browse files
committed
OxCaml: small integers
1 parent 8a3ddbd commit ba50f92

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

runtime/js/ints.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,63 @@ function caml_int_of_string(s) {
132132
return res | 0;
133133
}
134134

135+
//Provides: caml_parse_small_int
136+
//Requires: caml_ml_string_length, caml_string_unsafe_get
137+
//Requires: caml_parse_sign_and_base, caml_parse_digit, caml_failwith
138+
//Version: >= 5.2, < 5.3
139+
//OxCaml
140+
function caml_parse_small_int(err_msg, width, s) {
141+
var r = caml_parse_sign_and_base(s);
142+
var i = r[0],
143+
sign = r[1],
144+
base = r[2],
145+
signedness = r[3];
146+
var len = caml_ml_string_length(s);
147+
var threshold = (1 << width) - 1;
148+
var c = i < len ? caml_string_unsafe_get(s, i) : 0;
149+
var d = caml_parse_digit(c);
150+
if (d < 0 || d >= base) caml_failwith(err_msg);
151+
var res = d;
152+
for (i++; i < len; i++) {
153+
c = caml_string_unsafe_get(s, i);
154+
if (c === 95) continue;
155+
d = caml_parse_digit(c);
156+
if (d < 0 || d >= base) break;
157+
res = base * res + d;
158+
if (res > threshold) caml_failwith(err_msg);
159+
}
160+
if (i !== len) caml_failwith(err_msg);
161+
// For base different from 10, we expect an unsigned representation,
162+
// hence any value of 'res' (less than 'threshold') is acceptable.
163+
// But we have to convert the result back to a signed integer.
164+
if (signedness) {
165+
threshold = 1 << (width - 1);
166+
if (sign >= 0) {
167+
if (res >= threshold) caml_failwith(err_msg);
168+
} else {
169+
if (res > threshold) caml_failwith(err_msg);
170+
}
171+
}
172+
res = sign * res;
173+
return ((res << (32 - width)) >> 32 - width);
174+
}
175+
176+
//Provides: caml_int8_of_string (const)
177+
//Requires: caml_parse_small_int
178+
//Version: >= 5.2, < 5.3
179+
//OxCaml
180+
function caml_int8_of_string(s) {
181+
return caml_parse_small_int("Int8.of_string", 8, s);
182+
}
183+
184+
//Provides: caml_int16_of_string (const)
185+
//Requires: caml_parse_small_int
186+
//Version: >= 5.2, < 5.3
187+
//OxCaml
188+
function caml_int16_of_string(s) {
189+
return caml_parse_small_int("Int16.of_string", 16, s);
190+
}
191+
135192
//Provides: caml_mul const
136193
//Alias: caml_int32_mul
137194
//Alias: caml_nativeint_mul

runtime/wasm/ints.wat

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,24 @@
165165
(call $parse_int
166166
(local.get $v) (i32.const 31) (global.get $INT_ERRMSG))))
167167

168+
(@string $INT8_ERRMSG "Int8.of_string")
169+
170+
(func (export "caml_int8_of_string")
171+
(param $v (ref eq)) (result (ref eq))
172+
(ref.i31
173+
(i32.extend8_s
174+
(call $parse_int
175+
(local.get $v) (i32.const 8) (global.get $INT8_ERRMSG)))))
176+
177+
(@string $INT16_ERRMSG "Int16.of_string")
178+
179+
(func (export "caml_int16_of_string")
180+
(param $v (ref eq)) (result (ref eq))
181+
(ref.i31
182+
(i32.extend16_s
183+
(call $parse_int
184+
(local.get $v) (i32.const 16) (global.get $INT16_ERRMSG)))))
185+
168186
(func (export "caml_bswap16") (param (ref eq)) (result (ref eq))
169187
(local $x i32)
170188
(local.set $x (i31.get_s (ref.cast (ref i31) (local.get 0))))

0 commit comments

Comments
 (0)