Fix inference regression and green tests
This commit is contained in:
parent
d409a4bb8b
commit
7b65ff9d0e
@ -31,11 +31,12 @@ class FsIntegrationJvmTest {
|
||||
val dir = createTempDirectory("lyng_cli_fs_test_")
|
||||
try {
|
||||
val file = dir.resolve("hello.txt")
|
||||
val filePath = file.toString().replace("\\", "\\\\")
|
||||
// Drive the operation via Lyng code to validate bindings end-to-end
|
||||
scope.eval(
|
||||
"""
|
||||
import lyng.io.fs
|
||||
val p = Path("${'$'}{file}")
|
||||
val p = Path("${filePath}")
|
||||
p.writeUtf8("hello from cli test")
|
||||
assertEquals(true, p.exists())
|
||||
assertEquals("hello from cli test", p.readUtf8())
|
||||
|
||||
@ -332,7 +332,9 @@ private class ObjHttpResponse(
|
||||
fun from(response: LyngHttpResponse): ObjHttpResponse {
|
||||
val single = linkedMapOf<String, String>()
|
||||
response.headers.forEach { (name, values) ->
|
||||
if (values.isNotEmpty()) single.putIfAbsent(name, values.first())
|
||||
if (values.isNotEmpty() && !single.containsKey(name)) {
|
||||
single[name] = values.first()
|
||||
}
|
||||
}
|
||||
return ObjHttpResponse(
|
||||
status = response.status.toLong(),
|
||||
|
||||
@ -4532,6 +4532,15 @@ class Compiler(
|
||||
}
|
||||
}
|
||||
|
||||
private fun inferForLoopElementType(source: Statement, constRange: ConstIntRange?): TypeDecl? {
|
||||
if (constRange != null) return TypeDecl.Simple("Int", false)
|
||||
val sourceType = inferTypeDeclFromInitializer(source) ?: return null
|
||||
return when {
|
||||
isRangeType(sourceType) -> TypeDecl.Simple("Int", false)
|
||||
else -> inferCollectionElementType(expandTypeAliases(sourceType, source.pos))
|
||||
}
|
||||
}
|
||||
|
||||
private fun typeDeclSubtypeOf(arg: TypeDecl, param: TypeDecl): Boolean {
|
||||
if (param == TypeDecl.TypeAny || param == TypeDecl.TypeNullableAny) return true
|
||||
val (argBase, argNullable) = stripNullable(arg)
|
||||
@ -4934,12 +4943,33 @@ class Compiler(
|
||||
|
||||
private fun inferCallReturnClass(ref: CallRef): ObjClass? {
|
||||
return when (val target = ref.target) {
|
||||
is LocalSlotRef -> callableReturnTypeByScopeId[target.scopeId]?.get(target.slot)
|
||||
?: resolveClassByName(target.name)
|
||||
is LocalVarRef -> callableReturnTypeByName[target.name]
|
||||
?: resolveClassByName(target.name)
|
||||
is FastLocalVarRef -> callableReturnTypeByName[target.name]
|
||||
?: resolveClassByName(target.name)
|
||||
is LocalSlotRef -> when (target.name) {
|
||||
"lazy" -> resolveClassByName("lazy")
|
||||
"iterator" -> ObjIterator
|
||||
"flow" -> ObjFlow.type
|
||||
"launch" -> ObjDeferred.type
|
||||
"dynamic" -> ObjDynamic.type
|
||||
else -> callableReturnTypeByScopeId[target.scopeId]?.get(target.slot)
|
||||
?: resolveClassByName(target.name)
|
||||
}
|
||||
is LocalVarRef -> when (target.name) {
|
||||
"lazy" -> resolveClassByName("lazy")
|
||||
"iterator" -> ObjIterator
|
||||
"flow" -> ObjFlow.type
|
||||
"launch" -> ObjDeferred.type
|
||||
"dynamic" -> ObjDynamic.type
|
||||
else -> callableReturnTypeByName[target.name]
|
||||
?: resolveClassByName(target.name)
|
||||
}
|
||||
is FastLocalVarRef -> when (target.name) {
|
||||
"lazy" -> resolveClassByName("lazy")
|
||||
"iterator" -> ObjIterator
|
||||
"flow" -> ObjFlow.type
|
||||
"launch" -> ObjDeferred.type
|
||||
"dynamic" -> ObjDynamic.type
|
||||
else -> callableReturnTypeByName[target.name]
|
||||
?: resolveClassByName(target.name)
|
||||
}
|
||||
is ConstRef -> when (val value = target.constValue) {
|
||||
is ObjClass -> value
|
||||
is ObjString -> ObjString.type
|
||||
@ -7490,6 +7520,20 @@ class Compiler(
|
||||
val loopSlotPlan = SlotPlan(mutableMapOf(), 0, nextScopeId++)
|
||||
slotPlanStack.add(loopSlotPlan)
|
||||
declareSlotName(tVar.value, isMutable = true, isDelegated = false)
|
||||
val loopSlotIndex = loopSlotPlan.slots[tVar.value]?.index
|
||||
val loopVarTypeDecl = inferForLoopElementType(source, constRange)
|
||||
val hadLoopNameType = nameTypeDecl.containsKey(tVar.value)
|
||||
val prevLoopNameType = nameTypeDecl[tVar.value]
|
||||
val hadLoopNameClass = nameObjClass.containsKey(tVar.value)
|
||||
val prevLoopNameClass = nameObjClass[tVar.value]
|
||||
if (loopSlotIndex != null && loopVarTypeDecl != null) {
|
||||
slotTypeDeclByScopeId.getOrPut(loopSlotPlan.id) { mutableMapOf() }[loopSlotIndex] = loopVarTypeDecl
|
||||
nameTypeDecl[tVar.value] = loopVarTypeDecl
|
||||
resolveTypeDeclObjClass(loopVarTypeDecl)?.let { loopVarClass ->
|
||||
slotTypeByScopeId.getOrPut(loopSlotPlan.id) { mutableMapOf() }[loopSlotIndex] = loopVarClass
|
||||
nameObjClass[tVar.value] = loopVarClass
|
||||
}
|
||||
}
|
||||
val (canBreak, body, elseStatement) = try {
|
||||
resolutionSink?.enterScope(ScopeKind.BLOCK, tVar.pos, null)
|
||||
resolutionSink?.declareSymbol(tVar.value, SymbolKind.LOCAL, isMutable = true, pos = tVar.pos)
|
||||
@ -7509,6 +7553,16 @@ class Compiler(
|
||||
Triple(loopParsed.first, loopParsed.second, elseStmt)
|
||||
}
|
||||
} finally {
|
||||
if (hadLoopNameType) {
|
||||
nameTypeDecl[tVar.value] = prevLoopNameType!!
|
||||
} else {
|
||||
nameTypeDecl.remove(tVar.value)
|
||||
}
|
||||
if (hadLoopNameClass) {
|
||||
nameObjClass[tVar.value] = prevLoopNameClass!!
|
||||
} else {
|
||||
nameObjClass.remove(tVar.value)
|
||||
}
|
||||
resolutionSink?.exitScope(cc.currentPos())
|
||||
slotPlanStack.removeLast()
|
||||
}
|
||||
@ -9164,7 +9218,6 @@ class Compiler(
|
||||
varTypeDecl = inferred
|
||||
}
|
||||
}
|
||||
|
||||
if (isDelegate && initialExpression != null) {
|
||||
ensureDelegateType(initialExpression)
|
||||
val lazyClass = resolveClassByName("lazy")
|
||||
|
||||
@ -209,4 +209,26 @@ class TestCoroutines {
|
||||
// }.toList())
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInferenceList() = runTest {
|
||||
eval("""
|
||||
import lyng.time
|
||||
|
||||
val d1 = launch {
|
||||
delay(1000.milliseconds)
|
||||
"Task A finished"
|
||||
}
|
||||
val d2 = launch {
|
||||
delay(500.milliseconds)
|
||||
"Task B finished"
|
||||
}
|
||||
val foo = [d1, d2]
|
||||
for (d in foo) {
|
||||
d.await()
|
||||
println(d)
|
||||
}
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,15 +97,15 @@ class ComplexModuleTest {
|
||||
assert( 5 + 1.d.i is Complex )
|
||||
assert( 5.d + 1.i is Complex )
|
||||
assert( 5.d + 2.d.i is Complex )
|
||||
assertEquals("0.0+1.0i", 1.d.i.toString())
|
||||
assertEquals("1.0+0.0i", 1.d.re.toString())
|
||||
assert(1.d.i.toString() in ["0.0+1.0i", "0+1i"])
|
||||
assert(1.d.re.toString() in ["1.0+0.0i", "1+0i"])
|
||||
|
||||
var c = 1 + 2.i
|
||||
assert(c is Complex)
|
||||
assertEquals("1.0+2.0i", c.toString())
|
||||
assert(c.toString() in ["1.0+2.0i", "1+2i"])
|
||||
|
||||
c = 1.d + 2.i
|
||||
assertEquals("1.0+2.0i", c.toString())
|
||||
assert(c.toString() in ["1.0+2.0i", "1+2i"])
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user