mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Binary expression operator overloads for +/==; Check allocation flow in ternary expressions; Cache empty array buffers; Sealed decorator for non-derivable internals
This commit is contained in:
parent
9cc0fcd611
commit
4adb69f73a
2
dist/asc.js
vendored
2
dist/asc.js
vendored
File diff suppressed because one or more lines are too long
2
dist/asc.js.map
vendored
2
dist/asc.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js
vendored
2
dist/assemblyscript.js
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js.map
vendored
2
dist/assemblyscript.js.map
vendored
File diff suppressed because one or more lines are too long
@ -2672,7 +2672,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
expr = module.createBinary(BinaryOp.EqI32, leftExpr, rightExpr);
|
expr = module.createBinary(BinaryOp.EqI32, leftExpr, rightExpr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TypeKind.USIZE: // TODO: check operator overload
|
case TypeKind.USIZE: { // check operator overload
|
||||||
|
if (this.currentType.is(TypeFlags.REFERENCE)) {
|
||||||
|
let classInstance = assert(this.currentType.classReference);
|
||||||
|
let operatorName = classInstance.prototype.fnEquals;
|
||||||
|
if (operatorName != null) {
|
||||||
|
expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr);
|
||||||
|
assert(this.currentType == Type.bool);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fall-through
|
||||||
|
}
|
||||||
case TypeKind.ISIZE: {
|
case TypeKind.ISIZE: {
|
||||||
expr = module.createBinary(
|
expr = module.createBinary(
|
||||||
this.options.isWasm64
|
this.options.isWasm64
|
||||||
@ -2822,7 +2833,17 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
expr = module.createBinary(BinaryOp.AddI32, leftExpr, rightExpr);
|
expr = module.createBinary(BinaryOp.AddI32, leftExpr, rightExpr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TypeKind.USIZE: // TODO: check operator overload
|
case TypeKind.USIZE: { // check operator overload
|
||||||
|
if (this.currentType.is(TypeFlags.REFERENCE)) {
|
||||||
|
let classInstance = assert(this.currentType.classReference);
|
||||||
|
let operatorName = classInstance.prototype.fnConcat;
|
||||||
|
if (operatorName != null) {
|
||||||
|
expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fall-through
|
||||||
|
}
|
||||||
case TypeKind.ISIZE: {
|
case TypeKind.ISIZE: {
|
||||||
expr = module.createBinary(
|
expr = module.createBinary(
|
||||||
this.options.isWasm64
|
this.options.isWasm64
|
||||||
@ -3726,6 +3747,20 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
: expr;
|
: expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileOperatorOverload(
|
||||||
|
classInstance: Class,
|
||||||
|
operatorName: string,
|
||||||
|
leftExpr: ExpressionRef,
|
||||||
|
rightExpr: ExpressionRef
|
||||||
|
): ExpressionRef {
|
||||||
|
var classPrototype = classInstance.prototype;
|
||||||
|
var operatorPrototype = assert(assert(classPrototype.members).get(operatorName));
|
||||||
|
assert(operatorPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||||
|
var operatorInstance = (<FunctionPrototype>operatorPrototype).resolve();
|
||||||
|
if (!operatorInstance) return this.module.createUnreachable();
|
||||||
|
return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ]);
|
||||||
|
}
|
||||||
|
|
||||||
compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
|
compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
|
||||||
var currentFunction = this.currentFunction;
|
var currentFunction = this.currentFunction;
|
||||||
var resolved = this.program.resolveExpression(expression, currentFunction); // reports
|
var resolved = this.program.resolveExpression(expression, currentFunction); // reports
|
||||||
@ -4526,7 +4561,6 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
assert(parent.kind == ElementKind.CLASS);
|
assert(parent.kind == ElementKind.CLASS);
|
||||||
let thisType = (<Class>parent).type;
|
let thisType = (<Class>parent).type;
|
||||||
if (currentFunction.is(CommonFlags.CONSTRUCTOR)) {
|
if (currentFunction.is(CommonFlags.CONSTRUCTOR)) {
|
||||||
let nativeSizeType = this.options.nativeSizeType;
|
|
||||||
let flow = currentFunction.flow;
|
let flow = currentFunction.flow;
|
||||||
if (!flow.is(FlowFlags.ALLOCATES)) {
|
if (!flow.is(FlowFlags.ALLOCATES)) {
|
||||||
flow.set(FlowFlags.ALLOCATES);
|
flow.set(FlowFlags.ALLOCATES);
|
||||||
@ -5152,8 +5186,36 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
: this.compileExpression(ifElse, contextualType);
|
: this.compileExpression(ifElse, contextualType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ifThenExpr = this.compileExpression(ifThen, contextualType);
|
var currentFunction = this.currentFunction;
|
||||||
var ifElseExpr = this.compileExpression(ifElse, contextualType);
|
var ifThenExpr: ExpressionRef;
|
||||||
|
var ifElseExpr: ExpressionRef;
|
||||||
|
|
||||||
|
// if part of a constructor, keep track of memory allocations
|
||||||
|
if (currentFunction.is(CommonFlags.CONSTRUCTOR)) {
|
||||||
|
let flow = currentFunction.flow;
|
||||||
|
|
||||||
|
flow = flow.enterBranchOrScope();
|
||||||
|
currentFunction.flow = flow;
|
||||||
|
ifThenExpr = this.compileExpression(ifThen, contextualType);
|
||||||
|
let ifThenAllocates = flow.is(FlowFlags.ALLOCATES);
|
||||||
|
flow = flow.leaveBranchOrScope();
|
||||||
|
currentFunction.flow = flow;
|
||||||
|
|
||||||
|
flow = flow.enterBranchOrScope();
|
||||||
|
currentFunction.flow = flow;
|
||||||
|
ifElseExpr = this.compileExpression(ifElse, contextualType);
|
||||||
|
let ifElseAllocates = flow.is(FlowFlags.ALLOCATES);
|
||||||
|
flow = flow.leaveBranchOrScope();
|
||||||
|
currentFunction.flow = flow;
|
||||||
|
|
||||||
|
if (ifThenAllocates && ifElseAllocates) flow.set(FlowFlags.ALLOCATES);
|
||||||
|
|
||||||
|
// otherwise simplify
|
||||||
|
} else {
|
||||||
|
ifThenExpr = this.compileExpression(ifThen, contextualType);
|
||||||
|
ifElseExpr = this.compileExpression(ifElse, contextualType);
|
||||||
|
}
|
||||||
|
|
||||||
return this.module.createIf(condExpr, ifThenExpr, ifElseExpr);
|
return this.module.createIf(condExpr, ifThenExpr, ifElseExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ export enum DiagnosticCode {
|
|||||||
Structs_cannot_implement_interfaces = 208,
|
Structs_cannot_implement_interfaces = 208,
|
||||||
Invalid_regular_expression_flags = 209,
|
Invalid_regular_expression_flags = 209,
|
||||||
Implementation_0_must_match_the_signature_1 = 210,
|
Implementation_0_must_match_the_signature_1 = 210,
|
||||||
|
Class_0_is_sealed_and_cannot_be_extended = 211,
|
||||||
Unterminated_string_literal = 1002,
|
Unterminated_string_literal = 1002,
|
||||||
Identifier_expected = 1003,
|
Identifier_expected = 1003,
|
||||||
_0_expected = 1005,
|
_0_expected = 1005,
|
||||||
@ -122,6 +123,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
|||||||
case 208: return "Structs cannot implement interfaces.";
|
case 208: return "Structs cannot implement interfaces.";
|
||||||
case 209: return "Invalid regular expression flags.";
|
case 209: return "Invalid regular expression flags.";
|
||||||
case 210: return "Implementation '{0}' must match the signature '{1}'.";
|
case 210: return "Implementation '{0}' must match the signature '{1}'.";
|
||||||
|
case 211: return "Class '{0}' is sealed and cannot be extended.";
|
||||||
case 1002: return "Unterminated string literal.";
|
case 1002: return "Unterminated string literal.";
|
||||||
case 1003: return "Identifier expected.";
|
case 1003: return "Identifier expected.";
|
||||||
case 1005: return "'{0}' expected.";
|
case 1005: return "'{0}' expected.";
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"Structs cannot implement interfaces.": 208,
|
"Structs cannot implement interfaces.": 208,
|
||||||
"Invalid regular expression flags.": 209,
|
"Invalid regular expression flags.": 209,
|
||||||
"Implementation '{0}' must match the signature '{1}'.": 210,
|
"Implementation '{0}' must match the signature '{1}'.": 210,
|
||||||
|
"Class '{0}' is sealed and cannot be extended.": 211,
|
||||||
|
|
||||||
"Unterminated string literal.": 1002,
|
"Unterminated string literal.": 1002,
|
||||||
"Identifier expected.": 1003,
|
"Identifier expected.": 1003,
|
||||||
|
@ -171,6 +171,10 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
flags |= CommonFlags.UNMANAGED;
|
flags |= CommonFlags.UNMANAGED;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (text == "sealed") {
|
||||||
|
flags |= CommonFlags.SEALED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!decorators) decorators = [];
|
if (!decorators) decorators = [];
|
||||||
decorators.push(decorator);
|
decorators.push(decorator);
|
||||||
|
@ -2041,34 +2041,36 @@ export enum CommonFlags {
|
|||||||
BUILTIN = 1 << 14,
|
BUILTIN = 1 << 14,
|
||||||
/** Is unmanaged. */
|
/** Is unmanaged. */
|
||||||
UNMANAGED = 1 << 15,
|
UNMANAGED = 1 << 15,
|
||||||
|
/** Is sealed. */
|
||||||
|
SEALED = 1 << 16,
|
||||||
|
|
||||||
// Extended modifiers usually derived from basic modifiers or internal decorators
|
// Extended modifiers usually derived from basic modifiers or internal decorators
|
||||||
|
|
||||||
/** Is ambient, that is either declared or nested in a declared element. */
|
/** Is ambient, that is either declared or nested in a declared element. */
|
||||||
AMBIENT = 1 << 16,
|
AMBIENT = 1 << 17,
|
||||||
/** Is generic. */
|
/** Is generic. */
|
||||||
GENERIC = 1 << 17,
|
GENERIC = 1 << 18,
|
||||||
/** Is part of a generic context. */
|
/** Is part of a generic context. */
|
||||||
GENERIC_CONTEXT = 1 << 18,
|
GENERIC_CONTEXT = 1 << 19,
|
||||||
/** Is an instance member. */
|
/** Is an instance member. */
|
||||||
INSTANCE = 1 << 19,
|
INSTANCE = 1 << 20,
|
||||||
/** Is a constructor. */
|
/** Is a constructor. */
|
||||||
CONSTRUCTOR = 1 << 20,
|
CONSTRUCTOR = 1 << 21,
|
||||||
/** Is an arrow function. */
|
/** Is an arrow function. */
|
||||||
ARROW = 1 << 21,
|
ARROW = 1 << 22,
|
||||||
/** Is a module export. */
|
/** Is a module export. */
|
||||||
MODULE_EXPORT = 1 << 22,
|
MODULE_EXPORT = 1 << 23,
|
||||||
/** Is a module import. */
|
/** Is a module import. */
|
||||||
MODULE_IMPORT = 1 << 23,
|
MODULE_IMPORT = 1 << 24,
|
||||||
|
|
||||||
// Compilation states
|
// Compilation states
|
||||||
|
|
||||||
/** Is compiled. */
|
/** Is compiled. */
|
||||||
COMPILED = 1 << 24,
|
COMPILED = 1 << 25,
|
||||||
/** Has a constant value and is therefore inlined. */
|
/** Has a constant value and is therefore inlined. */
|
||||||
INLINED = 1 << 25,
|
INLINED = 1 << 26,
|
||||||
/** Is scoped. */
|
/** Is scoped. */
|
||||||
SCOPED = 1 << 26
|
SCOPED = 1 << 27
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base class of all program elements. */
|
/** Base class of all program elements. */
|
||||||
@ -2873,6 +2875,13 @@ export class ClassPrototype extends Element {
|
|||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (baseClass.is(CommonFlags.SEALED)) {
|
||||||
|
this.program.error(
|
||||||
|
DiagnosticCode.Class_0_is_sealed_and_cannot_be_extended,
|
||||||
|
declaration.extendsType.range, baseClass.internalName
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (baseClass.prototype.is(CommonFlags.UNMANAGED) != this.is(CommonFlags.UNMANAGED)) {
|
if (baseClass.prototype.is(CommonFlags.UNMANAGED) != this.is(CommonFlags.UNMANAGED)) {
|
||||||
this.program.error(
|
this.program.error(
|
||||||
DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa,
|
DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa,
|
||||||
|
3
std/assembly.d.ts
vendored
3
std/assembly.d.ts
vendored
@ -354,5 +354,8 @@ declare function operator(token: string): (target: any, propertyKey: string, des
|
|||||||
/** Annotates a class as being unmanaged with limited capabilities. */
|
/** Annotates a class as being unmanaged with limited capabilities. */
|
||||||
declare function unmanaged(target: Function): any;
|
declare function unmanaged(target: Function): any;
|
||||||
|
|
||||||
|
/** Annotates a class as being sealed / non-derivable. */
|
||||||
|
declare function sealed(target: Function): any;
|
||||||
|
|
||||||
/** Annotates a class field with an explicit offset. */
|
/** Annotates a class field with an explicit offset. */
|
||||||
declare function offset(offset: usize): any;
|
declare function offset(offset: usize): any;
|
||||||
|
@ -240,6 +240,7 @@ export class Array<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@unmanaged
|
@unmanaged
|
||||||
|
@sealed
|
||||||
export class CArray<T> {
|
export class CArray<T> {
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
const HEADER_SIZE: usize = sizeof<i32>();
|
const HEADER_SIZE: usize = sizeof<i32>();
|
||||||
|
|
||||||
@unmanaged
|
@sealed
|
||||||
export class ArrayBuffer {
|
export class ArrayBuffer {
|
||||||
|
|
||||||
readonly byteLength: i32;
|
readonly byteLength: i32;
|
||||||
|
|
||||||
constructor(length: i32) {
|
constructor(length: i32) {
|
||||||
if (<u32>length > 0x7fffffff) {
|
if (<u32>length > 0x7fffffff) throw new RangeError("Invalid array buffer length");
|
||||||
throw new RangeError("Invalid array buffer length");
|
|
||||||
}
|
|
||||||
var buffer = allocate_memory(HEADER_SIZE + <usize>length);
|
var buffer = allocate_memory(HEADER_SIZE + <usize>length);
|
||||||
store<i32>(buffer, length);
|
store<i32>(buffer, length);
|
||||||
return changetype<ArrayBuffer>(buffer);
|
return changetype<ArrayBuffer>(buffer);
|
||||||
@ -21,9 +19,21 @@ export class ArrayBuffer {
|
|||||||
if (end < 0) end = max(len + end, 0);
|
if (end < 0) end = max(len + end, 0);
|
||||||
else end = min(end, len);
|
else end = min(end, len);
|
||||||
var newLen = max(end - begin, 0);
|
var newLen = max(end - begin, 0);
|
||||||
var buffer = allocate_memory(HEADER_SIZE + <usize>newLen);
|
if (newLen) {
|
||||||
store<i32>(buffer, newLen);
|
let buffer = allocate_memory(HEADER_SIZE + <usize>newLen);
|
||||||
move_memory(buffer + HEADER_SIZE, changetype<usize>(this) + HEADER_SIZE + begin, newLen);
|
store<i32>(buffer, newLen);
|
||||||
return changetype<ArrayBuffer>(buffer);
|
move_memory(buffer + HEADER_SIZE, changetype<usize>(this) + HEADER_SIZE + begin, newLen);
|
||||||
|
return changetype<ArrayBuffer>(buffer);
|
||||||
|
} else if (ArrayBuffer.EMPTY) {
|
||||||
|
return ArrayBuffer.EMPTY;
|
||||||
|
} else {
|
||||||
|
let buffer = allocate_memory(HEADER_SIZE);
|
||||||
|
store<i32>(buffer, 0);
|
||||||
|
ArrayBuffer.EMPTY = changetype<ArrayBuffer>(buffer);
|
||||||
|
return changetype<ArrayBuffer>(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
static EMPTY: ArrayBuffer | null = null;
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
const EMPTY: String = changetype<String>("");
|
const EMPTY: String = changetype<String>("");
|
||||||
|
|
||||||
// number of bytes preceeding string data
|
// number of bytes preceeding string data
|
||||||
const HEAD: usize = 4;
|
const HEADER_SIZE: usize = 4;
|
||||||
|
|
||||||
function allocate(length: i32): String {
|
function allocate(length: i32): String {
|
||||||
assert(length > 0); // 0 -> EMPTY
|
assert(length > 0); // 0 -> EMPTY
|
||||||
var ptr = allocate_memory(HEAD + (<usize>length << 1));
|
var ptr = allocate_memory(HEADER_SIZE + (<usize>length << 1));
|
||||||
store<i32>(ptr, length);
|
store<i32>(ptr, length);
|
||||||
return changetype<String>(ptr);
|
return changetype<String>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@sealed
|
||||||
export class String {
|
export class String {
|
||||||
|
|
||||||
readonly length: i32; // capped to [0, 0x7fffffff]
|
readonly length: i32; // capped to [0, 0x7fffffff]
|
||||||
@ -28,9 +29,9 @@ export class String {
|
|||||||
changetype<usize>(out),
|
changetype<usize>(out),
|
||||||
load<u16>(
|
load<u16>(
|
||||||
changetype<usize>(this) + (<usize>pos << 1),
|
changetype<usize>(this) + (<usize>pos << 1),
|
||||||
HEAD
|
HEADER_SIZE
|
||||||
),
|
),
|
||||||
HEAD
|
HEADER_SIZE
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -42,7 +43,7 @@ export class String {
|
|||||||
}
|
}
|
||||||
return load<u16>(
|
return load<u16>(
|
||||||
changetype<usize>(this) + (<usize>pos << 1),
|
changetype<usize>(this) + (<usize>pos << 1),
|
||||||
HEAD
|
HEADER_SIZE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,14 +54,14 @@ export class String {
|
|||||||
}
|
}
|
||||||
var first = <i32>load<u16>(
|
var first = <i32>load<u16>(
|
||||||
changetype<usize>(this) + (<usize>pos << 1),
|
changetype<usize>(this) + (<usize>pos << 1),
|
||||||
HEAD
|
HEADER_SIZE
|
||||||
);
|
);
|
||||||
if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length) {
|
if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length) {
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
var second = <i32>load<u16>(
|
var second = <i32>load<u16>(
|
||||||
changetype<usize>(this) + ((<usize>pos + 1) << 1),
|
changetype<usize>(this) + ((<usize>pos + 1) << 1),
|
||||||
HEAD
|
HEADER_SIZE
|
||||||
);
|
);
|
||||||
if (second < 0xDC00 || second > 0xDFFF) {
|
if (second < 0xDC00 || second > 0xDFFF) {
|
||||||
return first;
|
return first;
|
||||||
@ -70,32 +71,26 @@ export class String {
|
|||||||
|
|
||||||
@operator("+")
|
@operator("+")
|
||||||
private static __concat(left: String, right: String): String {
|
private static __concat(left: String, right: String): String {
|
||||||
if (left == null) {
|
if (!changetype<usize>(left)) left = changetype<String>("null");
|
||||||
left = changetype<String>("null");
|
|
||||||
}
|
|
||||||
return left.concat(right);
|
return left.concat(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
concat(other: String): String {
|
concat(other: String): String {
|
||||||
assert(this != null);
|
assert(this != null);
|
||||||
if (other == null) {
|
if (other == null) other = changetype<String>("null");
|
||||||
other = changetype<String>("null");
|
|
||||||
}
|
|
||||||
var thisLen: isize = this.length;
|
var thisLen: isize = this.length;
|
||||||
var otherLen: isize = other.length;
|
var otherLen: isize = other.length;
|
||||||
var outLen: usize = thisLen + otherLen;
|
var outLen: usize = thisLen + otherLen;
|
||||||
if (outLen == 0) {
|
if (outLen == 0) return EMPTY;
|
||||||
return EMPTY;
|
|
||||||
}
|
|
||||||
var out = allocate(outLen);
|
var out = allocate(outLen);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD,
|
changetype<usize>(out) + HEADER_SIZE,
|
||||||
changetype<usize>(this) + HEAD,
|
changetype<usize>(this) + HEADER_SIZE,
|
||||||
thisLen << 1
|
thisLen << 1
|
||||||
);
|
);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD + (thisLen << 1),
|
changetype<usize>(out) + HEADER_SIZE + (thisLen << 1),
|
||||||
changetype<usize>(other) + HEAD,
|
changetype<usize>(other) + HEADER_SIZE,
|
||||||
otherLen << 1
|
otherLen << 1
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
@ -113,26 +108,21 @@ export class String {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !compare_memory(
|
return !compare_memory(
|
||||||
changetype<usize>(this) + HEAD + (start << 1),
|
changetype<usize>(this) + HEADER_SIZE + (start << 1),
|
||||||
changetype<usize>(searchString) + HEAD,
|
changetype<usize>(searchString) + HEADER_SIZE,
|
||||||
searchLength << 1
|
searchLength << 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@operator("==")
|
@operator("==")
|
||||||
private static __eq(left: String, right: String): bool {
|
private static __eq(left: String, right: String): bool {
|
||||||
if (left == null) {
|
if (!changetype<usize>(left)) return !changetype<usize>(right);
|
||||||
return right == null;
|
else if (!changetype<usize>(right)) return false;
|
||||||
} else if (right == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var leftLength = left.length;
|
var leftLength = left.length;
|
||||||
if (leftLength != right.length) {
|
if (leftLength != right.length) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !compare_memory(
|
return !compare_memory(
|
||||||
changetype<usize>(left) + HEAD,
|
changetype<usize>(left) + HEADER_SIZE,
|
||||||
changetype<usize>(right) + HEAD,
|
changetype<usize>(right) + HEADER_SIZE,
|
||||||
(<usize>leftLength << 1)
|
(<usize>leftLength << 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -154,8 +144,8 @@ export class String {
|
|||||||
// TODO: two-way, multiple char codes
|
// TODO: two-way, multiple char codes
|
||||||
for (let k: usize = start; <isize>k + searchLen <= len; ++k) {
|
for (let k: usize = start; <isize>k + searchLen <= len; ++k) {
|
||||||
if (!compare_memory(
|
if (!compare_memory(
|
||||||
changetype<usize>(this) + HEAD + (k << 1),
|
changetype<usize>(this) + HEADER_SIZE + (k << 1),
|
||||||
changetype<usize>(searchString) + HEAD,
|
changetype<usize>(searchString) + HEADER_SIZE,
|
||||||
searchLen << 1)
|
searchLen << 1)
|
||||||
) {
|
) {
|
||||||
return <i32>k;
|
return <i32>k;
|
||||||
@ -177,8 +167,8 @@ export class String {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !compare_memory(
|
return !compare_memory(
|
||||||
changetype<usize>(this) + HEAD + (start << 1),
|
changetype<usize>(this) + HEADER_SIZE + (start << 1),
|
||||||
changetype<usize>(searchString) + HEAD,
|
changetype<usize>(searchString) + HEADER_SIZE,
|
||||||
searchLength << 1
|
searchLength << 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -197,8 +187,8 @@ export class String {
|
|||||||
}
|
}
|
||||||
var out = allocate(resultLength);
|
var out = allocate(resultLength);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD,
|
changetype<usize>(out) + HEADER_SIZE,
|
||||||
changetype<usize>(this) + HEAD + (intStart << 1),
|
changetype<usize>(this) + HEADER_SIZE + (intStart << 1),
|
||||||
<usize>resultLength << 1
|
<usize>resultLength << 1
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
@ -220,8 +210,8 @@ export class String {
|
|||||||
}
|
}
|
||||||
var out = allocate(len);
|
var out = allocate(len);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD,
|
changetype<usize>(out) + HEADER_SIZE,
|
||||||
changetype<usize>(this) + HEAD + (from << 1),
|
changetype<usize>(this) + HEADER_SIZE + (from << 1),
|
||||||
len << 1
|
len << 1
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
@ -233,7 +223,7 @@ export class String {
|
|||||||
while (
|
while (
|
||||||
length &&
|
length &&
|
||||||
isWhiteSpaceOrLineTerminator(
|
isWhiteSpaceOrLineTerminator(
|
||||||
load<u16>(changetype<usize>(this) + (length << 1), HEAD)
|
load<u16>(changetype<usize>(this) + (length << 1), HEADER_SIZE)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
--length;
|
--length;
|
||||||
@ -242,7 +232,7 @@ export class String {
|
|||||||
while (
|
while (
|
||||||
start < length &&
|
start < length &&
|
||||||
isWhiteSpaceOrLineTerminator(
|
isWhiteSpaceOrLineTerminator(
|
||||||
load<u16>(changetype<usize>(this) + (start << 1), HEAD)
|
load<u16>(changetype<usize>(this) + (start << 1), HEADER_SIZE)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
++start, --length;
|
++start, --length;
|
||||||
@ -255,8 +245,8 @@ export class String {
|
|||||||
}
|
}
|
||||||
var out = allocate(length);
|
var out = allocate(length);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD,
|
changetype<usize>(out) + HEADER_SIZE,
|
||||||
changetype<usize>(this) + HEAD + (start << 1),
|
changetype<usize>(this) + HEADER_SIZE + (start << 1),
|
||||||
length << 1
|
length << 1
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
@ -269,7 +259,7 @@ export class String {
|
|||||||
while (
|
while (
|
||||||
start < len &&
|
start < len &&
|
||||||
isWhiteSpaceOrLineTerminator(
|
isWhiteSpaceOrLineTerminator(
|
||||||
load<u16>(changetype<usize>(this) + (start << 1), HEAD)
|
load<u16>(changetype<usize>(this) + (start << 1), HEADER_SIZE)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
++start;
|
++start;
|
||||||
@ -283,8 +273,8 @@ export class String {
|
|||||||
}
|
}
|
||||||
var out = allocate(outLen);
|
var out = allocate(outLen);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD,
|
changetype<usize>(out) + HEADER_SIZE,
|
||||||
changetype<usize>(this) + HEAD + (start << 1),
|
changetype<usize>(this) + HEADER_SIZE + (start << 1),
|
||||||
outLen << 1
|
outLen << 1
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
@ -296,7 +286,7 @@ export class String {
|
|||||||
while (
|
while (
|
||||||
len > 0 &&
|
len > 0 &&
|
||||||
isWhiteSpaceOrLineTerminator(
|
isWhiteSpaceOrLineTerminator(
|
||||||
load<u16>(changetype<usize>(this) + (len << 1), HEAD)
|
load<u16>(changetype<usize>(this) + (len << 1), HEADER_SIZE)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
--len;
|
--len;
|
||||||
@ -309,8 +299,8 @@ export class String {
|
|||||||
}
|
}
|
||||||
var out = allocate(len);
|
var out = allocate(len);
|
||||||
move_memory(
|
move_memory(
|
||||||
changetype<usize>(out) + HEAD,
|
changetype<usize>(out) + HEADER_SIZE,
|
||||||
changetype<usize>(this) + HEAD,
|
changetype<usize>(this) + HEADER_SIZE,
|
||||||
len << 1
|
len << 1
|
||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
@ -381,7 +371,7 @@ function parse<T>(str: String, radix: i32 = 0): T {
|
|||||||
return <T>NaN;
|
return <T>NaN;
|
||||||
}
|
}
|
||||||
var ptr = changetype<usize>(str) /* + HEAD -> offset */;
|
var ptr = changetype<usize>(str) /* + HEAD -> offset */;
|
||||||
var code = <i32>load<u16>(ptr, HEAD);
|
var code = <i32>load<u16>(ptr, HEADER_SIZE);
|
||||||
|
|
||||||
// determine sign
|
// determine sign
|
||||||
var sign: T;
|
var sign: T;
|
||||||
@ -389,13 +379,13 @@ function parse<T>(str: String, radix: i32 = 0): T {
|
|||||||
if (!--len) {
|
if (!--len) {
|
||||||
return <T>NaN;
|
return <T>NaN;
|
||||||
}
|
}
|
||||||
code = <i32>load<u16>(ptr += 2, HEAD);
|
code = <i32>load<u16>(ptr += 2, HEADER_SIZE);
|
||||||
sign = -1;
|
sign = -1;
|
||||||
} else if (code == CharCode.PLUS) {
|
} else if (code == CharCode.PLUS) {
|
||||||
if (!--len) {
|
if (!--len) {
|
||||||
return <T>NaN;
|
return <T>NaN;
|
||||||
}
|
}
|
||||||
code = <i32>load<u16>(ptr += 2, HEAD);
|
code = <i32>load<u16>(ptr += 2, HEADER_SIZE);
|
||||||
sign = 1;
|
sign = 1;
|
||||||
} else {
|
} else {
|
||||||
sign = 1;
|
sign = 1;
|
||||||
@ -404,7 +394,7 @@ function parse<T>(str: String, radix: i32 = 0): T {
|
|||||||
// determine radix
|
// determine radix
|
||||||
if (!radix) {
|
if (!radix) {
|
||||||
if (code == CharCode._0 && len > 2) {
|
if (code == CharCode._0 && len > 2) {
|
||||||
switch (<i32>load<u16>(ptr + 2, HEAD)) {
|
switch (<i32>load<u16>(ptr + 2, HEADER_SIZE)) {
|
||||||
case CharCode.B:
|
case CharCode.B:
|
||||||
case CharCode.b: {
|
case CharCode.b: {
|
||||||
ptr += 4; len -= 2;
|
ptr += 4; len -= 2;
|
||||||
@ -435,7 +425,7 @@ function parse<T>(str: String, radix: i32 = 0): T {
|
|||||||
// calculate value
|
// calculate value
|
||||||
var num: T = 0;
|
var num: T = 0;
|
||||||
while (len--) {
|
while (len--) {
|
||||||
code = <i32>load<u16>(ptr, HEAD);
|
code = <i32>load<u16>(ptr, HEADER_SIZE);
|
||||||
if (code >= CharCode._0 && code <= CharCode._9) {
|
if (code >= CharCode._0 && code <= CharCode._9) {
|
||||||
code -= CharCode._0;
|
code -= CharCode._0;
|
||||||
} else if (code >= CharCode.A && code <= CharCode.Z) {
|
} else if (code >= CharCode.A && code <= CharCode.Z) {
|
||||||
@ -460,7 +450,7 @@ export function parseFloat(str: String): f64 {
|
|||||||
return NaN;
|
return NaN;
|
||||||
}
|
}
|
||||||
var ptr = changetype<usize>(str) /* + HEAD -> offset */;
|
var ptr = changetype<usize>(str) /* + HEAD -> offset */;
|
||||||
var code = <i32>load<u16>(ptr, HEAD);
|
var code = <i32>load<u16>(ptr, HEADER_SIZE);
|
||||||
|
|
||||||
// determine sign
|
// determine sign
|
||||||
var sign: f64;
|
var sign: f64;
|
||||||
@ -468,13 +458,13 @@ export function parseFloat(str: String): f64 {
|
|||||||
if (!--len) {
|
if (!--len) {
|
||||||
return NaN;
|
return NaN;
|
||||||
}
|
}
|
||||||
code = <i32>load<u16>(ptr += 2, HEAD);
|
code = <i32>load<u16>(ptr += 2, HEADER_SIZE);
|
||||||
sign = -1;
|
sign = -1;
|
||||||
} else if (code == CharCode.PLUS) {
|
} else if (code == CharCode.PLUS) {
|
||||||
if (!--len) {
|
if (!--len) {
|
||||||
return NaN;
|
return NaN;
|
||||||
}
|
}
|
||||||
code = <i32>load<u16>(ptr += 2, HEAD);
|
code = <i32>load<u16>(ptr += 2, HEADER_SIZE);
|
||||||
sign = 1;
|
sign = 1;
|
||||||
} else {
|
} else {
|
||||||
sign = 1;
|
sign = 1;
|
||||||
@ -483,12 +473,12 @@ export function parseFloat(str: String): f64 {
|
|||||||
// calculate value
|
// calculate value
|
||||||
var num: f64 = 0;
|
var num: f64 = 0;
|
||||||
while (len--) {
|
while (len--) {
|
||||||
code = <i32>load<u16>(ptr, HEAD);
|
code = <i32>load<u16>(ptr, HEADER_SIZE);
|
||||||
if (code == CharCode.DOT) {
|
if (code == CharCode.DOT) {
|
||||||
ptr += 2;
|
ptr += 2;
|
||||||
let fac: f64 = 0.1; // precision :(
|
let fac: f64 = 0.1; // precision :(
|
||||||
while (len--) {
|
while (len--) {
|
||||||
code = <i32>load<u16>(ptr, HEAD);
|
code = <i32>load<u16>(ptr, HEADER_SIZE);
|
||||||
if (code == CharCode.E || code == CharCode.e) {
|
if (code == CharCode.E || code == CharCode.e) {
|
||||||
assert(false); // TODO
|
assert(false); // TODO
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
(global "$(lib)/allocator/arena/startOffset" (mut i32) (i32.const 0))
|
(global "$(lib)/allocator/arena/startOffset" (mut i32) (i32.const 0))
|
||||||
(global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0))
|
(global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0))
|
||||||
(global $std/arraybuffer/buffer (mut i32) (i32.const 0))
|
(global $std/arraybuffer/buffer (mut i32) (i32.const 0))
|
||||||
|
(global "$(lib)/arraybuffer/ArrayBuffer.EMPTY" (mut i32) (i32.const 0))
|
||||||
(global $std/arraybuffer/sliced (mut i32) (i32.const 0))
|
(global $std/arraybuffer/sliced (mut i32) (i32.const 0))
|
||||||
(global $HEAP_BASE i32 (i32.const 44))
|
(global $HEAP_BASE i32 (i32.const 44))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
@ -2028,82 +2029,105 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(i32.store
|
(if (result i32)
|
||||||
(tee_local $3
|
(tee_local $2
|
||||||
(call "$(lib)/allocator/arena/allocate_memory"
|
(select
|
||||||
(i32.add
|
(tee_local $3
|
||||||
(tee_local $2
|
(i32.sub
|
||||||
(select
|
(tee_local $2
|
||||||
(tee_local $3
|
(if (result i32)
|
||||||
(i32.sub
|
(i32.lt_s
|
||||||
(tee_local $2
|
(get_local $2)
|
||||||
(if (result i32)
|
(i32.const 0)
|
||||||
(i32.lt_s
|
)
|
||||||
(get_local $2)
|
(select
|
||||||
(i32.const 0)
|
(tee_local $3
|
||||||
)
|
(i32.add
|
||||||
(select
|
(get_local $5)
|
||||||
(tee_local $3
|
(get_local $2)
|
||||||
(i32.add
|
|
||||||
(get_local $5)
|
|
||||||
(get_local $2)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(tee_local $4
|
|
||||||
(i32.const 0)
|
|
||||||
)
|
|
||||||
(i32.gt_s
|
|
||||||
(get_local $3)
|
|
||||||
(get_local $4)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(select
|
|
||||||
(tee_local $3
|
|
||||||
(get_local $2)
|
|
||||||
)
|
|
||||||
(tee_local $4
|
|
||||||
(get_local $5)
|
|
||||||
)
|
|
||||||
(i32.lt_s
|
|
||||||
(get_local $3)
|
|
||||||
(get_local $4)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(get_local $1)
|
(tee_local $4
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(i32.gt_s
|
||||||
|
(get_local $3)
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(select
|
||||||
|
(tee_local $3
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(tee_local $4
|
||||||
|
(get_local $5)
|
||||||
|
)
|
||||||
|
(i32.lt_s
|
||||||
|
(get_local $3)
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(tee_local $4
|
|
||||||
(i32.const 0)
|
|
||||||
)
|
|
||||||
(i32.gt_s
|
|
||||||
(get_local $3)
|
|
||||||
(get_local $4)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
(get_local $1)
|
||||||
)
|
)
|
||||||
(i32.const 4)
|
)
|
||||||
|
(tee_local $4
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(i32.gt_s
|
||||||
|
(get_local $3)
|
||||||
|
(get_local $4)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(get_local $2)
|
(block (result i32)
|
||||||
)
|
(i32.store
|
||||||
(call "$(lib)/memory/move_memory"
|
(tee_local $3
|
||||||
(i32.add
|
(call "$(lib)/allocator/arena/allocate_memory"
|
||||||
(get_local $3)
|
(i32.add
|
||||||
(i32.const 4)
|
(get_local $2)
|
||||||
)
|
(i32.const 4)
|
||||||
(i32.add
|
)
|
||||||
(i32.add
|
)
|
||||||
(get_local $0)
|
)
|
||||||
(i32.const 4)
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(call "$(lib)/memory/move_memory"
|
||||||
|
(i32.add
|
||||||
|
(get_local $3)
|
||||||
|
(i32.const 4)
|
||||||
|
)
|
||||||
|
(i32.add
|
||||||
|
(i32.add
|
||||||
|
(get_local $0)
|
||||||
|
(i32.const 4)
|
||||||
|
)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
(if (result i32)
|
||||||
|
(get_global "$(lib)/arraybuffer/ArrayBuffer.EMPTY")
|
||||||
|
(get_global "$(lib)/arraybuffer/ArrayBuffer.EMPTY")
|
||||||
|
(block (result i32)
|
||||||
|
(i32.store
|
||||||
|
(tee_local $3
|
||||||
|
(call "$(lib)/allocator/arena/allocate_memory"
|
||||||
|
(i32.const 4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(set_global "$(lib)/arraybuffer/ArrayBuffer.EMPTY"
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
(get_local $3)
|
||||||
)
|
)
|
||||||
(get_local $1)
|
|
||||||
)
|
)
|
||||||
(get_local $2)
|
|
||||||
)
|
)
|
||||||
(get_local $3)
|
|
||||||
)
|
)
|
||||||
(func "$(lib)/arraybuffer/ArrayBuffer#slice|trampoline" (; 6 ;) (type $iiiii) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
|
(func "$(lib)/arraybuffer/ArrayBuffer#slice|trampoline" (; 6 ;) (type $iiiii) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
|
||||||
(block $N=2
|
(block $N=2
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
(global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0))
|
(global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0))
|
||||||
(global "$(lib)/arraybuffer/HEADER_SIZE" i32 (i32.const 4))
|
(global "$(lib)/arraybuffer/HEADER_SIZE" i32 (i32.const 4))
|
||||||
(global $std/arraybuffer/buffer (mut i32) (i32.const 0))
|
(global $std/arraybuffer/buffer (mut i32) (i32.const 0))
|
||||||
|
(global "$(lib)/arraybuffer/ArrayBuffer.EMPTY" (mut i32) (i32.const 0))
|
||||||
(global $std/arraybuffer/sliced (mut i32) (i32.const 0))
|
(global $std/arraybuffer/sliced (mut i32) (i32.const 0))
|
||||||
(global $HEAP_BASE i32 (i32.const 44))
|
(global $HEAP_BASE i32 (i32.const 44))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
@ -2280,7 +2281,6 @@
|
|||||||
(local $4 i32)
|
(local $4 i32)
|
||||||
(local $5 i32)
|
(local $5 i32)
|
||||||
(local $6 i32)
|
(local $6 i32)
|
||||||
(local $7 i32)
|
|
||||||
(set_local $3
|
(set_local $3
|
||||||
(i32.load
|
(i32.load
|
||||||
(get_local $0)
|
(get_local $0)
|
||||||
@ -2377,34 +2377,62 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(set_local $7
|
(if
|
||||||
(call "$(lib)/allocator/arena/allocate_memory"
|
(get_local $6)
|
||||||
(i32.add
|
(block
|
||||||
(i32.const 4)
|
(set_local $4
|
||||||
|
(call "$(lib)/allocator/arena/allocate_memory"
|
||||||
|
(i32.add
|
||||||
|
(i32.const 4)
|
||||||
|
(get_local $6)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.store
|
||||||
|
(get_local $4)
|
||||||
(get_local $6)
|
(get_local $6)
|
||||||
)
|
)
|
||||||
)
|
(call "$(lib)/memory/move_memory"
|
||||||
)
|
(i32.add
|
||||||
(i32.store
|
(get_local $4)
|
||||||
(get_local $7)
|
(i32.const 4)
|
||||||
(get_local $6)
|
)
|
||||||
)
|
(i32.add
|
||||||
(call "$(lib)/memory/move_memory"
|
(i32.add
|
||||||
(i32.add
|
(get_local $0)
|
||||||
(get_local $7)
|
(i32.const 4)
|
||||||
(i32.const 4)
|
)
|
||||||
)
|
(get_local $1)
|
||||||
(i32.add
|
)
|
||||||
(i32.add
|
(get_local $6)
|
||||||
(get_local $0)
|
)
|
||||||
(i32.const 4)
|
(return
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(get_global "$(lib)/arraybuffer/ArrayBuffer.EMPTY")
|
||||||
|
(return
|
||||||
|
(get_global "$(lib)/arraybuffer/ArrayBuffer.EMPTY")
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(set_local $4
|
||||||
|
(call "$(lib)/allocator/arena/allocate_memory"
|
||||||
|
(i32.const 4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.store
|
||||||
|
(get_local $4)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(set_global "$(lib)/arraybuffer/ArrayBuffer.EMPTY"
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
|
(return
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
(get_local $1)
|
|
||||||
)
|
)
|
||||||
(get_local $6)
|
|
||||||
)
|
|
||||||
(return
|
|
||||||
(get_local $7)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(func "$(lib)/arraybuffer/ArrayBuffer#slice|trampoline" (; 6 ;) (type $iiiii) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
|
(func "$(lib)/arraybuffer/ArrayBuffer#slice|trampoline" (; 6 ;) (type $iiiii) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,5 @@
|
|||||||
|
import "allocator/arena";
|
||||||
|
|
||||||
// preliminary
|
// preliminary
|
||||||
|
|
||||||
var str: string = "hi, I'm a string";
|
var str: string = "hi, I'm a string";
|
||||||
@ -31,3 +33,6 @@ assert(parseFloat("1") == 1);
|
|||||||
assert(parseFloat("0.1") == 0.1);
|
assert(parseFloat("0.1") == 0.1);
|
||||||
assert(parseFloat(".25") == 0.25);
|
assert(parseFloat(".25") == 0.25);
|
||||||
assert(parseFloat(".1foobar") == 0.1);
|
assert(parseFloat(".1foobar") == 0.1);
|
||||||
|
|
||||||
|
var c = "a" + "b";
|
||||||
|
assert(c == "ab");
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user