Static operator overloads

This commit is contained in:
dcodeIO 2018-01-28 06:18:27 +01:00
parent 3165f4337f
commit b1e7b75ad7
16 changed files with 379 additions and 149 deletions

19
NOTICE
View File

@ -1,4 +1,13 @@
Includes parts of TypeScript:
Copyright (c) 2017-2018 AssemblyScript authors.
The following authors have all licensed their contributions to AssemblyScript
under the licensing terms detailed in LICENSE.
* Daniel Wirtz <dcode@dcode.io>
================================================================================
This program includes parts of TypeScript:
https://github.com/Microsoft/TypeScript
@ -6,7 +15,9 @@ Includes parts of TypeScript:
Apache License, Version 2.0
https://www.apache.org/licenses/LICENSE-2.0
Includes parts of Binaryen:
================================================================================
This program includes parts of Binaryen:
https://github.com/WebAssembly/binaryen
@ -14,7 +25,9 @@ Includes parts of Binaryen:
Apache License, Version 2.0
https://www.apache.org/licenses/LICENSE-2.0
Includes parts of musl:
================================================================================
This program includes parts of musl:
http://www.musl-libc.org

View File

@ -1,18 +1,19 @@
// code below is generated from diagnosticsMessages.json by scripts/build-diagnostics
export enum DiagnosticCode {
Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast = 100,
Basic_type_0_cannot_be_nullable = 101,
Operation_not_supported = 102,
Operation_is_unsafe = 103,
Cannot_export_a_mutable_global = 104,
Compiling_constant_with_non_constant_initializer_as_mutable = 105,
Type_0_cannot_be_changed_to_type_1 = 106,
Structs_cannot_extend_classes_and_vice_versa = 107,
Structs_cannot_implement_interfaces = 108,
Invalid_regular_expression_flags = 109,
Type_0_cannot_be_reinterpreted_as_type_1 = 110,
Implementation_0_must_match_the_signature_1 = 111,
Operation_not_supported = 100,
Operation_is_unsafe = 101,
Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast = 200,
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
Type_0_cannot_be_changed_to_type_1 = 202,
Type_0_cannot_be_reinterpreted_as_type_1 = 203,
Basic_type_0_cannot_be_nullable = 204,
Cannot_export_a_mutable_global = 205,
Compiling_constant_with_non_constant_initializer_as_mutable = 206,
Structs_cannot_extend_classes_and_vice_versa = 207,
Structs_cannot_implement_interfaces = 208,
Invalid_regular_expression_flags = 209,
Implementation_0_must_match_the_signature_1 = 210,
Unterminated_string_literal = 1002,
Identifier_expected = 1003,
_0_expected = 1005,
@ -94,18 +95,19 @@ export enum DiagnosticCode {
export function diagnosticCodeToString(code: DiagnosticCode): string {
switch (code) {
case 100: return "Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.";
case 101: return "Basic type '{0}' cannot be nullable.";
case 102: return "Operation not supported.";
case 103: return "Operation is unsafe.";
case 104: return "Cannot export a mutable global.";
case 105: return "Compiling constant with non-constant initializer as mutable.";
case 106: return "Type '{0}' cannot be changed to type '{1}'.";
case 107: return "Structs cannot extend classes and vice-versa.";
case 108: return "Structs cannot implement interfaces.";
case 109: return "Invalid regular expression flags.";
case 110: return "Type '{0}' cannot be reinterpreted as type '{1}'.";
case 111: return "Implementation '{0}' must match the signature '{1}'.";
case 100: return "Operation not supported.";
case 101: return "Operation is unsafe.";
case 200: return "Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.";
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
case 202: return "Type '{0}' cannot be changed to type '{1}'.";
case 203: return "Type '{0}' cannot be reinterpreted as type '{1}'.";
case 204: return "Basic type '{0}' cannot be nullable.";
case 205: return "Cannot export a mutable global.";
case 206: return "Compiling constant with non-constant initializer as mutable.";
case 207: return "Structs cannot extend classes and vice-versa.";
case 208: return "Structs cannot implement interfaces.";
case 209: return "Invalid regular expression flags.";
case 210: return "Implementation '{0}' must match the signature '{1}'.";
case 1002: return "Unterminated string literal.";
case 1003: return "Identifier expected.";
case 1005: return "'{0}' expected.";

View File

@ -1,16 +1,17 @@
{
"Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.": 100,
"Basic type '{0}' cannot be nullable.": 101,
"Operation not supported.": 102,
"Operation is unsafe.": 103,
"Cannot export a mutable global.": 104,
"Compiling constant with non-constant initializer as mutable.": 105,
"Type '{0}' cannot be changed to type '{1}'.": 106,
"Structs cannot extend classes and vice-versa.": 107,
"Structs cannot implement interfaces.": 108,
"Invalid regular expression flags.": 109,
"Type '{0}' cannot be reinterpreted as type '{1}'.": 110,
"Implementation '{0}' must match the signature '{1}'.": 111,
"Operation not supported.": 100,
"Operation is unsafe.": 101,
"Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.": 200,
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,
"Type '{0}' cannot be changed to type '{1}'.": 202,
"Type '{0}' cannot be reinterpreted as type '{1}'.": 203,
"Basic type '{0}' cannot be nullable.": 204,
"Cannot export a mutable global.": 205,
"Compiling constant with non-constant initializer as mutable.": 206,
"Structs cannot extend classes and vice-versa.": 207,
"Structs cannot implement interfaces.": 208,
"Invalid regular expression flags.": 209,
"Implementation '{0}' must match the signature '{1}'.": 210,
"Unterminated string literal.": 1002,
"Identifier expected.": 1003,

View File

@ -107,7 +107,7 @@ export function formatDiagnosticMessage(message: DiagnosticMessage, useColors: b
if (useColors) sb.push(diagnosticCategoryToColor(message.category));
sb.push(diagnosticCategoryToString(message.category));
if (useColors) sb.push(colorReset);
sb.push(" AS");
sb.push(message.code < 1000 ? " AS" : " TS");
sb.push(message.code.toString(10));
sb.push(": ");
sb.push(message.message);

View File

@ -402,7 +402,7 @@ export class Program extends DiagnosticEmitter {
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
var name = declaration.name.name;
var internalName = declaration.fileLevelInternalName;
var instancePrototype: FunctionPrototype | null = null;
var prototype: FunctionPrototype | null = null;
// static methods become global functions
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
@ -419,9 +419,9 @@ export class Program extends DiagnosticEmitter {
}
} else
classPrototype.members = new Map();
var staticPrototype = new FunctionPrototype(this, name, internalName, declaration, null);
classPrototype.members.set(name, staticPrototype);
this.elements.set(internalName, staticPrototype);
prototype = new FunctionPrototype(this, name, internalName, declaration, null);
classPrototype.members.set(name, prototype);
this.elements.set(internalName, prototype);
// instance methods are remembered until resolved
} else {
@ -432,26 +432,31 @@ export class Program extends DiagnosticEmitter {
}
} else
classPrototype.instanceMembers = new Map();
instancePrototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype);
prototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype);
// if (classPrototype.isUnmanaged && instancePrototype.isAbstract) {
// this.error( Unmanaged classes cannot declare abstract methods. );
// }
classPrototype.instanceMembers.set(name, instancePrototype);
classPrototype.instanceMembers.set(name, prototype);
if (declaration.name.kind == NodeKind.CONSTRUCTOR) {
if (classPrototype.constructorPrototype)
this.error(DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, declaration.name.range);
else
classPrototype.constructorPrototype = instancePrototype;
classPrototype.constructorPrototype = prototype;
}
}
// handle operator annotations. operators are instance methods taking a second argument of the
// instance's type. return values vary depending on the operation.
if (declaration.decorators) {
for (var i = 0, k = declaration.decorators.length; i < k; ++i) {
var decorator = declaration.decorators[i];
this.checkOperators(declaration.decorators, prototype, classPrototype);
}
private checkOperators(decorators: Decorator[] | null, prototype: FunctionPrototype, classPrototype: ClassPrototype) {
// handle operator annotations. operators are either instance methods taking a second argument of the
// instance's type or static methods taking two arguments of the instance's type. return values vary
// depending on the operation.
if (decorators) {
for (var i = 0, k = decorators.length; i < k; ++i) {
var decorator = decorators[i];
if (decorator.decoratorKind == DecoratorKind.OPERATOR) {
if (!instancePrototype) {
if (!prototype) {
this.error(DiagnosticCode.Operation_not_supported, decorator.range);
continue;
}
@ -462,22 +467,22 @@ export class Program extends DiagnosticEmitter {
switch ((<StringLiteralExpression>firstArg).value) {
case "[]":
classPrototype.fnIndexedGet = instancePrototype.simpleName;
classPrototype.fnIndexedGet = prototype.simpleName;
break;
case "[]=":
classPrototype.fnIndexedSet = instancePrototype.simpleName;
classPrototype.fnIndexedSet = prototype.simpleName;
break;
case "+":
classPrototype.fnConcat = instancePrototype.simpleName;
classPrototype.fnConcat = prototype.simpleName;
break;
case "==":
classPrototype.fnEquals = instancePrototype.simpleName;
classPrototype.fnEquals = prototype.simpleName;
break;
default: // TBD: does it make sense to provide more, even though not JS/TS-compatible?
default:
this.error(DiagnosticCode.Operation_not_supported, firstArg.range);
}
} else

View File

@ -278,6 +278,10 @@ export class Range {
start: i32;
end: i32;
// TODO: set these while tokenizing
// line: i32;
// column: i32;
constructor(source: Source, start: i32, end: i32) {
this.source = source;
this.start = start;

View File

@ -19,6 +19,8 @@ export class Set<T> {
// FIXME: not a proper set implementation, just a filler
has(value: T): bool {
assert(this != null);
for (var index: usize = 0, limit: usize = this.__size; index < limit; ++index)
if (load<T>(this.__memory + index * sizeof<T>()) == value)
return true;
@ -26,6 +28,8 @@ export class Set<T> {
}
add(value: T): Set<T> {
assert(this != null);
if (this.__size >= this.__capacity) {
var newCapacity = max(this.__capacity << 1, 8);
var newMemory = allocate_memory(<usize>newCapacity * sizeof<T>());
@ -42,6 +46,8 @@ export class Set<T> {
}
delete(value: T): bool {
assert(this != null);
for (var index: usize = 0, limit: usize = this.__size; index < limit; ++index)
if (load<T>(this.__memory + index * sizeof<T>()) == value) {
if (index + 1 < this.__size)
@ -53,6 +59,8 @@ export class Set<T> {
}
clear(): void {
assert(this != null);
this.__size = 0;
}

View File

@ -1,10 +1,12 @@
// singleton empty string
const EMPTY: String = changetype<String>("");
// number of bytes preceeding string data
const HEAD: usize = 4;
function allocate(length: i32): String {
assert(<u32>length >= 1);
var ptr = allocate_memory(HEAD + length * 2);
assert(length > 0); // 0 -> EMPTY
var ptr = allocate_memory(HEAD + (<usize>length << 1));
store<i32>(ptr, length);
return changetype<String>(ptr);
}
@ -15,45 +17,75 @@ export class String {
@operator("[]")
charAt(pos: i32): String {
assert(this != null);
if (<u32>pos >= this.length)
return EMPTY;
var out = allocate(1);
store<u16>(
changetype<usize>(out),
load<u16>(changetype<usize>(this) + (<usize>pos << 1), HEAD),
load<u16>(
changetype<usize>(this) + (<usize>pos << 1),
HEAD
),
HEAD
);
return out;
}
charCodeAt(pos: i32): i32 {
assert(this != null);
if (<u32>pos >= this.length)
return -1; // NaN
return load<u16>(changetype<usize>(this) + (<usize>pos << 1), HEAD);
return -1; // (NaN)
return load<u16>(
changetype<usize>(this) + (<usize>pos << 1),
HEAD
);
}
codePointAt(pos: i32): i32 {
assert(this != null);
if (<u32>pos >= this.length)
return -1; // undefined
var first = <i32>load<u16>(changetype<usize>(this) + (<usize>pos << 1), HEAD);
return -1; // (undefined)
var first = <i32>load<u16>(
changetype<usize>(this) + (<usize>pos << 1),
HEAD
);
if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length)
return first;
var second = <i32>load<u16>(changetype<usize>(this) + ((<usize>pos + 1) << 1), HEAD);
var second = <i32>load<u16>(
changetype<usize>(this) + ((<usize>pos + 1) << 1),
HEAD
);
if (second < 0xDC00 || second > 0xDFFF)
return first;
return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000;
}
@operator("+")
private static __concat(left: String, right: String): String {
if (left == null)
left = changetype<String>("null");
return left.concat(right);
}
concat(other: String): String {
assert(this != null);
assert(other != null);
if (other == null)
other = changetype<String>("null");
var thisLen: isize = this.length;
var otherLen: isize = other.length;
var len: usize = thisLen + otherLen;
if (len == 0)
var outLen: usize = thisLen + otherLen;
if (outLen == 0)
return EMPTY;
var out = allocate(len);
var out = allocate(outLen);
move_memory(
changetype<usize>(out) + HEAD,
changetype<usize>(this) + HEAD,
@ -68,12 +100,17 @@ export class String {
}
endsWith(searchString: String, endPosition: i32 = 0x7fffffff): bool {
assert(searchString != null);
var end: isize = <isize>min<i32>(max<i32>(endPosition, 0), this.length);
assert(this != null);
if (searchString == null)
return false;
var end: isize = <isize>min(max(endPosition, 0), this.length);
var searchLength: isize = searchString.length;
var start: isize = end - searchLength;
if (start < 0)
return false;
return !compare_memory(
changetype<usize>(this) + HEAD + (start << 1),
changetype<usize>(searchString) + HEAD,
@ -82,17 +119,20 @@ export class String {
}
@operator("==")
private __eq(other: String): bool {
if (this == null)
return other == null;
else if (other == null)
private static __eq(left: String, right: String): bool {
if (left == null)
return right == null;
else if (right == null)
return false;
if (this.length != other.length)
var leftLength = left.length;
if (leftLength != right.length)
return false;
return !compare_memory(
changetype<usize>(this) + HEAD,
changetype<usize>(other) + HEAD,
<usize>(this.length << 1)
changetype<usize>(left) + HEAD,
changetype<usize>(right) + HEAD,
(<usize>leftLength << 1)
);
}
@ -101,11 +141,17 @@ export class String {
}
indexOf(searchString: String, position: i32 = 0): i32 {
assert(searchString != null);
assert(this != null);
if (searchString == null)
searchString = changetype<String>("null");
var pos: isize = position;
var len: isize = this.length;
var start: isize = min<isize>(max<isize>(pos, 0), len);
var searchLen: isize = searchString.length;
var searchLen: isize = <isize>searchString.length;
// TODO: two-way, multiple char codes
for (var k: usize = start; <isize>k + searchLen <= len; ++k)
if (!compare_memory(
changetype<usize>(this) + HEAD + (k << 1),
@ -118,13 +164,17 @@ export class String {
startsWith(searchString: String, position: i32 = 0): bool {
assert(this != null);
assert(searchString != null);
if (searchString == null)
searchString = changetype<String>("null");
var pos: isize = position;
var len: isize = this.length;
var start: isize = min<isize>(max<isize>(position, 0), len);
var searchLength: isize = searchString.length;
var searchLength: isize = <isize>searchString.length;
if (searchLength + start > len)
return false;
return !compare_memory(
changetype<usize>(this) + HEAD + (start << 1),
changetype<usize>(searchString) + HEAD,
@ -134,14 +184,17 @@ export class String {
substr(start: i32, length: i32 = i32.MAX_VALUE): String {
assert(this != null);
var intStart: isize = start;
var end: isize = length;
var size: isize = this.length;
if (intStart < 0)
intStart = max<isize>(size + intStart, 0);
var resultLength: isize = min<isize>(max<isize>(end, 0), size - intStart);
if (resultLength <= 0)
return EMPTY;
var out = allocate(resultLength);
move_memory(
changetype<usize>(out) + HEAD,
@ -153,6 +206,7 @@ export class String {
substring(start: i32, end: i32 = i32.MAX_VALUE): String {
assert(this != null);
var len = this.length;
var finalStart = min<i32>(max<i32>(start, 0), len);
var finalEnd = min<i32>(max<i32>(end, 0), len);
@ -161,8 +215,10 @@ export class String {
len = to - from;
if (!len)
return EMPTY;
if (!from && to == this.length)
return this;
var out = allocate(len);
move_memory(
changetype<usize>(out) + HEAD,
@ -174,17 +230,21 @@ export class String {
trim(): String {
assert(this != null);
var length: usize = this.length;
while (length && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (length << 1), HEAD)))
--length;
var start: usize = 0;
while (start < length && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (start << 1), HEAD))) {
++start; --length;
}
while (start < length && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (start << 1), HEAD)))
++start, --length;
if (!length)
return EMPTY;
if (!start && length == this.length)
return this;
var out = allocate(length);
move_memory(
changetype<usize>(out) + HEAD,
@ -196,15 +256,19 @@ export class String {
trimLeft(): String {
assert(this != null);
var start: isize = 0;
var len: isize = this.length;
while (start < len && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (start << 1), HEAD)))
++start;
if (!start)
return this;
var outLen = len - start;
if (!outLen)
return EMPTY;
var out = allocate(outLen);
move_memory(
changetype<usize>(out) + HEAD,
@ -216,13 +280,17 @@ export class String {
trimRight(): String {
assert(this != null);
var len: isize = this.length;
while (len > 0 && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (len << 1), HEAD)))
--len;
if (len <= 0)
return EMPTY;
if (<i32>len == this.length)
return this;
var out = allocate(len);
move_memory(
changetype<usize>(out) + HEAD,

View File

@ -4071,6 +4071,8 @@
GLOBAL: std:string/HEAD
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/String.__concat
FUNCTION_PROTOTYPE: std:string/String.__eq
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -284,6 +284,8 @@
GLOBAL: std:string/HEAD
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/String.__concat
FUNCTION_PROTOTYPE: std:string/String.__eq
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -2867,6 +2867,8 @@
GLOBAL: std:string/HEAD
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/String.__concat
FUNCTION_PROTOTYPE: std:string/String.__eq
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -1972,6 +1972,12 @@
(func $std:set/Set#add (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(if
(i32.eqz
(get_local $0)
)
(unreachable)
)
(if
(i32.ge_u
(i32.load offset=8
@ -2068,6 +2074,12 @@
(func $std:set/Set#has (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(if
(i32.eqz
(get_local $0)
)
(unreachable)
)
(set_local $3
(i32.load offset=8
(get_local $0)
@ -2114,6 +2126,12 @@
(func $std:set/Set#delete (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(if
(i32.eqz
(get_local $0)
)
(unreachable)
)
(set_local $3
(i32.load offset=8
(get_local $0)
@ -2212,6 +2230,7 @@
(i32.const 0)
)
(func $start (; 7 ;) (type $v)
(local $0 i32)
(set_global $std:heap/HEAP_OFFSET
(get_global $HEAP_BASE)
)
@ -2327,8 +2346,16 @@
)
(unreachable)
)
(if
(i32.eqz
(tee_local $0
(get_global $std/set/set)
)
)
(unreachable)
)
(i32.store offset=8
(get_global $std/set/set)
(get_local $0)
(i32.const 0)
)
(if

View File

@ -2247,6 +2247,15 @@
(local $3 i32)
(local $4 i32)
(local $5 i32)
(if
(i32.eqz
(i32.ne
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.ge_u
(i32.load offset=8
@ -2348,6 +2357,15 @@
(func $std:set/Set#has (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(if
(i32.eqz
(i32.ne
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(block $break|0
(block
(set_local $2
@ -2403,6 +2421,15 @@
(func $std:set/Set#delete (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(if
(i32.eqz
(i32.ne
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(block $break|0
(block
(set_local $2
@ -2510,6 +2537,15 @@
)
)
(func $std:set/Set#clear (; 8 ;) (type $iv) (param $0 i32)
(if
(i32.eqz
(i32.ne
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(i32.store offset=8
(get_local $0)
(i32.const 0)
@ -2760,6 +2796,8 @@
GLOBAL: std:string/HEAD
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/String.__concat
FUNCTION_PROTOTYPE: std:string/String.__eq
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -1,19 +1,49 @@
(module
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $iiii (func (param i32 i32 i32) (result i32)))
(type $v (func))
(global $std/string/str (mut i32) (i32.const 8))
(memory $0 1)
(data (i32.const 8) "\10\00\00\00h\00i\00,\00 \00I\00\'\00m\00 \00a\00 \00s\00t\00r\00i\00n\00g")
(data (i32.const 48) "\02\00\00\00h\00i")
(data (i32.const 56) "\06\00\00\00s\00t\00r\00i\00n\00g")
(data (i32.const 72) "\03\00\00\00I\00\'\00m")
(data (i32.const 88) "\01\00\00\00,")
(data (i32.const 96) "\01\00\00\00x")
(data (i32.const 56) "\04\00\00\00n\00u\00l\00l")
(data (i32.const 72) "\06\00\00\00s\00t\00r\00i\00n\00g")
(data (i32.const 88) "\03\00\00\00I\00\'\00m")
(data (i32.const 104) "\01\00\00\00,")
(data (i32.const 112) "\01\00\00\00x")
(export "getString" (func $std/string/getString))
(export "memory" (memory $0))
(start $start)
(func $std:heap/compare_memory (; 0 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(func $std:string/String#charCodeAt (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(if
(i32.eqz
(get_local $0)
)
(unreachable)
)
(if
(i32.ge_u
(get_local $1)
(i32.load
(get_local $0)
)
)
(return
(i32.const -1)
)
)
(i32.load16_u offset=4
(i32.add
(get_local $0)
(i32.shl
(get_local $1)
(i32.const 1)
)
)
)
)
(func $std:heap/compare_memory (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(if
(i32.eq
(get_local $0)
@ -73,7 +103,7 @@
(i32.const 0)
)
)
(func $std:string/String#startsWith (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(func $std:string/String#startsWith (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
@ -87,7 +117,9 @@
(i32.eqz
(get_local $1)
)
(unreachable)
(set_local $1
(i32.const 56)
)
)
(if
(i32.gt_s
@ -152,13 +184,21 @@
)
)
)
(func $std:string/String#endsWith (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(func $std:string/String#endsWith (; 3 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(if
(i32.eqz
(get_local $0)
)
(unreachable)
)
(if
(i32.eqz
(get_local $1)
)
(unreachable)
(return
(i32.const 0)
)
)
(if
(i32.lt_s
@ -221,16 +261,24 @@
)
)
)
(func $std:string/String#indexOf (; 3 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(func $std:string/String#indexOf (; 4 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(if
(i32.eqz
(get_local $1)
(get_local $0)
)
(unreachable)
)
(if
(i32.eqz
(get_local $1)
)
(set_local $1
(i32.const 56)
)
)
(set_local $4
(i32.load
(get_local $1)
@ -310,11 +358,10 @@
)
(i32.const -1)
)
(func $std/string/getString (; 4 ;) (type $i) (result i32)
(func $std/string/getString (; 5 ;) (type $i) (result i32)
(get_global $std/string/str)
)
(func $start (; 5 ;) (type $v)
(local $0 i32)
(func $start (; 6 ;) (type $v)
(if
(i32.ne
(get_global $std/string/str)
@ -333,26 +380,9 @@
)
(if
(i32.ne
(block $__inlined_func$std:string/String#charCodeAt (result i32)
(drop
(br_if $__inlined_func$std:string/String#charCodeAt
(i32.const -1)
(i32.ge_u
(i32.const 0)
(i32.load
(tee_local $0
(get_global $std/string/str)
)
)
)
)
)
(i32.load16_u offset=4
(i32.add
(get_local $0)
(i32.const 0)
)
)
(call $std:string/String#charCodeAt
(get_global $std/string/str)
(i32.const 0)
)
(i32.const 104)
)
@ -372,7 +402,7 @@
(i32.eqz
(call $std:string/String#endsWith
(get_global $std/string/str)
(i32.const 56)
(i32.const 72)
(i32.const 2147483647)
)
)
@ -382,10 +412,8 @@
(i32.eqz
(i32.ne
(call $std:string/String#indexOf
(tee_local $0
(get_global $std/string/str)
)
(i32.const 72)
(get_global $std/string/str)
(i32.const 88)
(i32.const 0)
)
(i32.const -1)
@ -397,7 +425,7 @@
(i32.ne
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 88)
(i32.const 104)
(i32.const 0)
)
(i32.const 2)
@ -408,7 +436,7 @@
(i32.ne
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 96)
(i32.const 112)
(i32.const 0)
)
(i32.const -1)

View File

@ -5,18 +5,28 @@
(type $v (func))
(global $std/string/str (mut i32) (i32.const 8))
(global $std:string/HEAD i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 102))
(global $HEAP_BASE i32 (i32.const 118))
(memory $0 1)
(data (i32.const 8) "\10\00\00\00h\00i\00,\00 \00I\00\'\00m\00 \00a\00 \00s\00t\00r\00i\00n\00g\00")
(data (i32.const 48) "\02\00\00\00h\00i\00")
(data (i32.const 56) "\06\00\00\00s\00t\00r\00i\00n\00g\00")
(data (i32.const 72) "\03\00\00\00I\00\'\00m\00")
(data (i32.const 88) "\01\00\00\00,\00")
(data (i32.const 96) "\01\00\00\00x\00")
(data (i32.const 56) "\04\00\00\00n\00u\00l\00l\00")
(data (i32.const 72) "\06\00\00\00s\00t\00r\00i\00n\00g\00")
(data (i32.const 88) "\03\00\00\00I\00\'\00m\00")
(data (i32.const 104) "\01\00\00\00,\00")
(data (i32.const 112) "\01\00\00\00x\00")
(export "getString" (func $std/string/getString))
(export "memory" (memory $0))
(start $start)
(func $std:string/String#charCodeAt (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(if
(i32.eqz
(i32.ne
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.ge_u
(get_local $1)
@ -129,13 +139,13 @@
(unreachable)
)
(if
(i32.eqz
(i32.ne
(get_local $1)
(i32.const 0)
)
(i32.eq
(get_local $1)
(i32.const 0)
)
(set_local $1
(i32.const 56)
)
(unreachable)
)
(set_local $3
(get_local $2)
@ -221,12 +231,21 @@
(if
(i32.eqz
(i32.ne
(get_local $1)
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eq
(get_local $1)
(i32.const 0)
)
(return
(i32.const 0)
)
)
(set_local $5
(select
(tee_local $3
@ -310,12 +329,21 @@
(if
(i32.eqz
(i32.ne
(get_local $1)
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eq
(get_local $1)
(i32.const 0)
)
(set_local $1
(i32.const 56)
)
)
(set_local $3
(get_local $2)
)
@ -480,7 +508,7 @@
(i32.eqz
(call $std:string/String#endsWith
(get_global $std/string/str)
(i32.const 56)
(i32.const 72)
(i32.const 2147483647)
)
)
@ -490,7 +518,7 @@
(i32.eqz
(call $std:string/String#includes
(get_global $std/string/str)
(i32.const 72)
(i32.const 88)
(i32.const 0)
)
)
@ -501,7 +529,7 @@
(i32.eq
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 88)
(i32.const 104)
(i32.const 0)
)
(i32.const 2)
@ -514,7 +542,7 @@
(i32.eq
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 96)
(i32.const 112)
(i32.const 0)
)
(i32.sub
@ -606,6 +634,8 @@
GLOBAL: std:string/HEAD
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/String.__concat
FUNCTION_PROTOTYPE: std:string/String.__eq
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -8,6 +8,6 @@ b / ig;
false && /abc/gX.test(someString) || true;
// ERROR 1161: "Unterminated regular expression literal." in regexp.ts @ 75,76
// ERROR 1005: "'/' expected." in regexp.ts @ 74,76
// ERROR 109: "Invalid regular expression flags." in regexp.ts @ 95,98
// ERROR 109: "Invalid regular expression flags." in regexp.ts @ 111,113
// ERROR 109: "Invalid regular expression flags." in regexp.ts @ 131,133
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 95,98
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 111,113
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 131,133