Add isArrayLike builtin (#453)

This commit is contained in:
Max Graey 2019-02-27 22:47:52 +02:00 committed by Daniel Wirtz
parent e8b0767143
commit aad263e670
8 changed files with 327 additions and 212 deletions

View File

@ -47,6 +47,7 @@ import {
import {
ElementKind,
OperatorKind,
FunctionPrototype,
Class,
Field,
@ -64,7 +65,7 @@ import {
} from "./resolver";
import {
CommonFlags, CommonSymbols
CommonFlags
} from "./common";
/** Symbols of various compiler built-ins. */
@ -76,6 +77,7 @@ export namespace BuiltinSymbols {
export const isReference = "~lib/builtins/isReference";
export const isString = "~lib/builtins/isString";
export const isArray = "~lib/builtins/isArray";
export const isArrayLike = "~lib/builtins/isArrayLike";
export const isFunction = "~lib/builtins/isFunction";
export const isNullable = "~lib/builtins/isNullable";
export const isDefined = "~lib/builtins/isDefined";
@ -350,6 +352,19 @@ export function compileCall(
: 0
);
}
case BuiltinSymbols.isArrayLike: { // isArrayLike<T!>() / isArrayLike<T?>(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.createUnreachable();
let classReference = type.classReference;
if (!classReference) return module.createI32(0);
return module.createI32(
classReference.lookupInSelf("length") && (
classReference.lookupOverload(OperatorKind.INDEXED_GET) ||
classReference.lookupOverload(OperatorKind.UNCHECKED_INDEXED_GET)
) ? 1 : 0
);
}
case BuiltinSymbols.isFunction: { // isFunction<T!> / isFunction<T?>(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;

View File

@ -9,6 +9,7 @@
@builtin export declare function isReference<T>(value?: T): bool;
@builtin export declare function isString<T>(value?: T): bool;
@builtin export declare function isArray<T>(value?: T): bool;
@builtin export declare function isArrayLike<T>(value?: T): bool;
@builtin export declare function isFunction<T>(value?: T): bool;
@builtin export declare function isNullable<T>(value?: T): bool;
@builtin export declare function isDefined(expression: void): bool;

View File

@ -128,6 +128,8 @@ declare function isReference<T>(value?: any): value is object | string;
declare function isString<T>(value?: any): value is string | String;
/** Tests if the specified type *or* expression can be used as an array. Compiles to a constant. */
declare function isArray<T>(value?: any): value is Array<any>;
/** Tests if the specified type *or* expression can be used as an array like object. Compiles to a constant. */
declare function isArrayLike<T>(value?: any): value is ArrayLike<any>;
/** Tests if the specified type *or* expression is of a function type. Compiles to a constant. */
declare function isFunction<T>(value?: any): value is (...args: any) => any;
/** Tests if the specified type *or* expression is of a nullable reference type. Compiles to a constant. */
@ -559,6 +561,11 @@ declare class DataView {
toString(): string;
}
interface ArrayLike<T> {
length: i32;
// [key: number]: T;
}
/** Interface for a typed view on an array buffer. */
interface ArrayBufferView<T> {
[key: number]: T;

View File

@ -106,6 +106,8 @@ declare function isReference(value: any): value is object | string;
declare function isString(value: any): value is string | String;
/** Tests if the specified value can be used as an array. */
declare function isArray(value: any): value is Array<any>;
/** Tests if the specified type *or* expression can be used as an array like object. Compiles to a constant. */
declare function isArrayLike(value: any): value is ArrayLike<any>;
/** Tests if the specified expression resolves to a defined element. */
declare function isDefined(expression: any): bool;
/** Tests if the specified expression evaluates to a constant value. */
@ -411,6 +413,11 @@ declare class Int32Array extends Array<i32> {}
declare class Float32Array extends Array<f32> {}
declare class Float64Array extends Array<f64> {}
interface ArrayLike<T> {
length: i32;
[key: number]: T;
}
/** Interface for a typed view on an array buffer. */
interface ArrayBufferView<T> {
[key: number]: T;

View File

@ -215,6 +215,13 @@ globalScope["isString"] = function isString(arg) {
};
globalScope["isArray"] = Array.isArray;
globalScope["isArrayLike"] = function isArrayLike(expr) {
return expr
&& typeof expr === 'object'
&& typeof expr.length === 'number'
&& expr.length >= 0
&& Math.trunc(expr.length) === expr.length;
}
globalScope["isDefined"] = function isDefined(expr) {
return typeof expr !== "undefined";

View File

@ -43,7 +43,7 @@
if
i32.const 0
i32.const 8
i32.const 59
i32.const 66
i32.const 19
call $~lib/env/abort
unreachable
@ -56,7 +56,7 @@
if
i32.const 0
i32.const 8
i32.const 60
i32.const 67
i32.const 20
call $~lib/env/abort
unreachable
@ -69,7 +69,7 @@
if
i32.const 0
i32.const 8
i32.const 61
i32.const 68
i32.const 20
call $~lib/env/abort
unreachable
@ -92,7 +92,7 @@
if
i32.const 0
i32.const 8
i32.const 77
i32.const 84
i32.const 19
call $~lib/env/abort
unreachable
@ -105,7 +105,7 @@
if
i32.const 0
i32.const 8
i32.const 78
i32.const 85
i32.const 20
call $~lib/env/abort
unreachable
@ -118,7 +118,7 @@
if
i32.const 0
i32.const 8
i32.const 79
i32.const 86
i32.const 20
call $~lib/env/abort
unreachable

View File

@ -11,6 +11,10 @@ assert(isReference<string>());
assert(!isReference<usize>());
assert(isArray<i32[]>());
assert(!isArray<usize>());
assert(isArrayLike<i32[]>());
assert(isArrayLike<string>());
assert(isArrayLike<Uint8Array>());
assert(!isArrayLike<i32>());
assert(isFunction<() => void>());
assert(!isFunction<u32>());
assert(isNullable<C | null>());
@ -25,6 +29,9 @@ assert(!isReference(changetype<usize>(null)));
assert(isString("1"));
assert(!isString(1));
assert(isArray(changetype<i32[]>(null)));
assert(isArrayLike(changetype<i32[]>(null)));
assert(isArrayLike(changetype<string>(null)));
assert(isArrayLike(changetype<Uint8Array>(null)));
assert(!isArray(changetype<usize>(null)));
assert(isFunction(changetype<() => void>(null)));
assert(!isFunction(changetype<u32>(null)));

View File

@ -157,8 +157,7 @@
call $~lib/env/abort
unreachable
end
i32.const 0
i32.eqz
i32.const 1
i32.eqz
if
i32.const 0
@ -194,7 +193,7 @@
if
i32.const 0
i32.const 8
i32.const 19
i32.const 18
i32.const 0
call $~lib/env/abort
unreachable
@ -205,7 +204,7 @@
if
i32.const 0
i32.const 8
i32.const 20
i32.const 19
i32.const 0
call $~lib/env/abort
unreachable
@ -215,7 +214,7 @@
if
i32.const 0
i32.const 8
i32.const 21
i32.const 20
i32.const 0
call $~lib/env/abort
unreachable
@ -226,7 +225,7 @@
if
i32.const 0
i32.const 8
i32.const 22
i32.const 21
i32.const 0
call $~lib/env/abort
unreachable
@ -325,13 +324,43 @@
call $~lib/env/abort
unreachable
end
i32.const 1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 32
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 33
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 34
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.eqz
i32.eqz
if
i32.const 0
i32.const 8
i32.const 32
i32.const 35
i32.const 0
call $~lib/env/abort
unreachable
@ -379,6 +408,48 @@
unreachable
end
i32.const 1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 43
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.eqz
i32.eqz
if
i32.const 0
i32.const 8
i32.const 44
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 45
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.eqz
i32.eqz
if
i32.const 0
i32.const 8
i32.const 46
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 1
i32.clz
drop
i32.const 1
@ -457,7 +528,7 @@
if
i32.const 0
i32.const 8
i32.const 59
i32.const 66
i32.const 19
call $~lib/env/abort
unreachable
@ -478,7 +549,7 @@
if
i32.const 0
i32.const 8
i32.const 60
i32.const 67
i32.const 20
call $~lib/env/abort
unreachable
@ -499,7 +570,7 @@
if
i32.const 0
i32.const 8
i32.const 61
i32.const 68
i32.const 20
call $~lib/env/abort
unreachable
@ -565,7 +636,7 @@
if
i32.const 0
i32.const 8
i32.const 77
i32.const 84
i32.const 19
call $~lib/env/abort
unreachable
@ -586,7 +657,7 @@
if
i32.const 0
i32.const 8
i32.const 78
i32.const 85
i32.const 20
call $~lib/env/abort
unreachable
@ -607,7 +678,7 @@
if
i32.const 0
i32.const 8
i32.const 79
i32.const 86
i32.const 20
call $~lib/env/abort
unreachable
@ -661,7 +732,7 @@
if
i32.const 0
i32.const 8
i32.const 96
i32.const 103
i32.const 0
call $~lib/env/abort
unreachable
@ -681,7 +752,7 @@
if
i32.const 0
i32.const 8
i32.const 97
i32.const 104
i32.const 0
call $~lib/env/abort
unreachable
@ -703,7 +774,7 @@
if
i32.const 0
i32.const 8
i32.const 98
i32.const 105
i32.const 0
call $~lib/env/abort
unreachable
@ -725,7 +796,7 @@
if
i32.const 0
i32.const 8
i32.const 99
i32.const 106
i32.const 0
call $~lib/env/abort
unreachable
@ -748,7 +819,7 @@
if
i32.const 0
i32.const 8
i32.const 100
i32.const 107
i32.const 0
call $~lib/env/abort
unreachable
@ -770,7 +841,7 @@
if
i32.const 0
i32.const 8
i32.const 101
i32.const 108
i32.const 0
call $~lib/env/abort
unreachable
@ -884,7 +955,7 @@
if
i32.const 0
i32.const 8
i32.const 132
i32.const 139
i32.const 0
call $~lib/env/abort
unreachable
@ -904,7 +975,7 @@
if
i32.const 0
i32.const 8
i32.const 133
i32.const 140
i32.const 0
call $~lib/env/abort
unreachable
@ -926,7 +997,7 @@
if
i32.const 0
i32.const 8
i32.const 134
i32.const 141
i32.const 0
call $~lib/env/abort
unreachable
@ -948,7 +1019,7 @@
if
i32.const 0
i32.const 8
i32.const 135
i32.const 142
i32.const 0
call $~lib/env/abort
unreachable
@ -971,7 +1042,7 @@
if
i32.const 0
i32.const 8
i32.const 136
i32.const 143
i32.const 0
call $~lib/env/abort
unreachable
@ -993,7 +1064,7 @@
if
i32.const 0
i32.const 8
i32.const 137
i32.const 144
i32.const 0
call $~lib/env/abort
unreachable
@ -1306,80 +1377,6 @@
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 256
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 257
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 258
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 259
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 4
drop
i32.const 1
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 261
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 1
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 262
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
@ -1388,8 +1385,8 @@
call $~lib/env/abort
unreachable
end
i32.const 4
i32.const 4
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
@ -1400,6 +1397,18 @@
call $~lib/env/abort
unreachable
end
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 265
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
@ -1407,7 +1416,69 @@
if
i32.const 0
i32.const 8
i32.const 265
i32.const 266
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 4
drop
i32.const 1
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 268
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 1
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 269
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 270
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 271
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 272
i32.const 0
call $~lib/env/abort
unreachable
@ -1418,66 +1489,6 @@
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 267
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 268
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 271
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 272
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 273
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
@ -1486,6 +1497,18 @@
call $~lib/env/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 275
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
@ -1493,7 +1516,55 @@
if
i32.const 0
i32.const 8
i32.const 276
i32.const 278
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 279
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 280
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 281
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 8
i32.const 283
i32.const 0
call $~lib/env/abort
unreachable
@ -1505,7 +1576,7 @@
if
i32.const 0
i32.const 8
i32.const 277
i32.const 284
i32.const 0
call $~lib/env/abort
unreachable
@ -1517,7 +1588,7 @@
if
i32.const 0
i32.const 8
i32.const 279
i32.const 286
i32.const 0
call $~lib/env/abort
unreachable
@ -1535,7 +1606,7 @@
if
i32.const 0
i32.const 8
i32.const 280
i32.const 287
i32.const 0
call $~lib/env/abort
unreachable
@ -1553,7 +1624,7 @@
if
i32.const 0
i32.const 8
i32.const 281
i32.const 288
i32.const 0
call $~lib/env/abort
unreachable
@ -1574,7 +1645,7 @@
if
i32.const 0
i32.const 8
i32.const 282
i32.const 289
i32.const 0
call $~lib/env/abort
unreachable
@ -1595,7 +1666,7 @@
if
i32.const 0
i32.const 8
i32.const 283
i32.const 290
i32.const 0
call $~lib/env/abort
unreachable
@ -1616,7 +1687,7 @@
if
i32.const 0
i32.const 8
i32.const 284
i32.const 291
i32.const 0
call $~lib/env/abort
unreachable
@ -1637,7 +1708,7 @@
if
i32.const 0
i32.const 8
i32.const 285
i32.const 292
i32.const 0
call $~lib/env/abort
unreachable
@ -1657,7 +1728,7 @@
if
i32.const 0
i32.const 8
i32.const 286
i32.const 293
i32.const 0
call $~lib/env/abort
unreachable
@ -1677,7 +1748,7 @@
if
i32.const 0
i32.const 8
i32.const 287
i32.const 294
i32.const 0
call $~lib/env/abort
unreachable
@ -1693,7 +1764,7 @@
if
i32.const 0
i32.const 8
i32.const 300
i32.const 307
i32.const 0
call $~lib/env/abort
unreachable
@ -1705,7 +1776,7 @@
if
i32.const 0
i32.const 8
i32.const 301
i32.const 308
i32.const 0
call $~lib/env/abort
unreachable
@ -1721,7 +1792,7 @@
if
i32.const 0
i32.const 8
i32.const 302
i32.const 309
i32.const 0
call $~lib/env/abort
unreachable
@ -1733,7 +1804,7 @@
if
i32.const 0
i32.const 8
i32.const 303
i32.const 310
i32.const 0
call $~lib/env/abort
unreachable
@ -1745,7 +1816,7 @@
if
i32.const 0
i32.const 8
i32.const 304
i32.const 311
i32.const 0
call $~lib/env/abort
unreachable
@ -1757,7 +1828,7 @@
if
i32.const 0
i32.const 8
i32.const 305
i32.const 312
i32.const 0
call $~lib/env/abort
unreachable
@ -1769,7 +1840,7 @@
if
i32.const 0
i32.const 8
i32.const 306
i32.const 313
i32.const 0
call $~lib/env/abort
unreachable
@ -1781,7 +1852,7 @@
if
i32.const 0
i32.const 8
i32.const 307
i32.const 314
i32.const 0
call $~lib/env/abort
unreachable
@ -1793,7 +1864,7 @@
if
i32.const 0
i32.const 8
i32.const 309
i32.const 316
i32.const 0
call $~lib/env/abort
unreachable
@ -1805,7 +1876,7 @@
if
i32.const 0
i32.const 8
i32.const 310
i32.const 317
i32.const 0
call $~lib/env/abort
unreachable
@ -1817,7 +1888,7 @@
if
i32.const 0
i32.const 8
i32.const 311
i32.const 318
i32.const 0
call $~lib/env/abort
unreachable
@ -1829,7 +1900,7 @@
if
i32.const 0
i32.const 8
i32.const 312
i32.const 319
i32.const 0
call $~lib/env/abort
unreachable
@ -1841,7 +1912,7 @@
if
i32.const 0
i32.const 8
i32.const 313
i32.const 320
i32.const 0
call $~lib/env/abort
unreachable
@ -1853,7 +1924,7 @@
if
i32.const 0
i32.const 8
i32.const 314
i32.const 321
i32.const 0
call $~lib/env/abort
unreachable
@ -1865,7 +1936,7 @@
if
i32.const 0
i32.const 8
i32.const 315
i32.const 322
i32.const 0
call $~lib/env/abort
unreachable
@ -1877,7 +1948,7 @@
if
i32.const 0
i32.const 8
i32.const 316
i32.const 323
i32.const 0
call $~lib/env/abort
unreachable
@ -1889,7 +1960,7 @@
if
i32.const 0
i32.const 8
i32.const 317
i32.const 324
i32.const 0
call $~lib/env/abort
unreachable
@ -1901,7 +1972,7 @@
if
i32.const 0
i32.const 8
i32.const 317
i32.const 324
i32.const 29
call $~lib/env/abort
unreachable
@ -1913,7 +1984,7 @@
if
i32.const 0
i32.const 8
i32.const 318
i32.const 325
i32.const 0
call $~lib/env/abort
unreachable
@ -1925,7 +1996,7 @@
if
i32.const 0
i32.const 8
i32.const 318
i32.const 325
i32.const 29
call $~lib/env/abort
unreachable
@ -1937,7 +2008,7 @@
if
i32.const 0
i32.const 8
i32.const 320
i32.const 327
i32.const 0
call $~lib/env/abort
unreachable
@ -1949,7 +2020,7 @@
if
i32.const 0
i32.const 8
i32.const 321
i32.const 328
i32.const 0
call $~lib/env/abort
unreachable
@ -1961,7 +2032,7 @@
if
i32.const 0
i32.const 8
i32.const 322
i32.const 329
i32.const 0
call $~lib/env/abort
unreachable
@ -1973,7 +2044,7 @@
if
i32.const 0
i32.const 8
i32.const 323
i32.const 330
i32.const 0
call $~lib/env/abort
unreachable
@ -1985,7 +2056,7 @@
if
i32.const 0
i32.const 8
i32.const 324
i32.const 331
i32.const 0
call $~lib/env/abort
unreachable
@ -1997,7 +2068,7 @@
if
i32.const 0
i32.const 8
i32.const 325
i32.const 332
i32.const 0
call $~lib/env/abort
unreachable
@ -2009,7 +2080,7 @@
if
i32.const 0
i32.const 8
i32.const 327
i32.const 334
i32.const 0
call $~lib/env/abort
unreachable
@ -2021,7 +2092,7 @@
if
i32.const 0
i32.const 8
i32.const 328
i32.const 335
i32.const 0
call $~lib/env/abort
unreachable
@ -2033,7 +2104,7 @@
if
i32.const 0
i32.const 8
i32.const 329
i32.const 336
i32.const 0
call $~lib/env/abort
unreachable
@ -2045,7 +2116,7 @@
if
i32.const 0
i32.const 8
i32.const 330
i32.const 337
i32.const 0
call $~lib/env/abort
unreachable
@ -2057,7 +2128,7 @@
if
i32.const 0
i32.const 8
i32.const 331
i32.const 338
i32.const 0
call $~lib/env/abort
unreachable
@ -2069,7 +2140,7 @@
if
i32.const 0
i32.const 8
i32.const 332
i32.const 339
i32.const 0
call $~lib/env/abort
unreachable