Support cross-backend adjustment - #471
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>
|
|
||
| override fun translate(finished: TmpL.ModuleSet) = buildList { | ||
| JavaTranslator(names, dependenciesBuilder).let { trans -> | ||
| JavaTranslator(names, dependenciesBuilder, adjusterFactory).let { trans -> |
There was a problem hiding this comment.
I've implemented adjustment only in be-java for now. And in separate test backends also.
|
|
||
| fun module(module: TmpL.Module): List<J.Program> { | ||
| this.module = module | ||
| adjuster = adjusterFactory?.makeAdjuster(module, this) |
There was a problem hiding this comment.
Each adjuster is per module, so I make an adjuster for each ModuleScope in JavaTranslator.
And the this will presumably cause a class cast exception in the adjuster factory if an unexpected type is given.
| ).exprOrReturnStatement(shouldReturn = result !is J.VoidType).also { add(it) } | ||
| ).let { call -> | ||
| adjuster?.adjustConnectedCall(fn, call as J.ExpressionStatementExpr) ?: call | ||
| }.exprOrReturnStatement(shouldReturn = result !is J.VoidType).also { add(it) } |
There was a problem hiding this comment.
Adjuster only operate in limited contexts so far, and connected call adjustment is one of those places.
And note that a class cast exception would happen here if adjusters don't dynamically full the generic function signature.
| val autodoc = autodocFor(t) | ||
| val name = names.moduleFunction(t.name).second.toIdentifier(t.name.pos) | ||
| val result = resultType(names, t.returnType, pos = t.returnType.pos) | ||
| val result = resultType(t) |
There was a problem hiding this comment.
For my adjuster in a separate repo, I wanted my capabilities and conveniences, so I factored out more helpers and made them public. Then modified code here to use the new helpers.
Note the t.returnType.pos. More cases said t.pos (or equivalent) for resultType calls, so that's what I put in the newly factored helper. If someone has strong opinions to the contrary, let me know.
| modFinal = final(m.assignOnce), | ||
| ), | ||
| type = JavaType.fromTmpL(m.type, names).toTypeAst(m.pos), | ||
| type = varType(m), |
There was a problem hiding this comment.
So varType and resultType were my main new factorings.
| ), | ||
| ), | ||
| errors, | ||
| ) |
There was a problem hiding this comment.
The one simple error is now two different kinds of errors.
| organization.backendBuckets, | ||
| ) | ||
| assertEquals(backends.keys - setOf(aloofBackend.backendId), organization.factoriesById.keys) | ||
| assertEquals(uselessAdjusterFactory, organization.adjusterFactories[needyFactory.backendId]) |
There was a problem hiding this comment.
And we also got the proper adjuster factory.
| libraryRoot = dirPath("a"), | ||
| supportedBackendList = emptyList(), | ||
| classifyTemperSource = ::defaultClassifyTemperSource, | ||
| ) |
There was a problem hiding this comment.
Moved this down to be closer to the related tests instead of the unrelated ones I was shoving in front of them.
| unknownPos, | ||
| listOf(backendId), | ||
| listOf(err.backendId), | ||
| ) |
There was a problem hiding this comment.
This is the error reporting for temper cli builds instead of funtests.
| dependencyResolver = dependencyResolver, | ||
| config = harness.backendConfig, | ||
| adjusterFactory = backendOrganization.adjusterFactories[factory.backendId], | ||
| ), |
There was a problem hiding this comment.
And here's the temper cli build grabbing the adjuster factories. I'm not sure we test this anywhere yet, but at least it doesn't break things.
| */ | ||
| fun <T : OutTree<*>> adjustConnectedCall(decl: TmpL.FunctionDeclaration, call: T): T? { | ||
| return null | ||
| } |
There was a problem hiding this comment.
Note the doc comment mentioning the need for careful type handling in adjusters to be sure to comply with the unenforceable generics signature. If people don't comply, there typically will be runtime cast exceptions, at least, rather than silent runtime errors.
| class TestAdjusterA : BackendAdjuster { | ||
| override fun <T : OutTree<*>> adjustConnectedCall(decl: TmpL.FunctionDeclaration, call: T): T? { | ||
| // Abusively just treat ids as calls to simplify. | ||
| call is TmpL.Id || return null |
There was a problem hiding this comment.
This handling is my recommended way to ensure type safety dynamically for backend adjusters.
Signed-off-by: Tom <tom@temper.systems>
| * JLS 15.26 TODO add array access | ||
| */ | ||
| LeftHandSide = NameExpr | FieldAccessExpr ; | ||
| LeftHandSide = NameExpr | FieldAccessExpr | StaticFieldAccessExpr ; |
There was a problem hiding this comment.
This is unrelated to backend adjustment itself, but it's handy for my needs in some adjuster code in a different repo.
Uh oh!
There was an error while loading. Please reload this page.