Builtins rewrite with type parameter inference; Small integer math optimizations; Switchify

This commit is contained in:
dcodeIO
2018-01-10 13:09:05 +01:00
parent 0de05b543b
commit fc777b3a89
64 changed files with 4894 additions and 1620 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@ export enum DiagnosticCode {
Structs_cannot_extend_classes_and_vice_versa = 107,
Structs_cannot_implement_interfaces = 108,
Invalid_regular_expression_flags = 109,
Type_0_cannot_be_reinterpreted_as_type_1 = 110,
Unterminated_string_literal = 1002,
Identifier_expected = 1003,
_0_expected = 1005,
@ -97,6 +98,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 107: return "Structs cannot extend classes and vice-versa.";
case 108: return "Structs cannot implement interfaces.";
case 109: return "Invalid regular expression flags.";
case 110: return "Type '{0}' cannot be reinterpreted as type '{1}'.";
case 1002: return "Unterminated string literal.";
case 1003: return "Identifier expected.";
case 1005: return "'{0}' expected.";

View File

@ -9,6 +9,7 @@
"Structs cannot extend classes and vice-versa.": 107,
"Structs cannot implement interfaces.": 108,
"Invalid regular expression flags.": 109,
"Type '{0}' cannot be reinterpreted as type '{1}'.": 110,
"Unterminated string literal.": 1002,
"Identifier expected.": 1003,

View File

@ -351,6 +351,8 @@ export class Range {
}
}
declare function parseFloat(str: string): f64;
export class Tokenizer extends DiagnosticEmitter {
source: Source;

View File

@ -58,8 +58,10 @@ export class Type {
functionType: Function | null;
/** Whether nullable or not. */
isNullable: bool = false;
/** Respective nullable type, if nullable. */
/** Respective nullable type, if non-nullable. */
nullableType: Type | null = null;
/** Respective non-nullable type, if nullable. */
nonNullableType: Type;
/** Constructs a new resolved type. */
constructor(kind: TypeKind, size: i32) {
@ -67,6 +69,7 @@ export class Type {
this.size = size;
this.byteSize = <i32>ceil<f64>(<f64>size / 8);
this.classType = null;
this.nonNullableType = this;
}
/** Sign-extending 32-bit shift, if a small signed integer. */
@ -75,23 +78,157 @@ export class Type {
get smallIntegerMask(): i32 { return -1 >>> (32 - this.size); }
/** Tests if this type is of any integer kind. */
get isAnyInteger(): bool { return this.kind >= TypeKind.I8 && this.kind <= TypeKind.BOOL; }
/** Tests if this type is of any small integer kind. */
get isSmallInteger(): bool { return this.size != 0 && this.size < 32; }
/** Tests if this type is of any long integer kind. */
get isLongInteger(): bool { return this.size == 64 && this.kind != TypeKind.F64; }
get isAnyInteger(): bool {
switch (this.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.I32:
case TypeKind.I64:
case TypeKind.ISIZE:
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.U32:
case TypeKind.U64:
case TypeKind.USIZE:
case TypeKind.BOOL:
return true;
default:
return false;
}
}
/** Tests if this type is of any unsigned integer kind. */
get isUnsignedInteger(): bool { return this.kind >= TypeKind.U8 && this.kind <= TypeKind.BOOL; }
get isAnyUnsignedInteger(): bool {
switch (this.kind) {
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.U32:
case TypeKind.U64:
case TypeKind.USIZE:
case TypeKind.BOOL:
return true;
default:
return false;
}
}
/** Tests if this type is of any signed integer kind. */
get isSignedInteger(): bool { return this.kind >= TypeKind.I8 && this.kind <= TypeKind.ISIZE; }
/** Tests if this type is of any size kind, i.e., `isize` or `usize`. */
get isAnySize(): bool { return this.kind == TypeKind.ISIZE || this.kind == TypeKind.USIZE; }
get isAnySignedInteger(): bool {
switch (this.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.I32:
case TypeKind.I64:
case TypeKind.ISIZE:
return true;
default:
return false;
}
}
/** Tests if this type is of any small integer kind. */
get isSmallInteger(): bool {
switch (this.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.BOOL:
return true;
default:
return false;
}
}
/** Tests if this type is of any small signed integer kind. */
get isSmallSignedInteger(): bool {
switch (this.kind) {
case TypeKind.I8:
case TypeKind.I16:
return true;
default:
return false;
}
}
/** Tests if this type is of any small unsigned integer kind. */
get isSmallUnsignedInteger(): bool {
switch (this.kind) {
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.BOOL:
return true;
default:
return false;
}
}
/** Tests if this type is of any long integer kind. */
get isLongInteger(): bool {
switch (this.kind) {
case TypeKind.I64:
case TypeKind.U64:
return true;
case TypeKind.ISIZE:
case TypeKind.USIZE:
return this.size == 64;
default:
return false;
}
}
/** Tests if this type is of any long signed integer kind. */
get isLongSignedInteger(): bool {
switch (this.kind) {
case TypeKind.I64:
return true;
case TypeKind.ISIZE:
return this.size == 64;
default:
return false;
}
}
/** Tests if this type is of any long unsigned integer kind. */
get isLongUnsignedInteger(): bool {
switch (this.kind) {
case TypeKind.U64:
return true;
case TypeKind.USIZE:
return this.size == 64;
default:
return false;
}
}
/** Tests if this type is of any size kind, that is `isize` or `usize`. */
get isAnySize(): bool {
switch (this.kind) {
case TypeKind.ISIZE:
case TypeKind.USIZE:
return true;
default:
return false;
}
}
/** Tests if this type is of any float kind, i.e., `f32` or `f64`. */
get isAnyFloat(): bool { return this.kind == TypeKind.F32 || this.kind == TypeKind.F64; }
get isAnyFloat(): bool {
switch (this.kind) {
case TypeKind.F32:
case TypeKind.F64:
return true;
default:
return false;
}
}
/** Tests if this type is a class type. */
get isClass(): bool { return this.classType != null; }
/** Tests if this type is a function type. */
get isFunction(): bool { return this.functionType != null; }
/** Tests if this type is a reference type. */
get isReference(): bool { return this.classType != null || this.functionType != null; }
/** Composes a class type from this type and a class. */
asClass(classType: Class): Type {
@ -103,7 +240,7 @@ export class Type {
/** Composes a function type from this type and a function. */
asFunction(functionType: Function): Type {
assert(this.kind == TypeKind.USIZE);
assert(this.kind == TypeKind.USIZE && !this.isReference);
var ret = new Type(this.kind, this.size);
ret.functionType = functionType;
return ret;
@ -111,9 +248,12 @@ export class Type {
/** Composes the respective nullable type of this type. */
asNullable(): Type | null {
assert(this.kind == TypeKind.USIZE);
if (this.isNullable && !this.nullableType)
assert(this.kind == TypeKind.USIZE && !this.isReference);
if (this.isNullable && !this.nullableType) {
(this.nullableType = new Type(this.kind, this.size)).isNullable = true;
this.nullableType.classType = this.classType;
this.nullableType.functionType = this.functionType;
}
return this.nullableType;
}
@ -226,6 +366,34 @@ export class Type {
}
}
/** Converts this type to its native `-1` value. */
toNativeNegOne(module: Module): ExpressionRef {
switch (this.kind) {
case TypeKind.VOID:
assert(false);
default:
return module.createI32(-1);
case TypeKind.ISIZE:
case TypeKind.USIZE:
if (this.size != 64)
return module.createI32(-1);
// fall-through
case TypeKind.I64:
case TypeKind.U64:
return module.createI64(-1, -1);
case TypeKind.F32:
return module.createF32(-1);
case TypeKind.F64:
return module.createF64(-1);
}
}
/** Converts this type to its signature string. */
toSignatureString(): string {
switch (this.kind) {