diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index d2e704d8b..82d9020c2 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -290,7 +290,7 @@ internal class AstChecker(private val program: Program, else if(param.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) { if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD && param.first.type != DataType.STR && param.first.type !in ArrayDatatypes && param.first.type != DataType.FLOAT) - err("parameter '${param.first.name}' should be (u)word/address") + err("parameter '${param.first.name}' should be (u)word (an address) or str") } else if(param.second.statusflag!=null) { if (param.first.type != DataType.UBYTE) @@ -626,7 +626,6 @@ internal class AstChecker(private val program: Program, } } - // string assignment is not supported in a vard if(decl.datatype==DataType.STR) { if(decl.value==null) err("string var must be initialized with a string literal") diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index eadba560e..a20714f76 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -252,7 +252,9 @@ private fun Prog8ANTLRParser.Asmsub_returnsContext.toAst(): List = asmsub_param().map { val vardecl = it.vardecl() - val datatype = vardecl.datatype()?.toAst() ?: DataType.UNDEFINED + var datatype = vardecl.datatype()?.toAst() ?: DataType.UNDEFINED + if(vardecl.ARRAYSIG()!=null || vardecl.arrayindex()!=null) + datatype = ElementToArrayTypes.getValue(datatype) val register = it.register().text var registerorpair: RegisterOrPair? = null var statusregister: Statusflag? = null @@ -318,7 +320,9 @@ private fun Prog8ANTLRParser.Sub_return_partContext.toAst(): List { private fun Prog8ANTLRParser.Sub_paramsContext.toAst(): List = vardecl().map { - val datatype = it.datatype()?.toAst() ?: DataType.UNDEFINED + var datatype = it.datatype()?.toAst() ?: DataType.UNDEFINED + if(it.ARRAYSIG()!=null || it.arrayindex()!=null) + datatype = ElementToArrayTypes.getValue(datatype) SubroutineParameter(it.varname.text, datatype, it.toPosition()) } diff --git a/compilerAst/test/TestSubroutines.kt b/compilerAst/test/TestSubroutines.kt new file mode 100644 index 000000000..9139e36aa --- /dev/null +++ b/compilerAst/test/TestSubroutines.kt @@ -0,0 +1,67 @@ +package prog8tests + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import prog8.ast.base.DataType +import prog8.ast.statements.Block +import prog8.ast.statements.Subroutine +import prog8.parser.Prog8Parser.parseModule +import prog8.parser.SourceCode +import kotlin.test.* + + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestSubroutines { + + @Test + fun stringParameterAcceptedInParser() { + // note: the *parser* should accept this as it is valid *syntax*, + // however, the compiler itself may or may not complain about it later. + val text = """ + main { + asmsub asmfunc(str thing @AY) { + } + + sub func(str thing) { + } + } + """ + val src = SourceCode.Text(text) + val module = parseModule(src) + val mainBlock = module.statements.single() as Block + val asmfunc = mainBlock.statements.filterIsInstance().single { it.name=="asmfunc"} + val func = mainBlock.statements.filterIsInstance().single { it.name=="func"} + assertTrue(asmfunc.isAsmSubroutine) + assertEquals(DataType.STR, asmfunc.parameters.single().type) + assertTrue(asmfunc.statements.isEmpty()) + assertFalse(func.isAsmSubroutine) + assertEquals(DataType.STR, func.parameters.single().type) + assertTrue(func.statements.isEmpty()) + } + + @Test + fun arrayParameterAcceptedInParser() { + // note: the *parser* should accept this as it is valid *syntax*, + // however, the compiler itself may or may not complain about it later. + val text = """ + main { + asmsub asmfunc(ubyte[] thing @AY) { + } + + sub func(ubyte[22] thing) { + } + } + """ + val src = SourceCode.Text(text) + val module = parseModule(src) + val mainBlock = module.statements.single() as Block + val asmfunc = mainBlock.statements.filterIsInstance().single { it.name=="asmfunc"} + val func = mainBlock.statements.filterIsInstance().single { it.name=="func"} + assertTrue(asmfunc.isAsmSubroutine) + assertEquals(DataType.ARRAY_UB, asmfunc.parameters.single().type) + assertTrue(asmfunc.statements.isEmpty()) + assertFalse(func.isAsmSubroutine) + assertEquals(DataType.ARRAY_UB, func.parameters.single().type) + assertTrue(func.statements.isEmpty()) + } +} diff --git a/examples/test.p8 b/examples/test.p8 index f5ba855fa..731497414 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,10 +1,16 @@ main { sub start() { - uword address = &irq - ; cx16.set_irq(&irq, false) - address++ + asmfunc("text") + func("text") } - sub irq() { + asmsub asmfunc(str thing @AY) { + %asm {{ + rts + }} + } + + + sub func(str thing) { } }