Repository navigation
Conversation
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
Signed-off-by: Tom <tom@temper.systems>
| private val vZero = Value(0, TInt) | ||
|
|
||
| internal fun dotHelperForOperator(member: Member): DotHelper { | ||
| fun dotHelperForOperator(member: Member): DotHelper { |
| import lang.temper.value.vVisibilitySymbol | ||
| import lang.temper.value.vWordSymbol | ||
| import lang.temper.value.valueContained | ||
| import lang.temper.value.void |
There was a problem hiding this comment.
I love having a semi-lock file of imports in every file. So fun.
| fun addAutosIfWanted() { | ||
| reifiedType ?: return | ||
| // First check our own auto keys. | ||
| val autoKeys = typeDecl?.autoKeys() ?: listOf() |
There was a problem hiding this comment.
This abstracts the idea of there possibly being more than one, although this pr doesn't allow for that.
| } | ||
| } | ||
| // Also check the parents' auto keys, just in case. | ||
| addAutoEqForSuperSealedIfWanted(autoKeys) |
There was a problem hiding this comment.
Realized probably best to skip this if we had one above, but it's rare that someone would label both, and we eventually dodge duplicate == anyway, so maybe ok.
| eqBuiltinName.builtinKey in autoKeys && return | ||
| val typeShape = reifiedType!!.type2.definition as? TypeShape ?: return | ||
| // We care about this type only if it's concrete or sealed. | ||
| typeShape.abstractness == Abstractness.Concrete || typeShape.decl()?.isSealed() == true || return |
There was a problem hiding this comment.
Again, this case is for when there ain't an @auto("=="), so it's ok to skip. We'll separately check each type we do add == to for seeing if it has only class or sealed subtypes, so if there's a mismatch there, it's handled elsewhere.
| "Auto method not allowed with unsealed subtype(s): Sneaky!", | ||
| "Auto method not support for interface that's not sealed!", | ||
| "Auto method cannot support multiple supertype(s): Root1, Root2!", | ||
| "Type WhichToUse must implement eq from Root1. Maybe add `public eq(other: Root1): Boolean`!" |
There was a problem hiding this comment.
One reason I kept this test in generate code stage instead of just define was so I could see this later stage errors such as this one.
| ```log | ||
| Some are twins: true | ||
| All are twins: false | ||
| ``` |
There was a problem hiding this comment.
As I comment, this isn't testing backends so much as just testing that the code gen works anywhere.
We still should make passes to generate idiomatic operator methods in backends, though. Testing those would be a lot in backend tests.
| @auto("==") | ||
| sealed interface High { | ||
| toString(): String; | ||
| } |
There was a problem hiding this comment.
Above is the only @auto.
| Low2(to be) == Low2(to be): true | ||
| Low1(11) == Low3: false | ||
| Low3 == Low3: true | ||
| ``` |
There was a problem hiding this comment.
But all the varieties seem to work fine.
| override fun hashCode() = stateVector.hashCode() | ||
|
|
||
| companion object { | ||
| operator fun invoke(string: String) = Value(string, TString) |
There was a problem hiding this comment.
Maybe should have added this long ago. I used it in the new frontend tree gen.
Signed-off-by: Tom <tom@temper.systems>
| }); | ||
| do {}; | ||
| void; | ||
| Maybe extends AnyValue; |
There was a problem hiding this comment.
No pure virtual ==/eq for Maybe because it has an unsealed subtype. Maybe should just generate one anyway? I do give an error message for it, in any case.
|
|
||
| <!-- snippet: builtin/@auto --> | ||
|
|
||
| <a name="builtin-@auto" class="snippet-anchor-name"></a> |
| The *\@auto* decorator currently applies to a class or sealed interface, | ||
| indicating that the specified operator should be automatically implemented | ||
| for this type. In the future, it might be possible to specify on an | ||
| individual method for a specific operator. |
There was a problem hiding this comment.
We had talked about a number of ways to get more fine-grained control.
Do you need to specify auto on the method or would you specify it on the class and then provide a stub method?
@auto("==")
export class C(...) {
@operator("==")
public equivalent(other: C): Boolean; // pure virtual, so needs an implementation
}
There was a problem hiding this comment.
We had talked about a number of ways to get more fine-grained control.
Do you need to specify auto on the method or would you specify it on the class and then provide a stub method?
I guess either could provide a name, yeah. I could see arguments either way.
| than class or sealed interface descendents. Inheriting `@auto("==")` from | ||
| multiple sealed ancestor interface branches is also an error. Further, if a | ||
| manual `@operator("==")` method exists for a type, no automatic | ||
| implementation is injected. |
There was a problem hiding this comment.
Could we extend this to sealed interfaces with unsealed interface descendants that have a manual @operator("==") method?
| } | ||
|
|
||
| @Suppress("SameParameterValue") | ||
| private fun errorTree(tree: Tree, leftIndex: Int, rightIndex: Int): CallTree = |
| if (illegalSuperTypes.isEmpty()) { | ||
| if (illegalSuperTypes.isNotEmpty()) { | ||
| (typeShape as MutableTypeShape).superTypes.removeAll(illegalSuperTypes) | ||
| } |
There was a problem hiding this comment.
This does make more sense.
I'm guessing this is part of an attempt to make sure later passes don't have to deal with super-type cycles.
That's not something people often write.
| export class HasOwn extends Maybe { | ||
| @operator("==") | ||
| public eq(other: Maybe): Boolean { | ||
| // No equality here! |
==if one already existseqfor generated methods in this pr@operator, I don't think)