mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-18 17:31:29 +00:00
Refactor number and string utils out of builtins, fixes #608
This commit is contained in:
@ -1,11 +1,3 @@
|
||||
// @ts-ignore: decorator
|
||||
@builtin @inline
|
||||
export const NaN: f64 = 0 / 0;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@builtin @inline
|
||||
export const Infinity: f64 = 1 / 0;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@builtin
|
||||
export declare function isInteger<T>(value?: T): bool;
|
||||
@ -58,20 +50,6 @@ export declare function isConstant(expression: void): bool;
|
||||
@builtin
|
||||
export declare function isManaged<T>(value?: T): bool;
|
||||
|
||||
export function isNaN<T extends number>(value: T): bool {
|
||||
if (!isFloat<T>()) {
|
||||
if (!isInteger<T>()) ERROR("numeric type expected");
|
||||
}
|
||||
return value != value;
|
||||
}
|
||||
|
||||
export function isFinite<T extends number>(value: T): bool {
|
||||
if (!isFloat<T>()) {
|
||||
if (!isInteger<T>()) ERROR("numeric type expected");
|
||||
}
|
||||
return value - value == 0;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@builtin
|
||||
export declare function clz<T>(value: T): T;
|
||||
|
@ -1,5 +1,26 @@
|
||||
import { itoa, dtoa } from "./util/number";
|
||||
import { isNaN as builtin_isNaN, isFinite as builtin_isFinite } from "./builtins";
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@builtin @inline
|
||||
export const NaN: f64 = 0 / 0;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@builtin @inline
|
||||
export const Infinity: f64 = 1 / 0;
|
||||
|
||||
export function isNaN<T extends number>(value: T): bool {
|
||||
if (!isFloat<T>()) {
|
||||
if (!isInteger<T>()) ERROR("numeric type expected");
|
||||
}
|
||||
return value != value;
|
||||
}
|
||||
|
||||
export function isFinite<T extends number>(value: T): bool {
|
||||
if (!isFloat<T>()) {
|
||||
if (!isInteger<T>()) ERROR("numeric type expected");
|
||||
}
|
||||
return value - value == 0;
|
||||
}
|
||||
|
||||
@sealed @unmanaged
|
||||
export abstract class I8 {
|
||||
@ -331,11 +352,11 @@ export abstract class F64 {
|
||||
static readonly NaN: f64 = NaN;
|
||||
|
||||
static isNaN(value: f64): bool {
|
||||
return builtin_isNaN<f64>(value);
|
||||
return isNaN<f64>(value);
|
||||
}
|
||||
|
||||
static isFinite(value: f64): bool {
|
||||
return builtin_isFinite<f64>(value);
|
||||
return isFinite<f64>(value);
|
||||
}
|
||||
|
||||
static isSafeInteger(value: f64): bool {
|
||||
@ -343,7 +364,7 @@ export abstract class F64 {
|
||||
}
|
||||
|
||||
static isInteger(value: f64): bool {
|
||||
return builtin_isFinite<f64>(value) && trunc<f64>(value) == value;
|
||||
return isFinite<f64>(value) && trunc<f64>(value) == value;
|
||||
}
|
||||
|
||||
static parseInt(value: string, radix: i32 = 0): f64 {
|
||||
@ -354,7 +375,7 @@ export abstract class F64 {
|
||||
return parseFloat(value);
|
||||
}
|
||||
|
||||
toString(this: f64): String {
|
||||
toString(this: f64, radix: i32 = 0): String {
|
||||
// TODO: radix
|
||||
return dtoa(this);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/// <reference path="./rt/index.d.ts" />
|
||||
|
||||
import { BLOCK, BLOCK_OVERHEAD, BLOCK_MAXSIZE } from "./rt/common";
|
||||
import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./util/string";
|
||||
import { compareImpl, strtol, strtod, isWhiteSpaceOrLineTerminator } from "./util/string";
|
||||
import { E_INVALIDLENGTH } from "./util/error";
|
||||
import { ArrayBufferView } from "./arraybuffer";
|
||||
import { idof } from "./builtins";
|
||||
@ -522,72 +522,10 @@ import { idof } from "./builtins";
|
||||
// @ts-ignore: nolib
|
||||
export type string = String;
|
||||
|
||||
export function parseInt(str: String, radix: i32 = 0): f64 {
|
||||
// @ts-ignore: string <-> String
|
||||
return parse<f64>(str, radix);
|
||||
export function parseInt(str: string, radix: i32 = 0): f64 {
|
||||
return strtol<f64>(str, radix);
|
||||
}
|
||||
|
||||
export function parseI32(str: String, radix: i32 = 0): i32 {
|
||||
// @ts-ignore: string <-> String
|
||||
return parse<i32>(str, radix);
|
||||
}
|
||||
|
||||
export function parseI64(str: String, radix: i32 = 0): i64 {
|
||||
// @ts-ignore: string <-> String
|
||||
return parse<i64>(str, radix);
|
||||
}
|
||||
|
||||
// FIXME: naive implementation
|
||||
export function parseFloat(str: String): f64 {
|
||||
var len: i32 = str.length;
|
||||
if (!len) return NaN;
|
||||
|
||||
var ptr = changetype<usize>(str);
|
||||
var code = <i32>load<u16>(ptr);
|
||||
|
||||
// determine sign
|
||||
var sign: f64;
|
||||
// trim white spaces
|
||||
while (isWhiteSpaceOrLineTerminator(code)) {
|
||||
code = <i32>load<u16>(ptr += 2);
|
||||
--len;
|
||||
}
|
||||
if (code == CharCode.MINUS) {
|
||||
if (!--len) return NaN;
|
||||
code = <i32>load<u16>(ptr += 2);
|
||||
sign = -1;
|
||||
} else if (code == CharCode.PLUS) {
|
||||
if (!--len) return NaN;
|
||||
code = <i32>load<u16>(ptr += 2);
|
||||
sign = 1;
|
||||
} else {
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
// calculate value
|
||||
var num: f64 = 0;
|
||||
while (len--) {
|
||||
code = <i32>load<u16>(ptr);
|
||||
if (code == CharCode.DOT) {
|
||||
ptr += 2;
|
||||
let fac: f64 = 0.1; // precision :(
|
||||
while (len--) {
|
||||
code = <i32>load<u16>(ptr);
|
||||
if (code == CharCode.E || code == CharCode.e) {
|
||||
assert(false); // TODO
|
||||
}
|
||||
code -= CharCode._0;
|
||||
if (<u32>code > 9) break;
|
||||
num += <f64>code * fac;
|
||||
fac *= 0.1;
|
||||
ptr += 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
code -= CharCode._0;
|
||||
if (<u32>code >= 10) break;
|
||||
num = (num * 10) + code;
|
||||
ptr += 2;
|
||||
}
|
||||
return sign * num;
|
||||
export function parseFloat(str: string): f64 {
|
||||
return strtod(str);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ export function isWhiteSpaceOrLineTerminator(c: i32): bool {
|
||||
}
|
||||
|
||||
/** Parses a string to an integer (usually), using the specified radix. */
|
||||
export function parse<T>(str: string, radix: i32 = 0): T {
|
||||
export function strtol<T>(str: string, radix: i32 = 0): T {
|
||||
var len: i32 = str.length;
|
||||
// @ts-ignore: cast
|
||||
if (!len) return <T>NaN;
|
||||
@ -139,3 +139,58 @@ export function parse<T>(str: string, radix: i32 = 0): T {
|
||||
// @ts-ignore: type
|
||||
return sign * num;
|
||||
}
|
||||
|
||||
// FIXME: naive implementation
|
||||
export function strtod(str: string): f64 {
|
||||
var len: i32 = str.length;
|
||||
if (!len) return NaN;
|
||||
|
||||
var ptr = changetype<usize>(str);
|
||||
var code = <i32>load<u16>(ptr);
|
||||
|
||||
// determine sign
|
||||
var sign: f64;
|
||||
// trim white spaces
|
||||
while (isWhiteSpaceOrLineTerminator(code)) {
|
||||
code = <i32>load<u16>(ptr += 2);
|
||||
--len;
|
||||
}
|
||||
if (code == CharCode.MINUS) {
|
||||
if (!--len) return NaN;
|
||||
code = <i32>load<u16>(ptr += 2);
|
||||
sign = -1;
|
||||
} else if (code == CharCode.PLUS) {
|
||||
if (!--len) return NaN;
|
||||
code = <i32>load<u16>(ptr += 2);
|
||||
sign = 1;
|
||||
} else {
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
// calculate value
|
||||
var num: f64 = 0;
|
||||
while (len--) {
|
||||
code = <i32>load<u16>(ptr);
|
||||
if (code == CharCode.DOT) {
|
||||
ptr += 2;
|
||||
let fac: f64 = 0.1; // precision :(
|
||||
while (len--) {
|
||||
code = <i32>load<u16>(ptr);
|
||||
if (code == CharCode.E || code == CharCode.e) {
|
||||
assert(false); // TODO
|
||||
}
|
||||
code -= CharCode._0;
|
||||
if (<u32>code > 9) break;
|
||||
num += <f64>code * fac;
|
||||
fac *= 0.1;
|
||||
ptr += 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
code -= CharCode._0;
|
||||
if (<u32>code >= 10) break;
|
||||
num = (num * 10) + code;
|
||||
ptr += 2;
|
||||
}
|
||||
return sign * num;
|
||||
}
|
||||
|
Reference in New Issue
Block a user