@@ -20,7 +20,7 @@ import {
2020} from "runtime/numbers"
2121import Atoi from "runtime/atoi/parse"
2222import Atof from "runtime/atof/parse"
23- import { newFloat64, newInt64 } from "runtime/dataStructures"
23+ import { newFloat64, newInt64, allocateString } from "runtime/dataStructures"
2424import Tags from "runtime/unsafe/tags"
2525import Exception from "runtime/exception"
2626
@@ -904,6 +904,68 @@ export let parseInt = Atoi.parseInt
904904 */
905905export let parseFloat = Atof.parseFloat
906906
907+ /**
908+ * Parses a string representation of an integer, float, or rational into a `Number`.
909+ * Underscores that appear in the numeric portion of the input are ignored.
910+ *
911+ * @param input: The string to parse
912+ * @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
913+ *
914+ * @since v0.5.5
915+ */
916+ @unsafe
917+ export let parse = input => {
918+ match (parseInt(input, 10)) {
919+ Ok(number) => Ok(number),
920+ Err(msg) =>
921+ match (parseFloat(input)) {
922+ Ok(number) => Ok(number),
923+ Err(_) => {
924+ // Split the input on a `/` and attempt to parse a rational
925+ let (+) = WasmI32.add
926+ let (-) = WasmI32.sub
927+ let (<) = WasmI32.ltU
928+ let (==) = WasmI32.eq
929+
930+ // Search for `/`
931+ let input = WasmI32.fromGrain(input)
932+ let len = WasmI32.load(input, 4n)
933+ let mut slashIdx = -1n
934+ for (let mut i = 0n; i < len; i += 1n) {
935+ if (WasmI32.load8U(input + i, 8n) == 0x2fn) {
936+ slashIdx = i
937+ break
938+ }
939+ }
940+
941+ if (slashIdx == -1n) {
942+ Err(msg)
943+ } else {
944+ let numeratorLen = slashIdx
945+ let denominatorLen = len - slashIdx - 1n
946+
947+ let numerator = allocateString(numeratorLen)
948+ Memory.copy(numerator + 8n, input + 8n, numeratorLen)
949+ let numerator = WasmI32.toGrain(numerator): String
950+
951+ let denominator = allocateString(denominatorLen)
952+ Memory.copy(
953+ denominator + 8n,
954+ input + 8n + slashIdx + 1n,
955+ denominatorLen
956+ )
957+ let denominator = WasmI32.toGrain(denominator): String
958+
959+ match ((parseInt(numerator, 10), parseInt(denominator, 10))) {
960+ (Ok(numerator), Ok(denominator)) => Ok(numerator / denominator),
961+ (Err(msg), _) | (_, Err(msg)) => Err(msg),
962+ }
963+ }
964+ },
965+ },
966+ }
967+ }
968+
907969/**
908970 * Computes how many times pi has to be subtracted to achieve the required bounds for sin.
909971 */
0 commit comments