big refactoring: all tests passed

This commit is contained in:
Sergey Chernov 2025-05-26 23:51:22 +04:00
parent eba29aedb7
commit 361c1d5b13
2 changed files with 51 additions and 14 deletions

View File

@ -283,27 +283,49 @@ class Compiler {
operand = Accessor { operand = Accessor {
statement.execute(it) statement.execute(it)
} }
cc.skipTokenOfType(Token.Type.NEWLINE, isOptional = true)
cc.skipTokenOfType(Token.Type.RPAREN, "missing ')'") cc.skipTokenOfType(Token.Type.RPAREN, "missing ')'")
} }
} }
Token.Type.ID -> { Token.Type.ID -> {
operand?.let { left -> // there could be terminal operators or keywords:// variable to read or like
// selector: <lvalue>, '.' , <id> when (t.value) {
// we replace operand with selector code, that "else" -> {
// is RW: cc.previous()
operand = Accessor({ return operand?.let { op -> statement(startPos) { op.getter(it) } }
it.pos = t.pos }
left.getter(it).readField(it, t.value) "if", "when", "do", "while", "return" -> {
}) { cxt, newValue -> if( operand != null ) throw ScriptError(t.pos, "unexpected keyword")
cxt.pos = t.pos cc.previous()
left.getter(cxt).writeField(cxt, t.value, newValue) val s = parseStatement(cc) ?: throw ScriptError(t.pos, "Expecting valid statement")
operand = Accessor { s.execute(it) }
}
"break", "continue" -> {
cc.previous()
return operand?.let { op -> statement(startPos) { op.getter(it) } }
}
else -> operand?.let { left ->
// selector: <lvalue>, '.' , <id>
// we replace operand with selector code, that
// is RW:
operand = Accessor({
it.pos = t.pos
left.getter(it).readField(it, t.value)
}) { cxt, newValue ->
cxt.pos = t.pos
left.getter(cxt).writeField(cxt, t.value, newValue)
}
} ?: run {
// variable to read or like
cc.previous()
operand = parseAccessor(cc)
} }
} ?: run {
// variable to read or like
cc.previous()
operand = parseAccessor(cc)
} }
// selector: <lvalue>, '.' , <id>
// we replace operand with selector code, that
// is RW:
} }
Token.Type.PLUS2 -> { Token.Type.PLUS2 -> {

View File

@ -443,6 +443,7 @@ class ScriptTest {
""" """
val count = 3 val count = 3
val res = if( count > 10 ) "too much" else "just " + count val res = if( count > 10 ) "too much" else "just " + count
println(count)
println(res) println(res)
res res
""".trimIndent() """.trimIndent()
@ -549,4 +550,18 @@ class ScriptTest {
// assertEquals( "4", c.eval("x+0").toString()) // assertEquals( "4", c.eval("x+0").toString())
} }
@Test
fun bookTest2() = runTest {
val src = """
fn check(amount, prefix = "answer: ") {
prefix + if( amount > 100 )
"enough"
else
"more"
}
""".trimIndent()
eval(src)
}
} }