improve ast check for multiple returnvalues assignment

This commit is contained in:
Irmen de Jong 2019-03-18 04:01:25 +01:00
parent 1e5b2e0be3
commit 747c9604dd
4 changed files with 38 additions and 19 deletions

View File

@ -355,7 +355,7 @@ private class AstChecker(private val namespace: INameScope,
// assigning from a functioncall COULD return multiple values (from an asm subroutine)
if(assignment.value is FunctionCall) {
val stmt = (assignment.value as FunctionCall).target.targetStatement(namespace)
if (stmt is Subroutine && stmt.returntypes.size > 1) {
if (stmt is Subroutine) {
if (stmt.isAsmSubroutine) {
if (stmt.returntypes.size != assignment.targets.size)
checkResult.add(ExpressionError("number of return values doesn't match number of assignment targets", assignment.value.position))
@ -371,7 +371,7 @@ private class AstChecker(private val namespace: INameScope,
checkResult.add(ExpressionError("return type mismatch for target ${thing.second.shortString()}", assignment.value.position))
}
}
} else
} else if(assignment.targets.size>1)
checkResult.add(ExpressionError("only asmsub subroutines can return multiple values", assignment.value.position))
}
}

View File

@ -644,10 +644,8 @@ internal class Compiler(private val rootModule: Module,
val funcname = expr.target.nameInSource[0]
translateBuiltinFunctionCall(funcname, expr.arglist)
} else {
when(target) {
is Subroutine -> translateSubroutineCall(target, expr.arglist, expr.position)
else -> TODO("non-builtin-function call to $target")
}
if (target is Subroutine) translateSubroutineCall(target, expr.arglist, expr.position)
else TODO("non-builtin-function call to $target")
}
}
is IdentifierReference -> translate(expr)
@ -670,7 +668,7 @@ internal class Compiler(private val rootModule: Module,
in ArrayDatatypes -> {
if(lv.heapId==null)
throw CompilerException("array should have been moved into heap ${lv.position}")
TODO("push address of array with PUSH_WORD")
TODO("push address of array with PUSH_ADDR_HEAPVAR")
}
else -> throw CompilerException("weird datatype")
}
@ -1013,7 +1011,7 @@ internal class Compiler(private val rootModule: Module,
// (in reversed order) otherwise the asm-subroutine can't be used in expressions.
for(rv in subroutine.asmReturnvaluesRegisters.reversed()) {
if(rv.statusflag!=null)
TODO("not yet supported: return values in cpu status flag $rv $subroutine")
TODO("not yet supported: return values in cpu status flag $rv ($subroutine)")
when(rv.registerOrPair) {
A,X,Y -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = rv.registerOrPair.name)
AX -> prog.instr(Opcode.PUSH_REGAX_WORD)

View File

@ -362,14 +362,13 @@ Operators
.. todo::
address-of: ``#`` or ``&`` (to stay close to C)
Takes the address of the symbol following it: ``word address = &somevar``
Takes the address of the symbol following it: ``word address = &somevar``
Perhaps requires an explicit pointer type as well instead of just word?
This can replace the ``memory`` var decl prefix as well, instead of
``memory uword var = $c000`` we could write ``&uword var = $c000``
arithmetic: ``+`` ``-`` ``*`` ``/`` ``**`` ``%``
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
``/`` is division (will result in integer division when using on integer operands, and a floating point division when at least one of the operands is a float)
@ -436,10 +435,20 @@ You call a subroutine like this::
[ result = ] subroutinename_or_address ( [argument...] )
; example:
resultvariable = subroutine ( arg1, arg2, arg3 )
resultvariable = subroutine(arg1, arg2, arg3)
Arguments are separated by commas. The argument list can also be empty if the subroutine
takes no parameters.
takes no parameters. If the subroutine returns a value, you can still omit the assignment to
a result variable (but the compiler will warn you about discarding the result of the call).
Normal subroutines can only return zero or one return values.
However, the special ``asmsub`` routines (implemented in assembly code or referencing
a routine in kernel ROM) can return more than one return values, for instance a status
in the carry bit and a number in A, or a 16-bit value in A/Y registers.
Only for these kind of subroutines it is possible to write a multi value assignment to
store the resulting values::
var1, var2, var3 = asmsubroutine()

View File

@ -6,14 +6,26 @@
; @todo see problem in looplabelproblem.p8
sub start() {
for ubyte i in "hello\n" {
c64.CHROUT(i)
}
str text = "hello"
ubyte ub1
ubyte ub2
ubyte ub3
ubyte ub4
ubyte ub5
for ubyte j in [1,2,3,4,5] {
c64scr.print_ub(j)
c64.CHROUT('\n')
}
ub1, ub2, ub3, ub4, ub5 = test()
}
sub test1() -> ubyte {
return 99
}
asmsub test() -> clobbers() -> (ubyte @Pc, ubyte @Pz, ubyte @Pn, ubyte @Pv, ubyte @A) {
%asm {{
lda #99
sec
rts
}}
}
}