|
Forum Index : Microcontroller and PC projects : PicoMite MMbasic V7.00.00 betas:
| Author | Message | ||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
Video https://github.com/UKTailwind/PicoMite/releases/tag/PicoMite-V7.0.00b1 Beta 1 (V7.0.00b1). Version 7 makes MMBasic faster on every board, and on the RP2350 it adds a compiler that runs most of a program as native code while leaving it exactly as you wrote it. You do not change your program to use it: switch it on, type RUN, and whatever the compiler can take runs compiled while the rest runs as before. Please run your own programs on this beta, first as they are and then (on an RP2350) compiled, and report anything that behaves differently, anything that fails, and anything that is slower than you expected. MM.VER reads 7.000001. Most boards are reset when they first boot this beta. Back up first. Every build except PicoMiteRP2040 has moved its flash region (see Memory and flash layout). On the first boot the options return to their defaults, saved variables and the three flash slots are erased, program memory is cleared and the A: drive is reformatted. Copy anything on A: to an SD card or your PC, and save your settings so you can put them back: OPTION DISK SAVE "B:/myoptions.txt" then after upgrading, OPTION DISK LOAD "B:/myoptions.txt". Save it to B:, not A:. A PicoComputer 3 configures itself again at the first boot, but its CPU speed and any options you set by hand need re-issuing. A board using a preset (OPTION RESET name) can simply be given the preset again. PicoMiteRP2040 coming from 6.04.00 RC2 keeps its settings and its A: drive. What to test 1. Your programs, as they are. The interpreter has changed underneath on every board (names are now stored as symbols, and local variables live on a stack), so run what you have and report any difference in output, any error that was not there before, and any program that has become slower. 2. On an RP2350: the same programs compiled. Type OPTION COMPILE ON at the command prompt and RUN. The output must be exactly what the interpreter gives. Tell us about any difference, and about programs whose speed-up seems poor: Seeing how much of a program runs compiled below shows how to find out why, and the answer tells us what to compile next. 3. If you can, once with OPTION COMPILE SHADOW. It runs the program compiled and checks every compiled value against the interpreter, stopping at the first line where they disagree. That line is exactly what we need. When you report, please give the build (the banner line or MM.DEVICE$), what OPTION COMPILE was set to, what PRINT MM.INFO(COMPILE) says after the run, and if possible the program. A note for timing comparisons: on the RP2350, RND reseeds itself from the hardware random number generator every 100 draws, so RANDOMIZE n does not repeat a sequence (this is not new). A program whose amount of work depends on RND does a different amount each run, so compare the time per unit of work (per frame, per point drawn) rather than the time for a whole run. Faster on every board Names are stored as symbols. When a program is saved, every variable, SUB, FUNCTION and label name becomes a two or three byte symbol, and the interpreter finds what a symbol refers to directly instead of searching for the name each time. LIST and EDIT show every name exactly as you typed it, and a program saved to a file is plain text as before. OPTION SYMBOLS OFF (a testing switch, not saved) saves programs without symbols, for comparing the two; it also stops the compiler, which needs them. Local variables live on a stack. A SUB or FUNCTION's parameters and LOCAL variables are made on entry and dropped on exit without searching or tidying a table, and each SUB's parameter list is read once rather than on every call. Calling a SUB or FUNCTION costs much less than it did: loops of calls are 12% to 39% quicker on a PicoComputer 3 and 17% to 55% on an RP2040. LOCAL strings and arrays are made faster when the heap is full: finding room for them no longer walks past every block already in use. Measured on an RP2040 PicoMiteVGA at 378 MHz, compared with V6.03.01: +----------------------------------------+----------+-----------------+----------------+ | program | V6.03.01 | V7.0.00b1 | | +========================================+==========+=================+================+ | PETSCII Robots, time to update a frame | 64.7 ms | 54.6 ms | 16% less | | Solar eclipse | 28 s | just under 23 s | about 18% less | +----------------------------------------+----------+-----------------+----------------+ The compiler (RP2350) Using it OPTION COMPILE ON ' compile at the next RUN OPTION COMPILE SHADOW ' compile, and check every compiled value against the interpreter OPTION COMPILE OFF ' interpret only (the default) Type it at the command prompt; it takes effect at the next RUN, and it is saved with the other options, so it stays in force after a restart until you change it. OPTION LIST shows it when it is ON or SHADOW, and OPTION DISK SAVE and OPTION DISK LOAD carry it. At RUN the firmware compiles the program, and its library if there is one, into a stream of native operations held apart from the program. It compiles only when the program or library has changed since the last compile, so the first RUN after an edit takes a moment longer (about 0.3 s for a 110 KB program on a PicoComputer 3) and later runs start as quickly as the interpreter. Statements the compiler cannot take stay in the stream as references to your text and run on the interpreter, interleaved with the compiled ones, so a program never has to be entirely compilable to benefit. Nothing about the program changes: LIST, EDIT, SAVE, error messages and line numbers, TRACE, ON ERROR, interrupts, CHAIN and libraries all behave as before. A program runs entirely as text when: • it was saved without symbols (OPTION SYMBOLS OFF): MM.INFO(COMPILE) says TEXT: saved without symbols; • its stream would not fit the space kept for it: TEXT: too big for the slot (n of m bytes). A stream is typically 1.4 to 3 times the size of the program (Exile 1.44, PETSCII Robots 1.72, the reference benchmark 1.85, Elite 2.87), and the space kept is three times the maximum program size, so every program that fits in memory should compile. Checking a program with SHADOW OPTION COMPILE SHADOW runs the program compiled, and wherever the compiler has worked out a value - the right-hand side of an assignment, an IF or ELSEIF condition, a DO or LOOP condition, a BOX/LINE/PIXEL/COLOUR argument - it works it out again with the interpreter and compares the two. If they differ in any bit the program stops at that line: [120] y = a * Sin(t) + b Error : SHADOW: compiled 3.5, text 3.25 It is slower than ON, since every checked value is worked out twice, and switching between ON and SHADOW recompiles at the next RUN. A statement that calls a user FUNCTION or uses RND is not checked, because the interpreter would make the call again or draw another random number. If a program behaves differently under OPTION COMPILE ON, running it under SHADOW is the quickest way to find where. Known differences from the interpreter • If a FUNCTION ERASEs a variable that the statement calling it goes on to use after the call, the interpreter quietly makes the variable again; a compiled statement stops with A FUNCTION changed a variable of this statement. A FUNCTION that erases or creates other variables is fine. • If a FUNCTION changes OPTION DEFAULT while another untyped FUNCTION is still to be called in the same statement, the statement stops with OPTION DEFAULT changed by a FUNCTION in this statement. • Programs run faster, so a program that relies on how long its statements take (a delay loop rather than PAUSE) will run differently. Speed Times as text and compiled on the same board and firmware (PicoComputer 3, RP2350 at 378 MHz; the first two with the HDMIUSB build, the rest with HDMIWEB): +------------------------------------------------+-------------+----------+------+ | program | interpreted | compiled | | +================================================+=============+==========+======+ | landscape (untyped FUNCTION in the inner loop) | 78.5 s | 21 s | 3.7x | | torus (nested loops, IF and PIXEL) | 40.5 s | 7.8 s | 5.2x | | galaxy (SIN/COS per point), per point | 255 us | 80 us | 3.2x | | reference benchmark | 15.4 s | 7.1 s | 2.2x | | Elite, per frame | 22.6 ms | 11.0 ms | 2.1x | | Prince of Persia port, per frame | 9.7 ms | 6.7 ms | 1.4x | | PETSCII Robots, frame update | 36.0 ms | 23.4 ms | 1.5x | +------------------------------------------------+-------------+----------+------+ Where the gain is smaller, the time goes on work the compiler cannot make faster: the maths library (a SIN or a ^ costs the same compiled or not), the drawing itself, and statements that are not compiled yet. In the galaxy program, once compiled, about a quarter of the time is in SIN, COS, LOG and ^, and a fifth in PIXEL. Where the stream is kept, and memory • With PSRAM the stream is kept in the part of PSRAM the firmware already reserves, above the five RAM slots. None of your PSRAM heap or RAM slots is used, and it is lost at power-off (the next RUN compiles again). • Without PSRAM it is kept in a hidden area of flash straight after the program, three program sizes long. It is rewritten only when the program has changed since its last compile, so an edit-and-run costs one erase of it, as saving the program already does. This area is why the A: drive is smaller on the RP2350 builds (see Memory and flash layout). • The compiler borrows some temporary memory while it compiles and returns it before the program starts; while the program runs it uses none of the heap. It does not reduce how deeply SUBs and FUNCTIONs can recurse: compiled code recurses as deep as the interpreter or deeper. What compiles Anything not listed here runs on the interpreter exactly as before. A statement that the compiler cannot take in full runs as text as a whole; the statements around it are still compiled. Statements assignment (LET, or name = ...) compiled when: the target is a numeric or string variable or a numeric array element, and the right-hand side is an expression the compiler takes (below) runs as text: a string array element, a structure member, a whole-array assignment IF ... THEN ... [ELSE ...] ENDIF, ELSEIF compiled when: multi-line, with any number of ELSEIF arms single-line IF ... THEN ... [ELSE ...] compiled when: the parts after THEN and ELSE are assignments; or, with no ELSE, the part after THEN is any statement (which then runs compiled or not on its own merits) runs as text: IF ... THEN GOTO, THEN followed by a line number, an ELSE whose parts are not assignments FOR ... TO ... [STEP ...], NEXT compiled when: the loop variable is a numeric variable runs as text: a user FUNCTION call in the start, limit or step DO [WHILE / UNTIL ...], LOOP [WHILE / UNTIL ...] runs as text: a user FUNCTION call in the condition SELECT CASE, CASE, CASE ELSE, END SELECT compiled when: the selector is numeric; CASE values, ranges (a TO b) and IS comparisons runs as text: a string selector EXIT FOR, EXIT DO, CONTINUE FOR runs as text: CONTINUE DO calling a SUB compiled when: up to 16 parameters; each argument a numeric expression or a variable (passed by reference) runs as text: a CSUB, a string, array or structure argument, an array element or a FUNCTION call as an argument, BYREF with an expression RETURN, END SUB, EXIT SUB, END FUNCTION, EXIT FUNCTION LOCAL [AS type] name [, name ...] runs as text: an initial value, an array, LENGTH INC var [, value] compiled when: a numeric variable or array element, or a string variable runs as text: a string array element BOX, LINE, PIXEL, COLOUR (COLOR) compiled when: every argument is an expression the compiler takes runs as text: LINE PLOT, LINE GRAPH, LINE AA; a user FUNCTION call in an argument; LINE and PIXEL under OPTION LEGACY ENDIF, END SELECT, DATA, comments, labels compiled when: (passed over) Not compiled, among others: PRINT, INPUT, GOTO, GOSUB, ON ... GOTO, DIM, STATIC, CONST, READ, ERASE, TEXT, CIRCLE, CLS, BLIT, SPRITE, PAUSE, file and pin commands. The variables they create are used by compiled statements like any others. Expressions • Operators: + - * /, \, MOD, ^ (when the left operand is a float), = <> < > <= >=, AND OR XOR, NOT, INV, <<, >>, unary - and +; + and the comparisons on strings. An integer ^ runs as text. • Literals: decimal numbers, hexadecimal, octal and binary numbers (&HFF, &O17, &B101), and strings of up to 64 characters with no backslash. • Variables: integer, float and string variables, global or local, including parameters, STATIC variables and constants; numeric array elements of any number of dimensions, with any expression as the index. Not string arrays or structure members. • Built-in functions: SIN COS TAN ATN SQR EXP LOG DEG RAD INT FIX ABS SGN PI RND; LEN ASC CHR$ MID$ STR$ SPACE$ LEFT$ RIGHT$ UCASE$ LCASE$ HEX$ OCT$ BIN$; INSTR with two strings or a start position and two strings; TRIM$ with one or two arguments; RGB(r, g, b) and RGB(name); MAP(n). These follow OPTION ANGLE and give the same errors as the interpreter. An argument may not call a user FUNCTION or be left empty. Not compiled: VAL, STRING$, MIN, MAX, CINT, ACOS, ASIN, ATAN2, TIMER, INKEY$, PEEK, PIN, MM. values and the rest. • User FUNCTIONs: any number of calls in an assignment, an IF or ELSEIF condition or an INC value, including calls inside another call's arguments. The FUNCTION must return a number: typed (As Integer, As Float, or a suffix) or untyped, when it takes the type OPTION DEFAULT gives it (float unless the program sets another). Arguments as for a SUB call. Not a FUNCTION returning a string or an array. New variables A variable that does not exist yet is made by the interpreter, as always: the first time a statement that makes it runs, that statement runs as text, and it is compiled from then on. A single-line IF is not held back by a variable that only its THEN or ELSE part uses: IF k$ = "q" THEN quit = 1 runs compiled on every pass, and only the pass that first sets quit runs as text. Seeing how much of a program runs compiled MM.INFO(COMPILE) says what the last RUN did. Print it at the end of the program, or type PRINT MM.INFO(COMPILE) at the prompt afterwards: COMPILED 3 REUSED 1 STMTS 3227 RAN 714382 MISS 25707 CODE 680945 SIZE 132348 OF 966656 +-----------------------+------------------------------------------------------------------------------------+ | field | meaning | +=======================+====================================================================================+ | COMPILED n / REUSED n | how many compiles, and how many runs that found the stream already compiled, since | | | power-on. At the prompt the word is NONE instead of COMPILED. | +-----------------------+------------------------------------------------------------------------------------+ | STMTS n | statements in the stream | +-----------------------+------------------------------------------------------------------------------------+ | RAN n | statements the last run executed through the stream | +-----------------------+------------------------------------------------------------------------------------+ | CODE n | how many of those ran as compiled code | +-----------------------+------------------------------------------------------------------------------------+ | MISS n | internal: lookups of where to go next | +-----------------------+------------------------------------------------------------------------------------+ | SIZE n OF m | bytes of stream, of the space kept for it | +-----------------------+------------------------------------------------------------------------------------+ CODE divided by RAN is the share of the work done compiled: 680945 of 714382 is 95% here. It can also say OFF, or TEXT: and a reason (above). OPTION PROFILING ON shows which statements ran as text. Put it as the program's first line (it must be in the program: RUN clears it), make sure the program finishes with END (the report is printed by END, not when a program runs off its last line or is stopped with Ctrl-C), and run it with OPTION COMPILE ON: [PERF] elapsed=61247333 us statements=772063 findvar=... user_subs=46912 local_peak=19/192 [PERF] top commands by dispatch count: 325725 Static 323875 Loop 56082 Blit Memory 2172 FRAMEBUFFER [PERF] top SUBs by exclusive (self) time: self_us incl_us calls self_us/call name 7444555 7444555 719 10354 writeworld_n With the compiler on, statements and the top commands list count only the statements that ran as text, so the list is exactly what is left uncompiled, command by command, busiest first. The SUB table shows where the time goes, so you can tell whether what is left is in a busy SUB or in start-up code. local_peak is the most local variables alive at once, of the number available. OPTION PROFILING ON, SAMPLE also samples where the processor is, and END adds the busiest lines: [PCSLINE] 29 4011 [PCSLINE] 23 3318 The first number is the line number, as the editor and error messages show it (-1 for a line in the library); the second is how many samples landed on it. Together with the command list this points at the lines worth changing, or worth telling us about. A typical session: > OPTION COMPILE ON > RUN ... the program, which starts with OPTION PROFILING ON and ends with END ... > PRINT MM.INFO(COMPILE) A warning when the stack runs low When a program has taken the stack to within 1 KB of its limit, the next command prompt shows Warning: the stack came within 536 bytes of its limit, at depth 12 where the depth is how many SUBs and FUNCTIONs were running. Deep recursion is the usual cause: a simple recursive FUNCTION reaches about 13 levels on an RP2350 and 9 on an RP2040 before Stack overflow, much as in 6.04.00. None of the programs we test with (the reference programs, Exile, Elite, the Prince of Persia port, PETSCII Robots and a corpus of 224 test programs) comes near it; if one of yours shows the warning, please send it to us. Fixed since 6.04.00 RC2 • RP2350 with PSRAM (a PicoComputer 3, for example): the board could stop with a hard fault, usually at the command prompt, after a program used WS2812 or BITSTREAM, or after anything that writes flash (saving a program, writing a file on A:, changing an option). Before each of these the firmware tidied the processor's cache in a way that the RP2350's erratum E11 turns into wrong reads of the firmware's own code. On a PicoComputer 3 a short WS2812 test faulted about one run in three; with the fix it ran 240 times without one. • RP2350 with PSRAM: writing or closing a file on A: could throw away data a program had just stored in PSRAM (a large array or string could lose its most recent changes). • OPTION LOCAL VARIABLES stayed in force after the program that set it had ended, so the next program ran with its split and could run out of global variables. RUN, NEW and LOAD put it back to the default; CHAIN keeps it for the chained program. • An expression passed to a BYVAL parameter (Inner 5, x()) could be refused with Array as BYVAL not allowed when an unrelated local array happened to occupy the first slot of the variable table. Passing a whole array BYVAL is still refused, and an array element is still accepted. • A float subtraction that overflows (1e308 - (-1e308)) stops with the same error as addition and multiplication, instead of giving INF. • LIBRARY LOAD refuses a library too big for its flash slot. The size check could never fire, so a library whose text outgrew the slot would have been written over program memory. Memory and flash layout Flash. Every build except PicoMiteRP2040 has moved its flash region since 6.04.00 RC2, so the first boot is the full reset described at the top. On the RP2350 builds the A: drive is smaller, mostly because of the stream's flash area (three program sizes, needed on boards without PSRAM); on a 4 MB board it keeps between 1.1 and 1.9 MB. The RP2040 builds lose 16 KB of A: or nothing. +----------------------+-----------+------------------+------------------+----------------+----------------+ | build | flash | maximum program | MMBasic heap | A: drive | locals / | | | region | | | | globals | +======================+===========+==================+==================+================+================+ | PicoMiteRP2040 | unchanged | 120 KB | 128 KB | unchanged | 240 / 256 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2040USB | moved | 120 KB | 124 KB | 16 KB smaller | 240 / 256 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2040MIN | moved | 112 KB (was 116) | 128 KB | same place and | 240 / 256 | | | | | | size | | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2040VGA | moved | 100 KB | 100 KB | 16 KB smaller | 240 / 240 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2040VGAUSB | moved | 96 KB | 96 KB | 16 KB smaller | 240 / 240 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | WebMiteRP2040 | moved | 88 KB | 88 KB | 16 KB smaller | 192 / 240 (was | | | | | | | 240 / 240) | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2350 | moved | 208 KB (was 300) | 300 KB | 288 KB smaller | 192 / 576 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2350USB | moved | 208 KB (was 296) | 296 KB | 320 KB smaller | 192 / 576 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2350BT | moved | 208 KB (was 272) | 272 KB | 416 KB smaller | 192 / 576 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2350BTH | moved | 208 KB (was 256) | 256 KB | 480 KB smaller | 192 / 576 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | WebMiteRP2350 | moved | 208 KB (was 256) | 248 KB (was 256) | 480 KB smaller | 192 / 576 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2350VGA | moved | 168 KB | 168 KB | 552 KB smaller | 192 / 544 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteRP2350VGAUSB | moved | 160 KB | 160 KB | 512 KB smaller | 192 / 544 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteHDMI | moved | 156 KB (was 160) | 156 KB (was 160) | 500 KB smaller | 192 / 544 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteHDMIUSB | moved | 148 KB (was 152) | 148 KB (was 152) | 460 KB smaller | 192 / 544 | +----------------------+-----------+------------------+------------------+----------------+----------------+ | PicoMiteHDMIWEB | moved | 144 KB | 144 KB | 480 KB smaller | 192 / 544 | +----------------------+-----------+------------------+------------------+----------------+----------------+ Program size. Five RP2350 builds now take programs of up to 208 KB rather than their heap size: the PSRAM reserve has to hold the five RAM slots and three program sizes of stream. The heap itself is unchanged except where the table says. On the HDMI and HDMIUSB builds, 4 KB of heap went to the variable table below, and the maximum program size follows the heap there. Local variables. Since locals live on a stack, the local region only needs to hold the most locals alive at once, not a hash table's slack. Real programs use far fewer than the space kept: the most we have measured is 125 (the reference benchmark); Exile 56, Elite and the Prince of Persia port about 44, PETSCII Robots 19. The RP2350 builds keep 192 local entries and have 64 more globals than before, so the total is the same or larger. The RP2040 builds keep RC2's 240 locals, except the WebMite, which has the RAM for 192. OPTION LOCAL VARIABLES moves the split as before, and now returns to the default at RUN, NEW and LOAD rather than staying in force for the next program (CHAIN keeps it). local_peak in the OPTION PROFILING report shows what a program actually uses. |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 6143 |
@Peter, On 2040VGA there is a language compatibility issue. TEXT x,y,"hello",C worked in 60300 in 70000 the C needs to be a "C". Found in start of Petscii Robots (controler config screen) After correction : The screen update is much faster. Volhout Edited 2026-09-30 21:08 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
If that is the only bug I'll be very happy. This is a huge change to the code. Note to everyone: OPTION TRACECACHE is removed. It was never very effective and the compiler is much more powerful and needs no user changes. A CSUB for really important code will still be faster and the mmb2csub script is still available and works as before. |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 6143 |
Hi Peter, Some quick feedback on 2040VGA V70000. Below programs run on V60302. 1/ The above issue with TEXT is in many programs (Blocks, Frogger, etc...) 2/ A tuned version of your RP2040VGA bad apple demo claims it has not enough memory to play WAV. Another version plays. Maybe an "edge" issue. 3/ ChessClient does not work since BOARD variable fails: BOARD is a reserved word? 4/ LogicAnalyzer : create ring buffer fails "not enough aligned memory". I thought memory map was identical. Apparently not on RAM. 5/ Rocks defines its own font (FONT #10). But the font is not found. Volhout Thursday evening I could look at 2040MIN on Game*Mite. Edited 2026-09-30 22:04 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
Could you point me at the programs or post them for me (or email) - thanks |
||||
| hhtg1968 Senior Member Joined: 25/05/2023 Location: GermanyPosts: 228 |
wow! i will intensively test this. most of my programs will be speeded up. my ecological simulation an my prime counter runs at a factor about 3-8! very, very cool |
||||
| terekgabor Senior Member Joined: 02/01/2026 Location: HungaryPosts: 139 |
Wow! No words Peter! I will test it a lot! Congrats again and again and again! G@bor |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
Volhout 1,4 and 5 are fixed in my dev environment. I really need the code for 3 and the version that fails for 2 to proceed |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1779 |
Hi Peter I had been wondering what you were working on. Great result. I really welcome the decision to bump the version number! Tests to follow. Regards Michael |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 6143 |
Hi Peter, Issue 2: Attached the MMbasic program. Do you also need the audio and video files, or do you still have these on your PC ? It's 10Mbyte... Issue 3: I think this is not about a reserved keyword BOARD, but the fac that there is a string variable called "board$" and a SUB called BOARD. It has not been a problem up to now. But not nice. badapple_mather_2040_tweaked.zip Regards, Volhout P.S. The ChessClient needs a second pico on UART GP4/5 with compiled TSCP to run. Edited 2026-09-30 23:58 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
This should have always been a bug and was on the rp2350 but the check on the rp2040 itself had a bug. It is a bug on the MM2 and every other (bug free) version of MMbasic so this will need you to change your code From the MM2 codebase // now scan the sub/fun table to make sure that there is not a sub/fun with the same name if(!(action & V_FUNCT)) { // don't do this if we are defining the local variable for a function name for(i = 0; i < MAXSUBFUN && subfun[i] != NULL; i++) { x = subfun[i]; // point to the command token x++; skipspace(x); // point to the identifier s = name; // point to the new variable if(*s != toupper(*x)) continue; // quick first test while(1) { if(!isnamechar(*s) && !isnamechar(*x)) error("A sub/fun has the same name: $", name); if(*s != toupper(*x) || *s == 0 || !isnamechar(*x) || s - name >= MAXVARLEN) break; s++; x++; } } } Edited 2026-10-01 00:33 by matherp |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1779 |
@Peter A question for clarification: DO [WHILE / UNTIL ...], LOOP [WHILE / UNTIL ...] runs as text: a user FUNCTION call in the condition Is "DO UNTIL" allowed now? ( I never understood why it was sometimes forbidden but sometimes worked anyway.) |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
Check the manual |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1779 |
Hmm, that (PicoMite, User Manual, MMBasic BASIC interpreter, version 7.0.00) looks unchanged. That means "do UNTIL" is still not allowed... Very regrettable! A follow-up question (since you're in a talkative mood) I recently tried out "Gosub" (I think for the first time in 40 years). Is it correct that Gosubs and their associated subroutines are only allowed within the main program and not within regular subroutines (Subs)? I couldn't find any information on this in the manual. I actually wanted to say that I found the behavior unexpected. Edited 2026-10-01 01:51 by twofingers |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11923 |
V7.00.00b2 is now available athttps://github.com/UKTailwind/PicoMite/releases/tag/PicoMite-V7.0.00b2 The optimisations in V7 use memory - nothing is free. Programs that run tight against the available memory of a specific firmware variant may not run under V7. To overcome this include the line OPTION SYMBOLS OFF as the first line in a program. It will then run without some of the optimisation but memory usage should be very similar to previous versions. ## Fixed since beta 1 - `TEXT x, y, s$, C` and the other justifications written without quotes (`CM`, `RB` and so on) work in a program again, as they do at the command prompt; beta 1 stored the letters as a name and the text came out unjustified. `GUI CAPTION` had the same problem. - A font defined with `DefineFont` in a program was not found when the program ran (`FONT #10` gave an error). - `PIO MAKE RING BUFFER` in a program could fail with `Not enough aligned memory` on an RP2040 PicoMiteVGA although the memory was free: the search for an aligned block now tries every boundary, and the heap now starts on a 256-byte boundary at the start of RAM. - `PLAY WAV` with a file that is not 16-bit PCM (8-bit, 24-bit, floating point, A-law or mu-law) took 4 KB of free memory for every refill of its buffers, so with little memory left it stopped with `Not enough memory for 4096 bytes`, or the sound stopped part way through the file with no error. It now takes 512 bytes, with no audible difference. - A program containing a statement that is just a one-letter name (a call to `SUB a`, say) could not be saved when names were stored as text, and the board then stopped responding. It now saves and runs. - More generally, an error while a program was being written to flash left the board unresponsive part way through printing the message, while the display kept running. The message is now printed and the prompt returns. - When a program runs out of memory for a request that the symbol tables could have covered, the error message now says how to get it back: `Not enough memory for 1920 bytes: put OPTION SYMBOLS OFF first`. - The manual's command list was missing `DO UNTIL condition ... LOOP` and `LOOP WHILE`; both have always worked. A program that uses the same name for a variable and a SUB or FUNCTION stops with `A sub/fun has the same name` on an RP2040, as it always has on the RP2350 and on the original MMBasic. This came in 6.04.00 RC2: before that the check never fired on the RP2040, so such a program may have run there. Rename one of the two. |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1779 |
?? I must have overlooked this: Although - I can't prove it - I seem to recall (for >v6) getting error messages with "Do Until" in some cases that made it necessary to replace it with "Do While Not" [...]. I'm pleased, but still skeptical ... Thanks for this useful addition! |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2026 |