functions are rewritten to new standard argparser/emitter too

This commit is contained in:
Sergey Chernov 2025-06-08 13:51:23 +04:00
parent 71a2933066
commit 9a08da0dfd
2 changed files with 25 additions and 46 deletions

View File

@ -348,7 +348,7 @@ class Compiler(
context.addItem("it", false, itValue)
} else {
// assign vars as declared the standard way
argsDeclaration.assignToContext(context)
argsDeclaration.assignToContext(context, defaultAccessType = AccessType.Val)
}
body.execute(context)
}
@ -417,6 +417,11 @@ class Compiler(
while (endTokenType == null) {
var t = cc.next()
when (t.type) {
Token.Type.RPAREN, Token.Type.ARROW -> {
// empty list?
endTokenType = t.type
}
Token.Type.NEWLINE -> {}
Token.Type.ID -> {
// visibility
@ -1046,12 +1051,6 @@ class Compiler(
}
}
data class FnParamDef(
val name: String,
val pos: Pos,
val defaultValue: Statement? = null
)
private fun parseFunctionDeclaration(tokens: CompilerContext): Statement {
var t = tokens.next()
val start = t.pos
@ -1062,27 +1061,10 @@ class Compiler(
t = tokens.next()
if (t.type != Token.Type.LPAREN)
throw ScriptError(t.pos, "Bad function definition: expected '(' after 'fn ${name}'")
val params = mutableListOf<FnParamDef>()
var defaultListStarted = false
do {
t = tokens.next()
if (t.type == Token.Type.RPAREN)
break
if (t.type != Token.Type.ID)
throw ScriptError(t.pos, "Expected identifier after '('")
val n = tokens.next()
val defaultValue = if (n.type == Token.Type.ASSIGN) {
parseExpression(tokens)?.also { defaultListStarted = true }
?: throw ScriptError(n.pos, "Expected initialization expression")
} else {
if (defaultListStarted)
throw ScriptError(n.pos, "requires default value too")
if (n.type != Token.Type.COMMA)
tokens.previous()
null
}
params.add(FnParamDef(t.value, t.pos, defaultValue))
} while (true)
val argsDeclaration = parseArgsDeclaration(tokens)
if( argsDeclaration == null || argsDeclaration.endTokenType != Token.Type.RPAREN)
throw ScriptError(t.pos, "Bad function definition: expected valid argument declaration or () after 'fn ${name}'")
// Here we should be at open body
val fnStatements = parseBlock(tokens)
@ -1096,21 +1078,7 @@ class Compiler(
val context = closure?.copy() ?: callerContext.raiseError("bug: closure not set")
// load params from caller context
for ((i, d) in params.withIndex()) {
if (i < callerContext.args.size)
context.addItem(d.name, false, callerContext.args.list[i].value)
else
context.addItem(
d.name,
false,
d.defaultValue?.execute(context)
?: throw ScriptError(
context.pos,
"missing required argument #${1 + i}: ${d.name}"
)
)
}
// save closure
argsDeclaration.assignToContext(context, callerContext.args, defaultAccessType = AccessType.Val)
fnStatements.execute(context)
}
return statement(start) { context ->

View File

@ -528,7 +528,7 @@ class ScriptTest {
// equal args,
// less args, no ellipsis, defaults, ok
val ttEnd = Token.Type.RBRACE
var pa = ArgsDeclaration(listOf(
val pa = ArgsDeclaration(listOf(
ArgsDeclaration.Item("a"),
ArgsDeclaration.Item("b", isEllipsis = true),
), ttEnd)
@ -551,7 +551,7 @@ class ScriptTest {
@Test
fun testAssignArgumentsStartEllipsis() = runTest {
val ttEnd = Token.Type.RBRACE
var pa = ArgsDeclaration(listOf(
val pa = ArgsDeclaration(listOf(
ArgsDeclaration.Item("a", isEllipsis = true),
ArgsDeclaration.Item("b"),
ArgsDeclaration.Item("c"),
@ -583,7 +583,7 @@ class ScriptTest {
@Test
fun testAssignArgumentsmiddleEllipsis() = runTest {
val ttEnd = Token.Type.RBRACE
var pa = ArgsDeclaration(listOf(
val pa = ArgsDeclaration(listOf(
ArgsDeclaration.Item("i"),
ArgsDeclaration.Item("a", isEllipsis = true),
ArgsDeclaration.Item("b"),
@ -1306,6 +1306,17 @@ class ScriptTest {
)
}
@Test
fun testNewFnParser() = runTest {
eval(
"""
fun f1(a,b) { a + b }
println(f1(1,2))
assertEquals( 7, f1(3,4) )
""".trimIndent()
)
}
@Test
fun testSpoilArgsBug() = runTest {
eval(