mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-11 23:07:25 +00:00
Preliminary strings
While not well-wrought, it's at least possible now to log some stuff when debugging
This commit is contained in:
parent
b548b5c81f
commit
de066fc128
@ -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"
|
||||
);
|
||||
|
@ -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();
|
||||
|
@ -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 ///////////////////////////////////
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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.";
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
6
std/assembly.d.ts
vendored
@ -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;
|
||||
|
@ -163,7 +163,7 @@ export class Array<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@explicit
|
||||
@unmanaged
|
||||
export class CArray<T> {
|
||||
|
||||
private constructor() {}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
419
tests/compiler/std/string.optimized.wast
Normal file
419
tests/compiler/std/string.optimized.wast
Normal 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)
|
||||
)
|
||||
)
|
||||
)
|
18
tests/compiler/std/string.ts
Normal file
18
tests/compiler/std/string.ts
Normal 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;
|
||||
}
|
647
tests/compiler/std/string.wast
Normal file
647
tests/compiler/std/string.wast
Normal 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
|
||||
;)
|
Loading…
x
Reference in New Issue
Block a user