From 52649a8e4f6a16b4b8fab1559a80b519cf27b571 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 8 Mar 2024 01:56:35 +0100 Subject: [PATCH] conv routines now return the string buffer address. --- compiler/res/prog8lib/conv.p8 | 212 ++++++++++-------- compiler/res/prog8lib/cx16/diskio.p8 | 3 +- compiler/res/prog8lib/diskio.p8 | 3 +- compiler/res/prog8lib/virtual/conv.p8 | 30 ++- compiler/res/prog8lib/virtual/textio.p8 | 30 +-- .../compiler/astprocessing/AstChecker.kt | 4 +- docs/source/todo.rst | 9 +- examples/cx16/automatons.p8 | 9 +- examples/cx16/bobs.p8 | 10 +- examples/cx16/cobramk3-gfx.p8 | 8 +- 10 files changed, 171 insertions(+), 147 deletions(-) diff --git a/compiler/res/prog8lib/conv.p8 b/compiler/res/prog8lib/conv.p8 index 00a26f62e..131aec67b 100644 --- a/compiler/res/prog8lib/conv.p8 +++ b/compiler/res/prog8lib/conv.p8 @@ -8,27 +8,29 @@ conv { str @shared string_out = "????????????????" ; result buffer for the string conversion routines -asmsub str_ub0 (ubyte value @ A) clobbers(A,X,Y) { +asmsub str_ub0 (ubyte value @ A) clobbers(X) -> str @AY { ; ---- convert the ubyte in A in decimal string form, with left padding 0s (3 positions total) %asm {{ - jsr conv.ubyte2decimal - sty string_out - sta string_out+1 - stx string_out+2 - lda #0 - sta string_out+3 - rts + jsr conv.ubyte2decimal + sty string_out + sta string_out+1 + stx string_out+2 + lda #0 + sta string_out+3 + lda #string_out + rts }} } -asmsub str_ub (ubyte value @ A) clobbers(A,X,Y) { +asmsub str_ub (ubyte value @ A) clobbers(X) -> str @AY { ; ---- convert the ubyte in A in decimal string form, without left padding 0s %asm {{ ldy #0 sty P8ZP_SCRATCH_B1 jsr conv.ubyte2decimal _output_byte_digits - ; hundreds? + ; hundreds? cpy #'0' beq + pha @@ -39,50 +41,54 @@ _output_byte_digits inc P8ZP_SCRATCH_B1 ; tens? + ldy P8ZP_SCRATCH_B1 - cmp #'0' + cmp #'0' beq + sta string_out,y iny -+ ; ones. - txa - sta string_out,y - iny - lda #0 - sta string_out,y - rts ++ ; ones. + txa + sta string_out,y + iny + lda #0 + sta string_out,y + lda #string_out + rts }} } -asmsub str_b (byte value @ A) clobbers(A,X,Y) { +asmsub str_b (byte value @ A) clobbers(X) -> str @AY { ; ---- convert the byte in A in decimal string form, without left padding 0s %asm {{ - ldy #0 - sty P8ZP_SCRATCH_B1 - cmp #0 - bpl + - pha - lda #'-' - sta string_out - inc P8ZP_SCRATCH_B1 - pla + ldy #0 + sty P8ZP_SCRATCH_B1 + cmp #0 + bpl + + pha + lda #'-' + sta string_out + inc P8ZP_SCRATCH_B1 + pla + jsr conv.byte2decimal - bra str_ub._output_byte_digits + bra str_ub._output_byte_digits }} } -asmsub str_ubhex (ubyte value @ A) clobbers(A,X,Y) { +asmsub str_ubhex (ubyte value @ A) clobbers(X) -> str @AY { ; ---- convert the ubyte in A in hex string form %asm {{ - jsr conv.ubyte2hex - sta string_out - sty string_out+1 - lda #0 - sta string_out+2 - rts + jsr conv.ubyte2hex + sta string_out + sty string_out+1 + lda #0 + sta string_out+2 + lda #string_out + rts }} } -asmsub str_ubbin (ubyte value @ A) clobbers(A,X,Y) { +asmsub str_ubbin (ubyte value @ A) clobbers(X) -> str @AY { ; ---- convert the ubyte in A in binary string form %asm {{ sta P8ZP_SCRATCH_B1 @@ -90,18 +96,20 @@ asmsub str_ubbin (ubyte value @ A) clobbers(A,X,Y) { sty string_out+8 ldy #7 - lsr P8ZP_SCRATCH_B1 - bcc + - lda #'1' - bne _digit -+ lda #'0' -_digit sta string_out,y - dey + bcc + + lda #'1' + bne _digit ++ lda #'0' +_digit sta string_out,y + dey bpl - + lda #string_out rts }} } -asmsub str_uwbin (uword value @ AY) clobbers(A,X,Y) { +asmsub str_uwbin (uword value @ AY) clobbers(X) -> str @AY { ; ---- convert the uword in A/Y in binary string form %asm {{ sta P8ZP_SCRATCH_REG @@ -111,79 +119,88 @@ asmsub str_uwbin (uword value @ AY) clobbers(A,X,Y) { sty string_out+16 ldy #7 - lsr P8ZP_SCRATCH_REG - bcc + - lda #'1' - bne _digit -+ lda #'0' -_digit sta string_out+8,y - dey + bcc + + lda #'1' + bne _digit ++ lda #'0' +_digit sta string_out+8,y + dey bpl - + lda #string_out rts }} } -asmsub str_uwhex (uword value @ AY) clobbers(A,Y) { +asmsub str_uwhex (uword value @ AY) -> str @AY { ; ---- convert the uword in A/Y in hexadecimal string form (4 digits) %asm {{ - pha - tya - jsr conv.ubyte2hex - sta string_out - sty string_out+1 - pla - jsr conv.ubyte2hex - sta string_out+2 - sty string_out+3 - lda #0 - sta string_out+4 - rts + pha + tya + jsr conv.ubyte2hex + sta string_out + sty string_out+1 + pla + jsr conv.ubyte2hex + sta string_out+2 + sty string_out+3 + lda #0 + sta string_out+4 + lda #string_out + rts }} } -asmsub str_uw0 (uword value @ AY) clobbers(A,X,Y) { +asmsub str_uw0 (uword value @ AY) clobbers(X) -> str @AY { ; ---- convert the uword in A/Y in decimal string form, with left padding 0s (5 positions total) %asm {{ jsr conv.uword2decimal ldy #0 -- lda conv.uword2decimal.decTenThousands,y - sta string_out,y - beq + - iny - bne - -+ rts +- lda conv.uword2decimal.decTenThousands,y + sta string_out,y + beq + + iny + bne - ++ + lda #string_out + rts }} } -asmsub str_uw (uword value @ AY) clobbers(A,X,Y) { +asmsub str_uw (uword value @ AY) clobbers(X) -> str @AY { ; ---- convert the uword in A/Y in decimal string form, without left padding 0s %asm {{ jsr conv.uword2decimal ldx #0 _output_digits ldy #0 -- lda conv.uword2decimal.decTenThousands,y - beq _allzero - cmp #'0' - bne _gotdigit - iny - bne - +- lda conv.uword2decimal.decTenThousands,y + beq _allzero + cmp #'0' + bne _gotdigit + iny + bne - _gotdigit sta string_out,x - inx - iny - lda conv.uword2decimal.decTenThousands,y - bne _gotdigit -_end lda #0 - sta string_out,x - rts + inx + iny + lda conv.uword2decimal.decTenThousands,y + bne _gotdigit +_end lda #0 + sta string_out,x + lda #string_out + rts _allzero lda #'0' - sta string_out,x - inx - bne _end + sta string_out,x + inx + bne _end }} } -asmsub str_w (word value @ AY) clobbers(A,X,Y) { +asmsub str_w (word value @ AY) clobbers(X) -> str @AY { ; ---- convert the (signed) word in A/Y in decimal string form, without left padding 0's %asm {{ cpy #0 @@ -191,18 +208,19 @@ asmsub str_w (word value @ AY) clobbers(A,X,Y) { pha lda #'-' sta string_out - tya - eor #255 - tay - pla - eor #255 - clc - adc #1 - bcc + - iny + tya + eor #255 + tay + pla + eor #255 + clc + adc #1 + bcc + + iny + jsr conv.uword2decimal ldx #1 bne str_uw._output_digits + rts }} } diff --git a/compiler/res/prog8lib/cx16/diskio.p8 b/compiler/res/prog8lib/cx16/diskio.p8 index 8d01af034..82054046a 100644 --- a/compiler/res/prog8lib/cx16/diskio.p8 +++ b/compiler/res/prog8lib/cx16/diskio.p8 @@ -493,8 +493,7 @@ no_mciout: str device_not_present_error = "device not present #xx" if cbm.READST()==128 { device_not_present_error[len(device_not_present_error)-2] = 0 - conv.str_ub(drivenumber) - void string.copy(conv.string_out, &device_not_present_error+len(device_not_present_error)-2) + void string.copy(conv.str_ub(drivenumber), &device_not_present_error+len(device_not_present_error)-2) return device_not_present_error } diff --git a/compiler/res/prog8lib/diskio.p8 b/compiler/res/prog8lib/diskio.p8 index 76163a437..d70b69ef6 100644 --- a/compiler/res/prog8lib/diskio.p8 +++ b/compiler/res/prog8lib/diskio.p8 @@ -429,8 +429,7 @@ _end rts str device_not_present_error = "device not present #xx" if cbm.READST()==128 { device_not_present_error[len(device_not_present_error)-2] = 0 - conv.str_ub(drivenumber) - void string.copy(conv.string_out, &device_not_present_error+len(device_not_present_error)-2) + void string.copy(conv.str_ub(drivenumber), &device_not_present_error+len(device_not_present_error)-2) return device_not_present_error } uword messageptr = &list_filename diff --git a/compiler/res/prog8lib/virtual/conv.p8 b/compiler/res/prog8lib/virtual/conv.p8 index bcda7477c..f8a95bbb4 100644 --- a/compiler/res/prog8lib/virtual/conv.p8 +++ b/compiler/res/prog8lib/virtual/conv.p8 @@ -8,7 +8,7 @@ conv { str string_out = "????????????????" ; result buffer for the string conversion routines -sub str_ub0(ubyte value) { +sub str_ub0(ubyte value) -> str { ; ---- convert the ubyte in A in decimal string form, with left padding 0s (3 positions total) ubyte hundreds = value / 100 value -= hundreds*100 @@ -18,14 +18,16 @@ sub str_ub0(ubyte value) { string_out[1] = tens+'0' string_out[2] = value+'0' string_out[3] = 0 + return string_out } -sub str_ub(ubyte value) { +sub str_ub(ubyte value) -> str { ; ---- convert the ubyte in A in decimal string form, without left padding 0s internal_str_ub(value, string_out) + return string_out } -sub str_b(byte value) { +sub str_b(byte value) -> str { ; ---- convert the byte in A in decimal string form, without left padding 0s uword out_ptr = &string_out if value<0 { @@ -34,6 +36,7 @@ sub str_b(byte value) { value = -value } internal_str_ub(value as ubyte, out_ptr) + return string_out } sub internal_str_ub(ubyte value, uword out_ptr) { @@ -60,14 +63,15 @@ output_ones: str hex_digits = "0123456789abcdef" -sub str_ubhex (ubyte value) { +sub str_ubhex (ubyte value) -> str { ; ---- convert the ubyte in A in hex string form string_out[0] = hex_digits[value>>4] string_out[1] = hex_digits[value&15] string_out[2] = 0 + return string_out } -sub str_ubbin (ubyte value) { +sub str_ubbin (ubyte value) -> str { ; ---- convert the ubyte in A in binary string form uword out_ptr = &string_out repeat 8 { @@ -79,9 +83,10 @@ sub str_ubbin (ubyte value) { out_ptr++ } @(out_ptr) = 0 + return string_out } -sub str_uwbin (uword value) { +sub str_uwbin (uword value) -> str { ; ---- convert the uword in A/Y in binary string form uword out_ptr = &string_out repeat 16 { @@ -93,9 +98,10 @@ sub str_uwbin (uword value) { out_ptr++ } @(out_ptr) = 0 + return string_out } -sub str_uwhex (uword value) { +sub str_uwhex (uword value) -> str { ; ---- convert the uword in A/Y in hexadecimal string form (4 digits) ubyte bits = msb(value) string_out[0] = hex_digits[bits>>4] @@ -104,9 +110,10 @@ sub str_uwhex (uword value) { string_out[2] = hex_digits[bits>>4] string_out[3] = hex_digits[bits&15] string_out[4] = 0 + return string_out } -sub str_uw0 (uword value) { +sub str_uw0 (uword value) -> str { ; ---- convert the uword in A/Y in decimal string form, with left padding 0s (5 positions total) uword value2 = value/10 ubyte digits = value-value2*10 as ubyte @@ -124,14 +131,16 @@ sub str_uw0 (uword value) { string_out[3] = tens+'0' string_out[4] = digits+'0' string_out[5] = 0 + return string_out } -sub str_uw (uword value) { +sub str_uw (uword value) -> str { ; ---- convert the uword in A/Y in decimal string form, without left padding 0s internal_str_uw(value, string_out) + return string_out } -sub str_w (word value) { +sub str_w (word value) -> str { ; ---- convert the (signed) word in A/Y in decimal string form, without left padding 0's uword out_ptr = &string_out if value<0 { @@ -140,6 +149,7 @@ sub str_w (word value) { value = -value } internal_str_uw(value as uword, out_ptr) + return string_out } sub internal_str_uw(uword value, uword out_ptr) { diff --git a/compiler/res/prog8lib/virtual/textio.p8 b/compiler/res/prog8lib/virtual/textio.p8 index 61560bb13..fd505bdc4 100644 --- a/compiler/res/prog8lib/virtual/textio.p8 +++ b/compiler/res/prog8lib/virtual/textio.p8 @@ -61,70 +61,60 @@ sub print (str text) { sub print_ub0 (ubyte value) { ; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total) - conv.str_ub0(value) - print(conv.string_out) + print(conv.str_ub0(value)) } sub print_ub (ubyte value) { ; ---- print the ubyte in decimal form, without left padding 0s - conv.str_ub(value) - print(conv.string_out) + print(conv.str_ub(value)) } sub print_b (byte value) { ; ---- print the byte in decimal form, without left padding 0s - conv.str_b(value) - print(conv.string_out) + print(conv.str_b(value)) } sub print_ubhex (ubyte value, ubyte prefix) { ; ---- print the ubyte in hex form if prefix chrout('$') - conv.str_ubhex(value) - print(conv.string_out) + print(conv.str_ubhex(value)) } sub print_ubbin (ubyte value, ubyte prefix) { ; ---- print the ubyte in binary form if prefix chrout('%') - conv.str_ubbin(value) - print(conv.string_out) + print(conv.str_ubbin(value)) } sub print_uwbin (uword value, ubyte prefix) { ; ---- print the uword in binary form if prefix chrout('%') - conv.str_uwbin(value) - print(conv.string_out) + print(conv.str_uwbin(value)) } sub print_uwhex (uword value, ubyte prefix) { ; ---- print the uword in hexadecimal form (4 digits) if prefix chrout('$') - conv.str_uwhex(value) - print(conv.string_out) + print(conv.str_uwhex(value)) } sub print_uw0 (uword value) { ; ---- print the uword value in decimal form, with left padding 0s (5 positions total) - conv.str_uw0(value) - print(conv.string_out) + print(conv.str_uw0(value)) } sub print_uw (uword value) { ; ---- print the uword in decimal form, without left padding 0s - conv.str_uw(value) - print(conv.string_out) + print(conv.str_uw(value)) } sub print_w (word value) { ; ---- print the (signed) word in decimal form, without left padding 0's - conv.str_w(value) - print(conv.string_out) + print(conv.str_w(value)) } sub input_chars (uword buffer) -> ubyte { diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 2e4b68765..7cd2ca855 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -179,7 +179,9 @@ internal class AstChecker(private val program: Program, } val iterableDt = forLoop.iterable.inferType(program).getOr(DataType.BYTE) - if(iterableDt !in IterableDatatypes && forLoop.iterable !is RangeExpression) { + if(forLoop.iterable is IFunctionCall) { + errors.err("can not loop over function call return value", forLoop.position) + } else if(iterableDt !in IterableDatatypes && forLoop.iterable !is RangeExpression) { errors.err("can only loop over an iterable type", forLoop.position) } else { val loopvar = forLoop.loopVar.targetVarDecl(program) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 693cf831a..abaae28b4 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,10 @@ TODO ==== +add a zsmkit example (next to zsound example) + +fix compiler crash for for cx16.r9L in conv.str_ub(number) {...} : can't iterate over class prog8.code.ast.PtFunctionCall - should have been replaced by a variable + ... @@ -26,14 +30,14 @@ Compiler: - OR.... make all this more generic and use some %segment option to create real segments for 64tass? - (need separate step in codegen and IR to write the "golden" variables) +- VM: implement more diskio support - do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block? -- VM: implement diskio support (let's start with the basics load, save, delete, rename, status?. no streaming, no directory listing) - ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really +- ir: fix call() return value handling - ir: proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg - ir: idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype) global initialization values are simply a list of LOAD instructions. Variables replaced include all subroutine parameters! So the only variables that remain as variables are arrays and strings. -- ir: fix call() return value handling - ir: add more optimizations in IRPeepholeOptimizer - ir: the @split arrays are currently also split in _lsb/_msb arrays in the IR, and operations take multiple (byte) instructions that may lead to verbose and slow operation and machine code generation down the line. maybe another representation is needed once actual codegeneration is done from the IR...? @@ -51,7 +55,6 @@ Compiler: Libraries: - gfx2: add EOR mode support like in monogfx and see PAINT for inspiration. Self modifying code to keep it optimized? -- conv: the routines could return the address of conv.string_out, and/or there could be versions that take the address of a different buffer and use it instead. - once kernal rom v47 is released, remove most of the workarounds in cx16 floats.parse_f() . Prototype parse routine in examples/cx16/floatparse.p8 - fix the problems in atari target, and flesh out its libraries. - c128 target: make syslib more complete (missing kernal routines)? diff --git a/examples/cx16/automatons.p8 b/examples/cx16/automatons.p8 index 73bcdbe44..179fe7b48 100644 --- a/examples/cx16/automatons.p8 +++ b/examples/cx16/automatons.p8 @@ -55,10 +55,11 @@ main { for cx16.r9L in "Cellular Automaton #" { cx16.GRAPH_put_next_char(cx16.r9L) } - conv.str_ub(number) - for cx16.r9L in conv.string_out { - cx16.GRAPH_put_next_char(cx16.r9L) - } + uword num_str = conv.str_ub(number) + do { + cx16.GRAPH_put_next_char(@(num_str)) + num_str++ + } until @(num_str)==0 } bool[8] states diff --git a/examples/cx16/bobs.p8 b/examples/cx16/bobs.p8 index 668a4d455..41de842c9 100644 --- a/examples/cx16/bobs.p8 +++ b/examples/cx16/bobs.p8 @@ -179,8 +179,8 @@ main { uword vmem = vmembase * 2048 ; mkword(vmembase,0) * 8 ubyte bank = vmembase>=32 vmem += 35 - conv.str_uw0(number) - uword pixelsptr = &numberpixels + (conv.string_out[1] & 15)*7 + uword number_str = conv.str_uw0(number) + uword pixelsptr = &numberpixels + (number_str[1] & 15)*7 ubyte pix cx16.VERA_CTRL = 0 cx16.VERA_ADDR_L = lsb(vmem) @@ -191,19 +191,19 @@ main { vmem++ cx16.VERA_ADDR_L = lsb(vmem) cx16.VERA_ADDR_M = msb(vmem) - pixelsptr = &numberpixels + (conv.string_out[2] & 15)*7 + pixelsptr = &numberpixels + (number_str[2] & 15)*7 for pix in 0 to 6 cx16.VERA_DATA0 = pixelsptr[pix] vmem++ cx16.VERA_ADDR_L = lsb(vmem) cx16.VERA_ADDR_M = msb(vmem) - pixelsptr = &numberpixels + (conv.string_out[3] & 15)*7 + pixelsptr = &numberpixels + (number_str[3] & 15)*7 for pix in 0 to 6 cx16.VERA_DATA0 = pixelsptr[pix] vmem++ cx16.VERA_ADDR_L = lsb(vmem) cx16.VERA_ADDR_M = msb(vmem) - pixelsptr = &numberpixels + (conv.string_out[4] & 15)*7 + pixelsptr = &numberpixels + (number_str[4] & 15)*7 for pix in 0 to 6 cx16.VERA_DATA0 = pixelsptr[pix] } diff --git a/examples/cx16/cobramk3-gfx.p8 b/examples/cx16/cobramk3-gfx.p8 index a3afd8ed0..72ea31b87 100644 --- a/examples/cx16/cobramk3-gfx.p8 +++ b/examples/cx16/cobramk3-gfx.p8 @@ -60,9 +60,11 @@ main { } sub print_number_gfx(ubyte num) { - conv.str_ub(num) - for cx16.r9L in conv.string_out - cx16.GRAPH_put_next_char(cx16.r9L) + uword num_str = conv.str_ub(num) + do { + cx16.GRAPH_put_next_char(@(num_str)) + num_str++ + } until @(num_str)==0 } const uword screen_width = 320