mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
improve ast check for multiple returnvalues assignment
This commit is contained in:
parent
1e5b2e0be3
commit
747c9604dd
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user