Skip to content

Commit 3de338d

Browse files
committed
proper overload argument types
1 parent 7c9115b commit 3de338d

File tree

3 files changed

+82
-56
lines changed

3 files changed

+82
-56
lines changed

src/compiler.ts

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ import {
158158
TernaryExpression,
159159
ArrayLiteralExpression,
160160
StringLiteralExpression,
161+
UnaryExpression,
161162
UnaryPostfixExpression,
162163
UnaryPrefixExpression,
163164

@@ -3534,7 +3535,7 @@ export class Compiler extends DiagnosticEmitter {
35343535
if (classReference) {
35353536
let overload = classReference.lookupOverload(OperatorKind.LT);
35363537
if (overload) {
3537-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
3538+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
35383539
break;
35393540
}
35403541
}
@@ -3634,7 +3635,7 @@ export class Compiler extends DiagnosticEmitter {
36343635
if (classReference) {
36353636
let overload = classReference.lookupOverload(OperatorKind.GT);
36363637
if (overload) {
3637-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
3638+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
36383639
break;
36393640
}
36403641
}
@@ -3734,7 +3735,7 @@ export class Compiler extends DiagnosticEmitter {
37343735
if (classReference) {
37353736
let overload = classReference.lookupOverload(OperatorKind.LE);
37363737
if (overload) {
3737-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
3738+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
37383739
break;
37393740
}
37403741
}
@@ -3834,7 +3835,7 @@ export class Compiler extends DiagnosticEmitter {
38343835
if (classReference) {
38353836
let overload = classReference.lookupOverload(OperatorKind.GE);
38363837
if (overload) {
3837-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
3838+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
38383839
break;
38393840
}
38403841
}
@@ -3941,7 +3942,7 @@ export class Compiler extends DiagnosticEmitter {
39413942
if (classReference) {
39423943
let overload = classReference.lookupOverload(OperatorKind.EQ);
39433944
if (overload) {
3944-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
3945+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
39453946
break;
39463947
}
39473948
}
@@ -4038,7 +4039,7 @@ export class Compiler extends DiagnosticEmitter {
40384039
if (classReference) {
40394040
let overload = classReference.lookupOverload(OperatorKind.NE);
40404041
if (overload) {
4041-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4042+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
40424043
break;
40434044
}
40444045
}
@@ -4138,7 +4139,7 @@ export class Compiler extends DiagnosticEmitter {
41384139
if (classReference) {
41394140
let overload = classReference.lookupOverload(OperatorKind.ADD);
41404141
if (overload) {
4141-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4142+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
41424143
break;
41434144
}
41444145
}
@@ -4227,7 +4228,7 @@ export class Compiler extends DiagnosticEmitter {
42274228
if (classReference) {
42284229
let overload = classReference.lookupOverload(OperatorKind.SUB);
42294230
if (overload) {
4230-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4231+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
42314232
break;
42324233
}
42334234
}
@@ -4317,7 +4318,7 @@ export class Compiler extends DiagnosticEmitter {
43174318
if (classReference) {
43184319
let overload = classReference.lookupOverload(OperatorKind.MUL);
43194320
if (overload) {
4320-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4321+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
43214322
break;
43224323
}
43234324
}
@@ -4407,7 +4408,7 @@ export class Compiler extends DiagnosticEmitter {
44074408
if (classReference) {
44084409
let overload = classReference.lookupOverload(OperatorKind.POW);
44094410
if (overload) {
4410-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4411+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
44114412
break;
44124413
}
44134414
}
@@ -4504,7 +4505,7 @@ export class Compiler extends DiagnosticEmitter {
45044505
if (classReference) {
45054506
let overload = classReference.lookupOverload(OperatorKind.DIV);
45064507
if (overload) {
4507-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4508+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
45084509
break;
45094510
}
45104511
}
@@ -4613,7 +4614,7 @@ export class Compiler extends DiagnosticEmitter {
46134614
if (classReference) {
46144615
let overload = classReference.lookupOverload(OperatorKind.REM);
46154616
if (overload) {
4616-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4617+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
46174618
break;
46184619
}
46194620
}
@@ -4779,7 +4780,7 @@ export class Compiler extends DiagnosticEmitter {
47794780
if (classReference) {
47804781
let overload = classReference.lookupOverload(OperatorKind.BITWISE_SHL);
47814782
if (overload) {
4782-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4783+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
47834784
break;
47844785
}
47854786
}
@@ -4845,7 +4846,7 @@ export class Compiler extends DiagnosticEmitter {
48454846
if (classReference) {
48464847
let overload = classReference.lookupOverload(OperatorKind.BITWISE_SHR);
48474848
if (overload) {
4848-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4849+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
48494850
break;
48504851
}
48514852
}
@@ -4933,7 +4934,7 @@ export class Compiler extends DiagnosticEmitter {
49334934
if (classReference) {
49344935
let overload = classReference.lookupOverload(OperatorKind.BITWISE_SHR_U);
49354936
if (overload) {
4936-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
4937+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
49374938
break;
49384939
}
49394940
}
@@ -5002,7 +5003,7 @@ export class Compiler extends DiagnosticEmitter {
50025003
if (classReference) {
50035004
let overload = classReference.lookupOverload(OperatorKind.BITWISE_AND);
50045005
if (overload) {
5005-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
5006+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
50065007
break;
50075008
}
50085009
}
@@ -5092,7 +5093,7 @@ export class Compiler extends DiagnosticEmitter {
50925093
if (classReference) {
50935094
let overload = classReference.lookupOverload(OperatorKind.BITWISE_OR);
50945095
if (overload) {
5095-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
5096+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
50965097
break;
50975098
}
50985099
}
@@ -5185,7 +5186,7 @@ export class Compiler extends DiagnosticEmitter {
51855186
if (classReference) {
51865187
let overload = classReference.lookupOverload(OperatorKind.BITWISE_XOR);
51875188
if (overload) {
5188-
expr = this.compileBinaryOverload(overload, left, leftExpr, right, expression);
5189+
expr = this.compileBinaryOverload(overload, leftExpr, leftType, right, expression);
51895190
break;
51905191
}
51915192
}
@@ -5505,40 +5506,34 @@ export class Compiler extends DiagnosticEmitter {
55055506
}
55065507

55075508
private compileUnaryOverload(
5508-
operatorInstance: Function,
5509-
value: Expression,
5509+
/** Overload function instance. */
5510+
overload: Function,
5511+
/** Compiled value expression. */
55105512
valueExpr: ExpressionRef,
5511-
reportNode: Node
5513+
/** Value type. */
5514+
valueType: Type,
5515+
/** Report node. */
5516+
reportNode: UnaryExpression
55125517
): ExpressionRef {
5513-
// FIXME: see comment in compileBinaryOverload below why recompiling on type mismatch
5514-
// is a bad idea currently. so this assumes that the type matches.
5515-
return this.makeCallDirect(operatorInstance, [ valueExpr ], reportNode, false);
5518+
valueExpr = this.convertExpression(valueExpr, valueType, overload.unaryOverloadValueType, false, false, reportNode);
5519+
return this.makeCallDirect(overload, [ valueExpr ], reportNode, false);
55165520
}
55175521

55185522
private compileBinaryOverload(
5519-
operatorInstance: Function,
5520-
left: Expression,
5523+
/** Overload function instance. */
5524+
overload: Function,
5525+
/** Compiled left expression. */
55215526
leftExpr: ExpressionRef,
5527+
/** Left expression type. */
5528+
leftType: Type,
5529+
/** Right expression to compile. */
55225530
right: Expression,
5523-
reportNode: Node
5531+
/** Report node. */
5532+
reportNode: BinaryExpression
55245533
): ExpressionRef {
5525-
var rightType: Type;
5526-
if (operatorInstance.is(CommonFlags.INSTANCE)) {
5527-
let classInstance = assert(operatorInstance.parent); assert(classInstance.kind == ElementKind.CLASS);
5528-
rightType = operatorInstance.signature.parameterTypes[0];
5529-
} else {
5530-
// FIXME: if LHS type differs we can't recompile left because that'd completely confuse
5531-
// local states, like having retained locals that actually do not even exist, possibly
5532-
// releasing something random in that local before and evil things like that. Hence this
5533-
// assumes that LHS type matches, which in turn means that static overloads must be
5534-
// guaranteed to never mismatch LHS type, which in turn means that we can't have shiny
5535-
// things like multiple static overloads for different combinations of LHS/RHS types.
5536-
// We might want that at some point of course, but requires to complete the resolver so
5537-
// it can actually resolve every kind of expression without ever having to recompile.
5538-
rightType = operatorInstance.signature.parameterTypes[1];
5539-
}
5540-
var rightExpr = this.compileExpression(right, rightType, Constraints.CONV_IMPLICIT);
5541-
return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ], reportNode);
5534+
leftExpr = this.convertExpression(leftExpr, leftType, overload.binaryOverloadLeftType, false, false, reportNode);
5535+
var rightExpr = this.compileExpression(right, overload.binaryOverloadRightType, Constraints.CONV_IMPLICIT);
5536+
return this.makeCallDirect(overload, [ leftExpr, rightExpr ], reportNode);
55425537
}
55435538

55445539
private compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
@@ -8640,7 +8635,7 @@ export class Compiler extends DiagnosticEmitter {
86408635
flow.freeTempLocal(tempLocal);
86418636
tempLocal = null;
86428637
}
8643-
expr = this.compileUnaryOverload(overload, expression.operand, getValue, expression);
8638+
expr = this.compileUnaryOverload(overload, getValue, this.currentType, expression);
86448639
if (isInstance) break;
86458640
return expr; // here
86468641
}
@@ -8729,7 +8724,7 @@ export class Compiler extends DiagnosticEmitter {
87298724
flow.freeTempLocal(tempLocal);
87308725
tempLocal = null;
87318726
}
8732-
expr = this.compileUnaryOverload(overload, expression.operand, getValue, expression);
8727+
expr = this.compileUnaryOverload(overload, getValue, this.currentType, expression);
87338728
if (overload.is(CommonFlags.INSTANCE)) break;
87348729
return expr; // here
87358730
}
@@ -8873,7 +8868,7 @@ export class Compiler extends DiagnosticEmitter {
88738868
let classReference = this.currentType.classReference;
88748869
if (classReference) {
88758870
let overload = classReference.lookupOverload(OperatorKind.PLUS);
8876-
if (overload) return this.compileUnaryOverload(overload, expression.operand, expr, expression);
8871+
if (overload) return this.compileUnaryOverload(overload, expr, this.currentType, expression);
88778872
}
88788873
this.error(
88798874
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
@@ -8908,7 +8903,7 @@ export class Compiler extends DiagnosticEmitter {
89088903
let classReference = this.currentType.classReference;
89098904
if (classReference) {
89108905
let overload = classReference.lookupOverload(OperatorKind.MINUS);
8911-
if (overload) return this.compileUnaryOverload(overload, expression.operand, expr, expression);
8906+
if (overload) return this.compileUnaryOverload(overload, expr, this.currentType, expression);
89128907
}
89138908
this.error(
89148909
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
@@ -8976,7 +8971,7 @@ export class Compiler extends DiagnosticEmitter {
89768971
if (classReference) {
89778972
let overload = classReference.lookupOverload(OperatorKind.PREFIX_INC);
89788973
if (overload) {
8979-
expr = this.compileUnaryOverload(overload, expression.operand, expr, expression);
8974+
expr = this.compileUnaryOverload(overload, expr, this.currentType, expression);
89808975
if (overload.is(CommonFlags.INSTANCE)) break; // re-assign
89818976
return expr; // skip re-assign
89828977
}
@@ -9047,7 +9042,7 @@ export class Compiler extends DiagnosticEmitter {
90479042
if (classReference) {
90489043
let overload = classReference.lookupOverload(OperatorKind.PREFIX_DEC);
90499044
if (overload) {
9050-
expr = this.compileUnaryOverload(overload, expression.operand, expr, expression);
9045+
expr = this.compileUnaryOverload(overload, expr, this.currentType, expression);
90519046
if (overload.is(CommonFlags.INSTANCE)) break; // re-assign
90529047
return expr; // skip re-assign
90539048
}
@@ -9116,7 +9111,7 @@ export class Compiler extends DiagnosticEmitter {
91169111
let classReference = this.currentType.classReference;
91179112
if (classReference) {
91189113
let overload = classReference.lookupOverload(OperatorKind.NOT);
9119-
if (overload) return this.compileUnaryOverload(overload, expression.operand, expr, expression);
9114+
if (overload) return this.compileUnaryOverload(overload, expr, this.currentType, expression);
91209115
}
91219116
// allow '!' for references even without an overload
91229117
}
@@ -9141,7 +9136,7 @@ export class Compiler extends DiagnosticEmitter {
91419136
let classReference = this.currentType.classReference;
91429137
if (classReference) {
91439138
let overload = classReference.lookupOverload(OperatorKind.BITWISE_NOT);
9144-
if (overload) return this.compileUnaryOverload(overload, expression.operand, expr, expression);
9139+
if (overload) return this.compileUnaryOverload(overload, expr, this.currentType, expression);
91459140
}
91469141
this.error(
91479142
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,

src/program.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,37 @@ export class Function extends TypedElement {
29592959
}
29602960
}
29612961
}
2962+
2963+
/** Gets the value type of an unary operator overload. */
2964+
get unaryOverloadValueType(): Type {
2965+
if (this.is(CommonFlags.INSTANCE)) {
2966+
return assert(this.signature.thisType);
2967+
}
2968+
var parameterTypes = this.signature.parameterTypes;
2969+
assert(parameterTypes.length >= 1);
2970+
return parameterTypes[0];
2971+
}
2972+
2973+
/** Gets the left type of a binary operator overload. */
2974+
get binaryOverloadLeftType(): Type {
2975+
if (this.is(CommonFlags.INSTANCE)) {
2976+
return assert(this.signature.thisType);
2977+
}
2978+
var parameterTypes = this.signature.parameterTypes;
2979+
assert(parameterTypes.length >= 2);
2980+
return parameterTypes[0];
2981+
}
2982+
2983+
/** Gets the right type of a binary operator overload. */
2984+
get binaryOverloadRightType(): Type {
2985+
var parameterTypes = this.signature.parameterTypes;
2986+
if (this.is(CommonFlags.INSTANCE)) {
2987+
assert(parameterTypes.length >= 1);
2988+
return parameterTypes[0];
2989+
}
2990+
assert(parameterTypes.length >= 2);
2991+
return parameterTypes[1];
2992+
}
29622993
}
29632994

29642995
var nextFunctionTarget = 0;

tests/compiler/resolve-unary.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,19 +131,19 @@ assert(
131131
class Bar {
132132
// static inc/dec don't reassign and can have different return type
133133
@operator.prefix("++")
134-
static prefix_inc(a: Foo): string {
134+
static prefix_inc(a: Bar): string {
135135
return "++i";
136136
}
137137
@operator.prefix("--")
138-
static prefix_dec(a: Foo): string {
138+
static prefix_dec(a: Bar): string {
139139
return "--i";
140140
}
141141
@operator.postfix("++")
142-
static postfix_inc(a: Foo): string {
142+
static postfix_inc(a: Bar): string {
143143
return "i++";
144144
}
145145
@operator.postfix("--")
146-
static postfix_dec(a: Foo): string {
146+
static postfix_dec(a: Bar): string {
147147
return "i--";
148148
}
149149
}

0 commit comments

Comments
 (0)