Skip to content

Tackle the case of === #1111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3935,8 +3935,8 @@ export class Compiler extends DiagnosticEmitter {
leftExpr = this.compileExpression(left, contextualType);
leftType = this.currentType;

// check operator overload
if (operator == Token.EQUALS_EQUALS && this.currentType.is(TypeFlags.REFERENCE)) {
// check operator overload
if (this.currentType.is(TypeFlags.REFERENCE)) {
let classReference = leftType.classReference;
if (classReference) {
let overload = classReference.lookupOverload(OperatorKind.EQ);
Expand Down
15 changes: 7 additions & 8 deletions std/assembly/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function ensureSize(array: usize, minSize: usize, alignLog2: u32): void {
let newCapacity = minSize << alignLog2;
let newData = __realloc(oldData, newCapacity); // keeps RC
memory.fill(newData + oldCapacity, 0, newCapacity - oldCapacity);
if (newData !== oldData) { // oldData has been free'd
if (changetype<usize>(newData) != changetype<usize>(oldData)) { // oldData has been free'd
store<usize>(array, newData, offsetof<ArrayBufferView>("buffer"));
store<usize>(array, newData, offsetof<ArrayBufferView>("dataStart"));
}
Expand All @@ -38,7 +38,10 @@ export class Array<T> extends ArrayBufferView {
private length_: i32;

static isArray<U>(value: U): bool {
return isReference<U>() ? builtin_isArray(value) && value !== null : false;
if (isReference<U>()) {
return value instanceof Array && changetype<usize>(value) != 0;
}
return false;
}

static create<T>(capacity: i32 = 0): Array<T> {
Expand Down Expand Up @@ -213,7 +216,7 @@ export class Array<T> extends ArrayBufferView {

concat(other: Array<T>): Array<T> {
var thisLen = this.length_;
var otherLen = select(0, other.length_, other === null);
var otherLen = select(0, other.length_, changetype<usize>(other) == 0);
var outLen = thisLen + otherLen;
if (<u32>outLen > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new Error(E_INVALIDLENGTH);
var out = changetype<Array<T>>(__allocArray(outLen, alignof<T>(), idof<Array<T>>())); // retains
Expand Down Expand Up @@ -472,11 +475,7 @@ export class Array<T> extends ArrayBufferView {
if (isBoolean<T>()) return joinBooleanArray(dataStart, length, separator);
if (isInteger<T>()) return joinIntegerArray<T>(dataStart, length, separator);
if (isFloat<T>()) return joinFloatArray<T>(dataStart, length, separator);

if (ASC_SHRINK_LEVEL < 1) {
if (isString<T>()) return joinStringArray(dataStart, length, separator);
}
// For rest objects and arrays use general join routine
Comment on lines -486 to -490
Copy link
Member

@MaxGraey MaxGraey Feb 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this conditional guard potentially decreased code size so recommend leave as is

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not sure about this one as well. Removed it because joinReferenceArray wasn't compatible with strings anymore, but there's probably something better we can do.

if (isString<T>()) return joinStringArray(dataStart, length, separator);
if (isReference<T>()) return joinReferenceArray<T>(dataStart, length, separator);
ERROR("unspported element type");
return <string>unreachable();
Expand Down
30 changes: 16 additions & 14 deletions std/assembly/arraybuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,23 @@ export abstract class ArrayBufferView {
@sealed export class ArrayBuffer {

static isView<T>(value: T): bool {
if (isNullable<T>()) {
if (value === null) return false;
if (isReference<T>()) {
if (isNullable<T>()) {
if (!changetype<usize>(value)) return false;
}
if (value instanceof Int8Array) return true;
if (value instanceof Uint8Array) return true;
if (value instanceof Uint8ClampedArray) return true;
if (value instanceof Int16Array) return true;
if (value instanceof Uint16Array) return true;
if (value instanceof Int32Array) return true;
if (value instanceof Uint32Array) return true;
if (value instanceof Int64Array) return true;
if (value instanceof Uint64Array) return true;
if (value instanceof Float32Array) return true;
if (value instanceof Float64Array) return true;
if (value instanceof DataView) return true;
}
if (value instanceof Int8Array) return true;
if (value instanceof Uint8Array) return true;
if (value instanceof Uint8ClampedArray) return true;
if (value instanceof Int16Array) return true;
if (value instanceof Uint16Array) return true;
if (value instanceof Int32Array) return true;
if (value instanceof Uint32Array) return true;
if (value instanceof Int64Array) return true;
if (value instanceof Uint64Array) return true;
if (value instanceof Float32Array) return true;
if (value instanceof Float64Array) return true;
if (value instanceof DataView) return true;
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion std/assembly/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class Map<K,V> {
}

has(key: K): bool {
return this.find(key, HASH<K>(key)) !== null;
return changetype<usize>(this.find(key, HASH<K>(key))) != 0;
}

@operator("[]")
Expand Down
2 changes: 1 addition & 1 deletion std/assembly/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export class Set<T> {

@operator("[]")
has(key: T): bool {
return this.find(key, HASH<T>(key)) !== null;
return changetype<usize>(this.find(key, HASH<T>(key))) != 0;
}

add(key: T): this {
Expand Down
52 changes: 28 additions & 24 deletions std/assembly/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,10 @@ import { idof } from "./builtins";
}

@operator("+") private static __concat(left: String, right: String): String {
return select<String>(left, changetype<String>("null"), left !== null).concat(right);
return select<String>(left, changetype<String>("null"), changetype<usize>(left) != 0).concat(right);
}

concat(other: String): String {
if (other === null) other = changetype<String>("null");
var thisSize: isize = this.length << 1;
var otherSize: isize = other.length << 1;
var outSize: usize = thisSize + otherSize;
Expand All @@ -77,7 +76,6 @@ import { idof } from "./builtins";
}

endsWith(search: String, end: i32 = String.MAX_LENGTH): bool {
if (search === null) return false;
end = min(max(end, 0), this.length);
var searchLength = <isize>search.length;
var searchStart = <isize>end - searchLength;
Expand All @@ -87,17 +85,17 @@ import { idof } from "./builtins";
}

@operator("==") private static __eq(left: String | null, right: String | null): bool {
if (left === right) return true;
if (left === null || right === null) return false;
var leftLength = left.length;
if (leftLength != right.length) return false;
if (changetype<usize>(left) == changetype<usize>(right)) return true;
if (!changetype<usize>(left) || !changetype<usize>(right)) return false;
var leftLength = changetype<String>(left).length;
if (leftLength != changetype<String>(right).length) return false;
// @ts-ignore: string <-> String
return !compareImpl(left, 0, right, 0, leftLength);
}

@operator.prefix("!")
private static __not(str: String | null): bool {
return str === null || !str.length;
return !changetype<usize>(str) || !changetype<String>(str).length;
}

@operator("!=")
Expand All @@ -106,30 +104,37 @@ import { idof } from "./builtins";
}

@operator(">") private static __gt(left: String | null, right: String | null): bool {
if (left === right || left === null || right === null) return false;
var leftLength = left.length;
if (
changetype<usize>(left) == changetype<usize>(right) ||
!changetype<usize>(left) ||
!changetype<usize>(right)
) return false;
var leftLength = changetype<String>(left).length;
if (!leftLength) return false;
var rightLength = right.length;
var rightLength = changetype<String>(right).length;
if (!rightLength) return true;
// @ts-ignore: string <-> String
return compareImpl(left, 0, right, 0, min(leftLength, rightLength)) > 0;
}

@operator(">=") private static __gte(left: String, right: String): bool {
@operator(">=") private static __gte(left: String | null, right: String | null): bool {
return !this.__lt(left, right);
}

@operator("<") private static __lt(left: String, right: String): bool {
if (left === right || left === null || right === null) return false;
var rightLength = right.length;
@operator("<") private static __lt(left: String | null, right: String | null): bool {
if (
changetype<usize>(left) == changetype<usize>(right) ||
!changetype<usize>(left) ||
!changetype<usize>(right)
) return false;
var rightLength = changetype<String>(right).length;
if (!rightLength) return false;
var leftLength = left.length;
var leftLength = changetype<String>(left).length;
if (!leftLength) return true;
// @ts-ignore: string <-> String
return compareImpl(left, 0, right, 0, min(leftLength, rightLength)) < 0;
return compareImpl(changetype<string>(left), 0, changetype<string>(right), 0, min(leftLength, rightLength)) < 0;
}

@operator("<=") private static __lte(left: String, right: String): bool {
@operator("<=") private static __lte(left: String | null, right: String | null): bool {
return !this.__gt(left, right);
}

Expand Down Expand Up @@ -165,7 +170,7 @@ import { idof } from "./builtins";

// TODO: implement full locale comparison with locales and Collator options
localeCompare(other: String): i32 {
if (other === this) return 0; // compare pointers
if (changetype<usize>(other) == changetype<usize>(this)) return 0;
var len: isize = this.length;
var otherLen: isize = other.length;
if (otherLen != len) return select(1, -1, len > otherLen);
Expand All @@ -175,7 +180,6 @@ import { idof } from "./builtins";
}

startsWith(search: String, start: i32 = 0): bool {
if (search === null) search = changetype<String>("null");
var len = <isize>this.length;
var searchStart = min(max(<isize>start, 0), len);
var searchLength = <isize>search.length;
Expand Down Expand Up @@ -445,9 +449,9 @@ import { idof } from "./builtins";

split(separator: String | null = null, limit: i32 = i32.MAX_VALUE): String[] {
if (!limit) return changetype<Array<String>>(__allocArray(0, alignof<String>(), idof<Array<String>>())); // retains
if (separator === null) return [this];
if (!changetype<usize>(separator)) return [this];
var length: isize = this.length;
var sepLen: isize = separator.length;
var sepLen: isize = changetype<String>(separator).length;
if (limit < 0) limit = i32.MAX_VALUE;
if (!sepLen) {
if (!length) return changetype<Array<String>>(__allocArray(0, alignof<String>(), idof<Array<String>>())); // retains
Expand All @@ -471,7 +475,7 @@ import { idof } from "./builtins";
}
var result = changetype<Array<String>>(__allocArray(0, alignof<String>(), idof<Array<String>>())); // retains
var end = 0, start = 0, i = 0;
while (~(end = this.indexOf(separator, start))) {
while (~(end = this.indexOf(changetype<String>(separator), start))) {
let len = end - start;
if (len > 0) {
let out = __alloc(<usize>len << 1, idof<String>());
Expand Down
9 changes: 6 additions & 3 deletions std/assembly/symbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ var nextId: usize = 12; // Symbol.unscopables + 1
static readonly unscopables: symbol = changetype<symbol>(11);

static for(key: string): symbol {
if (!stringToId) { stringToId = new Map(); idToString = new Map(); }
if (!stringToId) {
stringToId = new Map();
idToString = new Map();
}
else if (stringToId.has(key)) return changetype<symbol>(stringToId.get(key));
var id = nextId++;
if (!id) unreachable(); // out of ids
Expand All @@ -77,7 +80,7 @@ var nextId: usize = 12; // Symbol.unscopables + 1
}

static keyFor(sym: symbol): string | null {
return idToString !== null && idToString.has(changetype<usize>(sym))
return idToString != null && idToString.has(changetype<usize>(sym))
? idToString.get(changetype<usize>(sym))
: null;
}
Expand All @@ -98,7 +101,7 @@ var nextId: usize = 12; // Symbol.unscopables + 1
case 10: { str = "toStringTag"; break; }
case 11: { str = "unscopables"; break; }
default: {
if (idToString !== null && idToString.has(id)) str = idToString.get(id);
if (idToString != null && idToString.has(id)) str = idToString.get(id);
break;
}
}
Expand Down
6 changes: 3 additions & 3 deletions std/assembly/util/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ function hash64(key: u64): u32 {
return v;
}

function hashStr(key: string): u32 {
function hashStr(key: string | null): u32 {
var v = FNV_OFFSET;
if (key !== null) {
for (let i: usize = 0, k: usize = key.length << 1; i < k; ++i) {
if (changetype<usize>(key)) {
for (let i: usize = 0, k: usize = changetype<string>(key).length << 1; i < k; ++i) {
v = (v ^ <u32>load<u8>(changetype<usize>(key) + i)) * FNV_PRIME;
}
}
Expand Down
2 changes: 1 addition & 1 deletion std/assembly/util/memory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function memcpy(dest: usize, src: usize, n: usize): void { // see: musl/s
// @ts-ignore: decorator
@inline
export function memmove(dest: usize, src: usize, n: usize): void { // see: musl/src/string/memmove.c
if (dest === src) return;
if (dest == src) return;
if (ASC_SHRINK_LEVEL < 1) {
if (src + n <= dest || dest + n <= src) {
memcpy(dest, src, n);
Expand Down
6 changes: 5 additions & 1 deletion std/assembly/util/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ export function COMPARATOR<T>(): (a: T, b: T) => i32 {
}
} else if (isString<T>()) {
return (a: T, b: T): i32 => {
if (a === b || a === null || b === null) return 0;
if (
changetype<usize>(a) == changetype<usize>(b) ||
!changetype<usize>(a) ||
!changetype<usize>(b)
) return 0;
var alen = changetype<string>(a).length;
var blen = changetype<string>(b).length;
if (!alen && !blen) return 0;
Expand Down
13 changes: 7 additions & 6 deletions std/assembly/util/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,14 +412,14 @@ export function joinStringArray(dataStart: usize, length: i32, separator: string
for (let i = 0; i < length; ++i) {
value = load<string>(dataStart + (<usize>i << alignof<string>()));
// @ts-ignore: type
if (value !== null) estLen += value.length;
if (changetype<usize>(value)) estLen += value.length;
}
var offset = 0;
var sepLen = separator.length;
var result = __alloc((estLen + sepLen * lastIndex) << 1, idof<string>());
for (let i = 0; i < lastIndex; ++i) {
value = load<string>(dataStart + (<usize>i << alignof<string>()));
if (value !== null) {
if (changetype<usize>(value)) {
let valueLen = value.length;
memory.copy(
result + (<usize>offset << 1),
Expand All @@ -438,7 +438,7 @@ export function joinStringArray(dataStart: usize, length: i32, separator: string
}
}
value = load<string>(dataStart + (<usize>lastIndex << alignof<string>()));
if (value !== null) {
if (changetype<usize>(value)) {
memory.copy(
result + (<usize>offset << 1),
changetype<usize>(value),
Expand All @@ -449,25 +449,26 @@ export function joinStringArray(dataStart: usize, length: i32, separator: string
}

export function joinReferenceArray<T>(dataStart: usize, length: i32, separator: string): string {
assert(!isString<T>());
var lastIndex = length - 1;
if (lastIndex < 0) return "";
var value: T;
if (!lastIndex) {
value = load<T>(dataStart);
// @ts-ignore: type
return value !== null ? value.toString() : "";
return value ? value.toString() : "";
}
var result = "";
var sepLen = separator.length;
for (let i = 0; i < lastIndex; ++i) {
value = load<T>(dataStart + (<usize>i << alignof<T>()));
// @ts-ignore: type
if (value !== null) result += value.toString();
if (value) result += value.toString();
if (sepLen) result += separator;
}
value = load<T>(dataStart + (<usize>lastIndex << alignof<T>()));
// @ts-ignore: type
if (value !== null) result += value.toString();
if (value) result += value.toString();
return result;
}

Expand Down
6 changes: 3 additions & 3 deletions tests/compiler/assert-nonnull.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
if
i32.const 96
i32.const 160
i32.const 93
i32.const 96
i32.const 41
call $~lib/builtins/abort
unreachable
Expand All @@ -92,7 +92,7 @@
if
i32.const 208
i32.const 160
i32.const 97
i32.const 100
i32.const 39
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -121,7 +121,7 @@
if
i32.const 96
i32.const 160
i32.const 93
i32.const 96
i32.const 41
call $~lib/builtins/abort
unreachable
Expand Down
Loading