fixed samples test

This commit is contained in:
Sergey Chernov 2026-02-18 09:17:12 +03:00
parent a0ecbfd334
commit dc9885c218
4 changed files with 134 additions and 14 deletions

View File

@ -1,23 +1,23 @@
// Sample: Operator Overloading in Lyng
class Vector(val x, val y) {
class Vector<T>(val x: T, val y: T) {
// Overload +
fun plus(other) = Vector(x + other.x, y + other.y)
fun plus(other: Vector<U>) = Vector(x + other.x, y + other.y)
// Overload -
fun minus(other) = Vector(x - other.x, y - other.y)
fun minus(other: Vector<U>) = Vector(x - other.x, y - other.y)
// Overload unary -
fun negate() = Vector(-x, -y)
// Overload ==
fun equals(other) {
if (other is Vector) x == other.x && y == other.y
if (other is Vector<U>) x == other.x && y == other.y
else false
}
// Overload * (scalar multiplication)
fun mul(scalar) = Vector(x * scalar, y * scalar)
fun mul(scalar: Int | Real) = Vector(x * scalar, y * scalar)
override fun toString() = "Vector(${x}, ${y})"
}

View File

@ -13,7 +13,6 @@ fun findSumLimit(f) {
println("limit reached after "+n+" rounds")
break sum
}
n++
}
else {
println("limit not reached")

View File

@ -6797,6 +6797,118 @@ class Compiler(
return t.pos
}
private data class SmartCastTarget(
val name: String? = null,
val scopeId: Int? = null,
val slot: Int? = null,
val typeDecl: TypeDecl,
)
private data class SmartCastRestore(
val name: String?,
val nameHad: Boolean,
val namePrev: TypeDecl?,
val scopeId: Int?,
val slot: Int?,
val slotHad: Boolean,
val slotPrev: TypeDecl?,
val slotMapCreated: Boolean,
)
private fun smartCastTargetFromRef(ref: ObjRef, typeDecl: TypeDecl): SmartCastTarget? = when (ref) {
is LocalSlotRef -> {
val ownerScopeId = ref.captureOwnerScopeId ?: ref.scopeId
val ownerSlot = ref.captureOwnerSlot ?: ref.slot
SmartCastTarget(scopeId = ownerScopeId, slot = ownerSlot, typeDecl = typeDecl)
}
is LocalVarRef -> SmartCastTarget(name = ref.name, typeDecl = typeDecl)
is FastLocalVarRef -> SmartCastTarget(name = ref.name, typeDecl = typeDecl)
else -> null
}
private fun extractSmartCasts(condition: Statement): Pair<List<SmartCastTarget>, List<SmartCastTarget>> {
val ref = unwrapDirectRef(condition) ?: return emptyList<SmartCastTarget>() to emptyList()
if (ref !is BinaryOpRef) return emptyList<SmartCastTarget>() to emptyList()
if (ref.op != BinOp.IS && ref.op != BinOp.NOTIS) return emptyList<SmartCastTarget>() to emptyList()
val typeRef = ref.right as? net.sergeych.lyng.obj.TypeDeclRef ?: return emptyList<SmartCastTarget>() to emptyList()
val typeDecl = expandTypeAliases(typeRef.decl(), typeRef.pos())
val target = smartCastTargetFromRef(ref.left, typeDecl) ?: return emptyList<SmartCastTarget>() to emptyList()
return if (ref.op == BinOp.IS) {
listOf(target) to emptyList()
} else {
emptyList<SmartCastTarget>() to listOf(target)
}
}
private fun applySmartCasts(overrides: List<SmartCastTarget>): List<SmartCastRestore> {
if (overrides.isEmpty()) return emptyList()
val restores = ArrayList<SmartCastRestore>(overrides.size)
for (override in overrides) {
if (override.name != null) {
val had = nameTypeDecl.containsKey(override.name)
val prev = nameTypeDecl[override.name]
nameTypeDecl[override.name] = override.typeDecl
restores.add(
SmartCastRestore(
name = override.name,
nameHad = had,
namePrev = prev,
scopeId = null,
slot = null,
slotHad = false,
slotPrev = null,
slotMapCreated = false,
)
)
} else if (override.scopeId != null && override.slot != null) {
val map = slotTypeDeclByScopeId[override.scopeId]
val mapCreated = map == null
val targetMap = map ?: mutableMapOf<Int, TypeDecl>().also { slotTypeDeclByScopeId[override.scopeId] = it }
val had = targetMap.containsKey(override.slot)
val prev = targetMap[override.slot]
targetMap[override.slot] = override.typeDecl
restores.add(
SmartCastRestore(
name = null,
nameHad = false,
namePrev = null,
scopeId = override.scopeId,
slot = override.slot,
slotHad = had,
slotPrev = prev,
slotMapCreated = mapCreated,
)
)
}
}
return restores
}
private fun restoreSmartCasts(restores: List<SmartCastRestore>) {
if (restores.isEmpty()) return
for (restore in restores.asReversed()) {
if (restore.name != null) {
if (restore.nameHad) {
nameTypeDecl[restore.name] = restore.namePrev!!
} else {
nameTypeDecl.remove(restore.name)
}
} else if (restore.scopeId != null && restore.slot != null) {
val map = slotTypeDeclByScopeId[restore.scopeId]
if (map != null) {
if (restore.slotHad) {
map[restore.slot] = restore.slotPrev!!
} else {
map.remove(restore.slot)
}
if (restore.slotMapCreated && map.isEmpty()) {
slotTypeDeclByScopeId.remove(restore.scopeId)
}
}
}
}
}
private suspend fun parseIfStatement(): Statement {
val start = ensureLparen()
@ -6805,7 +6917,13 @@ class Compiler(
val pos = ensureRparen()
val ifBody = parseStatement() ?: throw ScriptError(pos, "Bad if statement: expected statement")
val (trueCasts, falseCasts) = extractSmartCasts(condition)
val ifRestores = applySmartCasts(trueCasts)
val ifBody = try {
parseStatement() ?: throw ScriptError(pos, "Bad if statement: expected statement")
} finally {
restoreSmartCasts(ifRestores)
}
cc.skipTokenOfType(Token.Type.NEWLINE, isOptional = true)
// could be else block:
@ -6813,8 +6931,12 @@ class Compiler(
// we generate different statements: optimization
val stmt = if (t2.type == Token.Type.ID && t2.value == "else") {
val elseBody =
val elseRestores = applySmartCasts(falseCasts)
val elseBody = try {
parseStatement() ?: throw ScriptError(pos, "Bad else statement: expected statement")
} finally {
restoreSmartCasts(elseRestores)
}
IfStatement(condition, ifBody, elseBody, start)
} else {
cc.previous()

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,11 +18,11 @@
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import net.sergeych.lyng.Scope
import net.sergeych.lyng.Script
import net.sergeych.lyng.toSource
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.io.path.extension
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.time.Clock
@ -31,9 +31,9 @@ suspend fun executeSampleTests(fileName: String) {
Files.readString(Paths.get(fileName))
}
runBlocking {
val c = Scope()
val c = Script.newScope()
val start = Clock.System.now()
c.eval(sample)
c.eval(sample.toSource(fileName))
val time = Clock.System.now() - start
println("$time: $fileName")
// delay(100)
@ -41,7 +41,6 @@ suspend fun executeSampleTests(fileName: String) {
}
}
@Ignore("TODO(compile-time-res): legacy tests disabled")
class SamplesTest {
@Test