vm: support non-unary functions in pipe expressions

This commit is contained in:
Irmen de Jong 2022-05-07 20:42:05 +02:00
parent 7c121bfc01
commit 8c4765b386
4 changed files with 53 additions and 2 deletions

View File

@ -85,12 +85,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return when (segment) {
is PtFunctionCall -> {
val segWithArg = PtFunctionCall(segment.functionName, segment.void, segment.type, segment.position)
segWithArg.children.add(0, PtMachineRegister(sourceReg, sourceDt, segment.position))
segWithArg.children.add(PtMachineRegister(sourceReg, sourceDt, segment.position))
segWithArg.children.addAll(segment.args)
segWithArg
}
is PtBuiltinFunctionCall -> {
val segWithArg = PtBuiltinFunctionCall(segment.name, segment.void, segment.hasNoSideEffects, segment.type, segment.position)
segWithArg.children.add(0, PtMachineRegister(sourceReg, sourceDt, segment.position))
segWithArg.children.add(PtMachineRegister(sourceReg, sourceDt, segment.position))
segWithArg.children.addAll(segment.args)
segWithArg
}
else -> throw AssemblyError("weird segment type")

View File

@ -1132,6 +1132,14 @@ internal class AstChecker(private val program: Program,
throw FatalAstException("pipe is missing one or more expressions")
if(pipe.segments.any { it !is IFunctionCall })
throw FatalAstException("pipe segments can only be function calls")
if(compilerOptions.compTarget !is VMTarget) {
pipe.segments.forEach {
it as IFunctionCall
if (it.args.size > 0)
errors.err("only unary functions supported in pipe expressions for now", it.position)
}
}
}
override fun visit(postIncrDecr: PostIncrDecr) {

View File

@ -17,6 +17,7 @@ import prog8.code.target.C64Target
import prog8.compiler.astprocessing.AstPreprocessor
import prog8.parser.Prog8Parser.parseModule
import prog8.code.core.SourceCode
import prog8.code.target.VMTarget
import prog8tests.helpers.*
@ -473,4 +474,39 @@ class TestPipes: FunSpec({
errors.errors[1] shouldContain ":7:42: invalid number of arguments"
errors.errors[2] shouldContain ":7:56: invalid number of arguments"
}
test("non-unary funcions in pipe ok for target virtual") {
val text = """
main {
sub start() {
uword @shared wvalue = add(3,4) |> add(48) |> mkword(234)
}
sub add(ubyte first, ubyte second) -> ubyte {
return first+second
}
}"""
val errors = ErrorReporterForTests()
val result = compileText(VMTarget(), optimize = false, text, writeAssembly = true, errors=errors)!!
errors.errors.size shouldBe 0
errors.warnings.size shouldBe 0
result.program.entrypoint.statements.size shouldBe 3
}
test("non-unary funcions in pipe not yet ok for other targets") {
// NOTE: once other targets also support this, merge this into the test above
val text = """
main {
sub start() {
uword @shared wvalue = add(3,4) |> add(48) |> mkword(234)
}
sub add(ubyte first, ubyte second) -> ubyte {
return first+second
}
}"""
val errors = ErrorReporterForTests()
compileText(C64Target(), optimize = false, text, writeAssembly = true, errors=errors) shouldBe null
errors.errors.size shouldBe 2
errors.errors[0] shouldContain "only unary"
errors.errors[1] shouldContain "only unary"
}
})

View File

@ -16,9 +16,14 @@ main {
}
sub start() {
; TODO: test with builtin function using multiple args (such as mkword)
ubyte source=99
ubyte value = add(3,4) |> add(10) |> mul(2) |> math.sin8u() ; TODO should not work yet on vm codegen, but it compiles.... :/
txt.print_ub(value)
txt.nl()
uword wvalue = add(3,4) |> add($30) |> mkword($ea)
txt.print_uwhex(wvalue, true)
txt.nl()
; expected output: aaabbb aaa bbb