Move built-in declarations to actual sources; Remove declaration is null checks; Resolve calls

This commit is contained in:
dcodeIO 2018-02-09 02:31:48 +01:00
parent a7e815dcec
commit ad92d91f01
24 changed files with 655 additions and 502 deletions

View File

@ -48,7 +48,7 @@ function main(argv, options, callback) {
if (!callback) callback = function defaultCallback(err) {
var code = 0;
if (err) {
stderr.write(err + os.EOL);
stderr.write(err.stack + os.EOL);
code = 1;
}
return code;
@ -195,7 +195,11 @@ function main(argv, options, callback) {
var module;
stats.compileCount++;
stats.compileTime += measure(() => module = assemblyscript.compile(parser, compilerOptions));
try {
stats.compileTime += measure(() => module = assemblyscript.compile(parser, compilerOptions));
} catch (e) {
return callback(e);
}
if (checkDiagnostics(parser, stderr)) {
if (module) module.dispose();
return callback(Error("Compile error"));

View File

@ -383,8 +383,7 @@ class Root {
// merge with current tail if adjacent
if (start - Block.INFO == tailRef) {
start -= Block.INFO;
let tail = changetype<Block>(tailRef);
tailInfo = tail.info;
tailInfo = changetype<Block>(tailRef).info;
}
} else
@ -407,7 +406,7 @@ class Root {
tail.info = 0 | LEFT_FREE;
this.tailRef = changetype<usize>(tail);
this.insert(left); // also sets jump
this.insert(left); // also merges with free left before tail / sets jump
return true;
}

5
examples/tlsf/index.js Normal file
View File

@ -0,0 +1,5 @@
const fs = require("fs");
module.exports = new WebAssembly.Instance(
new WebAssembly.Module(fs.readFileSync(__dirname + "/tlsf.optimized.wasm")),
{ env: { abort: function() { throw Error("abort called"); } } }
).exports;

View File

@ -5,7 +5,7 @@
"scripts": {
"build": "npm run build:untouched && npm run build:optimized",
"build:untouched": "asc assembly/tlsf.ts -t tlsf.untouched.wast -b tlsf.untouched.wasm --validate --sourceMap --measure",
"build:optimized": "asc -O3 assembly/tlsf.ts -b tlsf.optimized.wasm -t tlsf.optimized.wast --validate --noDebug --noAssert --sourceMap --measure",
"build:optimized": "asc assembly/tlsf.ts -t tlsf.optimized.wast -b tlsf.optimized.wasm --validate --sourceMap --measure --noDebug --noAssert --optimize",
"test": "node tests",
"test:forever": "node tests/forever"
}

View File

@ -20,7 +20,7 @@ function test(file) {
return String.fromCharCode.apply(String, str);
}
runner(exports, 5, 20000); // picked so I/O isn't the bottleneck
runner(exports, 20, 20000); // picked so I/O isn't the bottleneck
console.log("mem final: " + exports.memory.buffer.byteLength);
console.log();
}

View File

@ -560,7 +560,7 @@ export abstract class Node {
return elem;
}
static createParameter(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, isRest: bool, range: Range): Parameter {
static createParameter(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, kind: ParameterKind, range: Range): Parameter {
var elem = new Parameter();
elem.range = range;
(elem.name = identifier).parent = elem;
@ -568,7 +568,7 @@ export abstract class Node {
(<TypeNode>type).parent = elem;
if (elem.initializer = initializer)
(<Expression>initializer).parent = elem;
elem.isRest = isRest;
elem.parameterKind = kind;
return elem;
}
@ -1050,7 +1050,7 @@ export class Source extends Node {
/** 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.LIBRARY; }
get isLibrary(): bool { return this.sourceKind == SourceKind.LIBRARY; }
}
/** Base class of all declaration statements. */
@ -1352,18 +1352,28 @@ export class NamespaceDeclaration extends DeclarationStatement {
members: Statement[];
}
/** Represents the kind of a parameter. */
export enum ParameterKind {
/** No specific flags. */
DEFAULT,
/** Is an optional parameter. */
OPTIONAL,
/** Is a rest parameter. */
REST
}
/** Represents a function parameter. */
export class Parameter extends Node {
kind = NodeKind.PARAMETER;
/** Parameter name. */
name: IdentifierExpression | null;
name: IdentifierExpression;
/** Parameter type. */
type: TypeNode | null;
/** Parameter kind. */
parameterKind: ParameterKind;
/** Initializer expression, if present. */
initializer: Expression | null;
/** Whether a rest parameter or not. */
isRest: bool;
}
/** Represents a single modifier. */

View File

@ -46,147 +46,6 @@ import {
ElementKind
} from "./program";
/** Initializes the specified program with built-in constants and functions. */
export function initialize(program: Program): void {
// math
addConstant(program, "NaN", Type.f64);
addConstant(program, "Infinity", Type.f64);
addFunction(program, "isNaN", true);
addFunction(program, "isFinite", true);
addFunction(program, "clz", true);
addFunction(program, "ctz", true);
addFunction(program, "popcnt", true);
addFunction(program, "rotl", true);
addFunction(program, "rotr", true);
addFunction(program, "abs", true);
addFunction(program, "max", true);
addFunction(program, "min", true);
addFunction(program, "ceil", true);
addFunction(program, "floor", true);
addFunction(program, "copysign", true);
addFunction(program, "nearest", true);
addFunction(program, "reinterpret", true);
addFunction(program, "sqrt", true);
addFunction(program, "trunc", true);
// memory access
addFunction(program, "load", true);
addFunction(program, "store", true);
addFunction(program, "sizeof", true);
// control flow
addFunction(program, "select", true);
addFunction(program, "unreachable");
// host operations
addFunction(program, "current_memory");
addFunction(program, "grow_memory");
// addFunction(program, "move_memory");
// addFunction(program, "set_memory");
// other
addFunction(program, "changetype", true);
addFunction(program, "assert");
// abort is special in that it is imported conditionally. for example, when
// compiling with noAssert=true, it isn't necessary that it is present, that
// is if a user doesn't call it manually.
var abortPrototype = addFunction(program, "abort");
abortPrototype.set(ElementFlags.DECLARED);
abortPrototype.instances.set("", new Function(abortPrototype, "abort", null, [
new Parameter(null, program.options.usizeType), // message (string)
new Parameter(null, program.options.usizeType), // file name (string)
new Parameter(null, Type.u32), // line number
new Parameter(null, Type.u32) // column number
], Type.void, null));
// conversions and limits
var i32Func: FunctionPrototype,
u32Func: FunctionPrototype,
i64Func: FunctionPrototype,
u64Func: FunctionPrototype;
addFunction(program, "i8").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "i8.MIN_VALUE", null, Type.i8).withConstantIntegerValue(-128, -1) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "i8.MAX_VALUE", null, Type.i8).withConstantIntegerValue(127, 0) ]
]);
addFunction(program, "i16").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "i16.MIN_VALUE", null, Type.i16).withConstantIntegerValue(-32768, -1) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "i16.MAX_VALUE", null, Type.i16).withConstantIntegerValue(32767, 0) ]
]);
(i32Func = addFunction(program, "i32")).members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "i32.MIN_VALUE", null, Type.i32).withConstantIntegerValue(-2147483648, -1) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "i32.MAX_VALUE", null, Type.i32).withConstantIntegerValue(2147483647, 0) ]
]);
(i64Func = addFunction(program, "i64")).members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "i64.MIN_VALUE", null, Type.i64).withConstantIntegerValue(0, -2147483648) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "i64.MAX_VALUE", null, Type.i64).withConstantIntegerValue(-1, 2147483647) ]
]);
addFunction(program, "u8").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "u8.MIN_VALUE", null, Type.u8).withConstantIntegerValue(0, 0) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "u8.MAX_VALUE", null, Type.u8).withConstantIntegerValue(255, 0) ]
]);
addFunction(program, "u16").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "u16.MIN_VALUE", null, Type.u16).withConstantIntegerValue(0, 0) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "u16.MAX_VALUE", null, Type.u16).withConstantIntegerValue(65535, 0) ]
]);
(u32Func = addFunction(program, "u32")).members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "u32.MIN_VALUE", null, Type.u32).withConstantIntegerValue(0, 0) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "u32.MAX_VALUE", null, Type.u32).withConstantIntegerValue(-1, 0) ]
]);
(u64Func = addFunction(program, "u64")).members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "u64.MIN_VALUE", null, Type.u64).withConstantIntegerValue(0, 0) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "u64.MAX_VALUE", null, Type.i64).withConstantIntegerValue(-1, -1) ]
]);
addFunction(program, "bool").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "bool.MIN_VALUE", null, Type.bool).withConstantIntegerValue(0, 0) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "bool.MAX_VALUE", null, Type.bool).withConstantIntegerValue(1, 0) ]
]);
addFunction(program, "f32").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "f32.MIN_VALUE", null, Type.f32).withConstantFloatValue(-3.40282347e+38) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "f32.MAX_VALUE", null, Type.f32).withConstantFloatValue(3.40282347e+38) ],
[ "MIN_SAFE_INTEGER", new Global(program, "MIN_SAFE_INTEGER", "f32.MIN_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(-16777215) ],
[ "MAX_SAFE_INTEGER", new Global(program, "MAX_SAFE_INTEGER", "f32.MAX_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(16777215) ],
[ "EPSILON", new Global(program, "EPSILON", "f32.EPSILON", null, Type.f32).withConstantFloatValue(1.19209290e-07) ]
]);
addFunction(program, "f64").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "f64.MIN_VALUE", null, Type.f64).withConstantFloatValue(-1.7976931348623157e+308) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "f64.MAX_VALUE", null, Type.f64).withConstantFloatValue(1.7976931348623157e+308) ],
[ "MIN_SAFE_INTEGER", new Global(program, "MIN_SAFE_INTEGER", "f64.MIN_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(-9007199254740991) ],
[ "MAX_SAFE_INTEGER", new Global(program, "MAX_SAFE_INTEGER", "f64.MAX_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(9007199254740991) ],
[ "EPSILON", new Global(program, "EPSILON", "f64.EPSILON", null, Type.f64).withConstantFloatValue(2.2204460492503131e-16) ]
]);
if (program.options.isWasm64) {
program.elements.set("isize", i64Func);
program.elements.set("usize", u64Func);
addConstant(program, "HEAP_BASE", Type.usize64);
} else {
program.elements.set("isize", i32Func);
program.elements.set("usize", u32Func);
addConstant(program, "HEAP_BASE", Type.usize32);
}
}
/** Adds a built-in constant to the specified program. */
function addConstant(program: Program, name: string, type: Type): Global {
var global = new Global(program, name, name, null, type);
global.set(ElementFlags.BUILTIN);
global.set(ElementFlags.CONSTANT);
program.elements.set(name, global);
return global;
}
/** Adds a built-in function to the specified program. */
function addFunction(program: Program, name: string, isGeneric: bool = false): FunctionPrototype {
var prototype = new FunctionPrototype(program, name, name, null, null);
prototype.set(ElementFlags.BUILTIN);
if (isGeneric)
prototype.set(ElementFlags.GENERIC);
program.elements.set(name, prototype);
return prototype;
}
/** Compiles a get of a built-in global. */
export function compileGetConstant(compiler: Compiler, global: Global, reportNode: Node): ExpressionRef {
switch (global.internalName) { // switching on strings should become a compiler optimization eventually
@ -204,7 +63,8 @@ export function compileGetConstant(compiler: Compiler, global: Global, reportNod
return compiler.module.createF64(Infinity);
case "HEAP_BASE": // constant, but never inlined
return compiler.module.createGetGlobal("HEAP_BASE", (compiler.currentType = <Type>global.type).toNativeType());
compiler.currentType = compiler.options.usizeType;
return compiler.module.createGetGlobal("HEAP_BASE", compiler.options.nativeSizeType);
}
compiler.error(DiagnosticCode.Operation_not_supported, reportNode.range);
return compiler.module.createUnreachable();

View File

@ -219,12 +219,6 @@ export class Compiler extends DiagnosticEmitter {
this.options = options ? options : new Options();
this.memoryOffset = new U64(this.options.usizeType.byteSize); // leave space for `null`
this.module = Module.create();
// set up the start function wrapping top-level statements, of all files.
var startFunctionTemplate = new FunctionPrototype(program, "start", "start", null);
var startFunctionInstance = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
startFunctionInstance.set(ElementFlags.START);
this.currentFunction = this.startFunction = startFunctionInstance;
}
/** Performs compilation of the underlying {@link Program} to a {@link Module}. */
@ -233,6 +227,13 @@ export class Compiler extends DiagnosticEmitter {
// initialize lookup maps, built-ins, imports, exports, etc.
this.program.initialize(this.options);
// set up the start function wrapping top-level statements, of all files.
var startFunctionPrototype = assert(this.program.elements.get("start"));
assert(startFunctionPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
var startFunctionInstance = new Function(<FunctionPrototype>startFunctionPrototype, startFunctionPrototype.internalName, [], [], Type.void, null);
startFunctionInstance.set(ElementFlags.START);
this.currentFunction = this.startFunction = startFunctionInstance;
var sources = this.program.sources;
// compile entry file(s) while traversing to reachable elements
@ -389,31 +390,27 @@ export class Compiler extends DiagnosticEmitter {
var declaration = global.declaration;
var initExpr: ExpressionRef = 0;
if (global.type == Type.void) { // infer type
if (declaration) {
if (declaration.type) {
var resolvedType = this.program.resolveType(declaration.type); // reports
if (!resolvedType)
return false;
if (resolvedType == Type.void) {
this.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, declaration.type.range, "*", resolvedType.toString());
return false;
}
global.type = resolvedType;
} else if (declaration.initializer) { // infer type using void/NONE for proper literal inference
initExpr = this.compileExpression(declaration.initializer, Type.void, ConversionKind.NONE); // reports
if (this.currentType == Type.void) {
this.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, declaration.initializer.range, this.currentType.toString(), "<auto>");
return false;
}
global.type = this.currentType;
} else {
this.error(DiagnosticCode.Type_expected, declaration.name.range.atEnd);
if (declaration.type) {
var resolvedType = this.program.resolveType(declaration.type); // reports
if (!resolvedType)
return false;
if (resolvedType == Type.void) {
this.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, declaration.type.range, "*", resolvedType.toString());
return false;
}
} else
throw new Error("declaration expected");
global.type = resolvedType;
} else if (declaration.initializer) { // infer type using void/NONE for proper literal inference
initExpr = this.compileExpression(declaration.initializer, Type.void, ConversionKind.NONE); // reports
if (this.currentType == Type.void) {
this.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, declaration.initializer.range, this.currentType.toString(), "<auto>");
return false;
}
global.type = this.currentType;
} else {
this.error(DiagnosticCode.Type_expected, declaration.name.range.atEnd);
return false;
}
}
var nativeType = global.type.toNativeType();
@ -423,9 +420,8 @@ export class Compiler extends DiagnosticEmitter {
this.module.addGlobalImport(global.internalName, global.namespace ? global.namespace.simpleName : "env", global.simpleName, nativeType);
global.set(ElementFlags.COMPILED);
return true;
} else if (declaration) {
} else
this.error(DiagnosticCode.Operation_not_supported, declaration.range);
}
return false;
}
@ -433,7 +429,7 @@ export class Compiler extends DiagnosticEmitter {
if (global.is(ElementFlags.INLINED)) {
initExpr = this.compileInlineConstant(global, global.type);
} else if (declaration) {
} else {
if (declaration.initializer) {
if (!initExpr)
initExpr = this.compileExpression(declaration.initializer, global.type);
@ -449,8 +445,7 @@ export class Compiler extends DiagnosticEmitter {
}
} else
initExpr = global.type.toNativeZero(this.module);
} else
throw new Error("declaration expected");
}
var internalName = global.internalName;
if (initializeInStart) {
@ -482,10 +477,9 @@ export class Compiler extends DiagnosticEmitter {
throw new Error("concrete type expected");
}
global.set(ElementFlags.INLINED);
if (!declaration || declaration.isTopLevel) { // might be re-exported
if (declaration.isTopLevel) // might be re-exported
this.module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr);
}
if (declaration && declaration.range.source.isEntry && declaration.isTopLevelExport)
if (declaration.range.source.isEntry && declaration.isTopLevelExport)
this.module.addGlobalExport(global.internalName, declaration.programLevelInternalName);
} else
this.module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr);
@ -521,9 +515,9 @@ export class Compiler extends DiagnosticEmitter {
var valueDeclaration = val.declaration;
val.set(ElementFlags.COMPILED);
if (val.is(ElementFlags.INLINED)) {
if (!element.declaration || element.declaration.isTopLevelExport)
if (element.declaration.isTopLevelExport)
this.module.addGlobal(val.internalName, NativeType.I32, false, this.module.createI32(val.constantValue));
} else if (valueDeclaration) {
} else {
var initExpr: ExpressionRef;
if (valueDeclaration.value) {
initExpr = this.compileExpression(<Expression>valueDeclaration.value, Type.i32);
@ -561,12 +555,11 @@ export class Compiler extends DiagnosticEmitter {
} else
throw new Error("i32 expected");
}
} else
throw new Error("declaration expected");
}
previousValue = <EnumValue>val;
// export values if the enum is exported
if (element.declaration && element.declaration.range.source.isEntry && element.declaration.isTopLevelExport) {
if (element.declaration.range.source.isEntry && element.declaration.isTopLevelExport) {
if (member.is(ElementFlags.INLINED))
this.module.addGlobalExport(member.internalName, member.internalName);
else if (valueDeclaration)
@ -579,15 +572,15 @@ export class Compiler extends DiagnosticEmitter {
// functions
compileFunctionDeclaration(declaration: FunctionDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Function | null {
compileFunctionDeclaration(declaration: FunctionDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null): Function | null {
var element = this.program.elements.get(declaration.fileLevelInternalName);
if (!element || element.kind != ElementKind.FUNCTION_PROTOTYPE)
throw new Error("function expected");
return this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, alternativeReportNode); // reports
return this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, (<FunctionPrototype>element).declaration.name); // reports
}
compileFunctionUsingTypeArguments(prototype: FunctionPrototype, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Function | null {
var instance = prototype.resolveInclTypeArguments(typeArguments, contextualTypeArguments, alternativeReportNode); // reports
compileFunctionUsingTypeArguments(prototype: FunctionPrototype, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null, reportNode: Node): Function | null {
var instance = prototype.resolveInclTypeArguments(typeArguments, contextualTypeArguments, reportNode); // reports
if (!instance)
return null;
return this.compileFunction(instance) ? instance : null;
@ -597,20 +590,17 @@ export class Compiler extends DiagnosticEmitter {
if (instance.is(ElementFlags.COMPILED))
return true;
var declaration = instance.prototype.declaration;
assert(!instance.is(ElementFlags.BUILTIN) || instance.simpleName == "abort");
var declaration = instance.prototype.declaration;
if (instance.is(ElementFlags.DECLARED)) {
if (declaration && declaration.statements) {
if (declaration.statements) {
this.error(DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts, declaration.name.range);
return false;
}
} else {
if (!declaration)
throw new Error("declaration expected"); // built-ins are not compiled here
if (!declaration.statements) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.name.range);
return false;
}
} else if (!declaration.statements) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.name.range);
return false;
}
// might trigger compilation of other functions referring to this one
@ -619,7 +609,6 @@ export class Compiler extends DiagnosticEmitter {
// compile statements
var stmts: ExpressionRef[] | null = null;
if (!instance.is(ElementFlags.DECLARED)) {
declaration = assert(declaration, "declaration expected");
var previousFunction = this.currentFunction;
this.currentFunction = instance;
var statements = assert(declaration.statements, "implementation expected");
@ -661,7 +650,7 @@ export class Compiler extends DiagnosticEmitter {
ref = this.module.addFunction(instance.internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
// check module export
if (declaration && declaration.range.source.isEntry && declaration.isTopLevelExport)
if (declaration.range.source.isEntry && declaration.isTopLevelExport)
this.module.addFunctionExport(instance.internalName, declaration.name.name);
instance.finalize(this.module, ref);
@ -735,7 +724,7 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.FUNCTION_PROTOTYPE:
if ((noTreeShaking || (<FunctionPrototype>element).is(ElementFlags.EXPORTED)) && !(<FunctionPrototype>element).is(ElementFlags.GENERIC))
this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, []);
this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, [], null, (<FunctionPrototype>element).declaration.name);
break;
case ElementKind.GLOBAL:
@ -772,7 +761,7 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.FUNCTION_PROTOTYPE:
if (!(<FunctionPrototype>element).is(ElementFlags.GENERIC) && statement.range.source.isEntry) {
var functionInstance = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, []);
var functionInstance = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, [], null, (<FunctionPrototype>element).declaration.name);
if (functionInstance) {
var functionDeclaration = functionInstance.prototype.declaration;
if (functionDeclaration && functionDeclaration.needsExplicitExport(member))
@ -1451,14 +1440,19 @@ export class Compiler extends DiagnosticEmitter {
precomputeExpressionRef(expr: ExpressionRef): ExpressionRef {
var nativeType = this.currentType.toNativeType();
var typeRef = this.module.getFunctionTypeBySignature(nativeType, []);
if (!typeRef)
var typeRefAdded = false;
if (!typeRef) {
typeRef = this.module.addFunctionType(this.currentType.toSignatureString(), nativeType, []);
typeRefAdded = true;
}
var funcRef = this.module.addFunction("__precompute", typeRef, [], expr);
this.module.runPasses([ "precompute" ], funcRef);
var ret = _BinaryenFunctionGetBody(funcRef);
this.module.removeFunction("__precompute");
// TODO: also remove the function type somehow if no longer used or make the C-API accept
// a `null` typeRef, using an implicit type.
if (typeRefAdded) {
// TODO: also remove the function type somehow if no longer used or make the C-API accept
// a `null` typeRef, using an implicit type.
}
return ret;
}
@ -2656,56 +2650,62 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createUnreachable();
var element = resolved.element;
if (element.kind == ElementKind.FUNCTION_PROTOTYPE) {
var functionPrototype = <FunctionPrototype>element;
var functionInstance: Function | null = null;
if (functionPrototype.is(ElementFlags.BUILTIN)) {
var resolvedTypeArguments: Type[] | null = null;
if (expression.typeArguments) {
var k = expression.typeArguments.length;
resolvedTypeArguments = new Array<Type>(k);
var sb = new Array<string>(k);
for (var i = 0; i < k; ++i) {
var resolvedType = this.program.resolveType(expression.typeArguments[i], this.currentFunction.contextualTypeArguments, true); // reports
if (!resolvedType)
return this.module.createUnreachable();
resolvedTypeArguments[i] = resolvedType;
sb[i] = resolvedType.toString();
}
functionInstance = functionPrototype.instances.get(sb.join(","));
} else
functionInstance = functionPrototype.instances.get("");
if (!functionInstance) {
var expr = compileBuiltinCall(this, functionPrototype, resolvedTypeArguments, expression.arguments, contextualType, expression);
if (!expr) {
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return this.module.createUnreachable();
}
return expr;
}
} else {
// TODO: infer type arguments from parameter types if omitted
functionInstance = (<FunctionPrototype>element).resolveInclTypeArguments(expression.typeArguments, this.currentFunction.contextualTypeArguments, expression); // reports
}
if (!functionInstance)
return this.module.createUnreachable();
var numArguments = expression.arguments.length;
var numArgumentsInclThis = functionInstance.instanceMethodOf != null ? numArguments + 1 : numArguments;
var argumentIndex = 0;
var args = new Array<Expression>(numArgumentsInclThis);
if (functionInstance.instanceMethodOf) {
assert(resolved.targetExpression != null);
args[argumentIndex++] = <Expression>resolved.targetExpression;
}
for (i = 0; i < numArguments; ++i)
args[argumentIndex++] = expression.arguments[i];
return this.compileCall(functionInstance, args, expression);
if (element.kind != ElementKind.FUNCTION_PROTOTYPE) {
this.error(DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, expression.range, element.internalName);
return this.module.createUnreachable();
}
this.error(DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, expression.range, element.internalName);
return this.module.createUnreachable();
var functionPrototype = <FunctionPrototype>element;
var functionInstance: Function | null = null;
// TODO: generalize?
if (functionPrototype.is(ElementFlags.BUILTIN)) {
var resolvedTypeArguments: Type[] | null = null;
if (expression.typeArguments) {
var k = expression.typeArguments.length;
resolvedTypeArguments = new Array<Type>(k);
for (var i = 0; i < k; ++i) {
var resolvedType = this.program.resolveType(expression.typeArguments[i], this.currentFunction.contextualTypeArguments, true); // reports
if (!resolvedType)
return this.module.createUnreachable();
resolvedTypeArguments[i] = resolvedType;
}
}
var expr = compileBuiltinCall(this, functionPrototype, resolvedTypeArguments, expression.arguments, contextualType, expression);
if (!expr) {
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return this.module.createUnreachable();
}
return expr;
}
// TODO: infer type arguments from parameter types if omitted
var functionInstance = functionPrototype.resolveInclTypeArguments(expression.typeArguments, this.currentFunction.contextualTypeArguments, expression); // reports
if (!functionInstance)
return this.module.createUnreachable();
// TODO: generalize? (see above)
/* if (functionInstance.is(ElementFlags.BUILTIN)) {
var expr = compileBuiltinCall(this, functionPrototype, functionInstance.typeArguments, expression.arguments, contextualType, expression);
if (!expr) {
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return this.module.createUnreachable();
}
return expr;
} */
var numArguments = expression.arguments.length;
var numArgumentsInclThis = functionInstance.instanceMethodOf != null ? numArguments + 1 : numArguments;
var argumentIndex = 0;
var args = new Array<Expression>(numArgumentsInclThis);
if (functionInstance.instanceMethodOf) {
assert(resolved.targetExpression != null);
args[argumentIndex++] = <Expression>resolved.targetExpression;
}
for (i = 0; i < numArguments; ++i)
args[argumentIndex++] = expression.arguments[i];
return this.compileCall(functionInstance, args, expression);
}
/**
@ -2968,16 +2968,75 @@ export class Compiler extends DiagnosticEmitter {
compileStaticArray(elementType: Type, expressions: (Expression | null)[]): ExpressionRef {
// compile as static if all element expressions are precomputable, otherwise
// initialize in place.
var exprs = new Array<ExpressionRef>(expressions.length);
var isStatic = true;
var expr: BinaryenExpressionRef;
for (var i = 0; i < expressions.length; ++i) {
exprs[i] = expressions[i] ? this.compileExpression(<Expression>expressions[i], elementType) : elementType.toNativeZero(this.module);
if (isStatic && _BinaryenExpressionGetId(expr = this.precomputeExpressionRef(exprs[i])) == ExpressionId.Const) {
// TODO: use multiple arrays of possible native types?
} else
isStatic = false;
var size = expressions.length;
var nativeType = elementType.toNativeType();
var values: usize;
switch (nativeType) {
case NativeType.I32:
values = changetype<usize>(new Int32Array(size));
break;
case NativeType.I64:
values = changetype<usize>(new Array<I64>(size));
break;
case NativeType.F32:
values = changetype<usize>(new Float32Array(size));
break;
case NativeType.F64:
values = changetype<usize>(new Float64Array(size));
break;
default:
throw new Error("concrete type expected");
}
var exprs = new Array<ExpressionRef>(size);
var expr: BinaryenExpressionRef;
for (var i = 0; i < size; ++i) {
exprs[i] = expressions[i] ? this.compileExpression(<Expression>expressions[i], elementType) : elementType.toNativeZero(this.module);
if (isStatic) {
if (_BinaryenExpressionGetId(expr = this.precomputeExpressionRef(exprs[i])) == ExpressionId.Const) {
assert(_BinaryenExpressionGetType(expr) == nativeType);
switch (nativeType) {
case NativeType.I32:
changetype<i32[]>(values)[i] = _BinaryenConstGetValueI32(expr);
break;
case NativeType.I64:
changetype<I64[]>(values)[i] = new I64(_BinaryenConstGetValueI64Low(expr), _BinaryenConstGetValueI64High(expr));
break;
case NativeType.F32:
changetype<f32[]>(values)[i] = _BinaryenConstGetValueF32(expr);
break;
case NativeType.F64:
changetype<f64[]>(values)[i] = _BinaryenConstGetValueF64(expr);
break;
default:
assert(false); // checked above
}
} else {
// TODO: emit a warning if declared 'const'
isStatic = false;
}
}
}
if (isStatic) {
// TODO: convert to Uint8Array and create the segment
} else {
// TODO: initialize in place
}
// TODO: alternatively, static elements could go into data segments while
// dynamic ones are initialized on top? any benefits? (doesn't seem so)
throw new Error("not implemented");
}

View File

@ -21,11 +21,14 @@ export enum DiagnosticCode {
Trailing_comma_not_allowed = 1009,
Unexpected_token = 1012,
A_rest_parameter_must_be_last_in_a_parameter_list = 1014,
Parameter_cannot_have_question_mark_and_initializer = 1015,
A_required_parameter_cannot_follow_an_optional_parameter = 1016,
Enum_member_must_have_initializer = 1061,
Statements_are_not_allowed_in_ambient_contexts = 1036,
Initializers_are_not_allowed_in_ambient_contexts = 1039,
_0_modifier_cannot_be_used_here = 1042,
A_rest_parameter_cannot_be_optional = 1047,
A_rest_parameter_cannot_have_an_initializer = 1048,
A_set_accessor_must_have_exactly_one_parameter = 1049,
A_set_accessor_parameter_cannot_have_an_initializer = 1052,
A_get_accessor_cannot_have_parameters = 1054,
@ -115,11 +118,14 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 1009: return "Trailing comma not allowed.";
case 1012: return "Unexpected token.";
case 1014: return "A rest parameter must be last in a parameter list.";
case 1015: return "Parameter cannot have question mark and initializer.";
case 1016: return "A required parameter cannot follow an optional parameter.";
case 1061: return "Enum member must have initializer.";
case 1036: return "Statements are not allowed in ambient contexts.";
case 1039: return "Initializers are not allowed in ambient contexts.";
case 1042: return "'{0}' modifier cannot be used here.";
case 1047: return "A rest parameter cannot be optional.";
case 1048: return "A rest parameter cannot have an initializer.";
case 1049: return "A 'set' accessor must have exactly one parameter.";
case 1052: return "A 'set' accessor parameter cannot have an initializer.";
case 1054: return "A 'get' accessor cannot have parameters.";

View File

@ -20,11 +20,14 @@
"Trailing comma not allowed.": 1009,
"Unexpected token.": 1012,
"A rest parameter must be last in a parameter list.": 1014,
"Parameter cannot have question mark and initializer.": 1015,
"A required parameter cannot follow an optional parameter.": 1016,
"Enum member must have initializer.": 1061,
"Statements are not allowed in ambient contexts.": 1036,
"Initializers are not allowed in ambient contexts.": 1039,
"'{0}' modifier cannot be used here.": 1042,
"A rest parameter cannot be optional.": 1047,
"A rest parameter cannot have an initializer.": 1048,
"A 'set' accessor must have exactly one parameter.": 1049,
"A 'set' accessor parameter cannot have an initializer.": 1052,
"A 'get' accessor cannot have parameters.": 1054,

View File

@ -170,10 +170,8 @@ export abstract class DiagnosticEmitter {
emitDiagnostic(code: DiagnosticCode, category: DiagnosticCategory, range: Range, arg0: string | null = null, arg1: string | null = null) {
var message = DiagnosticMessage.create(code, category, arg0, arg1).withRange(range);
this.diagnostics.push(message);
/* if (!this.silentDiagnostics) {
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
console.log(<string>new Error("stack").stack);
} */
// console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
// console.log(<string>new Error("stack").stack);
}
error(code: DiagnosticCode, range: Range, arg0: string | null = null, arg1: string | null = null): void {

View File

@ -69,6 +69,7 @@ import {
Modifier,
ModifierKind,
Parameter,
ParameterKind,
ExportMember,
SwitchCase,
@ -1189,11 +1190,14 @@ export function serializeModifier(node: Modifier, sb: string[]): void {
}
export function serializeParameter(node: Parameter, sb: string[]): void {
if (node.isRest)
if (node.parameterKind == ParameterKind.REST)
sb.push("...");
serializeIdentifierExpression(node.name, sb);
if (node.type) {
sb.push(": ");
if (node.parameterKind == ParameterKind.OPTIONAL && !node.initializer)
sb.push("?: ");
else
sb.push(": ");
serializeTypeNode(node.type, sb);
}
if (node.initializer) {

View File

@ -23,6 +23,10 @@ import {
DiagnosticEmitter
} from "./diagnostics";
import {
I64
} from "./util/i64";
import {
normalize as normalizePath
} from "./util/path";
@ -66,6 +70,7 @@ import {
ModifierKind,
NamespaceDeclaration,
Parameter,
ParameterKind,
ReturnStatement,
SwitchCase,
SwitchStatement,
@ -533,12 +538,34 @@ export class Parser extends DiagnosticEmitter {
parseParameters(tn: Tokenizer): Parameter[] | null {
// at '(': (Parameter (',' Parameter)*)? ')'
var parameters = new Array<Parameter>();
var seenRest: Parameter | null = null;
var seenOptional = false;
var reportedRest = false;
if (tn.peek() != Token.CLOSEPAREN) {
do {
var param = this.parseParameter(tn);
if (!param)
return null;
parameters.push(<Parameter>param);
if (seenRest && !reportedRest) {
this.error(DiagnosticCode.A_rest_parameter_must_be_last_in_a_parameter_list, seenRest.name.range);
reportedRest = true;
}
switch (param.parameterKind) {
default:
if (seenOptional)
this.error(DiagnosticCode.A_required_parameter_cannot_follow_an_optional_parameter, param.name.range);
break;
case ParameterKind.OPTIONAL:
seenOptional = true;
break;
case ParameterKind.REST:
seenRest = param;
break;
}
parameters.push(param);
} while (tn.skip(Token.COMMA));
}
if (tn.skip(Token.CLOSEPAREN))
@ -549,8 +576,11 @@ export class Parser extends DiagnosticEmitter {
}
parseParameter(tn: Tokenizer): Parameter | null {
// '...'? Identifier (':' Type)? ('=' Expression)?
// '...'? Identifier '?'? (':' Type)? ('=' Expression)?
var isRest = false;
var seenRest = false;
var isOptional = false;
var seenOptional = false;
var startRange: Range | null = null;
if (tn.skip(Token.DOT_DOT_DOT)) {
isRest = true;
@ -561,6 +591,10 @@ export class Parser extends DiagnosticEmitter {
startRange = tn.range();
var identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
var type: TypeNode | null = null;
if (isOptional = tn.skip(Token.QUESTION)) {
if (isRest)
this.error(DiagnosticCode.A_rest_parameter_cannot_be_optional, identifier.range);
}
if (tn.skip(Token.COLON)) {
type = this.parseType(tn);
if (!type)
@ -568,11 +602,17 @@ export class Parser extends DiagnosticEmitter {
}
var initializer: Expression | null = null;
if (tn.skip(Token.EQUALS)) {
if (isRest)
this.error(DiagnosticCode.A_rest_parameter_cannot_have_an_initializer, identifier.range);
if (isOptional)
this.error(DiagnosticCode.Parameter_cannot_have_question_mark_and_initializer, identifier.range);
else
isOptional = true;
initializer = this.parseExpression(tn, Precedence.COMMA + 1);
if (!initializer)
return null;
}
return Node.createParameter(identifier, type, initializer, isRest, Range.join(<Range>startRange, tn.range()));
return Node.createParameter(identifier, type, initializer, isRest ? ParameterKind.REST : isOptional ? ParameterKind.OPTIONAL : ParameterKind.DEFAULT, Range.join(<Range>startRange, tn.range()));
} else
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;

View File

@ -1,7 +1,3 @@
import {
initialize as initializeBuiltins
} from "./builtins";
import {
Options
} from "./compiler";
@ -157,8 +153,6 @@ export class Program extends DiagnosticEmitter {
["boolean", Type.bool]
]);
initializeBuiltins(this);
var queuedExports = new Map<string,QueuedExport>();
var queuedImports = new Array<QueuedImport>();
var queuedDerivedClasses = new Array<ClassPrototype>();
@ -230,9 +224,8 @@ export class Program extends DiagnosticEmitter {
var currentExport: QueuedExport | null = queuedExport; // nullable below
do {
if (currentExport.isReExport) {
element = this.exports.get(currentExport.referencedName);
if (element) {
this.exports.set(exportName, element);
if (element = this.exports.get(currentExport.referencedName)) {
this.setExportAndCheckLibrary(exportName, element, currentExport.member.externalIdentifier);
break;
}
currentExport = queuedExports.get(currentExport.referencedName);
@ -241,9 +234,9 @@ export class Program extends DiagnosticEmitter {
} else {
if (
(element = this.elements.get(currentExport.referencedName)) || // normal export
(element = this.elements.get(currentExport.member.identifier.name)) // stdlib re-export
(element = this.elements.get(currentExport.member.identifier.name)) // library re-export
)
this.exports.set(exportName, element);
this.setExportAndCheckLibrary(exportName, element, currentExport.member.externalIdentifier);
else
this.error(DiagnosticCode.Cannot_find_name_0, queuedExport.member.range, queuedExport.member.identifier.name);
break;
@ -272,8 +265,7 @@ export class Program extends DiagnosticEmitter {
private tryResolveImport(referencedName: string, queuedExports: Map<string,QueuedExport>): Element | null {
var element: Element | null;
do {
element = this.exports.get(referencedName);
if (element)
if (element = this.exports.get(referencedName))
return element;
var queuedExport = queuedExports.get(referencedName);
if (!queuedExport)
@ -286,17 +278,33 @@ export class Program extends DiagnosticEmitter {
} while (true);
}
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))) {
private checkInternalDecorators(element: Element, declaration: DeclarationStatement): void {
var isBuiltin: bool = hasDecorator("builtin", declaration.decorators);
if (isBuiltin)
element.set(ElementFlags.BUILTIN);
if (
hasDecorator("global", declaration.decorators) ||
(
declaration.range.source.isLibrary &&
element.is(ElementFlags.EXPORTED) &&
(
assert(declaration.parent).kind == NodeKind.SOURCE ||
(
<Node>declaration.parent).kind == NodeKind.VARIABLE &&
assert((<Node>declaration.parent).parent).kind == NodeKind.SOURCE
)
)
) {
element.set(ElementFlags.GLOBAL);
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;
if (isBuiltin)
element.internalName = declaration.name.name;
}
}
return false;
}
private initializeClass(declaration: ClassDeclaration, queuedDerivedClasses: ClassPrototype[], namespace: Element | null = null): void {
@ -309,6 +317,8 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace;
this.elements.set(internalName, prototype);
this.checkInternalDecorators(prototype, declaration);
if (hasDecorator("unmanaged", declaration.decorators)) {
prototype.isUnmanaged = true;
if (declaration.implementsTypes && declaration.implementsTypes.length)
@ -363,14 +373,11 @@ export class Program extends DiagnosticEmitter {
}
}
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);
}
}
// check and possibly register string type
if (prototype.is(ElementFlags.GLOBAL) && declaration.name.name === "String" && !this.types.has("string")) {
var instance = prototype.resolve(null);
if (instance)
this.types.set("string", instance.type);
}
}
@ -569,7 +576,7 @@ export class Program extends DiagnosticEmitter {
enm.namespace = namespace;
this.elements.set(internalName, enm);
this.checkGlobalAlias(enm, declaration);
this.checkInternalDecorators(enm, declaration);
if (namespace) {
if (namespace.members) {
@ -613,6 +620,18 @@ export class Program extends DiagnosticEmitter {
this.initializeExport(members[i], statement.internalPath, queuedExports);
}
private setExportAndCheckLibrary(name: string, element: Element, identifier: IdentifierExpression): void {
this.exports.set(name, element);
if (identifier.range.source.isLibrary) { // add global alias
if (this.elements.has(identifier.name))
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, identifier.range, identifier.name);
else {
element.internalName = identifier.name;
this.elements.set(identifier.name, element);
}
}
}
private initializeExport(member: ExportMember, internalPath: string | null, queuedExports: Map<string,QueuedExport>): void {
var externalName = member.range.source.internalPath + PATH_DELIMITER + member.externalIdentifier.name;
if (this.exports.has(externalName)) {
@ -620,6 +639,7 @@ export class Program extends DiagnosticEmitter {
return;
}
var referencedName: string;
var referencedElement: Element | null;
var queuedExport: QueuedExport | null;
// export local element
@ -627,8 +647,8 @@ export class Program extends DiagnosticEmitter {
referencedName = member.range.source.internalPath + PATH_DELIMITER + member.identifier.name;
// resolve right away if the element exists
if (this.elements.has(referencedName)) {
this.exports.set(externalName, <Element>this.elements.get(referencedName));
if (referencedElement = this.elements.get(referencedName)) {
this.setExportAndCheckLibrary(externalName, referencedElement, member.externalIdentifier);
return;
}
@ -648,8 +668,8 @@ export class Program extends DiagnosticEmitter {
referencedName = (<string>internalPath) + PATH_DELIMITER + member.identifier.name;
// resolve right away if the export exists
if (this.exports.has(referencedName)) {
this.exports.set(externalName, <Element>this.exports.get(referencedName));
if (referencedElement = this.elements.get(referencedName)) {
this.setExportAndCheckLibrary(externalName, referencedElement, member.externalIdentifier);
return;
}
@ -657,8 +677,8 @@ export class Program extends DiagnosticEmitter {
var seen = new Set<QueuedExport>();
while (queuedExport = queuedExports.get(referencedName)) {
if (queuedExport.isReExport) {
if (this.exports.has(queuedExport.referencedName)) {
this.exports.set(externalName, <Element>this.exports.get(referencedName));
if (referencedElement = this.exports.get(queuedExport.referencedName)) {
this.setExportAndCheckLibrary(externalName, referencedElement, member.externalIdentifier);
return;
}
referencedName = queuedExport.referencedName;
@ -666,8 +686,8 @@ export class Program extends DiagnosticEmitter {
break;
seen.add(queuedExport);
} else {
if (this.elements.has(queuedExport.referencedName)) {
this.exports.set(externalName, <Element>this.elements.get(referencedName));
if (referencedElement = this.elements.get(queuedExport.referencedName)) {
this.setExportAndCheckLibrary(externalName, referencedElement, member.externalIdentifier);
return;
}
break;
@ -697,7 +717,7 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace;
this.elements.set(internalName, prototype);
this.checkGlobalAlias(prototype, declaration);
this.checkInternalDecorators(prototype, declaration);
if (namespace) {
if (namespace.members) {
@ -787,7 +807,7 @@ export class Program extends DiagnosticEmitter {
prototype.namespace = namespace;
this.elements.set(internalName, prototype);
this.checkGlobalAlias(prototype, declaration);
this.checkInternalDecorators(prototype, declaration);
if (namespace) {
if (namespace.members) {
@ -837,7 +857,7 @@ export class Program extends DiagnosticEmitter {
namespace = new Namespace(this, declaration.name.name, internalName, declaration);
namespace.namespace = parentNamespace;
this.elements.set(internalName, namespace);
this.checkGlobalAlias(namespace, declaration);
this.checkInternalDecorators(namespace, declaration);
}
if (parentNamespace) {
@ -922,13 +942,7 @@ export class Program extends DiagnosticEmitter {
global.namespace = namespace;
this.elements.set(internalName, global);
// 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.is(ElementFlags.EXPORTED))) {
if (this.elements.has(declaration.name.name))
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.name.range, internalName);
else
this.elements.set(declaration.name.name, global);
}
this.checkInternalDecorators(global, declaration);
if (namespace) {
if (namespace.members) {
@ -1202,6 +1216,18 @@ export class Program extends DiagnosticEmitter {
case NodeKind.ELEMENTACCESS:
return this.resolveElementAccess(<ElementAccessExpression>expression, contextualFunction);
case NodeKind.CALL:
var resolved = this.resolveExpression((<CallExpression>expression).expression, contextualFunction);
if (resolved) {
var element = resolved.element;
if (element && element.kind == ElementKind.FUNCTION_PROTOTYPE) {
var instance = (<FunctionPrototype>element).resolveInclTypeArguments((<CallExpression>expression).typeArguments, null, expression);
if (instance && instance.returnType.classType)
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(instance.returnType.classType);
}
}
break;
}
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return null;
@ -1356,12 +1382,13 @@ export class Namespace extends Element {
kind = ElementKind.NAMESPACE;
/** Declaration reference. */
declaration: NamespaceDeclaration | null; // more specific
declaration: NamespaceDeclaration; // more specific
/** Constructs a new namespace. */
constructor(program: Program, simpleName: string, internalName: string, declaration: NamespaceDeclaration | null = null) {
constructor(program: Program, simpleName: string, internalName: string, declaration: NamespaceDeclaration) {
super(program, simpleName, internalName);
if ((this.declaration = declaration) && this.declaration.modifiers) {
this.declaration = declaration;
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
@ -1380,12 +1407,13 @@ export class Enum extends Element {
kind = ElementKind.ENUM;
/** Declaration reference. */
declaration: EnumDeclaration | null;
declaration: EnumDeclaration;
/** Constructs a new enum. */
constructor(program: Program, simpleName: string, internalName: string, declaration: EnumDeclaration | null = null) {
constructor(program: Program, simpleName: string, internalName: string, declaration: EnumDeclaration) {
super(program, simpleName, internalName);
if ((this.declaration = declaration) && this.declaration.modifiers) {
this.declaration = declaration;
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
@ -1405,13 +1433,13 @@ export class EnumValue extends Element {
kind = ElementKind.ENUMVALUE;
/** Declaration reference. */
declaration: EnumValueDeclaration | null;
declaration: EnumValueDeclaration;
/** Parent enum. */
enum: Enum;
/** Constant value, if applicable. */
constantValue: i32 = 0;
constructor(enm: Enum, program: Program, simpleName: string, internalName: string, declaration: EnumValueDeclaration | null = null) {
constructor(enm: Enum, program: Program, simpleName: string, internalName: string, declaration: EnumValueDeclaration) {
super(program, simpleName, internalName);
this.enum = enm;
this.declaration = declaration;
@ -1423,7 +1451,7 @@ export class VariableLikeElement extends Element {
// kind varies
/** Declaration reference. */
declaration: VariableLikeDeclarationStatement | null;
declaration: VariableLikeDeclarationStatement;
/** Variable type. Is {@link Type.void} for type-inferred {@link Global}s before compilation. */
type: Type;
/** Constant integer value, if applicable. */
@ -1449,28 +1477,25 @@ export class Global extends VariableLikeElement {
kind = ElementKind.GLOBAL;
constructor(program: Program, simpleName: string, internalName: string, declaration: VariableLikeDeclarationStatement | null = null, type: Type) {
constructor(program: Program, simpleName: string, internalName: string, declaration: VariableLikeDeclarationStatement, type: Type) {
super(program, simpleName, internalName);
if (this.declaration = declaration) {
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
case ModifierKind.CONST: this.set(ElementFlags.CONSTANT); break;
case ModifierKind.LET: this.set(ElementFlags.SCOPED); break;
case ModifierKind.DECLARE: this.set(ElementFlags.DECLARED); break;
case ModifierKind.READONLY: this.set(this.declaration.initializer ? ElementFlags.CONSTANT | ElementFlags.READONLY : ElementFlags.READONLY); break;
case ModifierKind.PUBLIC:
case ModifierKind.PRIVATE:
case ModifierKind.PROTECTED:
case ModifierKind.STATIC: break; // static fields become globals
default: throw new Error("unexpected modifier");
}
this.declaration = declaration;
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
case ModifierKind.CONST: this.set(ElementFlags.CONSTANT); break;
case ModifierKind.LET: this.set(ElementFlags.SCOPED); break;
case ModifierKind.DECLARE: this.set(ElementFlags.DECLARED); break;
case ModifierKind.READONLY: this.set(this.declaration.initializer ? ElementFlags.CONSTANT | ElementFlags.READONLY : ElementFlags.READONLY); break;
case ModifierKind.PUBLIC:
case ModifierKind.PRIVATE:
case ModifierKind.PROTECTED:
case ModifierKind.STATIC: break; // static fields become globals
default: throw new Error("unexpected modifier");
}
}
} else {
this.set(ElementFlags.CONSTANT | ElementFlags.INLINED); // built-ins have constant values
}
this.type = type; // resolved later if `void`
}
@ -1482,14 +1507,14 @@ export class Parameter {
// not an Element on its own
/** Parameter name. */
name: string | null;
name: string;
/** Parameter type. */
type: Type;
/** Parameter initializer. */
initializer: Expression | null;
/** Constructs a new function parameter. */
constructor(name: string | null, type: Type, initializer: Expression | null = null) {
constructor(name: string, type: Type, initializer: Expression | null = null) {
this.name = name;
this.type = type;
this.initializer = initializer;
@ -1517,7 +1542,7 @@ export class FunctionPrototype extends Element {
kind = ElementKind.FUNCTION_PROTOTYPE;
/** Declaration reference. */
declaration: FunctionDeclaration | null;
declaration: FunctionDeclaration;
/** If an instance method, the class prototype reference. */
classPrototype: ClassPrototype | null;
/** Resolved instances. */
@ -1526,28 +1551,27 @@ export class FunctionPrototype extends Element {
classTypeArguments: Type[] | null = null;
/** Constructs a new function prototype. */
constructor(program: Program, simpleName: string, internalName: string, declaration: FunctionDeclaration | null, classPrototype: ClassPrototype | null = null) {
constructor(program: Program, simpleName: string, internalName: string, declaration: FunctionDeclaration, classPrototype: ClassPrototype | null = null) {
super(program, simpleName, internalName);
if (this.declaration = declaration) {
if (this.declaration.modifiers)
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
case ModifierKind.DECLARE: this.set(ElementFlags.DECLARED); break;
case ModifierKind.GET: this.set(ElementFlags.GETTER); break;
case ModifierKind.SET: this.set(ElementFlags.SETTER); break;
case ModifierKind.STATIC:
case ModifierKind.ABSTRACT:
case ModifierKind.PRIVATE:
case ModifierKind.PROTECTED:
case ModifierKind.PUBLIC: break; // already handled
default: throw new Error("unexpected modifier");
}
this.declaration = declaration;
if (this.declaration.modifiers)
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
case ModifierKind.DECLARE: this.set(ElementFlags.DECLARED); break;
case ModifierKind.GET: this.set(ElementFlags.GETTER); break;
case ModifierKind.SET: this.set(ElementFlags.SETTER); break;
case ModifierKind.STATIC:
case ModifierKind.ABSTRACT:
case ModifierKind.PRIVATE:
case ModifierKind.PROTECTED:
case ModifierKind.PUBLIC: break; // already handled
default: throw new Error("unexpected modifier");
}
if (this.declaration.typeParameters.length)
this.set(ElementFlags.GENERIC);
}
}
if (this.declaration.typeParameters.length)
this.set(ElementFlags.GENERIC);
if (this.classPrototype = classPrototype)
this.set(ElementFlags.INSTANCE);
}
@ -1559,8 +1583,6 @@ export class FunctionPrototype extends Element {
return instance;
var declaration = this.declaration;
if (!declaration)
throw new Error("cannot resolve built-ins");
// inherit contextual type arguments
var inheritedTypeArguments = contextualTypeArguments;
@ -1576,8 +1598,6 @@ export class FunctionPrototype extends Element {
if (!this.classPrototype)
throw new Error("partially resolved instance method must reference its class prototype");
var classDeclaration = (<ClassPrototype>this.classPrototype).declaration;
if (!classDeclaration)
throw new Error("cannot resolve built-ins");
var classTypeParameters = classDeclaration.typeParameters;
if ((k = this.classTypeArguments.length) != classTypeParameters.length)
throw new Error("type argument count mismatch");
@ -1605,7 +1625,7 @@ export class FunctionPrototype extends Element {
typeNode = assert(parameterDeclaration.type);
var parameterType = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports
if (parameterType) {
parameters[i] = new Parameter(parameterDeclaration.name ? parameterDeclaration.name.name : null, parameterType, parameterDeclaration.initializer);
parameters[i] = new Parameter(parameterDeclaration.name.name, parameterType, parameterDeclaration.initializer);
parameterTypes[i] = parameterType;
} else
return null;
@ -1641,13 +1661,11 @@ export class FunctionPrototype extends Element {
return instance;
}
resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null, alternativeReportNode: Node | null): Function | null {
resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null, reportNode: Node): Function | null {
var resolvedTypeArguments: Type[] | null = null;
if (this.is(ElementFlags.GENERIC)) {
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
if (!this.declaration)
throw new Error("cannot resolve built-ins");
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, alternativeReportNode);
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, reportNode);
if (!resolvedTypeArguments)
return null;
}
@ -1709,7 +1727,7 @@ export class Function extends Element {
this.returnType = returnType;
this.instanceMethodOf = instanceMethodOf;
this.flags = prototype.flags;
if (!prototype.is(ElementFlags.BUILTIN | ElementFlags.DECLARED)) {
if (!(prototype.is(ElementFlags.BUILTIN) || prototype.is(ElementFlags.DECLARED))) {
var localIndex = 0;
if (instanceMethodOf) {
assert(this.is(ElementFlags.INSTANCE)); // internal error
@ -1851,15 +1869,16 @@ export class FieldPrototype extends Element {
kind = ElementKind.FIELD_PROTOTYPE;
/** Declaration reference. */
declaration: FieldDeclaration | null;
declaration: FieldDeclaration;
/** Parent class prototype. */
classPrototype: ClassPrototype;
/** Constructs a new field prototype. */
constructor(classPrototype: ClassPrototype, simpleName: string, internalName: string, declaration: FieldDeclaration | null = null) {
constructor(classPrototype: ClassPrototype, simpleName: string, internalName: string, declaration: FieldDeclaration) {
super(classPrototype.program, simpleName, internalName);
this.classPrototype = classPrototype;
if ((this.declaration = declaration) && this.declaration.modifiers) {
this.declaration = declaration;
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
@ -1923,7 +1942,7 @@ export class ClassPrototype extends Element {
kind = ElementKind.CLASS_PROTOTYPE;
/** Declaration reference. */
declaration: ClassDeclaration | null;
declaration: ClassDeclaration;
/** Resolved instances. */
instances: Map<string,Class> = new Map();
/** Instance member prototypes. */
@ -1942,22 +1961,21 @@ export class ClassPrototype extends Element {
/** Overloaded equality comparison method, if any. */
fnEquals: string | null = null;
constructor(program: Program, simpleName: string, internalName: string, declaration: ClassDeclaration | null = null) {
constructor(program: Program, simpleName: string, internalName: string, declaration: ClassDeclaration) {
super(program, simpleName, internalName);
if (this.declaration = declaration) {
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
case ModifierKind.DECLARE: this.set(ElementFlags.DECLARED); break;
default: throw new Error("unexpected modifier");
}
this.declaration = declaration;
if (this.declaration.modifiers) {
for (var i = 0, k = this.declaration.modifiers.length; i < k; ++i) {
switch (this.declaration.modifiers[i].modifierKind) {
case ModifierKind.IMPORT: this.set(ElementFlags.IMPORTED); break;
case ModifierKind.EXPORT: this.set(ElementFlags.EXPORTED); break;
case ModifierKind.DECLARE: this.set(ElementFlags.DECLARED); break;
default: throw new Error("unexpected modifier");
}
}
if (this.declaration.typeParameters.length)
this.set(ElementFlags.GENERIC);
}
if (this.declaration.typeParameters.length)
this.set(ElementFlags.GENERIC);
}
/** Whether an unamanaged class or not. */
@ -1970,10 +1988,6 @@ export class ClassPrototype extends Element {
if (instance)
return instance;
var declaration = this.declaration;
if (!declaration)
throw new Error("cannot resolve built-ins");
// inherit contextual type arguments
var inheritedTypeArguments = contextualTypeArguments;
contextualTypeArguments = new Map();
@ -1981,6 +1995,7 @@ export class ClassPrototype extends Element {
for (var [inheritedName, inheritedType] of inheritedTypeArguments)
contextualTypeArguments.set(inheritedName, inheritedType);
var declaration = this.declaration;
var baseClass: Class | null = null;
if (declaration.extendsType) {
var baseClassType = this.program.resolveType(declaration.extendsType, null); // reports
@ -2039,8 +2054,6 @@ export class ClassPrototype extends Element {
if (!instance.members)
instance.members = new Map();
var fieldDeclaration = (<FieldPrototype>member).declaration;
if (!fieldDeclaration)
throw new Error("cannot resolve built-ins");
if (!fieldDeclaration.type)
throw new Error("type expected"); // TODO: check if parent class defines a type for it already
var fieldType = this.program.resolveType(fieldDeclaration.type, instance.contextualTypeArguments); // reports
@ -2091,8 +2104,6 @@ export class ClassPrototype extends Element {
var resolvedTypeArguments: Type[] | null = null;
if (this.is(ElementFlags.GENERIC)) {
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
if (!this.declaration)
throw new Error("cannot resolve built-ins");
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, alternativeReportNode);
if (!resolvedTypeArguments)
return null;
@ -2171,10 +2182,10 @@ export class InterfacePrototype extends ClassPrototype {
kind = ElementKind.INTERFACE_PROTOTYPE;
/** Declaration reference. */
declaration: InterfaceDeclaration | null; // more specific
declaration: InterfaceDeclaration; // more specific
/** Constructs a new interface prototype. */
constructor(program: Program, simpleName: string, internalName: string, declaration: InterfaceDeclaration | null = null) {
constructor(program: Program, simpleName: string, internalName: string, declaration: InterfaceDeclaration) {
super(program, simpleName, internalName, declaration);
}
}

3
std/assembly.d.ts vendored
View File

@ -297,3 +297,6 @@ declare function unmanaged(target: Function): any;
/** Annotates a class field with an explicit offset. */
declare function offset(offset: usize): any;
/** Annotates an element as begin built-in. */
declare function builtin(target: Function): any;

208
std/assembly/builtins.ts Normal file
View File

@ -0,0 +1,208 @@
@builtin
export declare const NaN: f64; // | f32
@builtin
export declare const Infinity: f64; // | f32
@builtin
export declare function isNaN<T>(value: T): bool;
@builtin
export declare function isFinite<T>(value: T): bool;
@builtin
export declare function clz<T>(value: T): T;
@builtin
export declare function ctz<T>(value: T): T;
@builtin
export declare function popcnt<T>(value: T): T;
@builtin
export declare function rotl<T>(value: T, shift: T): T;
@builtin
export declare function rotr<T>(value: T, shift: T): T;
@builtin
export declare function abs<T>(value: T): T;
@builtin
export declare function max<T>(left: T, right: T): T;
@builtin
export declare function min<T>(left: T, right: T): T;
@builtin
export declare function ceil<T>(value: T): T;
@builtin
export declare function floor<T>(value: T): T;
@builtin
export declare function copysign<T>(left: T, right: T): T;
@builtin
export declare function nearest<T>(left: T, right: T): T;
@builtin
export declare function reinterpret<T>(value: void): T;
@builtin
export declare function sqrt<T>(value: T): T;
@builtin
export declare function trunc<T>(value: T): T;
@builtin
export declare function load<T>(offset: usize, constantOffset?: usize): T;
@builtin
export declare function store<T>(offset: usize, value: void, constantOffset?: usize): T;
@builtin
export declare function sizeof<T>(): usize;
@builtin
export declare function select<T>(ifTrue: T, ifFalse: T, condition: bool): T;
@builtin
export declare function unreachable(): void;
@builtin
export declare function current_memory(): i32;
@builtin
export declare function grow_memory(pages: i32): i32;
// @builtin
// export declare function move_memory(dest: usize, src: usize: n: usize): void;
// @builtin
// export declare function set_memory(dest: usize, value: u32, n: usize): void;
@builtin
export declare function changetype<T>(value: void): T;
@builtin
export declare function assert<T>(isTrueish: T, message?: string): T;
@builtin
export declare function abort(message?: string | null, fileName?: string | null, lineNumber?: u32, columnNumber?: u32): void;
@builtin
declare function i8(value: void): i8;
namespace i8 {
export const MIN_VALUE: i8 = -128;
export const MAX_VALUE: i8 = 127;
}
export { i8 };
@builtin
declare function i16(value: void): i16;
namespace i16 {
export const MIN_VALUE: i16 = -32768;
export const MAX_VALUE: i16 = 32767;
}
export { i16 };
@builtin
declare function i32(value: void): i32;
namespace i32 {
export const MIN_VALUE: i32 = -2147483648;
export const MAX_VALUE: i32 = 2147483647;
}
export { i32 };
@builtin
declare function i64(value: void): i64;
namespace i64 {
export const MIN_VALUE: i64 = -9223372036854775808;
export const MAX_VALUE: i64 = 9223372036854775807;
}
export { i64 };
@builtin
declare function isize(value: void): isize;
namespace isize {
export const MIN_VALUE: isize = sizeof<i32>() == sizeof<isize>() ? -2147483648 : <usize>-9223372036854775808;
export const MAX_VALUE: isize = sizeof<i32>() == sizeof<isize>() ? 2147483647 : <usize>9223372036854775807;
}
export { isize };
@builtin
declare function u8(value: void): u8;
namespace u8 {
export const MIN_VALUE: u8 = 0;
export const MAX_VALUE: u8 = 255;
}
export { u8 };
@builtin
declare function u16(value: void): u16;
namespace u16 {
export const MIN_VALUE: u16 = 0;
export const MAX_VALUE: u16 = 65535;
}
export { u16 };
@builtin
declare function u32(value: void): u32;
namespace u32 {
export const MIN_VALUE: u32 = 0;
export const MAX_VALUE: u32 = 4294967295;
}
export { u32 };
@builtin
declare function u64(value: void): u64;
namespace u64 {
export const MIN_VALUE: u64 = 0;
export const MAX_VALUE: u64 = 18446744073709551615;
}
export { u64 };
@builtin
declare function usize(value: void): usize;
namespace usize {
export const MIN_VALUE: usize = 0;
export const MAX_VALUE: usize = sizeof<u32>() == sizeof<usize>() ? 4294967295 : <usize>18446744073709551615;
}
export { usize };
@builtin
declare function bool(value: void): bool;
namespace bool {
export const MIN_VALUE: bool = 0;
export const MAX_VALUE: bool = 1;
}
export { bool };
@builtin
declare function f32(value: void): f32;
namespace f32 {
export const MIN_VALUE: f32 = -3.40282347e+38;
export const MAX_VALUE: f32 = 3.40282347e+38;
export const MIN_SAFE_INTEGER: f32 = -16777215;
export const MAX_SAFE_INTEGER: f32 = 16777215;
export const EPSILON: f32 = 1.19209290e-07;
}
export { f32 };
@builtin
declare function f64(value: void): f64;
namespace f64 {
export const MIN_VALUE: f64 = -1.7976931348623157e+308;
export const MAX_VALUE: f64 = 1.7976931348623157e+308;
export const MIN_SAFE_INTEGER: f64 = -9007199254740991;
export const MAX_SAFE_INTEGER: f64 = 9007199254740991;
export const EPSILON: f64 = 2.2204460492503131e-16;
}
export{ f64 };
@builtin
export declare const HEAP_BASE: usize;
@builtin
export declare function start(): void;

2
std/portable.d.ts vendored
View File

@ -169,6 +169,8 @@ declare class Uint32Array extends Array<u32> {}
declare class Int8Array extends Array<i8> {}
declare class Int16Array extends Array<i16> {}
declare class Int32Array extends Array<i32> {}
declare class Float32Array extends Array<f32> {}
declare class Float64Array extends Array<f64> {}
declare class String {
static fromCharCode(ls: i32, hs?: i32): string;

View File

@ -2,6 +2,9 @@
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $i (func (result i32)))
(type $v (func))
(type $I (func (result i64)))
(type $f (func (result f32)))
(type $F (func (result f64)))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $builtins/b (mut i32) (i32.const 0))
(global $builtins/i (mut i32) (i32.const 0))
@ -12,34 +15,6 @@
(global $builtins/u (mut i32) (i32.const 0))
(global $builtins/U (mut i64) (i64.const 0))
(global $builtins/s (mut i32) (i32.const 0))
(global $i8.MIN_VALUE i32 (i32.const -128))
(global $i8.MAX_VALUE i32 (i32.const 127))
(global $i16.MIN_VALUE i32 (i32.const -32768))
(global $i16.MAX_VALUE i32 (i32.const 32767))
(global $i32.MIN_VALUE i32 (i32.const -2147483648))
(global $i32.MAX_VALUE i32 (i32.const 2147483647))
(global $i64.MIN_VALUE i64 (i64.const -9223372036854775808))
(global $i64.MAX_VALUE i64 (i64.const 9223372036854775807))
(global $u8.MIN_VALUE i32 (i32.const 0))
(global $u8.MAX_VALUE i32 (i32.const 255))
(global $u16.MIN_VALUE i32 (i32.const 0))
(global $u16.MAX_VALUE i32 (i32.const 65535))
(global $u32.MIN_VALUE i32 (i32.const 0))
(global $u32.MAX_VALUE i32 (i32.const -1))
(global $u64.MIN_VALUE i64 (i64.const 0))
(global $u64.MAX_VALUE i64 (i64.const -1))
(global $bool.MIN_VALUE i32 (i32.const 0))
(global $bool.MAX_VALUE i32 (i32.const 1))
(global $f32.MIN_VALUE f32 (f32.const -3402823466385288598117041e14))
(global $f32.MAX_VALUE f32 (f32.const 3402823466385288598117041e14))
(global $f32.MIN_SAFE_INTEGER f32 (f32.const -16777215))
(global $f32.MAX_SAFE_INTEGER f32 (f32.const 16777215))
(global $f32.EPSILON f32 (f32.const 1.1920928955078125e-07))
(global $f64.MIN_VALUE f64 (f64.const -1797693134862315708145274e284))
(global $f64.MAX_VALUE f64 (f64.const 1797693134862315708145274e284))
(global $f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991))
(global $f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991))
(global $f64.EPSILON f64 (f64.const 2.220446049250313e-16))
(global $HEAP_BASE i32 (i32.const 36))
(memory $0 1)
(data (i32.const 8) "\0b\00\00\00b\00u\00i\00l\00t\00i\00n\00s\00.\00t\00s\00")

View File

@ -4,8 +4,6 @@
(type $fff (func (param f32 f32) (result f32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $f64.EPSILON f64 (f64.const 2.220446049250313e-16))
(global $f32.EPSILON f32 (f32.const 1.1920928955078125e-07))
(global $HEAP_BASE i32 (i32.const 28))
(memory $0 1)
(data (i32.const 8) "\07\00\00\00f\00m\00o\00d\00.\00t\00s\00")

View File

@ -1,27 +1,9 @@
(module
(type $i (func (result i32)))
(type $I (func (result i64)))
(type $f (func (result f32)))
(type $F (func (result f64)))
(type $v (func))
(global $i8.MIN_VALUE i32 (i32.const -128))
(global $i8.MAX_VALUE i32 (i32.const 127))
(global $i16.MIN_VALUE i32 (i32.const -32768))
(global $i16.MAX_VALUE i32 (i32.const 32767))
(global $i32.MIN_VALUE i32 (i32.const -2147483648))
(global $i32.MAX_VALUE i32 (i32.const 2147483647))
(global $i64.MIN_VALUE i64 (i64.const -9223372036854775808))
(global $i64.MAX_VALUE i64 (i64.const 9223372036854775807))
(global $u8.MIN_VALUE i32 (i32.const 0))
(global $u8.MAX_VALUE i32 (i32.const 255))
(global $u16.MIN_VALUE i32 (i32.const 0))
(global $u16.MAX_VALUE i32 (i32.const 65535))
(global $u32.MIN_VALUE i32 (i32.const 0))
(global $u32.MAX_VALUE i32 (i32.const -1))
(global $u64.MIN_VALUE i64 (i64.const 0))
(global $u64.MAX_VALUE i64 (i64.const -1))
(global $bool.MIN_VALUE i32 (i32.const 0))
(global $bool.MAX_VALUE i32 (i32.const 1))
(global $f32.MIN_SAFE_INTEGER f32 (f32.const -16777215))
(global $f32.MAX_SAFE_INTEGER f32 (f32.const 16777215))
(global $f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991))
(global $f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))

View File

@ -1,17 +1,9 @@
(module
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $iiv (func (param i32 i32)))
(type $i (func (result i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $i8.MAX_VALUE i32 (i32.const 127))
(global $i8.MIN_VALUE i32 (i32.const -128))
(global $u8.MAX_VALUE i32 (i32.const 255))
(global $i16.MIN_VALUE i32 (i32.const -32768))
(global $i16.MAX_VALUE i32 (i32.const 32767))
(global $u16.MAX_VALUE i32 (i32.const 65535))
(global $i32.MAX_VALUE i32 (i32.const 2147483647))
(global $i32.MIN_VALUE i32 (i32.const -2147483648))
(global $u32.MAX_VALUE i32 (i32.const -1))
(global $retain-i32/si (mut i32) (i32.const 0))
(global $retain-i32/ui (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 40))

View File

@ -1,6 +1,9 @@
(module
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $i (func (result i32)))
(type $I (func (result i64)))
(type $f (func (result f32)))
(type $F (func (result f64)))
(type $ii (func (param i32) (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $fff (func (param f32 f32) (result f32)))
@ -39,34 +42,6 @@
(global $builtins/u (mut i32) (i32.const 0))
(global $builtins/U (mut i64) (i64.const 0))
(global $builtins/s (mut i32) (i32.const 0))
(global $i8.MIN_VALUE i32 (i32.const -128))
(global $i8.MAX_VALUE i32 (i32.const 127))
(global $i16.MIN_VALUE i32 (i32.const -32768))
(global $i16.MAX_VALUE i32 (i32.const 32767))
(global $i32.MIN_VALUE i32 (i32.const -2147483648))
(global $i32.MAX_VALUE i32 (i32.const 2147483647))
(global $i64.MIN_VALUE i64 (i64.const -9223372036854775808))
(global $i64.MAX_VALUE i64 (i64.const 9223372036854775807))
(global $u8.MIN_VALUE i32 (i32.const 0))
(global $u8.MAX_VALUE i32 (i32.const 255))
(global $u16.MIN_VALUE i32 (i32.const 0))
(global $u16.MAX_VALUE i32 (i32.const 65535))
(global $u32.MIN_VALUE i32 (i32.const 0))
(global $u32.MAX_VALUE i32 (i32.const -1))
(global $u64.MIN_VALUE i64 (i64.const 0))
(global $u64.MAX_VALUE i64 (i64.const -1))
(global $bool.MIN_VALUE i32 (i32.const 0))
(global $bool.MAX_VALUE i32 (i32.const 1))
(global $f32.MIN_VALUE f32 (f32.const -3402823466385288598117041e14))
(global $f32.MAX_VALUE f32 (f32.const 3402823466385288598117041e14))
(global $f32.MIN_SAFE_INTEGER f32 (f32.const -16777215))
(global $f32.MAX_SAFE_INTEGER f32 (f32.const 16777215))
(global $f32.EPSILON f32 (f32.const 1.1920928955078125e-07))
(global $f64.MIN_VALUE f64 (f64.const -1797693134862315708145274e284))
(global $f64.MAX_VALUE f64 (f64.const 1797693134862315708145274e284))
(global $f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991))
(global $f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991))
(global $f64.EPSILON f64 (f64.const 2.220446049250313e-16))
(global $showcase/ANamespace.aNamespacedGlobal (mut i32) (i32.const 42))
(global $showcase/AnEnum.ONE i32 (i32.const 1))
(global $showcase/AnEnum.TWO i32 (i32.const 2))

View File

@ -0,0 +1,6 @@
function restValid(a: i32, ...b: i32[]): void {}
function restParameterMustBeLast(...a: i32[], b: i32): void {}
function optionalValid(a: i32, b?: i32): void {}
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {}
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {}

View File

@ -0,0 +1,13 @@
function restValid(a: i32, ...b: Array<i32>): void {
}
function restParameterMustBeLast(...a: Array<i32>, b: i32): void {
}
function optionalValid(a: i32, b?: i32): void {
}
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {
}
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {
}
// ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts @ 85,86
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts @ 210,211
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts @ 293,294