Static operator overloads

This commit is contained in:
dcodeIO
2018-01-28 06:18:27 +01:00
parent 3165f4337f
commit b1e7b75ad7
16 changed files with 379 additions and 149 deletions

View File

@ -1,18 +1,19 @@
// code below is generated from diagnosticsMessages.json by scripts/build-diagnostics
export enum DiagnosticCode {
Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast = 100,
Basic_type_0_cannot_be_nullable = 101,
Operation_not_supported = 102,
Operation_is_unsafe = 103,
Cannot_export_a_mutable_global = 104,
Compiling_constant_with_non_constant_initializer_as_mutable = 105,
Type_0_cannot_be_changed_to_type_1 = 106,
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,
Implementation_0_must_match_the_signature_1 = 111,
Operation_not_supported = 100,
Operation_is_unsafe = 101,
Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast = 200,
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
Type_0_cannot_be_changed_to_type_1 = 202,
Type_0_cannot_be_reinterpreted_as_type_1 = 203,
Basic_type_0_cannot_be_nullable = 204,
Cannot_export_a_mutable_global = 205,
Compiling_constant_with_non_constant_initializer_as_mutable = 206,
Structs_cannot_extend_classes_and_vice_versa = 207,
Structs_cannot_implement_interfaces = 208,
Invalid_regular_expression_flags = 209,
Implementation_0_must_match_the_signature_1 = 210,
Unterminated_string_literal = 1002,
Identifier_expected = 1003,
_0_expected = 1005,
@ -94,18 +95,19 @@ export enum DiagnosticCode {
export function diagnosticCodeToString(code: DiagnosticCode): string {
switch (code) {
case 100: return "Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.";
case 101: return "Basic type '{0}' cannot be nullable.";
case 102: return "Operation not supported.";
case 103: return "Operation is unsafe.";
case 104: return "Cannot export a mutable global.";
case 105: return "Compiling constant with non-constant initializer as mutable.";
case 106: return "Type '{0}' cannot be changed to type '{1}'.";
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 111: return "Implementation '{0}' must match the signature '{1}'.";
case 100: return "Operation not supported.";
case 101: return "Operation is unsafe.";
case 200: return "Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.";
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
case 202: return "Type '{0}' cannot be changed to type '{1}'.";
case 203: return "Type '{0}' cannot be reinterpreted as type '{1}'.";
case 204: return "Basic type '{0}' cannot be nullable.";
case 205: return "Cannot export a mutable global.";
case 206: return "Compiling constant with non-constant initializer as mutable.";
case 207: return "Structs cannot extend classes and vice-versa.";
case 208: return "Structs cannot implement interfaces.";
case 209: return "Invalid regular expression flags.";
case 210: return "Implementation '{0}' must match the signature '{1}'.";
case 1002: return "Unterminated string literal.";
case 1003: return "Identifier expected.";
case 1005: return "'{0}' expected.";

View File

@ -1,16 +1,17 @@
{
"Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.": 100,
"Basic type '{0}' cannot be nullable.": 101,
"Operation not supported.": 102,
"Operation is unsafe.": 103,
"Cannot export a mutable global.": 104,
"Compiling constant with non-constant initializer as mutable.": 105,
"Type '{0}' cannot be changed to type '{1}'.": 106,
"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,
"Implementation '{0}' must match the signature '{1}'.": 111,
"Operation not supported.": 100,
"Operation is unsafe.": 101,
"Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.": 200,
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,
"Type '{0}' cannot be changed to type '{1}'.": 202,
"Type '{0}' cannot be reinterpreted as type '{1}'.": 203,
"Basic type '{0}' cannot be nullable.": 204,
"Cannot export a mutable global.": 205,
"Compiling constant with non-constant initializer as mutable.": 206,
"Structs cannot extend classes and vice-versa.": 207,
"Structs cannot implement interfaces.": 208,
"Invalid regular expression flags.": 209,
"Implementation '{0}' must match the signature '{1}'.": 210,
"Unterminated string literal.": 1002,
"Identifier expected.": 1003,

View File

@ -107,7 +107,7 @@ export function formatDiagnosticMessage(message: DiagnosticMessage, useColors: b
if (useColors) sb.push(diagnosticCategoryToColor(message.category));
sb.push(diagnosticCategoryToString(message.category));
if (useColors) sb.push(colorReset);
sb.push(" AS");
sb.push(message.code < 1000 ? " AS" : " TS");
sb.push(message.code.toString(10));
sb.push(": ");
sb.push(message.message);

View File

@ -402,7 +402,7 @@ export class Program extends DiagnosticEmitter {
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
var name = declaration.name.name;
var internalName = declaration.fileLevelInternalName;
var instancePrototype: FunctionPrototype | null = null;
var prototype: FunctionPrototype | null = null;
// static methods become global functions
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
@ -419,9 +419,9 @@ export class Program extends DiagnosticEmitter {
}
} else
classPrototype.members = new Map();
var staticPrototype = new FunctionPrototype(this, name, internalName, declaration, null);
classPrototype.members.set(name, staticPrototype);
this.elements.set(internalName, staticPrototype);
prototype = new FunctionPrototype(this, name, internalName, declaration, null);
classPrototype.members.set(name, prototype);
this.elements.set(internalName, prototype);
// instance methods are remembered until resolved
} else {
@ -432,26 +432,31 @@ export class Program extends DiagnosticEmitter {
}
} else
classPrototype.instanceMembers = new Map();
instancePrototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype);
prototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype);
// if (classPrototype.isUnmanaged && instancePrototype.isAbstract) {
// this.error( Unmanaged classes cannot declare abstract methods. );
// }
classPrototype.instanceMembers.set(name, instancePrototype);
classPrototype.instanceMembers.set(name, prototype);
if (declaration.name.kind == NodeKind.CONSTRUCTOR) {
if (classPrototype.constructorPrototype)
this.error(DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, declaration.name.range);
else
classPrototype.constructorPrototype = instancePrototype;
classPrototype.constructorPrototype = prototype;
}
}
// handle operator annotations. operators are instance methods taking a second argument of the
// instance's type. return values vary depending on the operation.
if (declaration.decorators) {
for (var i = 0, k = declaration.decorators.length; i < k; ++i) {
var decorator = declaration.decorators[i];
this.checkOperators(declaration.decorators, prototype, classPrototype);
}
private checkOperators(decorators: Decorator[] | null, prototype: FunctionPrototype, classPrototype: ClassPrototype) {
// handle operator annotations. operators are either instance methods taking a second argument of the
// instance's type or static methods taking two arguments of the instance's type. return values vary
// depending on the operation.
if (decorators) {
for (var i = 0, k = decorators.length; i < k; ++i) {
var decorator = decorators[i];
if (decorator.decoratorKind == DecoratorKind.OPERATOR) {
if (!instancePrototype) {
if (!prototype) {
this.error(DiagnosticCode.Operation_not_supported, decorator.range);
continue;
}
@ -462,22 +467,22 @@ export class Program extends DiagnosticEmitter {
switch ((<StringLiteralExpression>firstArg).value) {
case "[]":
classPrototype.fnIndexedGet = instancePrototype.simpleName;
classPrototype.fnIndexedGet = prototype.simpleName;
break;
case "[]=":
classPrototype.fnIndexedSet = instancePrototype.simpleName;
classPrototype.fnIndexedSet = prototype.simpleName;
break;
case "+":
classPrototype.fnConcat = instancePrototype.simpleName;
classPrototype.fnConcat = prototype.simpleName;
break;
case "==":
classPrototype.fnEquals = instancePrototype.simpleName;
classPrototype.fnEquals = prototype.simpleName;
break;
default: // TBD: does it make sense to provide more, even though not JS/TS-compatible?
default:
this.error(DiagnosticCode.Operation_not_supported, firstArg.range);
}
} else

View File

@ -278,6 +278,10 @@ export class Range {
start: i32;
end: i32;
// TODO: set these while tokenizing
// line: i32;
// column: i32;
constructor(source: Source, start: i32, end: i32) {
this.source = source;
this.start = start;