mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +00:00
Move built-in declarations to actual sources; Remove declaration is null checks; Resolve calls
This commit is contained in:
parent
a7e815dcec
commit
ad92d91f01
@ -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"));
|
||||
|
@ -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
5
examples/tlsf/index.js
Normal 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;
|
@ -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"
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
22
src/ast.ts
22
src/ast.ts
@ -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. */
|
||||
|
144
src/builtins.ts
144
src/builtins.ts
@ -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();
|
||||
|
295
src/compiler.ts
295
src/compiler.ts
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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.";
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
273
src/program.ts
273
src/program.ts
@ -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
3
std/assembly.d.ts
vendored
@ -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
208
std/assembly/builtins.ts
Normal 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
2
std/portable.d.ts
vendored
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
6
tests/parser/parameter-order.ts
Normal file
6
tests/parser/parameter-order.ts
Normal 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 {}
|
13
tests/parser/parameter-order.ts.fixture.ts
Normal file
13
tests/parser/parameter-order.ts.fixture.ts
Normal 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
|
Loading…
x
Reference in New Issue
Block a user