Implicitly alias stdlib exports as program globals, see #8

This commit is contained in:
dcodeIO 2018-01-12 15:36:17 +01:00
parent 3980e53bb7
commit 2df318a7ec
27 changed files with 417 additions and 179 deletions

62
package-lock.json generated
View File

@ -33,7 +33,7 @@
"requires": { "requires": {
"@types/events": "1.1.0", "@types/events": "1.1.0",
"@types/minimatch": "3.0.2", "@types/minimatch": "3.0.2",
"@types/node": "8.5.2" "@types/node": "8.5.8"
} }
}, },
"@types/long": { "@types/long": {
@ -55,9 +55,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "8.5.2", "version": "8.5.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.8.tgz",
"integrity": "sha512-KA4GKOpgXnrqEH2eCVhiv2CsxgXGQJgV1X0vsGlh+WCnxbeAE1GT44ZsTU1IN5dEeV/gDupKa7gWo08V5IxWVQ==", "integrity": "sha512-8KmlRxwbKZfjUHFIt3q8TF5S2B+/E5BaAoo/3mgc5h6FJzqxXkCK/VMetO+IRDtwtU6HUvovHMBn+XRj7SV9Qg==",
"dev": true "dev": true
}, },
"@types/strip-bom": { "@types/strip-bom": {
@ -141,6 +141,15 @@
"normalize-path": "2.1.1" "normalize-path": "2.1.1"
} }
}, },
"argparse": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
"integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
"dev": true,
"requires": {
"sprintf-js": "1.0.3"
}
},
"arr-diff": { "arr-diff": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
@ -481,9 +490,9 @@
"dev": true "dev": true
}, },
"commander": { "commander": {
"version": "2.12.2", "version": "2.13.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
"integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
"dev": true "dev": true
}, },
"concat-map": { "concat-map": {
@ -771,6 +780,12 @@
"estraverse": "4.2.0" "estraverse": "4.2.0"
} }
}, },
"esprima": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
"integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
"dev": true
},
"esrecurse": { "esrecurse": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
@ -1204,6 +1219,16 @@
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
"dev": true "dev": true
}, },
"js-yaml": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
"integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
"dev": true,
"requires": {
"argparse": "1.0.9",
"esprima": "4.0.0"
}
},
"json-loader": { "json-loader": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
@ -2040,6 +2065,12 @@
"integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
"dev": true "dev": true
}, },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"stream-browserify": { "stream-browserify": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
@ -2202,28 +2233,29 @@
"dev": true "dev": true
}, },
"tslint": { "tslint": {
"version": "5.8.0", "version": "5.9.1",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz",
"integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=",
"dev": true, "dev": true,
"requires": { "requires": {
"babel-code-frame": "6.26.0", "babel-code-frame": "6.26.0",
"builtin-modules": "1.1.1", "builtin-modules": "1.1.1",
"chalk": "2.3.0", "chalk": "2.3.0",
"commander": "2.12.2", "commander": "2.13.0",
"diff": "3.4.0", "diff": "3.4.0",
"glob": "7.1.2", "glob": "7.1.2",
"js-yaml": "3.10.0",
"minimatch": "3.0.4", "minimatch": "3.0.4",
"resolve": "1.5.0", "resolve": "1.5.0",
"semver": "5.4.1", "semver": "5.4.1",
"tslib": "1.8.1", "tslib": "1.8.1",
"tsutils": "2.14.0" "tsutils": "2.16.0"
} }
}, },
"tsutils": { "tsutils": {
"version": "2.14.0", "version": "2.16.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.14.0.tgz", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.16.0.tgz",
"integrity": "sha512-f6axSMV0RoUufiKiRQgmRlN1c+Ag+mDaZjcd6bHdvplT/zyhuMCGqw3pJS8s3+0x4EVkdoQajs9PchdDZlguvw==", "integrity": "sha512-9Ier/60O7OZRNPiw+or5QAtAY4kQA+WDiO/r6xOYATEyefH9bdfvTRLCxrYnFhQlZfET2vYXKfpr3Vw2BiArZw==",
"dev": true, "dev": true,
"requires": { "requires": {
"tslib": "1.8.1" "tslib": "1.8.1"

View File

@ -21,14 +21,14 @@
"@types/glob": "^5.0.34", "@types/glob": "^5.0.34",
"@types/long": "^3.0.32", "@types/long": "^3.0.32",
"@types/minimist": "^1.2.0", "@types/minimist": "^1.2.0",
"@types/node": "^8.5.2", "@types/node": "^8.5.8",
"chalk": "^2.3.0", "chalk": "^2.3.0",
"diff": "^3.4.0", "diff": "^3.4.0",
"long": "^3.2.0", "long": "^3.2.0",
"source-map-support": "^0.5.0", "source-map-support": "^0.5.0",
"ts-loader": "^3.2.0", "ts-loader": "^3.2.0",
"ts-node": "^4.1.0", "ts-node": "^4.1.0",
"tslint": "^5.8.0", "tslint": "^5.9.1",
"typescript": "^2.6.2", "typescript": "^2.6.2",
"webpack": "^3.10.0" "webpack": "^3.10.0"
}, },

View File

@ -1176,12 +1176,20 @@ export enum ModifierKind {
/** Base class of all statement nodes. */ /** Base class of all statement nodes. */
export abstract class Statement extends Node { } export abstract class Statement extends Node { }
export enum SourceKind {
DEFAULT,
ENTRY,
STDLIB
}
/** A top-level source node. */ /** A top-level source node. */
export class Source extends Node { export class Source extends Node {
kind = NodeKind.SOURCE; kind = NodeKind.SOURCE;
parent = null; parent = null;
/** Source kind. */
sourceKind: SourceKind;
/** Path as provided to the parser. */ /** Path as provided to the parser. */
path: string; path: string;
/** Normalized path. */ /** Normalized path. */
@ -1194,21 +1202,24 @@ export class Source extends Node {
text: string; text: string;
/** Tokenizer reference. */ /** Tokenizer reference. */
tokenizer: Tokenizer | null = null; tokenizer: Tokenizer | null = null;
/** Whether an entry file or not. */
isEntry: bool;
/** Constructs a new source node. */ /** Constructs a new source node. */
constructor(path: string, text: string, isEntry: bool = false) { constructor(path: string, text: string, kind: SourceKind = SourceKind.DEFAULT) {
super(); super();
this.sourceKind = kind;
this.path = path; this.path = path;
this.normalizedPath = normalizePath(path, true); this.normalizedPath = normalizePath(path, true);
this.internalPath = mangleInternalPath(this.normalizedPath); this.internalPath = mangleInternalPath(this.normalizedPath);
this.statements = new Array(); this.statements = new Array();
this.range = new Range(this, 0, text.length); this.range = new Range(this, 0, text.length);
this.text = text; this.text = text;
this.isEntry = isEntry;
} }
/** Tests if this source is an entry file. */
get isEntry(): bool { return this.sourceKind == SourceKind.ENTRY; }
/** Tests if this source is a stdlib file. */
get isStdlib(): bool { return this.sourceKind == SourceKind.STDLIB; }
serialize(sb: string[]): void { serialize(sb: string[]): void {
for (var i: i32 = 0, k: i32 = this.statements.length; i < k; ++i) { for (var i: i32 = 0, k: i32 = this.statements.length; i < k; ++i) {
this.statements[i].serialize(sb); this.statements[i].serialize(sb);
@ -1236,6 +1247,8 @@ export abstract class DeclarationStatement extends Statement {
/** Gets the mangled internal name of this declaration. */ /** Gets the mangled internal name of this declaration. */
get internalName(): string { return this._cachedInternalName === null ? this._cachedInternalName = mangleInternalName(this) : this._cachedInternalName; } get internalName(): string { return this._cachedInternalName === null ? this._cachedInternalName = mangleInternalName(this) : this._cachedInternalName; }
/** Tests if this is a top-level declaration. */
get isTopLevel(): bool { return this.parent != null && this.parent.kind == NodeKind.SOURCE; }
} }
/** Base class of all variable-like declaration statements with a type and initializer. */ /** Base class of all variable-like declaration statements with a type and initializer. */

View File

@ -54,6 +54,7 @@ import {
NodeKind, NodeKind,
TypeNode, TypeNode,
Source, Source,
SourceKind,
Statement, Statement,
BlockStatement, BlockStatement,
@ -2113,26 +2114,24 @@ export class Compiler extends DiagnosticEmitter {
left = this.module.createTeeLocal(tempLocal.index, left); left = this.module.createTeeLocal(tempLocal.index, left);
} }
// make a condition that checks !left in case an optimizer can take advantage of guaranteed 0 or 1
// binaryen just switches the arms here, see: https://github.com/WebAssembly/binaryen/issues/1355
possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER);
condition = makeEqualsZero(left, this.currentType, this.module); condition = makeIsTrueish(left, this.currentType, this.module);
// simplify when cloning left without side effects was successful // simplify when cloning left without side effects was successful
if (expr) if (expr)
expr = this.module.createIf( expr = this.module.createIf(
condition, // if !left condition, // left
expr, // then cloned left right, // ? right
right // else right expr // : cloned left
); );
// otherwise make use of the temp. local // otherwise make use of the temp. local
else { else {
assert(tempLocal); assert(tempLocal);
expr = this.module.createIf( expr = this.module.createIf(
condition, // if !left condition,
this.module.createGetLocal((<Local>tempLocal).index, this.currentType.toNativeType()), right,
right this.module.createGetLocal((<Local>tempLocal).index, this.currentType.toNativeType())
); );
} }
break; break;
@ -2150,26 +2149,24 @@ export class Compiler extends DiagnosticEmitter {
left = this.module.createTeeLocal(tempLocal.index, left); left = this.module.createTeeLocal(tempLocal.index, left);
} }
// make a condition that checks !left in case an optimizer can take advantage of guaranteed 0 or 1
// binaryen just switches the arms here, see: https://github.com/WebAssembly/binaryen/issues/1355
possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if right already did possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if right already did
condition = makeEqualsZero(left, this.currentType, this.module); condition = makeIsTrueish(left, this.currentType, this.module);
// simplify when cloning left without side effects was successful // simplify when cloning left without side effects was successful
if (expr) if (expr)
expr = this.module.createIf( expr = this.module.createIf(
condition, // if !left condition, // left
right, // then right expr, // ? cloned left
expr // else cloned left right // : right
); );
// otherwise make use of the temp. local // otherwise make use of the temp. local
else { else {
assert(tempLocal); assert(tempLocal);
expr = this.module.createIf( expr = this.module.createIf(
condition, // if !left condition,
right, this.module.createGetLocal((<Local>tempLocal).index, this.currentType.toNativeType()),
this.module.createGetLocal((<Local>tempLocal).index, this.currentType.toNativeType()) right
); );
} }
break; break;
@ -2482,7 +2479,7 @@ export class Compiler extends DiagnosticEmitter {
assert(contextualType.kind == TypeKind.USIZE); assert(contextualType.kind == TypeKind.USIZE);
this.currentType = Type.usize64; this.currentType = Type.usize64;
} }
return this.module.createI64(0, 0); return this.module.createI64(0);
} }
if (!contextualType.classType) { if (!contextualType.classType) {
assert(contextualType.kind == TypeKind.USIZE); assert(contextualType.kind == TypeKind.USIZE);
@ -2706,7 +2703,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.U64: case TypeKind.U64:
op = BinaryOp.AddI64; op = BinaryOp.AddI64;
nativeType = NativeType.I64; nativeType = NativeType.I64;
nativeOne = this.module.createI64(1, 0); nativeOne = this.module.createI64(1);
break; break;
case TypeKind.F32: case TypeKind.F32:
@ -2754,7 +2751,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.U64: case TypeKind.U64:
op = BinaryOp.SubI64; op = BinaryOp.SubI64;
nativeType = NativeType.I64; nativeType = NativeType.I64;
nativeOne = this.module.createI64(1, 0); nativeOne = this.module.createI64(1);
break; break;
case TypeKind.F32: case TypeKind.F32:
@ -2851,7 +2848,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.I64: case TypeKind.I64:
case TypeKind.U64: case TypeKind.U64:
expr = this.module.createBinary(BinaryOp.SubI64, this.module.createI64(0, 0), expr); expr = this.module.createBinary(BinaryOp.SubI64, this.module.createI64(0), expr);
break; break;
case TypeKind.F32: case TypeKind.F32:
@ -2892,7 +2889,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.I64: case TypeKind.I64:
case TypeKind.U64: case TypeKind.U64:
expr = this.module.createBinary(BinaryOp.AddI64, expr, this.module.createI64(1, 0)); expr = this.module.createBinary(BinaryOp.AddI64, expr, this.module.createI64(1));
break; break;
case TypeKind.F32: case TypeKind.F32:
@ -2934,7 +2931,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.I64: case TypeKind.I64:
case TypeKind.U64: case TypeKind.U64:
expr = this.module.createBinary(BinaryOp.SubI64, expr, this.module.createI64(1, 0)); expr = this.module.createBinary(BinaryOp.SubI64, expr, this.module.createI64(1));
break; break;
case TypeKind.F32: case TypeKind.F32:
@ -2949,7 +2946,7 @@ export class Compiler extends DiagnosticEmitter {
case Token.EXCLAMATION: // must wrap small integers case Token.EXCLAMATION: // must wrap small integers
expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE);
expr = makeEqualsZero(expr, this.currentType, this.module); expr = makeIsFalseish(expr, this.currentType, this.module);
this.currentType = Type.bool; this.currentType = Type.bool;
break; break;
@ -3052,7 +3049,7 @@ function makeInlineConstant(element: VariableLikeElement, module: Module): Expre
case TypeKind.U64: case TypeKind.U64:
return element.constantIntegerValue return element.constantIntegerValue
? module.createI64(element.constantIntegerValue.lo, element.constantIntegerValue.hi) ? module.createI64(element.constantIntegerValue.lo, element.constantIntegerValue.hi)
: module.createI64(0, 0); : module.createI64(0);
case TypeKind.F32: case TypeKind.F32:
return module.createF32((<VariableLikeElement>element).constantFloatValue); return module.createF32((<VariableLikeElement>element).constantFloatValue);
@ -3114,7 +3111,8 @@ export function makeSmallIntegerWrap(expr: ExpressionRef, type: Type, module: Mo
return expr; return expr;
} }
export function makeEqualsZero(expr: ExpressionRef, type: Type, module: Module): ExpressionRef { /** Creates a comparison whether an expression is not 'true' in a broader sense. */
export function makeIsFalseish(expr: ExpressionRef, type: Type, module: Module): ExpressionRef {
switch (type.kind) { switch (type.kind) {
default: // any integer up to 32 bits default: // any integer up to 32 bits
@ -3126,8 +3124,9 @@ export function makeEqualsZero(expr: ExpressionRef, type: Type, module: Module):
expr = module.createUnary(UnaryOp.EqzI64, expr); expr = module.createUnary(UnaryOp.EqzI64, expr);
break; break;
case TypeKind.ISIZE:
case TypeKind.USIZE: case TypeKind.USIZE:
// TODO: strings
case TypeKind.ISIZE:
expr = module.createUnary(type.size == 64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32, expr); expr = module.createUnary(type.size == 64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32, expr);
break; break;
@ -3144,3 +3143,38 @@ export function makeEqualsZero(expr: ExpressionRef, type: Type, module: Module):
} }
return expr; return expr;
} }
/** Creates a comparison whether an expression is 'true' in a broader sense. */
export function makeIsTrueish(expr: ExpressionRef, type: Type, module: Module): ExpressionRef {
switch (type.kind) {
default: // any integer up to 32 bits
expr = module.createBinary(BinaryOp.NeI32, expr, module.createI32(0));
break;
case TypeKind.I64:
case TypeKind.U64:
expr = module.createBinary(BinaryOp.NeI64, expr, module.createI64(0));
break;
case TypeKind.USIZE:
// TODO: strings
case TypeKind.ISIZE:
expr = type.size == 64
? module.createBinary(BinaryOp.NeI64, expr, module.createI64(0))
: module.createBinary(BinaryOp.NeI32, expr, module.createI32(0));
break;
case TypeKind.F32:
expr = module.createBinary(BinaryOp.NeF32, expr, module.createF32(0));
break;
case TypeKind.F64:
expr = module.createBinary(BinaryOp.NeF64, expr, module.createF64(0));
break;
case TypeKind.VOID:
throw new Error("concrete type expected");
}
return expr;
}

View File

@ -306,7 +306,7 @@ export class Module {
return _BinaryenConst(this.ref, this.lit); return _BinaryenConst(this.ref, this.lit);
} }
createI64(lo: i32, hi: i32): ExpressionRef { createI64(lo: i32, hi: i32 = 0): ExpressionRef {
if (this.noEmit) return 0; if (this.noEmit) return 0;
_BinaryenLiteralInt64(this.lit, lo, hi); _BinaryenLiteralInt64(this.lit, lo, hi);
return _BinaryenConst(this.ref, this.lit); return _BinaryenConst(this.ref, this.lit);

View File

@ -30,6 +30,7 @@ import {
Node, Node,
NodeKind, NodeKind,
Source, Source,
SourceKind,
TypeNode, TypeNode,
Expression, Expression,
@ -104,7 +105,7 @@ export class Parser extends DiagnosticEmitter {
return; // already parsed return; // already parsed
this.seenlog.add(normalizedPath); this.seenlog.add(normalizedPath);
var source = new Source(path, text, isEntry); var source = new Source(path, text, isEntry ? SourceKind.ENTRY : path.startsWith("std:") ? SourceKind.STDLIB : SourceKind.DEFAULT);
this.program.sources.push(source); this.program.sources.push(source);
var tn = new Tokenizer(source, this.program.diagnostics); var tn = new Tokenizer(source, this.program.diagnostics);

View File

@ -269,6 +269,15 @@ export class Program extends DiagnosticEmitter {
} while (true); } while (true);
} }
private checkGlobalAlias(element: Element, declaration: DeclarationStatement) {
if (hasDecorator("global", declaration.decorators) || (declaration.range.source.isStdlib && assert(declaration.parent).kind == NodeKind.SOURCE && element.isExported)) {
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);
}
}
private initializeClass(declaration: ClassDeclaration, queuedDerivedClasses: ClassPrototype[], namespace: Element | null = null): void { private initializeClass(declaration: ClassDeclaration, queuedDerivedClasses: ClassPrototype[], namespace: Element | null = null): void {
var internalName = declaration.internalName; var internalName = declaration.internalName;
if (this.elements.has(internalName)) { if (this.elements.has(internalName)) {
@ -279,13 +288,8 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace; prototype.namespace = namespace;
this.elements.set(internalName, prototype); this.elements.set(internalName, prototype);
// add program-level alias if annotated as @global this.checkGlobalAlias(prototype, declaration);
if (hasDecorator("global", declaration.decorators)) {
if (this.elements.has(declaration.name.name))
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
else
this.elements.set(declaration.name.name, prototype);
}
if (hasDecorator("struct", declaration.decorators)) { if (hasDecorator("struct", declaration.decorators)) {
prototype.isStruct = true; prototype.isStruct = true;
if (declaration.implementsTypes && declaration.implementsTypes.length) if (declaration.implementsTypes && declaration.implementsTypes.length)
@ -522,6 +526,8 @@ export class Program extends DiagnosticEmitter {
enm.namespace = namespace; enm.namespace = namespace;
this.elements.set(internalName, enm); this.elements.set(internalName, enm);
this.checkGlobalAlias(enm, declaration);
if (namespace) { if (namespace) {
if (namespace.members) { if (namespace.members) {
if (namespace.members.has(declaration.name.name)) { if (namespace.members.has(declaration.name.name)) {
@ -648,12 +654,7 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace; prototype.namespace = namespace;
this.elements.set(internalName, prototype); this.elements.set(internalName, prototype);
if (hasDecorator("global", declaration.decorators)) { this.checkGlobalAlias(prototype, declaration);
if (this.elements.has(declaration.name.name))
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
else
this.elements.set(declaration.name.name, prototype);
}
if (namespace) { if (namespace) {
if (namespace.members) { if (namespace.members) {
@ -743,6 +744,8 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace; prototype.namespace = namespace;
this.elements.set(internalName, prototype); this.elements.set(internalName, prototype);
this.checkGlobalAlias(prototype, declaration);
if (namespace) { if (namespace) {
if (namespace.members) { if (namespace.members) {
if (namespace.members.has(prototype.internalName)) { if (namespace.members.has(prototype.internalName)) {
@ -791,6 +794,7 @@ export class Program extends DiagnosticEmitter {
namespace = new Namespace(this, declaration.name.name, internalName, declaration); namespace = new Namespace(this, declaration.name.name, internalName, declaration);
namespace.namespace = parentNamespace; namespace.namespace = parentNamespace;
this.elements.set(internalName, namespace); this.elements.set(internalName, namespace);
this.checkGlobalAlias(namespace, declaration);
} }
if (parentNamespace) { if (parentNamespace) {
@ -875,7 +879,8 @@ export class Program extends DiagnosticEmitter {
global.namespace = namespace; global.namespace = namespace;
this.elements.set(internalName, global); this.elements.set(internalName, global);
if (hasDecorator("global", declaration.decorators)) { // differs a bit from this.checkGlobalAlias in that it checks the statement's parent
if (hasDecorator("global", declaration.decorators) || (declaration.range.source.isStdlib && assert(statement.parent).kind == NodeKind.SOURCE && global.isExported)) {
if (this.elements.has(declaration.name.name)) if (this.elements.has(declaration.name.name))
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName); this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
else else

View File

@ -219,7 +219,7 @@ export class Type {
case TypeKind.I64: case TypeKind.I64:
case TypeKind.U64: case TypeKind.U64:
return module.createI64(0, 0); return module.createI64(0);
case TypeKind.F32: case TypeKind.F32:
return module.createF32(0); return module.createF32(0);
@ -247,7 +247,7 @@ export class Type {
case TypeKind.I64: case TypeKind.I64:
case TypeKind.U64: case TypeKind.U64:
return module.createI64(1, 0); return module.createI64(1);
case TypeKind.F32: case TypeKind.F32:
return module.createF32(1); return module.createF32(1);

View File

@ -1,4 +1,3 @@
@global
export class Array<T> { export class Array<T> {
private ptr: usize; private ptr: usize;
@ -39,7 +38,6 @@ export class Array<T> {
// TODO // TODO
} }
@global
@struct @struct
export class CArray<T> { export class CArray<T> {

View File

@ -1,4 +1,3 @@
@global
export class Error { export class Error {
name: string = "Error"; name: string = "Error";
@ -10,7 +9,6 @@ export class Error {
} }
} }
@global
export class RangeError extends Error { export class RangeError extends Error {
name: string = "RangeError"; name: string = "RangeError";
} }

View File

@ -6,7 +6,6 @@ var HEAP_OFFSET: usize = HEAP_BASE; // HEAP_BASE is a constant generated by the
// TODO: maybe tlsf // TODO: maybe tlsf
@global
export class Heap { export class Heap {
static get used(): usize { return HEAP_OFFSET - HEAP_BASE; } static get used(): usize { return HEAP_OFFSET - HEAP_BASE; }

View File

@ -1,4 +1,3 @@
@global
export class Map<K,V> { export class Map<K,V> {
// TODO // TODO
} }

View File

@ -1,5 +1,4 @@
@global export class RegExp {
class RegExp {
// @binding(CALL_NEW, [ STRING, STRING], OBJECT_HANDLE) // @binding(CALL_NEW, [ STRING, STRING], OBJECT_HANDLE)
constructor(pattern: string, flags: string = "") { throw new Error("unreachable"); } constructor(pattern: string, flags: string = "") { throw new Error("unreachable"); }

View File

@ -1,4 +1,3 @@
@global
export class Set<T> { export class Set<T> {
// TODO // TODO
} }

View File

@ -1,6 +1,5 @@
const EMPTY: String = changetype<String>(""); const EMPTY: String = changetype<String>("");
@global
export class String { export class String {
// [key: number]: string; // [key: number]: string;
@ -197,13 +196,11 @@ function isWhiteSpaceOrLineTerminator(c: u16): bool {
} }
} }
// @global
// @binding(CALL, [ STRING, PASS_THRU ], PASS_THRU) // @binding(CALL, [ STRING, PASS_THRU ], PASS_THRU)
export function parseInt(str: string, radix: i32 = 10): f64 { export function parseInt(str: string, radix: i32 = 10): f64 {
throw new Error("not implemented"); throw new Error("not implemented");
} }
// @global
// @binding(CALL, [ STRING ], PASS_THRU) // @binding(CALL, [ STRING ], PASS_THRU)
export function parseFloat(str: string): f64 { export function parseFloat(str: string): f64 {
throw new Error("not implemented"); throw new Error("not implemented");

View File

@ -72,11 +72,11 @@
(if (if
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i64.eq (i64.eq
(i64.shl (i64.shl
@ -86,24 +86,26 @@
(i64.const 0) (i64.const 0)
) )
) )
(i32.const 0)
) )
(get_local $8)
(f64.ne (f64.ne
(tee_local $7 (tee_local $7
(get_local $1) (get_local $1)
) )
(get_local $7) (get_local $7)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
) )
(i32.const 0)
) )
(get_local $8)
(i32.eq (i32.eq
(get_local $4) (get_local $4)
(i32.const 2047) (i32.const 2047)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
@ -542,11 +544,11 @@
(if (if
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i32.eq (i32.eq
(i32.shl (i32.shl
@ -556,24 +558,26 @@
(i32.const 0) (i32.const 0)
) )
) )
(i32.const 0)
) )
(get_local $8)
(f32.ne (f32.ne
(tee_local $7 (tee_local $7
(get_local $1) (get_local $1)
) )
(get_local $7) (get_local $7)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
) )
(i32.const 0)
) )
(get_local $8)
(i32.eq (i32.eq
(get_local $4) (get_local $4)
(i32.const 255) (i32.const 255)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )

View File

@ -211,7 +211,11 @@
(if (if
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.ge_u (i32.lt_u
(get_local $2)
(i32.const 2)
)
(i32.lt_u
(get_local $2) (get_local $2)
(i32.const 2) (i32.const 2)
) )
@ -219,10 +223,6 @@
(get_local $2) (get_local $2)
(i32.const 3) (i32.const 3)
) )
(i32.lt_u
(get_local $2)
(i32.const 2)
)
) )
(i32.const 1) (i32.const 1)
) )

View File

@ -237,20 +237,21 @@
(if (if
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.lt_u (i32.lt_u
(get_local $8) (get_local $8)
(i32.const 2) (i32.const 2)
) )
) (i32.const 0)
(i32.gt_u
(get_local $8)
(i32.const 3)
) )
(i32.lt_u (i32.lt_u
(get_local $8) (get_local $8)
(i32.const 2) (i32.const 2)
) )
(i32.gt_u
(get_local $8)
(i32.const 3)
)
) )
(i32.const 1) (i32.const 1)
) )

View File

@ -1,10 +1,12 @@
(module (module
(type $ii (func (param i32) (result i32))) (type $ii (func (param i32) (result i32)))
(type $v (func))
(memory $0 1) (memory $0 1)
(export "ifThenElse" (func $if/ifThenElse)) (export "ifThenElse" (func $if/ifThenElse))
(export "ifThen" (func $if/ifThen)) (export "ifThen" (func $if/ifThen))
(export "ifThenElseBlock" (func $if/ifThenElse)) (export "ifThenElseBlock" (func $if/ifThenElse))
(export "memory" (memory $0)) (export "memory" (memory $0))
(start $start)
(func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32) (func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32)
(if (result i32) (if (result i32)
(get_local $0) (get_local $0)
@ -21,4 +23,51 @@
) )
(i32.const 0) (i32.const 0)
) )
(func $start (; 2 ;) (type $v)
(if
(call $if/ifThenElse
(i32.const 0)
)
(unreachable)
)
(if
(i32.ne
(call $if/ifThenElse
(i32.const 1)
)
(i32.const 1)
)
(unreachable)
)
(if
(call $if/ifThen
(i32.const 0)
)
(unreachable)
)
(if
(i32.ne
(call $if/ifThen
(i32.const 1)
)
(i32.const 1)
)
(unreachable)
)
(if
(call $if/ifThenElse
(i32.const 0)
)
(unreachable)
)
(if
(i32.ne
(call $if/ifThenElse
(i32.const 1)
)
(i32.const 1)
)
(unreachable)
)
)
) )

View File

@ -5,12 +5,18 @@ export function ifThenElse(n: i32): bool {
return false; return false;
} }
assert(ifThenElse(0) == false);
assert(ifThenElse(1) == true);
export function ifThen(n: i32): bool { export function ifThen(n: i32): bool {
if (n) if (n)
return true; return true;
return false; return false;
} }
assert(ifThen(0) == false);
assert(ifThen(1) == true);
export function ifThenElseBlock(n: i32): bool { export function ifThenElseBlock(n: i32): bool {
if (n) { if (n) {
; // nop ; // nop
@ -20,3 +26,6 @@ export function ifThenElseBlock(n: i32): bool {
return false; return false;
} }
} }
assert(ifThenElseBlock(0) == false);
assert(ifThenElseBlock(1) == true);

View File

@ -1,11 +1,13 @@
(module (module
(type $ii (func (param i32) (result i32))) (type $ii (func (param i32) (result i32)))
(type $v (func))
(global $HEAP_BASE i32 (i32.const 4)) (global $HEAP_BASE i32 (i32.const 4))
(memory $0 1) (memory $0 1)
(export "ifThenElse" (func $if/ifThenElse)) (export "ifThenElse" (func $if/ifThenElse))
(export "ifThen" (func $if/ifThen)) (export "ifThen" (func $if/ifThen))
(export "ifThenElseBlock" (func $if/ifThenElseBlock)) (export "ifThenElseBlock" (func $if/ifThenElseBlock))
(export "memory" (memory $0)) (export "memory" (memory $0))
(start $start)
(func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32) (func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32)
(if (if
(get_local $0) (get_local $0)
@ -45,6 +47,74 @@
) )
) )
) )
(func $start (; 3 ;) (type $v)
(if
(i32.eqz
(i32.eq
(call $if/ifThenElse
(i32.const 0)
)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $if/ifThenElse
(i32.const 1)
)
(i32.const 1)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $if/ifThen
(i32.const 0)
)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $if/ifThen
(i32.const 1)
)
(i32.const 1)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $if/ifThenElseBlock
(i32.const 0)
)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(call $if/ifThenElseBlock
(i32.const 1)
)
(i32.const 1)
)
)
(unreachable)
)
)
) )
(; (;
[program.elements] [program.elements]

View File

@ -13,85 +13,90 @@
(local $1 f64) (local $1 f64)
(drop (drop
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 0)
(i32.const 0) (i32.const 0)
) )
(i32.const 0)
(unreachable) (unreachable)
(i32.const 0)
) )
) )
(drop (drop
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 0) (f64.const 0)
(f64.const 0) (f64.const 0)
) )
(f64.const 0)
(unreachable) (unreachable)
(f64.const 0)
) )
) )
(drop (drop
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 1) (i32.const 1)
(i32.const 0)
) )
(unreachable)
(i32.const 1) (i32.const 1)
(unreachable)
) )
) )
(drop (drop
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 1) (f64.const 1)
(f64.const 0) (f64.const 0)
) )
(unreachable)
(f64.const 1) (f64.const 1)
(unreachable)
) )
) )
(drop (drop
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $0 (tee_local $0
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 1) (i32.const 1)
(i32.const 0)
) )
(i32.const 1)
(i32.const 2) (i32.const 2)
(i32.const 1)
) )
) )
(i32.const 0)
) )
(unreachable)
(get_local $0) (get_local $0)
(unreachable)
) )
) )
(drop (drop
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(tee_local $1 (tee_local $1
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 1) (f64.const 1)
(f64.const 0) (f64.const 0)
) )
(f64.const 1)
(f64.const 2) (f64.const 2)
(f64.const 1)
) )
) )
(f64.const 0) (f64.const 0)
) )
(unreachable)
(get_local $1) (get_local $1)
(unreachable)
) )
) )
(set_global $logical/i (set_global $logical/i
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 1) (i32.const 1)
(i32.const 0)
) )
(i32.const 1)
(i32.const 2) (i32.const 2)
(i32.const 1)
) )
) )
(if (if
@ -105,11 +110,12 @@
) )
(set_global $logical/i (set_global $logical/i
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 0)
(i32.const 0) (i32.const 0)
) )
(i32.const 1)
(i32.const 0) (i32.const 0)
(i32.const 1)
) )
) )
(if (if
@ -123,11 +129,12 @@
) )
(set_global $logical/I (set_global $logical/I
(if (result i64) (if (result i64)
(i64.eqz (i64.ne
(i64.const 1) (i64.const 1)
(i64.const 0)
) )
(i64.const 1)
(i64.const 2) (i64.const 2)
(i64.const 1)
) )
) )
(if (if
@ -141,11 +148,12 @@
) )
(set_global $logical/I (set_global $logical/I
(if (result i64) (if (result i64)
(i64.eqz (i64.ne
(i64.const 0)
(i64.const 0) (i64.const 0)
) )
(i64.const 1)
(i64.const 0) (i64.const 0)
(i64.const 1)
) )
) )
(if (if
@ -159,12 +167,12 @@
) )
(set_global $logical/f (set_global $logical/f
(if (result f32) (if (result f32)
(f32.eq (f32.ne
(f32.const 1) (f32.const 1)
(f32.const 0) (f32.const 0)
) )
(f32.const 1)
(f32.const 2) (f32.const 2)
(f32.const 1)
) )
) )
(if (if
@ -178,12 +186,12 @@
) )
(set_global $logical/f (set_global $logical/f
(if (result f32) (if (result f32)
(f32.eq (f32.ne
(f32.const 0) (f32.const 0)
(f32.const 0) (f32.const 0)
) )
(f32.const 1)
(f32.const 0) (f32.const 0)
(f32.const 1)
) )
) )
(if (if
@ -197,12 +205,12 @@
) )
(set_global $logical/F (set_global $logical/F
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 1) (f64.const 1)
(f64.const 0) (f64.const 0)
) )
(f64.const 1)
(f64.const 2) (f64.const 2)
(f64.const 1)
) )
) )
(if (if
@ -216,12 +224,12 @@
) )
(set_global $logical/F (set_global $logical/F
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 0) (f64.const 0)
(f64.const 0) (f64.const 0)
) )
(f64.const 1)
(f64.const 0) (f64.const 0)
(f64.const 1)
) )
) )
(if (if

View File

@ -27,14 +27,15 @@
(loop $continue|0 (loop $continue|0
(if (if
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(get_local $2) (get_local $2)
(i32.const 0)
) )
(get_local $2)
(i32.rem_u (i32.rem_u
(get_local $4) (get_local $4)
(i32.const 4) (i32.const 4)
) )
(get_local $2)
) )
(block (block
(block (block

View File

@ -135,14 +135,15 @@
(loop $continue|0 (loop $continue|0
(if (if
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(get_local $2) (get_local $2)
(i32.const 0)
) )
(get_local $2)
(i32.rem_u (i32.rem_u
(get_local $4) (get_local $4)
(i32.const 4) (i32.const 4)
) )
(get_local $2)
) )
(block (block
(block (block
@ -1992,11 +1993,11 @@
(if (if
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i64.eq (i64.eq
(i64.shl (i64.shl
@ -2006,24 +2007,26 @@
(i64.const 0) (i64.const 0)
) )
) )
(i32.const 0)
) )
(get_local $8)
(f64.ne (f64.ne
(tee_local $7 (tee_local $7
(get_local $1) (get_local $1)
) )
(get_local $7) (get_local $7)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
) )
(i32.const 0)
) )
(get_local $8)
(i32.eq (i32.eq
(get_local $4) (get_local $4)
(i32.const 2047) (i32.const 2047)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
@ -2462,11 +2465,11 @@
(if (if
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $8 (tee_local $8
(i32.eq (i32.eq
(i32.shl (i32.shl
@ -2476,24 +2479,26 @@
(i32.const 0) (i32.const 0)
) )
) )
(i32.const 0)
) )
(get_local $8)
(f32.ne (f32.ne
(tee_local $7 (tee_local $7
(get_local $1) (get_local $1)
) )
(get_local $7) (get_local $7)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
) )
(i32.const 0)
) )
(get_local $8)
(i32.eq (i32.eq
(get_local $4) (get_local $4)
(i32.const 255) (i32.const 255)
) )
(get_local $8)
) )
(i32.const 1) (i32.const 1)
) )
@ -4231,85 +4236,90 @@
) )
(drop (drop
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 0)
(i32.const 0) (i32.const 0)
) )
(i32.const 0)
(unreachable) (unreachable)
(i32.const 0)
) )
) )
(drop (drop
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 0) (f64.const 0)
(f64.const 0) (f64.const 0)
) )
(f64.const 0)
(unreachable) (unreachable)
(f64.const 0)
) )
) )
(drop (drop
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 1) (i32.const 1)
(i32.const 0)
) )
(unreachable)
(i32.const 1) (i32.const 1)
(unreachable)
) )
) )
(drop (drop
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 1) (f64.const 1)
(f64.const 0) (f64.const 0)
) )
(unreachable)
(f64.const 1) (f64.const 1)
(unreachable)
) )
) )
(drop (drop
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $0 (tee_local $0
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 1) (i32.const 1)
(i32.const 0)
) )
(i32.const 1)
(i32.const 2) (i32.const 2)
(i32.const 1)
) )
) )
(i32.const 0)
) )
(unreachable)
(get_local $0) (get_local $0)
(unreachable)
) )
) )
(drop (drop
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(tee_local $3 (tee_local $3
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 1) (f64.const 1)
(f64.const 0) (f64.const 0)
) )
(f64.const 1)
(f64.const 2) (f64.const 2)
(f64.const 1)
) )
) )
(f64.const 0) (f64.const 0)
) )
(unreachable)
(get_local $3) (get_local $3)
(unreachable)
) )
) )
(set_global $logical/i (set_global $logical/i
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 1) (i32.const 1)
(i32.const 0)
) )
(i32.const 1)
(i32.const 2) (i32.const 2)
(i32.const 1)
) )
) )
(if (if
@ -4323,11 +4333,12 @@
) )
(set_global $logical/i (set_global $logical/i
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(i32.const 0)
(i32.const 0) (i32.const 0)
) )
(i32.const 1)
(i32.const 0) (i32.const 0)
(i32.const 1)
) )
) )
(if (if
@ -4341,11 +4352,12 @@
) )
(set_global $logical/I (set_global $logical/I
(if (result i64) (if (result i64)
(i64.eqz (i64.ne
(i64.const 1) (i64.const 1)
(i64.const 0)
) )
(i64.const 1)
(i64.const 2) (i64.const 2)
(i64.const 1)
) )
) )
(if (if
@ -4359,11 +4371,12 @@
) )
(set_global $logical/I (set_global $logical/I
(if (result i64) (if (result i64)
(i64.eqz (i64.ne
(i64.const 0)
(i64.const 0) (i64.const 0)
) )
(i64.const 1)
(i64.const 0) (i64.const 0)
(i64.const 1)
) )
) )
(if (if
@ -4377,12 +4390,12 @@
) )
(set_global $logical/f (set_global $logical/f
(if (result f32) (if (result f32)
(f32.eq (f32.ne
(f32.const 1) (f32.const 1)
(f32.const 0) (f32.const 0)
) )
(f32.const 1)
(f32.const 2) (f32.const 2)
(f32.const 1)
) )
) )
(if (if
@ -4396,12 +4409,12 @@
) )
(set_global $logical/f (set_global $logical/f
(if (result f32) (if (result f32)
(f32.eq (f32.ne
(f32.const 0) (f32.const 0)
(f32.const 0) (f32.const 0)
) )
(f32.const 1)
(f32.const 0) (f32.const 0)
(f32.const 1)
) )
) )
(if (if
@ -4415,12 +4428,12 @@
) )
(set_global $logical/F (set_global $logical/F
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 1) (f64.const 1)
(f64.const 0) (f64.const 0)
) )
(f64.const 1)
(f64.const 2) (f64.const 2)
(f64.const 1)
) )
) )
(if (if
@ -4434,12 +4447,12 @@
) )
(set_global $logical/F (set_global $logical/F
(if (result f64) (if (result f64)
(f64.eq (f64.ne
(f64.const 0) (f64.const 0)
(f64.const 0) (f64.const 0)
) )
(f64.const 1)
(f64.const 0) (f64.const 0)
(f64.const 1)
) )
) )
(if (if

View File

@ -80,7 +80,9 @@
CLASS_PROTOTYPE: String CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseFloat FUNCTION_PROTOTYPE: std:string/parseFloat
FUNCTION_PROTOTYPE: parseFloat
[program.exports] [program.exports]
CLASS_PROTOTYPE: std:array/Array CLASS_PROTOTYPE: std:array/Array
CLASS_PROTOTYPE: std:array/CArray CLASS_PROTOTYPE: std:array/CArray
@ -88,6 +90,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: std:heap/Heap CLASS_PROTOTYPE: std:heap/Heap
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: std:set/Set CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: std:string/String CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/parseInt FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -528,14 +528,15 @@
(loop $continue|0 (loop $continue|0
(if (if
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(get_local $2) (get_local $2)
(i32.const 0)
) )
(get_local $2)
(i32.rem_u (i32.rem_u
(get_local $1) (get_local $1)
(i32.const 4) (i32.const 4)
) )
(get_local $2)
) )
(block (block
(block (block
@ -2337,10 +2338,10 @@
(loop $continue|0 (loop $continue|0
(if (if
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(get_local $2) (get_local $2)
(i32.const 0)
) )
(get_local $2)
(i32.eq (i32.eq
(i32.load8_u (i32.load8_u
(get_local $0) (get_local $0)
@ -2349,6 +2350,7 @@
(get_local $1) (get_local $1)
) )
) )
(get_local $2)
) )
(block (block
(block (block
@ -2600,7 +2602,9 @@
CLASS_PROTOTYPE: String CLASS_PROTOTYPE: String
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
FUNCTION_PROTOTYPE: std:string/parseInt FUNCTION_PROTOTYPE: std:string/parseInt
FUNCTION_PROTOTYPE: parseInt
FUNCTION_PROTOTYPE: std:string/parseFloat FUNCTION_PROTOTYPE: std:string/parseFloat
FUNCTION_PROTOTYPE: parseFloat
GLOBAL: std/heap/size GLOBAL: std/heap/size
GLOBAL: std/heap/ptr1 GLOBAL: std/heap/ptr1
GLOBAL: std/heap/ptr2 GLOBAL: std/heap/ptr2
@ -2612,6 +2616,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: std:heap/Heap CLASS_PROTOTYPE: std:heap/Heap
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
CLASS_PROTOTYPE: std:regexp/RegExp
CLASS_PROTOTYPE: std:set/Set CLASS_PROTOTYPE: std:set/Set
CLASS_PROTOTYPE: std:string/String CLASS_PROTOTYPE: std:string/String
FUNCTION_PROTOTYPE: std:string/parseInt FUNCTION_PROTOTYPE: std:string/parseInt

View File

@ -160,7 +160,7 @@
(loop $continue|3 (loop $continue|3
(if (if
(if (result i32) (if (result i32)
(i32.eqz (i32.ne
(tee_local $0 (tee_local $0
(block (result i32) (block (result i32)
(set_local $0 (set_local $0
@ -175,8 +175,8 @@
(get_local $0) (get_local $0)
) )
) )
(i32.const 0)
) )
(get_local $0)
(block (result i32) (block (result i32)
(set_global $while/m (set_global $while/m
(i32.add (i32.add
@ -186,6 +186,7 @@
) )
(get_global $while/m) (get_global $while/m)
) )
(get_local $0)
) )
(block (block
(nop) (nop)