Preliminary strings

While not well-wrought, it's at least possible now to log some stuff when debugging
This commit is contained in:
dcodeIO 2018-01-27 05:35:14 +01:00
parent b548b5c81f
commit de066fc128
22 changed files with 1267 additions and 112 deletions

View File

@ -17,7 +17,7 @@ const FL_INDEX_COUNT: u32 = FL_INDEX_MAX - FL_INDEX_SHIFT + 1;
const SMALL_BLOCK_SIZE: u32 = 1 << FL_INDEX_SHIFT;
/** Block header structure. */
@explicit
@unmanaged
class BlockHeader {
/////////////////////////////// Constants ///////////////////////////////////
@ -41,7 +41,7 @@ class BlockHeader {
// the prev_phys_block field, and no larger than the number of addressable
// bits for FL_INDEX.
static readonly BLOCK_SIZE_MIN: usize = BlockHeader.SIZE - sizeof<usize>();
static readonly BLOCK_SIZE_MAX: usize = <usize>1 << FL_INDEX_MAX;
static readonly BLOCK_SIZE_MAX: usize = 1 << <usize>FL_INDEX_MAX;
///////////////////////////////// Fields ////////////////////////////////////
@ -157,7 +157,7 @@ class BlockHeader {
/** Marks this block as being 'free'. */
markAsFree(): void {
var next = this.linkNext(); // Link the block to the next block, first.
var next = this.linkNext(); // Link the block to the next block first.
next.tagAsPrevFree();
this.tagAsFree();
}
@ -206,7 +206,7 @@ class BlockHeader {
}
/** The TLSF control structure. */
@explicit
@unmanaged
class Control extends BlockHeader { // Empty lists point here, indicating free
// The control structure uses 3188 bytes in WASM32.
@ -297,6 +297,9 @@ class Control extends BlockHeader { // Empty lists point here, indicating free
block.next_free = current;
block.prev_free = this;
current.prev_free = block;
assert(block.isFree,
"block must be free"
);
assert(block.toDataPtr() == align_ptr(block.toDataPtr(), ALIGN_SIZE),
"block not aligned properly"
);

View File

@ -53,7 +53,7 @@ function test(file) {
tlsf.check_pool(0);
}
} finally {
mem(tlsf.memory, 0, 4096);
// mem(tlsf.memory, 0, 4096);
console.log("memSize=" + memSize);
}
console.log();

View File

@ -11,7 +11,7 @@ const SWEEP: u8 = 2;
const GRAY: u32 = 2;
/** Header for a managed object. */
@explicit
@unmanaged
class ObjectHeader {
/////////////////////////////// Constants ///////////////////////////////////
@ -73,7 +73,7 @@ class ObjectHeader {
}
/** Garbage collector data. */
@explicit
@unmanaged
class Control {
/////////////////////////////// Constants ///////////////////////////////////

View File

@ -361,8 +361,8 @@ export abstract class Node {
stmt.decoratorKind = DecoratorKind.OPERATOR;
break;
case "explicit":
stmt.decoratorKind = DecoratorKind.EXPLICIT;
case "unmanaged":
stmt.decoratorKind = DecoratorKind.UNMANAGED;
break;
case "offset":
@ -1159,7 +1159,7 @@ export const enum DecoratorKind {
CUSTOM,
GLOBAL,
OPERATOR,
EXPLICIT,
UNMANAGED,
OFFSET
}

View File

@ -1566,9 +1566,8 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
} else
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE);
// TODO: report message to embedder, requires strings
type = compiler.currentType;
// arg1 = operands.length == 2 ? compiler.compileExpression(operands[1], Type.string) : usizeType.toNativeZero(module);
arg1 = operands.length == 2 ? compiler.compileExpression(operands[1], compiler.options.usizeType) : compiler.options.usizeType.toNativeZero(module);
compiler.currentType = type.nonNullableType;
// just return ifTrueish if assertions are disabled, or simplify if dropped anyway

View File

@ -196,6 +196,8 @@ export class Compiler extends DiagnosticEmitter {
memoryOffset: U64 = new U64(8, 0); // leave space for (any size of) NULL
/** Memory segments being compiled. */
memorySegments: MemorySegment[] = new Array();
/** Map of already compiled static string segments. */
stringSegments: Map<string,MemorySegment> = new Map();
/** Already processed file names. */
files: Set<string> = new Set();
@ -2859,6 +2861,29 @@ export class Compiler extends DiagnosticEmitter {
this.currentType = contextualType.is(TypeFlags.SIGNED) ? Type.i32 : Type.u32;
return this.module.createI32(intValue.toI32());
case LiteralKind.STRING:
var stringValue = (<StringLiteralExpression>expression).value;
var stringSegment: MemorySegment | null = this.stringSegments.get(stringValue);
if (!stringSegment) {
var stringLength = stringValue.length;
var stringBuffer = new Uint8Array(4 + stringLength * 2);
stringBuffer[0] = stringLength & 0xff;
stringBuffer[1] = (stringLength >>> 8) & 0xff;
stringBuffer[2] = (stringLength >>> 16) & 0xff;
stringBuffer[3] = (stringLength >>> 24) & 0xff;
for (var i = 0; i < stringLength; ++i) {
stringBuffer[4 + i * 2] = stringValue.charCodeAt(i) & 0xff;
stringBuffer[5 + i * 2] = (stringValue.charCodeAt(i) >>> 8) & 0xff;
}
stringSegment = this.addMemorySegment(stringBuffer);
this.stringSegments.set(stringValue, stringSegment);
}
var stringOffset = stringSegment.offset;
this.currentType = this.options.usizeType;
return this.options.isWasm64
? this.module.createI64(stringOffset.lo, stringOffset.hi)
: this.module.createI32(stringOffset.lo);
// case LiteralKind.OBJECT:
// case LiteralKind.REGEXP:
// case LiteralKind.STRING:

View File

@ -78,6 +78,7 @@ export enum DiagnosticCode {
_get_and_set_accessor_must_have_the_same_type = 2380,
Constructor_implementation_is_missing = 2390,
Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391,
Multiple_constructor_implementations_are_not_allowed = 2392,
Duplicate_function_implementation = 2393,
Export_declaration_conflicts_with_exported_declaration_of_0 = 2484,
Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property = 2540,
@ -170,6 +171,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 2380: return "'get' and 'set' accessor must have the same type.";
case 2390: return "Constructor implementation is missing.";
case 2391: return "Function implementation is missing or not immediately following the declaration.";
case 2392: return "Multiple constructor implementations are not allowed.";
case 2393: return "Duplicate function implementation.";
case 2484: return "Export declaration conflicts with exported declaration of '{0}'.";
case 2540: return "Cannot assign to '{0}' because it is a constant or a read-only property.";

View File

@ -78,6 +78,7 @@
"'get' and 'set' accessor must have the same type.": 2380,
"Constructor implementation is missing.": 2390,
"Function implementation is missing or not immediately following the declaration.": 2391,
"Multiple constructor implementations are not allowed.": 2392,
"Duplicate function implementation.": 2393,
"Export declaration conflicts with exported declaration of '{0}'.": 2484,
"Cannot assign to '{0}' because it is a constant or a read-only property.": 2540,

View File

@ -741,13 +741,14 @@ export class Parser extends DiagnosticEmitter {
}
}
if (tn.skip(Token.CONSTRUCTOR) || tn.skip(Token.IDENTIFIER)) { // order is important
var identifier: IdentifierExpression = tn.token == Token.CONSTRUCTOR
var isConstructor = tn.skip(Token.CONSTRUCTOR);
if (isConstructor || tn.skip(Token.IDENTIFIER)) {
var identifier = isConstructor
? Node.createConstructorExpression(tn.range())
: Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
var typeParameters: TypeParameter[] | null;
if (tn.skip(Token.LESSTHAN)) {
if (identifier.kind == NodeKind.CONSTRUCTOR)
if (isConstructor)
this.error(DiagnosticCode.Type_parameters_cannot_appear_on_a_constructor_declaration, tn.range()); // recoverable
typeParameters = this.parseTypeParameters(tn);
if (!typeParameters)
@ -755,9 +756,6 @@ export class Parser extends DiagnosticEmitter {
} else
typeParameters = [];
if (identifier.kind == NodeKind.CONSTRUCTOR && tn.peek() != Token.OPENPAREN)
this.error(DiagnosticCode.Constructor_implementation_is_missing, tn.range());
// method: '(' Parameters (':' Type)? '{' Statement* '}' ';'?
if (tn.skip(Token.OPENPAREN)) {
var parameters = this.parseParameters(tn);
@ -802,6 +800,12 @@ export class Parser extends DiagnosticEmitter {
tn.skip(Token.SEMICOLON);
return retMethod;
} else if (isConstructor) {
this.error(DiagnosticCode.Constructor_implementation_is_missing, identifier.range());
} else if (isGetter || isSetter) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, identifier.range());
// field: (':' Type)? ('=' Expression)? ';'?
} else {
var modifier: Modifier | null;

View File

@ -276,15 +276,17 @@ export class Program extends DiagnosticEmitter {
} while (true);
}
private checkGlobalAlias(element: Element, declaration: DeclarationStatement) {
private checkGlobalAlias(element: Element, declaration: DeclarationStatement): bool {
if (hasDecorator("global", declaration.decorators) || (declaration.range.source.isStdlib && assert(declaration.parent).kind == NodeKind.SOURCE && element.is(ElementFlags.EXPORTED))) {
if (this.elements.has(declaration.name.name))
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, element.internalName);
else {
this.elements.set(declaration.name.name, element);
this.exports.set(declaration.name.name, element);
return true;
}
}
return false;
}
private initializeClass(declaration: ClassDeclaration, queuedDerivedClasses: ClassPrototype[], namespace: Element | null = null): void {
@ -297,10 +299,8 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace;
this.elements.set(internalName, prototype);
this.checkGlobalAlias(prototype, declaration);
if (hasDecorator("explicit", declaration.decorators)) {
prototype.isExplicit = true;
if (hasDecorator("unmanaged", declaration.decorators)) {
prototype.isUnmanaged = true;
if (declaration.implementsTypes && declaration.implementsTypes.length)
this.error(DiagnosticCode.Structs_cannot_implement_interfaces, Range.join(declaration.name.range, declaration.implementsTypes[declaration.implementsTypes.length - 1].range));
} else if (declaration.implementsTypes.length)
@ -352,6 +352,16 @@ export class Program extends DiagnosticEmitter {
throw new Error("class member expected");
}
}
if (this.checkGlobalAlias(prototype, declaration)) {
if (declaration.name.name === "String") {
var instance = prototype.resolve(null, null);
if (instance) {
assert(!this.types.has("string"));
this.types.set("string", instance.type);
}
}
}
}
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
@ -396,6 +406,7 @@ export class Program extends DiagnosticEmitter {
// static methods become global functions
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
assert(declaration.name.kind != NodeKind.CONSTRUCTOR);
if (this.elements.has(internalName)) {
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
@ -422,10 +433,16 @@ export class Program extends DiagnosticEmitter {
} else
classPrototype.instanceMembers = new Map();
instancePrototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype);
// if (classPrototype.isExplicit && instancePrototype.isAbstract) {
// this.error( Explicit classes cannot declare abstract methods. );
// if (classPrototype.isUnmanaged && instancePrototype.isAbstract) {
// this.error( Unmanaged classes cannot declare abstract methods. );
// }
classPrototype.instanceMembers.set(name, instancePrototype);
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;
}
}
// handle operator annotations. operators are instance methods taking a second argument of the
@ -1260,8 +1277,8 @@ export enum ElementFlags {
PRIVATE = 1 << 15,
/** Is an abstract member. */
ABSTRACT = 1 << 16,
/** Is an explicitly layed out and allocated class with limited capabilites. */
EXPLICIT = 1 << 17,
/** Is an unmanaged class with limited capabilites. */
UNMANAGED = 1 << 17,
/** Has already inherited base class static members. */
HAS_STATIC_BASE_MEMBERS = 1 << 18,
/** Is scoped. */
@ -1879,6 +1896,8 @@ export class ClassPrototype extends Element {
instanceMembers: Map<string,Element> | null = null;
/** Base class prototype, if applicable. */
basePrototype: ClassPrototype | null = null; // set in Program#initialize
/** Constructor prototype. */
constructorPrototype: FunctionPrototype | null = null;
/** Overloaded indexed get method, if any. */
fnIndexedGet: string | null = null;
@ -1907,9 +1926,9 @@ export class ClassPrototype extends Element {
}
}
/** Whether explicitly layed out and allocated */
get isExplicit(): bool { return (this.flags & ElementFlags.EXPLICIT) != 0; }
set isExplicit(is: bool) { if (is) this.flags |= ElementFlags.EXPLICIT; else this.flags &= ~ElementFlags.EXPLICIT; }
/** Whether an unamanaged class or not. */
get isUnmanaged(): bool { return (this.flags & ElementFlags.UNMANAGED) != 0; }
set isUnmanaged(is: bool) { if (is) this.flags |= ElementFlags.UNMANAGED; else this.flags &= ~ElementFlags.UNMANAGED; }
resolve(typeArguments: Type[] | null, contextualTypeArguments: Map<string,Type> | null = null): Class | null {
var instanceKey = typeArguments ? typesToString(typeArguments) : "";
@ -1937,7 +1956,7 @@ export class ClassPrototype extends Element {
this.program.error(DiagnosticCode.A_class_may_only_extend_another_class, declaration.extendsType.range);
return null;
}
if (baseClass.prototype.isExplicit != this.isExplicit) {
if (baseClass.prototype.isUnmanaged != this.isUnmanaged) {
this.program.error(DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa, Range.join(declaration.name.range, declaration.extendsType.range));
return null;
}

6
std/assembly.d.ts vendored
View File

@ -287,8 +287,8 @@ declare function global(target: Function): any;
/** Annotates a method as an operator overload. */
declare function operator(token: string): any;
/** Annotates a class as explicitly layed out and allocated. */
declare function explicit(target: Function): any;
/** Annotates a class as being unmanaged with limited capabilities. */
declare function unmanaged(target: Function): any;
/** Annoates a class field with an explicit offset. */
/** Annotates a class field with an explicit offset. */
declare function offset(offset: usize): any;

View File

@ -163,7 +163,7 @@ export class Array<T> {
}
}
@explicit
@unmanaged
export class CArray<T> {
private constructor() {}

View File

@ -1,93 +1,94 @@
const EMPTY: String = changetype<String>("");
function allocate(length: i32): String {
var ptr = allocate_memory(4 + length * 2);
store<i32>(ptr, length);
return changetype<String>(ptr);
}
@unmanaged
export class String {
private __memory: usize;
readonly length: i32;
constructor(ptr: usize, length: i32) {
if (length < 0)
throw new RangeError("invalid length");
this.__memory = ptr;
this.length = length;
}
@operator("[]")
charAt(pos: i32): String {
if (<u32>pos >= this.length)
return changetype<String>("");
return new String(this.__memory + (<usize>pos << 1), 1);
return EMPTY;
var out = allocate(1);
store<u16>(changetype<usize>(out), load<u16>(changetype<usize>(this) + (<usize>pos << 1), 4), 4);
return out;
}
charCodeAt(pos: i32): i32 {
if (<u32>pos >= this.length)
return -1; // NaN
return load<u16>(this.__memory + (<usize>pos << 1));
return load<u16>(changetype<usize>(this) + (<usize>pos << 1), 4);
}
codePointAt(pos: i32): i32 {
if (<u32>pos >= this.length)
return -1; // undefined
var first = <i32>load<u16>(this.__memory + (<usize>pos << 1));
var first = <i32>load<u16>(changetype<usize>(this) + (<usize>pos << 1), 4);
if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length)
return first;
var second = <i32>load<u16>(this.__memory + ((<usize>pos + 1) << 1));
var second = <i32>load<u16>(changetype<usize>(this) + ((<usize>pos + 1) << 1), 4);
if (second < 0xDC00 || second > 0xDFFF)
return first;
return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000;
}
@operator("+")
concat(other: this): String {
concat(other: String): String {
assert(this != null);
assert(other != null);
var thisLen: isize = this.length;
var otherLen: isize = other.length;
var len: usize = thisLen + otherLen;
var newMemory = allocate_memory(len << 1);
move_memory(newMemory, this.__memory, thisLen << 1);
move_memory(newMemory + (thisLen << 1), other.__memory, otherLen << 1);
return new String(newMemory, <i32>len);
var out = allocate(len);
move_memory(changetype<usize>(out) + 4, changetype<usize>(this) + 4, thisLen << 1);
move_memory(changetype<usize>(out) + 4 + (thisLen << 1), changetype<usize>(other) + 4, otherLen << 1);
return out;
}
endsWith(searchString: this, endPosition: i32 = 0x7fffffff): bool {
endsWith(searchString: String, endPosition: i32 = 0x7fffffff): bool {
assert(searchString != null);
var end: isize = <isize>min<i32>(max<i32>(endPosition, 0), this.length);
var searchLength: isize = searchString.length;
var start: isize = end - searchLength;
if (start < 0)
return false;
return !compare_memory(this.__memory + (start << 1), searchString.__memory, searchLength << 1);
return !compare_memory(changetype<usize>(this) + 4 + (start << 1), changetype<usize>(searchString) + 4, searchLength << 1);
}
@operator("==")
private __eq(other: this): bool {
private __eq(other: String): bool {
if (this == null)
return other == null;
else if (other == null)
return false;
if (this.length != other.length)
return false;
return !compare_memory(this.__memory, other.__memory, <usize>this.length);
return !compare_memory(changetype<usize>(this) + 4, changetype<usize>(other) + 4, <usize>(this.length << 1));
}
includes(searchString: this, position: i32 = 0): bool {
includes(searchString: String, position: i32 = 0): bool {
return this.indexOf(searchString, position) != -1;
}
indexOf(searchString: this, position: i32 = 0): i32 {
indexOf(searchString: String, position: i32 = 0): i32 {
assert(searchString != 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;
for (var k: usize = start; <isize>k + searchLen <= len; ++k)
if (!compare_memory(this.__memory + (k << 1), searchString.__memory, searchLen << 1))
if (!compare_memory(changetype<usize>(this) + 4 + (k << 1), changetype<usize>(searchString) + 4, searchLen << 1))
return <i32>k;
return -1;
}
startsWith(searchString: this, position: i32 = 0): bool {
startsWith(searchString: String, position: i32 = 0): bool {
assert(this != null);
assert(searchString != null);
var pos: isize = position;
@ -96,7 +97,7 @@ export class String {
var searchLength: isize = searchString.length;
if (searchLength + start > len)
return false;
return !compare_memory(this.__memory + (start << 1), searchString.__memory, searchLength << 1);
return !compare_memory(changetype<usize>(this) + 4 + (start << 1), changetype<usize>(searchString) + 4, searchLength << 1);
}
substr(start: i32, length: i32 = i32.MAX_VALUE): String {
@ -109,7 +110,9 @@ export class String {
var resultLength: isize = min<isize>(max<isize>(end, 0), size - intStart);
if (resultLength < 0)
return EMPTY;
return new String(this.__memory + (intStart << 1), <i32>resultLength);
var out = allocate(resultLength);
move_memory(changetype<usize>(out) + 4, changetype<usize>(this) + 4 + (intStart << 1), <usize>resultLength << 1);
return out;
}
substring(start: i32, end: i32 = i32.MAX_VALUE): String {
@ -124,46 +127,55 @@ export class String {
return EMPTY;
if (!from && to == this.length)
return this;
return new String(this.__memory + (from << 1), len);
var out = allocate(len);
move_memory(changetype<usize>(out) + 4, changetype<usize>(this) + 4 + (from << 1), len << 1);
return out;
}
trim(): String {
assert(this != null);
var length: usize = this.length;
while (length && isWhiteSpaceOrLineTerminator(load<u16>(this.__memory + (length << 1))))
while (length && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (length << 1), 4)))
--length;
var start: usize = 0;
while (start < length && isWhiteSpaceOrLineTerminator(load<u16>(this.__memory + (start << 1)))) {
while (start < length && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (start << 1), 4))) {
++start; --length;
}
if (!length)
return EMPTY;
if (!start && length == this.length)
return this;
return new String(this.__memory + (start << 1), length);
var out = allocate(length);
move_memory(changetype<usize>(out) + 4, changetype<usize>(this) + 4 + (start << 1), length << 1);
return out;
}
trimLeft(): String {
assert(this != null);
var start: isize = 0;
var len: isize = this.length;
while (start < len && isWhiteSpaceOrLineTerminator(load<u16>(this.__memory + (start << 1))))
while (start < len && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (start << 1), 4)))
++start;
if (!start)
return this;
return new String(this.__memory + (start << 1), <i32>(len - start));
var outLen = len - start;
var out = allocate(outLen);
move_memory(changetype<usize>(out) + 4, changetype<usize>(this) + 4 + (start << 1), outLen << 1);
return out;
}
trimRight(): String {
assert(this != null);
var len: isize = this.length;
while (len > 0 && isWhiteSpaceOrLineTerminator(load<u16>(this.__memory + (len << 1))))
while (len > 0 && isWhiteSpaceOrLineTerminator(load<u16>(changetype<usize>(this) + (len << 1), 4)))
--len;
if (len <= 0)
return EMPTY;
if (<i32>len == this.length)
return this;
return new String(this.__memory, <i32>len);
var out = allocate(len);
move_memory(changetype<usize>(out) + 4, changetype<usize>(this) + 4, len << 1);
return out;
}
}

View File

@ -1,6 +1,7 @@
(module
(type $v (func))
(memory $0 1)
(data (i32.const 8) "\0c\00\00\00m\00u\00s\00t\00 \00b\00e\00 \00t\00r\00u\00e")
(export "memory" (memory $0))
(start $start)
(func $start (; 0 ;) (type $v)

View File

@ -1,7 +1,8 @@
(module
(type $v (func))
(global $HEAP_BASE i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 36))
(memory $0 1)
(data (i32.const 8) "\0c\00\00\00m\00u\00s\00t\00 \00b\00e\00 \00t\00r\00u\00e\00")
(export "memory" (memory $0))
(start $start)
(func $start (; 0 ;) (type $v)

View File

@ -4037,8 +4037,8 @@
FUNCTION_PROTOTYPE: usize
GLOBAL: HEAP_BASE
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: Array
PROPERTY: std:array/Array#length
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
@ -4065,9 +4065,10 @@
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: Set
PROPERTY: std:set/Set#size
CLASS_PROTOTYPE: Set
GLOBAL: std:string/EMPTY
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
@ -4078,14 +4079,14 @@
GLOBAL: std/array/arr
GLOBAL: std/array/i
[program.exports]
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError
FUNCTION_PROTOTYPE: allocate_memory
FUNCTION_PROTOTYPE: std:heap/allocate_memory
FUNCTION_PROTOTYPE: free_memory
@ -4096,14 +4097,14 @@
FUNCTION_PROTOTYPE: std:heap/set_memory
FUNCTION_PROTOTYPE: compare_memory
FUNCTION_PROTOTYPE: std:heap/compare_memory
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: String
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseFloat

View File

@ -250,8 +250,8 @@
FUNCTION_PROTOTYPE: usize
GLOBAL: HEAP_BASE
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: Array
PROPERTY: std:array/Array#length
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
@ -278,9 +278,10 @@
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: Set
PROPERTY: std:set/Set#size
CLASS_PROTOTYPE: Set
GLOBAL: std:string/EMPTY
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
@ -290,14 +291,14 @@
FUNCTION_PROTOTYPE: parseFloat
GLOBAL: std/carray/arr
[program.exports]
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError
FUNCTION_PROTOTYPE: allocate_memory
FUNCTION_PROTOTYPE: std:heap/allocate_memory
FUNCTION_PROTOTYPE: free_memory
@ -308,14 +309,14 @@
FUNCTION_PROTOTYPE: std:heap/set_memory
FUNCTION_PROTOTYPE: compare_memory
FUNCTION_PROTOTYPE: std:heap/compare_memory
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: String
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseFloat

View File

@ -2833,8 +2833,8 @@
FUNCTION_PROTOTYPE: usize
GLOBAL: HEAP_BASE
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: Array
PROPERTY: std:array/Array#length
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
@ -2861,9 +2861,10 @@
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: Set
PROPERTY: std:set/Set#size
CLASS_PROTOTYPE: Set
GLOBAL: std:string/EMPTY
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
@ -2876,14 +2877,14 @@
GLOBAL: std/heap/ptr2
GLOBAL: std/heap/i
[program.exports]
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError
FUNCTION_PROTOTYPE: allocate_memory
FUNCTION_PROTOTYPE: std:heap/allocate_memory
FUNCTION_PROTOTYPE: free_memory
@ -2894,14 +2895,14 @@
FUNCTION_PROTOTYPE: std:heap/set_memory
FUNCTION_PROTOTYPE: compare_memory
FUNCTION_PROTOTYPE: std:heap/compare_memory
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: String
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseFloat

View File

@ -2726,8 +2726,8 @@
FUNCTION_PROTOTYPE: usize
GLOBAL: HEAP_BASE
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: Array
PROPERTY: std:array/Array#length
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
@ -2754,9 +2754,10 @@
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: Set
PROPERTY: std:set/Set#size
CLASS_PROTOTYPE: Set
GLOBAL: std:string/EMPTY
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
@ -2766,14 +2767,14 @@
FUNCTION_PROTOTYPE: parseFloat
GLOBAL: std/set/set
[program.exports]
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError
FUNCTION_PROTOTYPE: allocate_memory
FUNCTION_PROTOTYPE: std:heap/allocate_memory
FUNCTION_PROTOTYPE: free_memory
@ -2784,14 +2785,14 @@
FUNCTION_PROTOTYPE: std:heap/set_memory
FUNCTION_PROTOTYPE: compare_memory
FUNCTION_PROTOTYPE: std:heap/compare_memory
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: String
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseFloat

View File

@ -0,0 +1,419 @@
(module
(type $i (func (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")
(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)
(if
(i32.eq
(get_local $0)
(get_local $1)
)
(return
(i32.const 0)
)
)
(loop $continue|0
(if
(if (result i32)
(get_local $2)
(i32.eq
(i32.load8_u
(get_local $0)
)
(i32.load8_u
(get_local $1)
)
)
(get_local $2)
)
(block
(set_local $2
(i32.sub
(get_local $2)
(i32.const 1)
)
)
(set_local $0
(i32.add
(get_local $0)
(i32.const 1)
)
)
(set_local $1
(i32.add
(get_local $1)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
(if (result i32)
(get_local $2)
(i32.sub
(i32.load8_u
(get_local $0)
)
(i32.load8_u
(get_local $1)
)
)
(i32.const 0)
)
)
(func $std:string/String#startsWith (; 1 ;) (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 $0)
)
(unreachable)
)
(if
(i32.eqz
(get_local $1)
)
(unreachable)
)
(if
(i32.gt_s
(i32.add
(tee_local $4
(i32.load
(get_local $1)
)
)
(tee_local $2
(select
(tee_local $2
(select
(get_local $2)
(i32.const 0)
(i32.gt_s
(get_local $2)
(get_local $3)
)
)
)
(tee_local $3
(tee_local $5
(i32.load
(get_local $0)
)
)
)
(i32.lt_s
(get_local $2)
(get_local $3)
)
)
)
)
(get_local $5)
)
(return
(i32.const 0)
)
)
(i32.eqz
(call $std:heap/compare_memory
(i32.add
(i32.add
(get_local $0)
(i32.const 4)
)
(i32.shl
(get_local $2)
(i32.const 1)
)
)
(i32.add
(get_local $1)
(i32.const 4)
)
(i32.shl
(get_local $4)
(i32.const 1)
)
)
)
)
(func $std:string/String#endsWith (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(if
(i32.eqz
(get_local $1)
)
(unreachable)
)
(if
(i32.lt_s
(tee_local $3
(i32.sub
(select
(tee_local $2
(select
(get_local $2)
(i32.const 0)
(i32.gt_s
(get_local $2)
(get_local $3)
)
)
)
(tee_local $3
(i32.load
(get_local $0)
)
)
(i32.lt_s
(get_local $2)
(get_local $3)
)
)
(tee_local $2
(i32.load
(get_local $1)
)
)
)
)
(i32.const 0)
)
(return
(i32.const 0)
)
)
(i32.eqz
(call $std:heap/compare_memory
(i32.add
(i32.add
(get_local $0)
(i32.const 4)
)
(i32.shl
(get_local $3)
(i32.const 1)
)
)
(i32.add
(get_local $1)
(i32.const 4)
)
(i32.shl
(get_local $2)
(i32.const 1)
)
)
)
)
(func $std:string/String#indexOf (; 3 ;) (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)
)
(unreachable)
)
(set_local $4
(i32.load
(get_local $1)
)
)
(set_local $2
(select
(tee_local $2
(select
(get_local $2)
(i32.const 0)
(i32.gt_s
(get_local $2)
(get_local $3)
)
)
)
(tee_local $3
(tee_local $5
(i32.load
(get_local $0)
)
)
)
(i32.lt_s
(get_local $2)
(get_local $3)
)
)
)
(loop $continue|0
(if
(i32.le_s
(i32.add
(get_local $2)
(get_local $4)
)
(get_local $5)
)
(block
(if
(i32.eqz
(call $std:heap/compare_memory
(i32.add
(i32.add
(get_local $0)
(i32.const 4)
)
(i32.shl
(get_local $2)
(i32.const 1)
)
)
(i32.add
(get_local $1)
(i32.const 4)
)
(i32.shl
(get_local $4)
(i32.const 1)
)
)
)
(return
(get_local $2)
)
)
(set_local $2
(i32.add
(get_local $2)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
(i32.const -1)
)
(func $std/string/getString (; 4 ;) (type $i) (result i32)
(get_global $std/string/str)
)
(func $start (; 5 ;) (type $v)
(local $0 i32)
(if
(i32.ne
(get_global $std/string/str)
(i32.const 8)
)
(unreachable)
)
(if
(i32.ne
(i32.load
(get_global $std/string/str)
)
(i32.const 16)
)
(unreachable)
)
(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)
)
)
)
(i32.const 104)
)
(unreachable)
)
(if
(i32.eqz
(call $std:string/String#startsWith
(get_global $std/string/str)
(i32.const 48)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(call $std:string/String#endsWith
(get_global $std/string/str)
(i32.const 56)
(i32.const 2147483647)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.ne
(call $std:string/String#indexOf
(tee_local $0
(get_global $std/string/str)
)
(i32.const 72)
(i32.const 0)
)
(i32.const -1)
)
)
(unreachable)
)
(if
(i32.ne
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 88)
(i32.const 0)
)
(i32.const 2)
)
(unreachable)
)
(if
(i32.ne
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 96)
(i32.const 0)
)
(i32.const -1)
)
(unreachable)
)
)
)

View File

@ -0,0 +1,18 @@
// preliminary
var str: string = "hi, I'm a string";
// exactly once in static memory
assert(changetype<usize>(str) === changetype<usize>("hi, I'm a string"));
assert(str.length == 16);
assert(str.charCodeAt(0) == 0x68);
assert(str.startsWith("hi"));
assert(str.endsWith("string"));
assert(str.includes("I'm"));
assert(str.indexOf(",") == 2);
assert(str.indexOf("x") == -1);
export function getString(): string {
return str;
}

View File

@ -0,0 +1,647 @@
(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))
(global $HEAP_BASE i32 (i32.const 102))
(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")
(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.ge_u
(get_local $1)
(i32.load
(get_local $0)
)
)
(return
(i32.sub
(i32.const 0)
(i32.const 1)
)
)
)
(return
(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)
(get_local $1)
)
(return
(i32.const 0)
)
)
(block $break|0
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(i32.eq
(i32.load8_u
(get_local $0)
)
(i32.load8_u
(get_local $1)
)
)
(get_local $2)
)
(block
(block
(set_local $2
(i32.sub
(get_local $2)
(i32.const 1)
)
)
(set_local $0
(i32.add
(get_local $0)
(i32.const 1)
)
)
(set_local $1
(i32.add
(get_local $1)
(i32.const 1)
)
)
)
(br $continue|0)
)
)
)
)
(return
(if (result i32)
(get_local $2)
(i32.sub
(i32.load8_u
(get_local $0)
)
(i32.load8_u
(get_local $1)
)
)
(i32.const 0)
)
)
)
(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)
(local $6 i32)
(local $7 i32)
(local $8 i32)
(if
(i32.eqz
(i32.ne
(get_local $0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.ne
(get_local $1)
(i32.const 0)
)
)
(unreachable)
)
(set_local $3
(get_local $2)
)
(set_local $4
(i32.load
(get_local $0)
)
)
(set_local $7
(select
(tee_local $5
(select
(tee_local $5
(get_local $2)
)
(tee_local $6
(i32.const 0)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(tee_local $6
(get_local $4)
)
(i32.lt_s
(get_local $5)
(get_local $6)
)
)
)
(set_local $8
(i32.load
(get_local $1)
)
)
(if
(i32.gt_s
(i32.add
(get_local $8)
(get_local $7)
)
(get_local $4)
)
(return
(i32.const 0)
)
)
(return
(i32.eqz
(call $std:heap/compare_memory
(i32.add
(i32.add
(get_local $0)
(i32.const 4)
)
(i32.shl
(get_local $7)
(i32.const 1)
)
)
(i32.add
(get_local $1)
(i32.const 4)
)
(i32.shl
(get_local $8)
(i32.const 1)
)
)
)
)
)
(func $std:string/String#endsWith (; 3 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
(local $7 i32)
(if
(i32.eqz
(i32.ne
(get_local $1)
(i32.const 0)
)
)
(unreachable)
)
(set_local $5
(select
(tee_local $3
(select
(tee_local $3
(get_local $2)
)
(tee_local $4
(i32.const 0)
)
(i32.gt_s
(get_local $3)
(get_local $4)
)
)
)
(tee_local $4
(i32.load
(get_local $0)
)
)
(i32.lt_s
(get_local $3)
(get_local $4)
)
)
)
(set_local $6
(i32.load
(get_local $1)
)
)
(set_local $7
(i32.sub
(get_local $5)
(get_local $6)
)
)
(if
(i32.lt_s
(get_local $7)
(i32.const 0)
)
(return
(i32.const 0)
)
)
(return
(i32.eqz
(call $std:heap/compare_memory
(i32.add
(i32.add
(get_local $0)
(i32.const 4)
)
(i32.shl
(get_local $7)
(i32.const 1)
)
)
(i32.add
(get_local $1)
(i32.const 4)
)
(i32.shl
(get_local $6)
(i32.const 1)
)
)
)
)
)
(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)
(local $6 i32)
(local $7 i32)
(local $8 i32)
(local $9 i32)
(if
(i32.eqz
(i32.ne
(get_local $1)
(i32.const 0)
)
)
(unreachable)
)
(set_local $3
(get_local $2)
)
(set_local $4
(i32.load
(get_local $0)
)
)
(set_local $7
(select
(tee_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(i32.const 0)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(tee_local $6
(get_local $4)
)
(i32.lt_s
(get_local $5)
(get_local $6)
)
)
)
(set_local $8
(i32.load
(get_local $1)
)
)
(block $break|0
(set_local $9
(get_local $7)
)
(loop $continue|0
(if
(i32.le_s
(i32.add
(get_local $9)
(get_local $8)
)
(get_local $4)
)
(block
(if
(i32.eqz
(call $std:heap/compare_memory
(i32.add
(i32.add
(get_local $0)
(i32.const 4)
)
(i32.shl
(get_local $9)
(i32.const 1)
)
)
(i32.add
(get_local $1)
(i32.const 4)
)
(i32.shl
(get_local $8)
(i32.const 1)
)
)
)
(return
(get_local $9)
)
)
(set_local $9
(i32.add
(get_local $9)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
)
(return
(i32.sub
(i32.const 0)
(i32.const 1)
)
)
)
(func $std:string/String#includes (; 5 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(return
(i32.ne
(call $std:string/String#indexOf
(get_local $0)
(get_local $1)
(get_local $2)
)
(i32.sub
(i32.const 0)
(i32.const 1)
)
)
)
)
(func $std/string/getString (; 6 ;) (type $i) (result i32)
(return
(get_global $std/string/str)
)
)
(func $start (; 7 ;) (type $v)
(if
(i32.eqz
(i32.eq
(get_global $std/string/str)
(i32.const 8)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.load
(get_global $std/string/str)
)
(i32.const 16)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $std:string/String#charCodeAt
(get_global $std/string/str)
(i32.const 0)
)
(i32.const 104)
)
)
(unreachable)
)
(if
(i32.eqz
(call $std:string/String#startsWith
(get_global $std/string/str)
(i32.const 48)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(call $std:string/String#endsWith
(get_global $std/string/str)
(i32.const 56)
(i32.const 2147483647)
)
)
(unreachable)
)
(if
(i32.eqz
(call $std:string/String#includes
(get_global $std/string/str)
(i32.const 72)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 88)
(i32.const 0)
)
(i32.const 2)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $std:string/String#indexOf
(get_global $std/string/str)
(i32.const 96)
(i32.const 0)
)
(i32.sub
(i32.const 0)
(i32.const 1)
)
)
)
(unreachable)
)
)
)
(;
[program.elements]
GLOBAL: NaN
GLOBAL: Infinity
FUNCTION_PROTOTYPE: isNaN
FUNCTION_PROTOTYPE: isFinite
FUNCTION_PROTOTYPE: clz
FUNCTION_PROTOTYPE: ctz
FUNCTION_PROTOTYPE: popcnt
FUNCTION_PROTOTYPE: rotl
FUNCTION_PROTOTYPE: rotr
FUNCTION_PROTOTYPE: abs
FUNCTION_PROTOTYPE: max
FUNCTION_PROTOTYPE: min
FUNCTION_PROTOTYPE: ceil
FUNCTION_PROTOTYPE: floor
FUNCTION_PROTOTYPE: copysign
FUNCTION_PROTOTYPE: nearest
FUNCTION_PROTOTYPE: reinterpret
FUNCTION_PROTOTYPE: sqrt
FUNCTION_PROTOTYPE: trunc
FUNCTION_PROTOTYPE: load
FUNCTION_PROTOTYPE: store
FUNCTION_PROTOTYPE: sizeof
FUNCTION_PROTOTYPE: select
FUNCTION_PROTOTYPE: unreachable
FUNCTION_PROTOTYPE: current_memory
FUNCTION_PROTOTYPE: grow_memory
FUNCTION_PROTOTYPE: changetype
FUNCTION_PROTOTYPE: assert
FUNCTION_PROTOTYPE: i8
FUNCTION_PROTOTYPE: i16
FUNCTION_PROTOTYPE: i32
FUNCTION_PROTOTYPE: i64
FUNCTION_PROTOTYPE: u8
FUNCTION_PROTOTYPE: u16
FUNCTION_PROTOTYPE: u32
FUNCTION_PROTOTYPE: u64
FUNCTION_PROTOTYPE: bool
FUNCTION_PROTOTYPE: f32
FUNCTION_PROTOTYPE: f64
FUNCTION_PROTOTYPE: isize
FUNCTION_PROTOTYPE: usize
GLOBAL: HEAP_BASE
CLASS_PROTOTYPE: std:array/Array
PROPERTY: std:array/Array#length
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError
GLOBAL: std:heap/ALIGN_LOG2
GLOBAL: std:heap/ALIGN_SIZE
GLOBAL: std:heap/ALIGN_MASK
GLOBAL: std:heap/HEAP_OFFSET
FUNCTION_PROTOTYPE: std:heap/allocate_memory
FUNCTION_PROTOTYPE: allocate_memory
FUNCTION_PROTOTYPE: std:heap/free_memory
FUNCTION_PROTOTYPE: free_memory
FUNCTION_PROTOTYPE: std:heap/copy_memory
FUNCTION_PROTOTYPE: std:heap/move_memory
FUNCTION_PROTOTYPE: move_memory
FUNCTION_PROTOTYPE: std:heap/set_memory
FUNCTION_PROTOTYPE: set_memory
FUNCTION_PROTOTYPE: std:heap/compare_memory
FUNCTION_PROTOTYPE: compare_memory
CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
PROPERTY: std:set/Set#size
CLASS_PROTOTYPE: Set
GLOBAL: std:string/EMPTY
FUNCTION_PROTOTYPE: std:string/allocate
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseFloat
FUNCTION_PROTOTYPE: parseFloat
GLOBAL: std/string/str
FUNCTION_PROTOTYPE: std/string/getString
[program.exports]
CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: Array
CLASS_PROTOTYPE: std:array/CArray
CLASS_PROTOTYPE: CArray
CLASS_PROTOTYPE: std:error/Error
CLASS_PROTOTYPE: Error
CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError
FUNCTION_PROTOTYPE: allocate_memory
FUNCTION_PROTOTYPE: std:heap/allocate_memory
FUNCTION_PROTOTYPE: free_memory
FUNCTION_PROTOTYPE: std:heap/free_memory
FUNCTION_PROTOTYPE: move_memory
FUNCTION_PROTOTYPE: std:heap/move_memory
FUNCTION_PROTOTYPE: set_memory
FUNCTION_PROTOTYPE: std:heap/set_memory
FUNCTION_PROTOTYPE: compare_memory
FUNCTION_PROTOTYPE: std:heap/compare_memory
CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: RegExp
CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: Set
CLASS_PROTOTYPE: std:string/String
CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseFloat
FUNCTION_PROTOTYPE: std:string/parseFloat
FUNCTION_PROTOTYPE: std/string/getString
;)