Move some numeric builtins to stdlib; Minor refactoring

This commit is contained in:
dcodeIO
2018-04-17 02:50:38 +02:00
parent 6d0b5d92c2
commit 4929fca363
26 changed files with 1987 additions and 1746 deletions

View File

@ -1767,23 +1767,17 @@ export class WhileStatement extends Statement {
statement: Statement;
}
/** Gets the first decorator by name within at set of decorators, if present. */
export function getFirstDecorator(name: string, decorators: DecoratorNode[] | null): DecoratorNode | null {
/** Tests if a specific decorator is present within the specified decorators. */
export function hasDecorator(name: string, decorators: DecoratorNode[] | null): bool {
if (decorators) {
for (let i = 0, k = decorators.length; i < k; ++i) {
let decorator = decorators[i];
let expression = decorator.name;
let expression = decorators[i].name;
if (expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>expression).text == name) {
return decorator;
return true;
}
}
}
return null;
}
/** Tests if a specific decorator is present within the specified decorators. */
export function hasDecorator(name: string, decorators: DecoratorNode[] | null): bool {
return getFirstDecorator(name, decorators) != null;
return false;
}
/** Mangles a declaration's name to an internal name. */

View File

@ -54,22 +54,6 @@ export function compileGetConstant(
reportNode: Node
): ExpressionRef {
switch (global.internalName) {
case "NaN": { // context-sensitive
if (compiler.currentType == Type.f32) {
return compiler.module.createF32(NaN);
} else {
compiler.currentType = Type.f64;
return compiler.module.createF64(NaN);
}
}
case "Infinity": { // context-sensitive
if (compiler.currentType == Type.f32) {
return compiler.module.createF32(Infinity);
} else {
compiler.currentType = Type.f64;
return compiler.module.createF64(Infinity);
}
}
case "HEAP_BASE": { // never inlined for linking purposes
compiler.currentType = compiler.options.usizeType;
return compiler.module.createGetGlobal("HEAP_BASE", compiler.currentType.toNativeType());
@ -154,143 +138,6 @@ export function compileCall(
// math
case "isNaN": { // isNaN<T?>(value: T) -> bool
compiler.currentType = Type.bool;
if (operands.length != 1) {
if (typeArguments && typeArguments.length != 1) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments.length.toString(10)
);
}
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "1", operands.length.toString(10)
);
return module.createUnreachable();
}
if (typeArguments) {
if (typeArguments.length != 1) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments.length.toString(10)
);
return module.createUnreachable();
}
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
} else {
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
}
switch (compiler.currentType.kind) {
case TypeKind.F32: {
ret = module.createBinary(
BinaryOp.GtU32,
module.createBinary(
BinaryOp.AndI32,
module.createUnary(UnaryOp.ReinterpretF32, arg0),
module.createI32(0x7FFFFFFF)
),
module.createI32(0x7F800000)
);
break;
}
case TypeKind.F64: {
ret = module.createBinary(
BinaryOp.GtU64,
module.createBinary(
BinaryOp.AndI64,
module.createUnary(UnaryOp.ReinterpretF64, arg0),
module.createI64(0xFFFFFFFF, 0x7FFFFFFF)
),
module.createI64(0, 0x7FF00000)
);
break;
}
case TypeKind.VOID: {
compiler.error(
DiagnosticCode.Operation_not_supported,
reportNode.range
);
ret = module.createUnreachable();
break;
}
default: { // every other type is never NaN
ret = module.createI32(0);
break;
}
}
compiler.currentType = Type.bool;
return ret;
}
case "isFinite": { // isFinite<T?>(value: T) -> bool
compiler.currentType = Type.bool;
if (operands.length != 1) {
if (typeArguments && typeArguments.length != 1) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments.length.toString(10)
);
}
compiler.error(
DiagnosticCode.Expected_0_arguments_but_got_1,
reportNode.range, "1", operands.length.toString(10)
);
return module.createUnreachable();
}
if (typeArguments) {
if (typeArguments.length != 1) {
compiler.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, "1", typeArguments.length.toString(10)
);
return module.createUnreachable();
}
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
} else {
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
}
switch (compiler.currentType.kind) {
case TypeKind.F32: {
ret = module.createBinary(
BinaryOp.LtU32,
module.createBinary(
BinaryOp.AndI32,
module.createUnary(UnaryOp.ReinterpretF32, arg0),
module.createI32(0x7FFFFFFF)
),
module.createI32(0x7F800000)
);
break;
}
case TypeKind.F64: {
ret = module.createBinary(
BinaryOp.LtU64,
module.createBinary(
BinaryOp.AndI64,
module.createUnary(UnaryOp.ReinterpretF64, arg0),
module.createI64(0xFFFFFFFF, 0x7FFFFFFF)
),
module.createI64(0, 0x7FF00000)
);
break;
}
case TypeKind.VOID: {
compiler.error(
DiagnosticCode.Operation_not_supported,
reportNode.range
);
ret = module.createUnreachable();
break;
}
default: { // every other type is always finite
ret = module.createI32(1);
break;
}
}
compiler.currentType = Type.bool;
return ret;
}
case "clz": { // clz<T?>(value: T) -> T
if (operands.length != 1) {
if (typeArguments) {

View File

@ -266,12 +266,10 @@ export class Compiler extends DiagnosticEmitter {
this.startFunction = startFunctionInstance;
this.currentFunction = startFunctionInstance;
// compile entry file(s) while traversing to reachable elements
// compile entry file(s) while traversing reachable elements
var sources = program.sources;
for (let i = 0, k = sources.length; i < k; ++i) {
if (sources[i].isEntry) {
this.compileSource(sources[i]);
}
if (sources[i].isEntry) this.compileSource(sources[i]);
}
// compile the start function if not empty
@ -326,7 +324,7 @@ export class Compiler extends DiagnosticEmitter {
);
}
// import memory if requested
// import memory if requested (default memory is named '0' by Binaryen)
if (options.importMemory) module.addMemoryImport("0", "env", "memory");
// set up function table
@ -343,7 +341,7 @@ export class Compiler extends DiagnosticEmitter {
functionTableExported = true;
}
// import table if requested
// import table if requested (default table is named '0' by Binaryen)
if (options.importTable) {
module.addTableImport("0", "env", "table");
if (!functionTableExported) module.addTableExport("0", "table");
@ -354,6 +352,7 @@ export class Compiler extends DiagnosticEmitter {
// sources
/** Compiles a source by looking it up by path first. */
compileSourceByPath(normalizedPathWithoutExtension: string, reportNode: Node): void {
var source = this.program.lookupSourceByPath(normalizedPathWithoutExtension);
if (!source) {
@ -366,8 +365,9 @@ export class Compiler extends DiagnosticEmitter {
this.compileSource(source);
}
/** Compiles a source. */
compileSource(source: Source): void {
if (source.is(CommonFlags.COMPILED)) return;
if (source.is(CommonFlags.COMPILED)) return;
source.set(CommonFlags.COMPILED);
// compile top-level statements
@ -2098,12 +2098,16 @@ export class Compiler extends DiagnosticEmitter {
)
: this.module.createI64(0);
}
case TypeKind.F64: {
if (!(element.is(CommonFlags.BUILTIN) && contextualType == Type.f32)) {
return this.module.createF64((<VariableLikeElement>element).constantFloatValue);
}
// otherwise fall-through: basically precomputes f32.demote/f64 of NaN / Infinity
this.currentType = Type.f32;
}
case TypeKind.F32: {
return this.module.createF32((<VariableLikeElement>element).constantFloatValue);
}
case TypeKind.F64: {
return this.module.createF64((<VariableLikeElement>element).constantFloatValue);
}
default: {
assert(false);
return this.module.createUnreachable();
@ -2324,18 +2328,14 @@ export class Compiler extends DiagnosticEmitter {
expr = module.createUnary(UnaryOp.TruncF32ToI64, expr);
} else {
expr = module.createUnary(UnaryOp.TruncF32ToI32, expr);
if (toType.is(TypeFlags.SMALL)) {
expr = makeSmallIntegerWrap(expr, toType, module);
}
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
}
} else {
if (toType.is(TypeFlags.LONG)) {
expr = module.createUnary(UnaryOp.TruncF32ToU64, expr);
} else {
expr = module.createUnary(UnaryOp.TruncF32ToU32, expr);
if (toType.is(TypeFlags.SMALL)) {
expr = makeSmallIntegerWrap(expr, toType, module);
}
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
}
}
@ -2346,18 +2346,14 @@ export class Compiler extends DiagnosticEmitter {
expr = module.createUnary(UnaryOp.TruncF64ToI64, expr);
} else {
expr = module.createUnary(UnaryOp.TruncF64ToI32, expr);
if (toType.is(TypeFlags.SMALL)) {
expr = makeSmallIntegerWrap(expr, toType, module);
}
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
}
} else {
if (toType.is(TypeFlags.LONG)) {
expr = module.createUnary(UnaryOp.TruncF64ToU64, expr);
} else {
expr = module.createUnary(UnaryOp.TruncF64ToU32, expr);
if (toType.is(TypeFlags.SMALL)) {
expr = makeSmallIntegerWrap(expr, toType, module);
}
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
}
}
}
@ -2415,9 +2411,7 @@ export class Compiler extends DiagnosticEmitter {
// i64 to i32
if (!toType.is(TypeFlags.LONG)) {
expr = module.createUnary(UnaryOp.WrapI64, expr); // discards upper bits
if (toType.is(TypeFlags.SMALL)) {
expr = makeSmallIntegerWrap(expr, toType, module);
}
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
}
// i32 to i64
@ -2426,7 +2420,7 @@ export class Compiler extends DiagnosticEmitter {
// i32 or smaller to even smaller or same size int with change of sign
} else if (
toType.is(TypeFlags.SMALL) &&
toType.is(TypeFlags.SHORT) &&
(
fromType.size > toType.size ||
(
@ -4097,7 +4091,7 @@ export class Compiler extends DiagnosticEmitter {
leftExpr = module.createTeeLocal(tempLocal.index, leftExpr);
}
possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER);
possiblyOverflows = this.currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER);
condExpr = makeIsTrueish(leftExpr, this.currentType, module);
// simplify when cloning left without side effects was successful
@ -4143,7 +4137,7 @@ export class Compiler extends DiagnosticEmitter {
leftExpr = module.createTeeLocal(tempLocal.index, leftExpr);
}
possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if right did
possiblyOverflows = this.currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER); // if right did
condExpr = makeIsTrueish(leftExpr, this.currentType, module);
// simplify when cloning left without side effects was successful
@ -4179,7 +4173,7 @@ export class Compiler extends DiagnosticEmitter {
}
}
if (possiblyOverflows && wrapSmallIntegers) {
assert(this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER)); // must be a small int
assert(this.currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER)); // must be a small int
expr = makeSmallIntegerWrap(expr, this.currentType, module);
}
return compound
@ -6201,7 +6195,7 @@ export class Compiler extends DiagnosticEmitter {
}
if (possiblyOverflows) {
assert(currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER));
assert(currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER));
setValue = makeSmallIntegerWrap(setValue, currentType, module);
}
@ -6252,7 +6246,7 @@ export class Compiler extends DiagnosticEmitter {
false // wrapped below
);
currentType = this.currentType;
possiblyOverflows = currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if operand already did
possiblyOverflows = currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER); // if operand already did
break;
}
case Token.MINUS: {
@ -6553,7 +6547,7 @@ export class Compiler extends DiagnosticEmitter {
}
}
if (possiblyOverflows && wrapSmallIntegers) {
assert(currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER));
assert(currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER));
expr = makeSmallIntegerWrap(expr, currentType, module);
}
return compound

View File

@ -36,17 +36,27 @@ abstract class ExportsWalker {
/** Program reference. */
program: Program;
/** Whether to include private members */
private includePrivate: bool;
/** Already seen elements. */
private seen: Set<Element> = new Set();
/** Constructs a new Element walker. */
constructor(program: Program) {
constructor(program: Program, includePrivate: bool = false) {
this.program = program;
this.includePrivate;
}
/** Walks all exports and calls the respective handlers. */
walk(): void {
for (let element of this.program.moduleLevelExports.values()) this.visitElement(element);
}
/** Visits an element.*/
visitElement(element: Element): void {
if (element.is(CommonFlags.PRIVATE) && !this.includePrivate) return;
if (this.seen.has(element)) return;
this.seen.add(element);
switch (element.kind) {
case ElementKind.GLOBAL: {
if (element.is(CommonFlags.COMPILED)) this.visitGlobal(<Global>element);
@ -57,11 +67,11 @@ abstract class ExportsWalker {
break;
}
case ElementKind.FUNCTION_PROTOTYPE: {
this.visitCompiledFunctions(<FunctionPrototype>element);
this.visitFunctionInstances(<FunctionPrototype>element);
break;
}
case ElementKind.CLASS_PROTOTYPE: {
this.visitCompiledClasses(<ClassPrototype>element);
this.visitClassInstances(<ClassPrototype>element);
break;
}
case ElementKind.FIELD: {
@ -71,26 +81,26 @@ abstract class ExportsWalker {
case ElementKind.PROPERTY: {
let prop = <Property>element;
let getter = prop.getterPrototype;
if (getter) this.visitCompiledFunctions(getter);
if (getter) this.visitFunctionInstances(getter);
let setter = prop.setterPrototype;
if (setter) this.visitCompiledFunctions(setter);
if (setter) this.visitFunctionInstances(setter);
break;
}
case ElementKind.NAMESPACE: {
if (hasCompiledMember(<Namespace>element)) this.visitNamespace(<Namespace>element);
if (hasCompiledMember(element)) this.visitNamespace(element);
break;
}
default: assert(false);
}
}
visitCompiledFunctions(element: FunctionPrototype): void {
private visitFunctionInstances(element: FunctionPrototype): void {
for (let instance of element.instances.values()) {
if (instance.is(CommonFlags.COMPILED)) this.visitFunction(<Function>instance);
}
}
visitCompiledClasses(element: ClassPrototype): void {
private visitClassInstances(element: ClassPrototype): void {
for (let instance of element.instances.values()) {
if (instance.is(CommonFlags.COMPILED)) this.visitClass(<Class>instance);
}
@ -114,17 +124,14 @@ export class IDLBuilder extends ExportsWalker {
}
private sb: string[] = [];
private seen: Set<Element> = new Set();
private indentLevel: i32 = 0;
/** Constructs a new WebIDL builder. */
constructor(program: Program) {
super(program);
constructor(program: Program, includePrivate: bool = false) {
super(program, includePrivate);
}
visitGlobal(element: Global): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
var isConst = element.is(CommonFlags.INLINED);
indent(sb, this.indentLevel);
@ -151,8 +158,6 @@ export class IDLBuilder extends ExportsWalker {
}
visitEnum(element: Enum): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
indent(sb, this.indentLevel++);
sb.push("interface ");
@ -184,8 +189,6 @@ export class IDLBuilder extends ExportsWalker {
}
visitFunction(element: Function): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
var signature = element.signature;
indent(sb, this.indentLevel);
@ -217,8 +220,6 @@ export class IDLBuilder extends ExportsWalker {
}
visitClass(element: Class): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
indent(sb, this.indentLevel++);
sb.push("interface ");
@ -238,8 +239,6 @@ export class IDLBuilder extends ExportsWalker {
}
visitNamespace(element: Namespace): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
indent(sb, this.indentLevel++);
sb.push("interface ");
@ -298,17 +297,14 @@ export class TSDBuilder extends ExportsWalker {
}
private sb: string[] = [];
private seen: Set<Element> = new Set();
private indentLevel: i32 = 0;
/** Constructs a new WebIDL builder. */
constructor(program: Program) {
super(program);
constructor(program: Program, includePrivate: bool = false) {
super(program, includePrivate);
}
visitGlobal(element: Global): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
var isConst = element.is(CommonFlags.INLINED);
indent(sb, this.indentLevel);
@ -327,8 +323,6 @@ export class TSDBuilder extends ExportsWalker {
}
visitEnum(element: Enum): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
indent(sb, this.indentLevel++);
sb.push("enum ");
@ -339,7 +333,6 @@ export class TSDBuilder extends ExportsWalker {
let numMembers = members.size;
for (let [name, member] of members) {
if (member.kind == ElementKind.ENUMVALUE) {
this.seen.add(member);
indent(sb, this.indentLevel);
sb.push(name);
if (member.is(CommonFlags.INLINED)) {
@ -357,8 +350,6 @@ export class TSDBuilder extends ExportsWalker {
}
visitFunction(element: Function): void {
if (this.seen.has(element)) return;
this.seen.add(element);
if (element.is(CommonFlags.PRIVATE)) return;
var sb = this.sb;
var signature = element.signature;
@ -397,8 +388,6 @@ export class TSDBuilder extends ExportsWalker {
}
visitClass(element: Class): void {
if (this.seen.has(element)) return;
this.seen.add(element);
var sb = this.sb;
var isInterface = element.kind == ElementKind.INTERFACE;
indent(sb, this.indentLevel++);
@ -530,8 +519,6 @@ export class TSDBuilder extends ExportsWalker {
}
}
// TODO: C bindings? or is this sufficiently covered by WebIDL and using a 3rd-party tool?
// helpers
/** Tests if a namespace-like element has at least one compiled member. */

View File

@ -2600,7 +2600,7 @@ export class FunctionPrototype extends Element {
if (isInstance) {
classInstance = assert(classPrototype).resolve(classTypeArguments, contextualTypeArguments); // reports
if (!classInstance) return null;
thisType = classInstance.type.asThis();
thisType = classInstance.type;
contextualTypeArguments.set("this", thisType);
}

View File

@ -69,20 +69,18 @@ export const enum TypeFlags {
INTEGER = 1 << 2,
/** Is a floating point type. */
FLOAT = 1 << 3,
/** Is a sized integer type with a target specific bit size. */
SIZE = 1 << 4,
/** Is a small type that is emulated in a larger type. */
SMALL = 1 << 5,
/** Is a long type larger than 32-bits. */
/** Is a pointer type. */
POINTER = 1 << 4,
/** Is smaller than 32-bits. */
SHORT = 1 << 5,
/** Is larger than 32-bits. */
LONG = 1 << 6,
/** Is a value type. */
VALUE = 1 << 7,
/** Is a reference type. */
REFERENCE = 1 << 8,
/** Is a nullable type. */
NULLABLE = 1 << 9,
/** Is the special 'this' type. */
THIS = 1 << 10
NULLABLE = 1 << 9
}
/** Represents a resolved type. */
@ -94,21 +92,19 @@ export class Type {
flags: TypeFlags;
/** Size in bits. */
size: u32;
/** Size in bytes. Ceiled to 8-bits. */
/** Size in bytes. */
byteSize: i32;
/** Underlying class reference, if a class type. */
classReference: Class | null;
/** Underlying function reference, if a function type. */
/** Underlying signature reference, if a function type. */
signatureReference: Signature | null;
/** Respective nullable type, if non-nullable. */
nullableType: Type | null = null;
/** Respective non-nullable type, if nullable. */
nonNullableType: Type;
/** Respective special 'this' type. */
thisType: Type | null = null;
/** Cached nullable type, if non-nullable. */
private cachedNullableType: Type | null = null;
/** Constructs a new resolved type. */
constructor(kind: TypeKind, flags: TypeFlags, size: i32) {
constructor(kind: TypeKind, flags: TypeFlags, size: u32) {
this.kind = kind;
this.flags = flags;
this.size = size;
@ -128,7 +124,7 @@ export class Type {
return ~0 >>> (targetType.size - this.size);
}
/** Tests if this type has the specified flags. */
/** Tests if this type has (all of) the specified flags. */
is(flags: TypeFlags): bool { return (this.flags & flags) == flags; }
/** Tests if this type has any of the specified flags. */
isAny(flags: TypeFlags): bool { return (this.flags & flags) != 0; }
@ -152,25 +148,13 @@ export class Type {
/** Composes the respective nullable type of this type. */
asNullable(): Type {
assert(this.is(TypeFlags.REFERENCE));
if (!this.nullableType) {
if (!this.cachedNullableType) {
assert(!this.is(TypeFlags.NULLABLE));
this.nullableType = new Type(this.kind, this.flags | TypeFlags.NULLABLE, this.size);
this.nullableType.classReference = this.classReference; // either a class reference
this.nullableType.signatureReference = this.signatureReference; // or a function reference
this.cachedNullableType = new Type(this.kind, this.flags | TypeFlags.NULLABLE, this.size);
this.cachedNullableType.classReference = this.classReference; // either a class reference
this.cachedNullableType.signatureReference = this.signatureReference; // or a function reference
}
return this.nullableType;
}
/** Composes the respective 'this' type of this type. */
asThis(): Type {
var thisType = this.thisType;
if (thisType) return thisType;
thisType = new Type(this.kind, this.flags | TypeFlags.THIS, this.size);
thisType.classReference = this.classReference;
thisType.nullableType = this.nullableType;
thisType.nonNullableType = this.nonNullableType;
this.thisType = thisType;
return thisType;
return this.cachedNullableType;
}
/** Tests if a value of this type is assignable to a target of the specified type. */
@ -213,11 +197,8 @@ export class Type {
/** Determines the common compatible type of two types, if any. */
static commonCompatible(left: Type, right: Type, signednessIsImportant: bool): Type | null {
if (right.isAssignableTo(left, signednessIsImportant)) {
return left;
} else if (left.isAssignableTo(right, signednessIsImportant)) {
return right;
}
if (right.isAssignableTo(left, signednessIsImportant)) return left;
else if (left.isAssignableTo(right, signednessIsImportant)) return right;
return null;
}
@ -233,16 +214,12 @@ export class Type {
case TypeKind.U16: return "u16";
case TypeKind.U32: {
let functionType = this.signatureReference;
return kindOnly || !functionType
? "u32"
: functionType.toString(true);
return kindOnly || !functionType ? "u32" : functionType.toString(true);
}
case TypeKind.U64: return "u64";
case TypeKind.USIZE: {
let classType = this.classReference;
return kindOnly || !classType
? "usize"
: classType.toString();
return kindOnly || !classType ? "usize" : classType.toString();
}
case TypeKind.BOOL: return "bool";
case TypeKind.F32: return "f32";
@ -332,7 +309,7 @@ export class Type {
/** An 8-bit signed integer. */
static readonly i8: Type = new Type(TypeKind.I8,
TypeFlags.SIGNED |
TypeFlags.SMALL |
TypeFlags.SHORT |
TypeFlags.INTEGER |
TypeFlags.VALUE, 8
);
@ -340,7 +317,7 @@ export class Type {
/** A 16-bit signed integer. */
static readonly i16: Type = new Type(TypeKind.I16,
TypeFlags.SIGNED |
TypeFlags.SMALL |
TypeFlags.SHORT |
TypeFlags.INTEGER |
TypeFlags.VALUE, 16
);
@ -363,8 +340,8 @@ export class Type {
/** A 32-bit signed size. WASM32 only. */
static readonly isize32: Type = new Type(TypeKind.ISIZE,
TypeFlags.SIGNED |
TypeFlags.SIZE |
TypeFlags.INTEGER |
TypeFlags.POINTER |
TypeFlags.VALUE, 32
);
@ -372,15 +349,15 @@ export class Type {
static readonly isize64: Type = new Type(TypeKind.ISIZE,
TypeFlags.SIGNED |
TypeFlags.LONG |
TypeFlags.SIZE |
TypeFlags.INTEGER |
TypeFlags.POINTER |
TypeFlags.VALUE, 64
);
/** An 8-bit unsigned integer. */
static readonly u8: Type = new Type(TypeKind.U8,
TypeFlags.UNSIGNED |
TypeFlags.SMALL |
TypeFlags.SHORT |
TypeFlags.INTEGER |
TypeFlags.VALUE, 8
);
@ -388,7 +365,7 @@ export class Type {
/** A 16-bit unsigned integer. */
static readonly u16: Type = new Type(TypeKind.U16,
TypeFlags.UNSIGNED |
TypeFlags.SMALL |
TypeFlags.SHORT |
TypeFlags.INTEGER |
TypeFlags.VALUE, 16
);
@ -411,8 +388,8 @@ export class Type {
/** A 32-bit unsigned size. WASM32 only. */
static readonly usize32: Type = new Type(TypeKind.USIZE,
TypeFlags.UNSIGNED |
TypeFlags.SIZE |
TypeFlags.INTEGER |
TypeFlags.POINTER |
TypeFlags.VALUE, 32
);
@ -420,15 +397,15 @@ export class Type {
static readonly usize64: Type = new Type(TypeKind.USIZE,
TypeFlags.UNSIGNED |
TypeFlags.LONG |
TypeFlags.SIZE |
TypeFlags.INTEGER |
TypeFlags.POINTER |
TypeFlags.VALUE, 64
);
/** A 1-bit unsigned integer. */
static readonly bool: Type = new Type(TypeKind.BOOL,
TypeFlags.UNSIGNED |
TypeFlags.SMALL |
TypeFlags.SHORT |
TypeFlags.INTEGER |
TypeFlags.VALUE, 1
);
@ -456,9 +433,7 @@ export class Type {
export function typesToNativeTypes(types: Type[]): NativeType[] {
var numTypes = types.length;
var ret = new Array<NativeType>(numTypes);
for (let i = 0; i < numTypes; ++i) {
ret[i] = types[i].toNativeType();
}
for (let i = 0; i < numTypes; ++i) ret[i] = types[i].toNativeType();
return ret;
}
@ -467,9 +442,7 @@ export function typesToString(types: Type[]): string {
var numTypes = types.length;
if (!numTypes) return "";
var sb = new Array<string>(numTypes);
for (let i = 0; i < numTypes; ++i) {
sb[i] = types[i].toString();
}
for (let i = 0; i < numTypes; ++i) sb[i] = types[i].toString();
return sb.join(",");
}
@ -524,31 +497,23 @@ export class Signature {
var thisThisType = this.thisType;
var targetThisType = target.thisType;
if (thisThisType) {
if (!(targetThisType && thisThisType.isAssignableTo(targetThisType))) {
return false;
}
if (!(targetThisType && thisThisType.isAssignableTo(targetThisType))) return false;
} else if (targetThisType) {
return false;
}
// check rest parameter
if (this.hasRest != target.hasRest) {
return false; // TODO
}
if (this.hasRest != target.hasRest) return false; // TODO
// check parameter types
var thisParameterTypes = this.parameterTypes;
var targetParameterTypes = target.parameterTypes;
var numParameters = thisParameterTypes.length;
if (numParameters != targetParameterTypes.length) {
return false;
}
if (numParameters != targetParameterTypes.length) return false;
for (let i = 0; i < numParameters; ++i) {
let thisParameterType = thisParameterTypes[i];
let targetParameterType = targetParameterTypes[i];
if (!thisParameterType.isAssignableTo(targetParameterType)) {
return false;
}
if (!thisParameterType.isAssignableTo(targetParameterType)) return false;
}
// check return type
@ -562,9 +527,7 @@ export class Signature {
var sb = [];
if (thisType) sb.push(thisType.toSignatureString());
if (parameterTypes) {
for (let i = 0, k = parameterTypes.length; i < k; ++i) {
sb.push(parameterTypes[i].toSignatureString());
}
for (let i = 0, k = parameterTypes.length; i < k; ++i) sb.push(parameterTypes[i].toSignatureString());
}
sb.push(returnType.toSignatureString());
return sb.join("");
@ -598,16 +561,10 @@ export class Signature {
for (let i = 0; i < numParameters; ++i, ++index) {
if (index) sb.push(", ");
if (i == restIndex) sb.push("...");
if (i < numNames) {
sb.push((<string[]>names)[i]);
} else {
sb.push(getGenericParameterName(i));
}
if (i >= optionalStart && i != restIndex) {
sb.push("?: ");
} else {
sb.push(": ");
}
if (i < numNames) sb.push((<string[]>names)[i]);
else sb.push(getGenericParameterName(i));
if (i >= optionalStart && i != restIndex) sb.push("?: ");
else sb.push(": ");
sb.push(parameters[i].toString());
}
}