parent
f616326383
commit
2e96d75b9f
@ -1385,6 +1385,7 @@ Typical set of String functions includes:
|
|||||||
| trim() | trim space chars from both ends |
|
| trim() | trim space chars from both ends |
|
||||||
| startsWith(prefix) | true if starts with a prefix |
|
| startsWith(prefix) | true if starts with a prefix |
|
||||||
| endsWith(prefix) | true if ends with a prefix |
|
| endsWith(prefix) | true if ends with a prefix |
|
||||||
|
| last() | get last character of a string or throw |
|
||||||
| take(n) | get a new string from up to n first characters |
|
| take(n) | get a new string from up to n first characters |
|
||||||
| takeLast(n) | get a new string from up to n last characters |
|
| takeLast(n) | get a new string from up to n last characters |
|
||||||
| drop(n) | get a new string dropping n first chars, or empty string |
|
| drop(n) | get a new string dropping n first chars, or empty string |
|
||||||
|
|||||||
@ -213,25 +213,40 @@ private class Parser(fromPos: Pos) {
|
|||||||
|
|
||||||
'!' -> {
|
'!' -> {
|
||||||
if (currentChar == 'i') {
|
if (currentChar == 'i') {
|
||||||
|
// Potentially !in / !is, but only if a word boundary follows
|
||||||
pos.advance()
|
pos.advance()
|
||||||
when (currentChar) {
|
when (currentChar) {
|
||||||
'n' -> {
|
'n' -> {
|
||||||
pos.advance()
|
pos.advance()
|
||||||
|
// if next char continues an identifier, it's actually '!'+identifier starting with "in..."
|
||||||
|
if (idNextChars(currentChar)) {
|
||||||
|
// backtrack to right after '!'
|
||||||
|
pos.back()
|
||||||
|
pos.back()
|
||||||
|
Token("!", from, Token.Type.NOT)
|
||||||
|
} else
|
||||||
Token("!in", from, Token.Type.NOTIN)
|
Token("!in", from, Token.Type.NOTIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
's' -> {
|
's' -> {
|
||||||
pos.advance()
|
pos.advance()
|
||||||
|
// if next char continues an identifier, it's actually '!'+identifier starting with "is..."
|
||||||
|
if (idNextChars(currentChar)) {
|
||||||
|
// backtrack to right after '!'
|
||||||
|
pos.back()
|
||||||
|
pos.back()
|
||||||
|
Token("!", from, Token.Type.NOT)
|
||||||
|
} else
|
||||||
Token("!is", from, Token.Type.NOTIS)
|
Token("!is", from, Token.Type.NOTIS)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
// it was just '!i' followed by something else; revert one step and return '!'
|
||||||
pos.back()
|
pos.back()
|
||||||
Token("!", from, Token.Type.NOT)
|
Token("!", from, Token.Type.NOT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else if (currentChar == '=') {
|
||||||
if (currentChar == '=') {
|
|
||||||
pos.advance()
|
pos.advance()
|
||||||
if (currentChar == '=') {
|
if (currentChar == '=') {
|
||||||
pos.advance()
|
pos.advance()
|
||||||
|
|||||||
@ -173,6 +173,9 @@ data class ObjString(val value: String) : Obj() {
|
|||||||
thisAs<ObjString>().value.map { ObjChar(it) }.toMutableList()
|
thisAs<ObjString>().value.map { ObjChar(it) }.toMutableList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
addFn("last") {
|
||||||
|
ObjChar(thisAs<ObjString>().value.lastOrNull() ?: raiseNoSuchElement("empty string"))
|
||||||
|
}
|
||||||
addFn("encodeUtf8") { ObjBuffer(thisAs<ObjString>().value.encodeToByteArray().asUByteArray()) }
|
addFn("encodeUtf8") { ObjBuffer(thisAs<ObjString>().value.encodeToByteArray().asUByteArray()) }
|
||||||
addFn("size") { ObjInt(thisAs<ObjString>().value.length.toLong()) }
|
addFn("size") { ObjInt(thisAs<ObjString>().value.length.toLong()) }
|
||||||
addFn("toReal") {
|
addFn("toReal") {
|
||||||
|
|||||||
@ -4012,4 +4012,41 @@ class ScriptTest {
|
|||||||
""".trimIndent()).decodeSerializable<TestJson4>()
|
""".trimIndent()).decodeSerializable<TestJson4>()
|
||||||
assertEquals( TestJson4(TestEnum.One), x)
|
assertEquals( TestJson4(TestEnum.One), x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLogicalNot() = runTest {
|
||||||
|
eval("""
|
||||||
|
val vf = false
|
||||||
|
fun f() { false }
|
||||||
|
assert( !false )
|
||||||
|
assert( !vf )
|
||||||
|
assert( !f() )
|
||||||
|
|
||||||
|
val vt = true
|
||||||
|
fun ft() { true }
|
||||||
|
if( !true )
|
||||||
|
throw "impossible"
|
||||||
|
|
||||||
|
if( !ft() )
|
||||||
|
throw "impossible"
|
||||||
|
|
||||||
|
if( !vt )
|
||||||
|
throw "impossible"
|
||||||
|
|
||||||
|
// real world sample
|
||||||
|
|
||||||
|
fun isSignedByAdmin() {
|
||||||
|
// just ok
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requireAdmin() {
|
||||||
|
// this caused compilation error:
|
||||||
|
if( !isSignedByAdmin() )
|
||||||
|
throw "Admin signature required"
|
||||||
|
}
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user