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 {
statement.execute(it)
}
cc.skipTokenOfType(Token.Type.NEWLINE, isOptional = true)
cc.skipTokenOfType(Token.Type.RPAREN, "missing ')'")
}
}
Token.Type.ID -> {
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)
// there could be terminal operators or keywords:// variable to read or like
when (t.value) {
"else" -> {
cc.previous()
return operand?.let { op -> statement(startPos) { op.getter(it) } }
}
"if", "when", "do", "while", "return" -> {
if( operand != null ) throw ScriptError(t.pos, "unexpected keyword")
cc.previous()
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 -> {

View File

@ -443,6 +443,7 @@ class ScriptTest {
"""
val count = 3
val res = if( count > 10 ) "too much" else "just " + count
println(count)
println(res)
res
""".trimIndent()
@ -549,4 +550,18 @@ class ScriptTest {
// 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)
}
}