added clamp function and extensions, fixed bug in range coloring
This commit is contained in:
1 parent
0759346e4b
commit
5dc2159024
9 files changed
+205
-16
No files matched your search
@@ -20,10 +20,7 @@ package net.sergeych.lyng
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.yield
|
||||
import net.sergeych.lyng.Script.Companion.defaultImportManager
|
||||
import net.sergeych.lyng.miniast.addConstDoc
|
||||
import net.sergeych.lyng.miniast.addFnDoc
|
||||
import net.sergeych.lyng.miniast.addVoidFnDoc
|
||||
import net.sergeych.lyng.miniast.type
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
import net.sergeych.lyng.stdlib_included.rootLyng
|
||||
@@ -162,6 +159,42 @@ class Script(
|
||||
if (x is ObjInt) ObjInt(x.value.absoluteValue) else ObjReal(x.toDouble().absoluteValue)
|
||||
}
|
||||
|
||||
addFnDoc(
|
||||
"clamp",
|
||||
doc = "Clamps the value within the specified range. If the value is outside the range, it is set to the nearest boundary. Respects inclusive/exclusive range ends.",
|
||||
params = listOf(ParamDoc("value"), ParamDoc("range")),
|
||||
moduleName = "lyng.stdlib"
|
||||
) {
|
||||
val value = requiredArg<Obj>(0)
|
||||
val range = requiredArg<ObjRange>(1)
|
||||
|
||||
var result = value
|
||||
if (range.start != null && !range.start.isNull) {
|
||||
if (result.compareTo(this, range.start) < 0) {
|
||||
result = range.start
|
||||
}
|
||||
}
|
||||
if (range.end != null && !range.end.isNull) {
|
||||
val cmp = range.end.compareTo(this, result)
|
||||
if (range.isEndInclusive) {
|
||||
if (cmp < 0) result = range.end
|
||||
} else {
|
||||
if (cmp <= 0) {
|
||||
if (range.end is ObjInt) {
|
||||
result = ObjInt.of(range.end.value - 1)
|
||||
} else if (range.end is ObjChar) {
|
||||
result = ObjChar((range.end.value.code - 1).toChar())
|
||||
} else {
|
||||
// For types where we can't easily find "previous" value (like Real),
|
||||
// we just return the exclusive boundary as a fallback.
|
||||
result = range.end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
addVoidFn("assert") {
|
||||
val cond = requiredArg<ObjBool>(0)
|
||||
val message = if (args.size > 1)
|
||||
|
||||
@@ -760,6 +760,38 @@ open class Obj {
|
||||
) {
|
||||
thisObj.toJson(this).toString().toObj()
|
||||
}
|
||||
addFnDoc(
|
||||
name = "clamp",
|
||||
doc = "Clamps this value within the specified range. If the value is outside the range, it is set to the nearest boundary. Respects inclusive/exclusive range ends.",
|
||||
params = listOf(ParamDoc("range")),
|
||||
moduleName = "lyng.stdlib"
|
||||
) {
|
||||
val range = requiredArg<ObjRange>(0)
|
||||
|
||||
var result = thisObj
|
||||
if (range.start != null && !range.start.isNull) {
|
||||
if (result.compareTo(this, range.start) < 0) {
|
||||
result = range.start
|
||||
}
|
||||
}
|
||||
if (range.end != null && !range.end.isNull) {
|
||||
val cmp = range.end.compareTo(this, result)
|
||||
if (range.isEndInclusive) {
|
||||
if (cmp < 0) result = range.end
|
||||
} else {
|
||||
if (cmp <= 0) {
|
||||
if (range.end is ObjInt) {
|
||||
result = ObjInt.of(range.end.value - 1)
|
||||
} else if (range.end is ObjChar) {
|
||||
result = ObjChar((range.end.value.code - 1).toChar())
|
||||
} else {
|
||||
result = range.end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4986,5 +4986,41 @@ class ScriptTest {
|
||||
assertEquals(["bar"], A().f2("bar"))
|
||||
""")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClamp() = runTest {
|
||||
eval("""
|
||||
// Global clamp
|
||||
assertEquals(5, clamp(5, 0..10))
|
||||
assertEquals(0, clamp(-5, 0..10))
|
||||
assertEquals(10, clamp(15, 0..10))
|
||||
|
||||
// Extension clamp
|
||||
assertEquals(5, 5.clamp(0..10))
|
||||
assertEquals(0, (-5).clamp(0..10))
|
||||
assertEquals(10, 15.clamp(0..10))
|
||||
|
||||
// Exclusive range
|
||||
assertEquals(9, 15.clamp(0..<10))
|
||||
assertEquals(0, (-5).clamp(0..<10))
|
||||
|
||||
// Open-ended range
|
||||
assertEquals(10, 15.clamp(..10))
|
||||
assertEquals(-5, (-5).clamp(..10))
|
||||
assertEquals(5, 5.clamp(0..))
|
||||
assertEquals(0, (-5).clamp(0..))
|
||||
|
||||
// Character range
|
||||
assertEquals('e', 'e'.clamp('a'..'z'))
|
||||
assertEquals('a', ' '.clamp('a'..'z'))
|
||||
assertEquals('z', '}'.clamp('a'..'z'))
|
||||
assertEquals('y', '}'.clamp('a'..<'z'))
|
||||
|
||||
// Real numbers (boundaries are inclusive in current impl for Real)
|
||||
assertEquals(5.5, 5.5.clamp(0.0..10.0))
|
||||
assertEquals(0.0, (-1.5).clamp(0.0..10.0))
|
||||
assertEquals(10.0, 15.5.clamp(0.0..10.0))
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user