! ================================================================
    ! SUPER TINY BASIC INTERPRETER VERSION 1.0
    ! ================================================================
    ! A complete BASIC interpreter implementation built with Hobby BASIC
    ! Optimized for Windows 11 Console
    ! See LICENCE.TXT for Hobby BASIC and Super Tiny BASIC terms of use
    !
    ! About the name — why "Super Tiny BASIC"
    ! Tiny BASIC historically referred to extremely small BASIC interpreters
    ! that could fit in ~4 KB of memory. Super Tiny BASIC keeps the nostalgic
    ! spirit (single-letter variables, single-line IF, simple loops and I/O)
    ! while providing a more practical, feature-friendly environment implemented
    ! in Hobby BASIC. It's not the 4 KB minimalist implementation — it's a
    ! playful, lightweight, and hackable interpreter inspired by that tradition.
    !
    ! Full source code and example programs included in the EXAMPLES\TINY folder.
    !
    ! Features:
    ! - BASIC commands: LET, PRINT, INPUT, IF-THEN-ELSE, FOR-NEXT, WHILE-WEND,
    !   GOSUB-RETURN, REM, CLS, WAIT, END, LOCATE, COLOR, INKEY
    ! - Numeric variables: Single letters A-Z only (e.g., A, B, X)
    ! - Expression parser: Arithmetic (+, -, *, /, %), comparison (=, <>, <, >, <=, >=),
    !   and logical operators (AND, OR) with proper precedence
    ! - Built-in functions:
    !     * RND()    - Returns random integer
    !     * CHR(n)   - Returns character with specified ASCII code (in PRINT statements)
    ! - Comprehensive error handling with detailed error messages
    ! - File operations: LOAD and SAVE programs to disk
    ! - Console control: LOCATE (set cursor position), COLOR (set colors), CLS (clear screen),
    !   WAIT (delay)
    ! - INKEY command with two modes:
    !     * Standalone: INKEY (stores key info in variables I, J, K)
    !     * Assignment: A=INKEY (stores key value in specified variable)
    ! - Multi-statement lines using colon (:) separator
    ! - String literals supported in PRINT and INPUT statements (e.g., PRINT "HELLO")
    ! - Automatic uppercase conversion for keywords and variables outside of string literals
    ! - Program editing: Line number-based entry and deletion
    !
    ! Example Programs Included:
    !   STRESS.BAS    - Comprehensive language test
    !   ADVANCED.BAS  - Complex expressions test
    !   MEGATEST.BAS  - Multi-category test suite
    !   MANUAL.BAS    - Language examples guide
    !   100LINES.BAS  - Compact code test
    !   GUESSNUM.BAS  - Number guessing game
    !   COINFLIP.BAS  - Coin toss game
    !   CODEBREAK.BAS - Code breaking puzzle
    !   HORSERACE.BAS - Horse racing game
    !   FOREST.BAS    - Text adventure game
    !
    ! This interpreter demonstrates the power of Hobby BASIC for
    ! creating complex console applications while maintaining the
    ! simplicity and readability of classic BASIC syntax.
    ! ================================================================

    ! Set current directory to TINY examples folder
    path$ = RIGHT(PATH(2), -3) + "\EXAMPLES\"
    FILE(path$, 4)

    ! Initialize console environment
    view 11
    screen 80, 40, 9999
    title "Super Tiny BASIC Ιnterpreter Version 1.0"
    cursor 1
    color 0, 7
    cls

    ! Predefined character sets for fast INSET() validation
    ! INSET() is faster than ASCII range checks
    DIGITS$ = "0123456789"
    LETTERS$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

    ! Program storage arrays
    MAX_LINES = 10000
    dim prog$[MAX_LINES]     ! Array for program lines
    dim prog_num[MAX_LINES]  ! Array for line numbers
    dim vars[26]             ! Variables A-Z

    ! FOR-NEXT loop management arrays
    dim loop_var$[10]        ! Stack for loop variable names
    dim loop_end[10]         ! Stack for loop end values
    dim loop_step[10]        ! Stack for loop step values
    dim loop_pc[10]          ! Stack for program counters
    loop_count = 0           ! Active loop counter

    ! GOSUB-RETURN stack management
    dim gosub_stack[20]      ! Return address stack
    gosub_sp = 0             ! Stack pointer

    ! WHILE-WEND loop management
    dim while_pc[20]         ! WHILE statement positions
    dim while_conditions$[20]! WHILE conditions
    while_count = 0          ! Active WHILE loop counter

    ! Display program header and instructions
    print "=== Super Tiny BASIC Interpreter ==="
    print "Optimized for Windows 11 Console"
    print "Built with Hobby BASIC"
    print
    print "-------------------------------------------------"
    print "Commands available:"
    print "  LOAD <file.bas>   - Load a program (e.g., LOAD FOREST.BAS)"
    print "  SAVE <file.bas>   - Save current program to file"
    print "  RUN               - Run the loaded program"
    print "  LIST              - Show program listing"
    print "  NEW               - Clear program from memory"
    print "  CLS               - Clear the screen"
    print ""
    print "Enter program lines directly to build your code."
    print "-------------------------------------------------"
    print

! ================================================================
! MAIN INPUT LOOP
! Handles user commands and program line entry
! ================================================================
input_loop#
    line$ = ""
    input "> ", line$

    ! Convert to uppercase outside of strings
    line$ = TRIM(0, ucase_outside_strings(line$))

    ! Handle empty input
    if LEN(line$) = 0 then goto input_loop

    ! Process interpreter commands
    if LEFT(line$, 4) = "LOAD"
        gosub load_command
        goto input_loop
    elseif LEFT(line$, 4) = "SAVE"
        gosub save_command
        goto input_loop
    elseif line$ = "CLS"
        color 0, 7 : cls
        goto input_loop
    elseif line$ = "LIST"
        execute_flag = 0
        goto program_listing
    elseif line$ = "RUN"
        execute_flag = 1
        goto program_listing
    elseif line$ = "NEW"
        line_count = 0
        print "Program cleared."
        goto input_loop
    endif

    ! Handle line deletion (empty line after line number)
    space_pos = FIND(line$, " ")
    if space_pos = 0
        line_num= VAL(TRIM(0, line$))

        if line_num < 1 or line_num > MAX_LINES
            print "Syntax Error: Line must start with a number (1-", MAX_LINES, ")"
            goto input_loop
        endif

        ! Find and delete the specified line
        existing_line_index = -1
        for i = 0 to line_count - 1
            if prog_num[i] = line_num
                existing_line_index = i
                break
            endif
        next

        if existing_line_index >= 0
            ! Shift array elements to remove the line
            for i = existing_line_index to line_count - 2
                prog_num[i] = prog_num[i + 1]
                prog$[i] = prog$[i + 1]
            next
            line_count--
            print "Line ", line_num, " deleted"
        else
            print "Line ", line_num, " not found"
        endif
        goto input_loop
    endif

    ! Extract line number from input
    line_num$ = TRIM(0, LEFT(line$, space_pos - 1))
    line_num = VAL(line_num$)

    if line_num < 1 or line_num > MAX_LINES
        print "Syntax Error: Invalid line number '", TRIM(0, line_num$), "'"
        goto input_loop
    endif

    ! Check if line number already exists
    existing_line_index = -1
    for i = 0 to line_count - 1
        if prog_num[i] = line_num
            existing_line_index = i
            break
        endif
    next

    ! Replace existing line or add new line
    if existing_line_index >= 0
        prog$[existing_line_index] = line$
        print "Line ", line_num, " replaced"
    else
        ! Check if program storage is full
        if line_count >= MAX_LINES
            print "Program storage full."
            goto program_listing
        endif

        ! Add new line to program
        prog_num[line_count] = line_num
        prog$[line_count] = line$
        line_count++
    endif

    goto input_loop

! ================================================================
! LOAD COMMAND SUBROUTINE
! Loads a BASIC program from file
! ================================================================
load_command#
    path$ = TRIM(0, MID(line$, 5, LEN(line$) - 4))

    ! Load file contents
    load path$, source$
    if V0 = -1
        print "Load error: File not found or cannot be read"
    else
        ! Clear current program
        line_count = 0

        ! Split file content into lines
        dim lines$[MAX_LINES].ZERO
        num_lines = split(source$, CHR(10), lines$[])

        ! Process each line
        for i = 0 to num_lines - 1
            current_line$ = TRIM(0, ucase_outside_strings(lines$[i]))

            if LEN(current_line$) > 0
                space_pos = FIND(current_line$, " ")
                if space_pos > 0
                    line_num = VAL(TRIM(0, LEFT(current_line$, space_pos - 1)))

                    ! Validate line number and add to program (allow 1..MAX_LINES)
                    if line_num >= 1 and line_num <= MAX_LINES
                        prog_num[line_count] = line_num
                        prog$[line_count] = current_line$
                        line_count++
                    endif
                endif
            endif
        next
        print "Program loaded: ", path$, " (", num_lines, " lines)"
        print "Type LIST to view or RUN to execute"
    endif
    return

! ================================================================
! SAVE COMMAND SUBROUTINE
! Saves the current program to a file
! ================================================================
save_command#
    save_part$ = TRIM(1, MID(line$, 5, LEN(line$) - 4))
    path$ = TRIM(0, save_part$)

    ! Build program source from lines
    source$ = ""
    for i = 0 to line_count - 1
        source$ = source$ + prog$[i] + EOL$
    next

    ! Save to file
    save path$, source$
    if V0 = -1
        print "Save error: Cannot write to file"
    else
        print "Program saved: ", path$, " (", line_count, " lines)"
    endif
    return

! ================================================================
! PROGRAM LISTING AND EXECUTION
! Handles both program display and execution
! ================================================================
program_listing#
    ! Sort program lines by line number (bubble sort)
    for i = 0 to line_count - 2
        for j = i + 1 to line_count - 1
            if prog_num[i] > prog_num[j]
                swap prog_num[i], prog_num[j]
                swap prog$[i], prog$[j]
            endif
        next
    next

    ! Display program listing if not in execute mode
    if not execute_flag
        print
        print "--- Program Listing ---"
        for i = 0 to line_count - 1
            print prog$[i]
            if i % 10 = 0 and KEY(27) then break
            wait 1
        next
        print "--- End of Listing ---"
        print
        goto input_loop
    endif

    ! Execute program
    print
    print "--- Running Program ---"

    ! Create line number to index mapping for faster GOTO/GOSUB
    dim line_map[MAX_LINES].FILL -1

    for i = 0 to line_count - 1
        if prog_num[i] >= 1 and prog_num[i] <= MAX_LINES
            line_map[prog_num[i]] = i
        endif
    next

    ! Main program execution loop
    pc = 0
    dim cmd_list$[100]
    fatal_error = 0

    while pc < line_count and not fatal_error
        current_line$ = prog$[pc]

        ! Search for space character
        space_pos = 0
        for i = 1 to LEN(current_line$)
            if MID(current_line$, i, 1) = " "
                space_pos = i
                break
            endif
        next

        if space_pos = 0
            ! Check if line contains only a valid line number
            line_num = VAL(current_line$)
            if line_num >= 0
                pc++  ! Skip to next line if only line number
            else
                print "Syntax Error in line: ", current_line$
                pc++
            endif
        else
            ! Extract line number and commands
            line_num = VAL(LEFT(current_line$, space_pos))
            commands$ = TRIM(1, MID(current_line$, space_pos + 1, LEN(current_line$) - space_pos))

            ! Split multiple commands on same line (separated by colons)
            cmd_list$[].ZERO
            num_cmds = split_commands(commands$, ":", byref cmd_list$[])
            jump_occurred = 0

            ! Execute each command in sequence
            for i = 0 to num_cmds - 1
                if jump_occurred then break
                command$ = TRIM(0, cmd_list$[i])
                if LEN(command$) > 0
                    jump_occurred = execute_command(command$, byref pc, line_map[])
                    if fatal_error then break
                endif
            next

            ! Move to next line if no jump occurred
            if not jump_occurred
                pc++
            endif
        endif
    endw

! ================================================================
! PROGRAM END HANDLING
! Set text color and print program termination message
! Wait for key press
! Restore current directory to the program's original folder
! ================================================================
program_end#
    color 0, 7
    print "--- Program Finished ---"
    inkey
    end

! ================================================================
! UCASE OUTSIDE STRINGS FUNCTION
! Converts characters to uppercase and replaces tabs with spaces,
! but preserves case and tabs inside strings
! ================================================================
sub ucase_outside_strings(s$)
    local result$ = s$
    local i, in_string = 0

    for i = 0 to LEN(s$)-1
        if result$(i) = CHR(34)          ! Check for quote
            in_string = 1 - in_string    ! Toggle string mode
        elseif not in_string
            result$(i) = UCASE(result$(i))  ! Convert to uppercase
            if result$(i) = CHR(9) then result$(i)  = CHR(32) ! Replace tab with spaces
        endif
    next

    rets result$
ends

! ================================================================
! DISPLAY_ERROR SUBROUTINE
! Displays error message with line number
! ================================================================
sub display_error(msg$)
    color 0, 7
    print : print "[", line_num, "] ", msg$
    fatal_error = 1
    rets
ends

! ================================================================
! SPLIT COMMANDS FUNCTION
! Splits commands separated by colons, respecting strings and comments,
! and keeps entire IF ... THEN ... ELSE ... as a single command.
! ================================================================
sub split_commands(commands$, separator$, result$[])
    local in_string = 0      ! Track if we're inside a string
    local in_rem = 0         ! Track if we're inside a REM comment
    local current_cmd$ = ""  ! Current command being built
    local count = 0          ! Number of commands found
    local i, char$, look$

    for i = 0 to LEN(commands$)-1
        char$ = commands$(i)

        ! If we're inside a REM comment, add all characters
        if in_rem
            current_cmd$ = current_cmd$ + char$

        ! Handle string literals
        elseif char$ = CHR(34)
            in_string = 1 - in_string
            current_cmd$ = current_cmd$ + char$

        ! Check for REM comments outside strings
        elseif not in_string and not in_rem and MID(commands$, i, 3) = "REM"
            in_rem = 1
            current_cmd$ = current_cmd$ + char$

        ! Handle command separators outside strings and comments
        elseif char$ = separator$ and not in_string and not in_rem
            ! If the command built so far starts with IF, do NOT split here.
            ! This keeps the whole IF ... THEN ... ELSE ... (even with colons) as one command.
            look$ = TRIM(0, current_cmd$)
            if LEN(look$) >= 2 and LEFT(look$, 2) = "IF"
                current_cmd$ = current_cmd$ + char$    ! treat ':' as normal char inside IF
            else
                result$[count] = TRIM(0, current_cmd$)
                count++
                current_cmd$ = ""
            endif

        ! Add regular characters
        else
            current_cmd$ = current_cmd$ + char$
        endif
    next

    ! Check for unclosed string at the end of parsing
    if in_string and not in_rem
        display_error("Syntax Error: Unclosed string in command")
        rets
    endif

    ! Add the last command if it exists
    if LEN(TRIM(0, current_cmd$)) > 0
        result$[count] = TRIM(0, current_cmd$)
        count++
    endif

    rets count
ends


! ================================================================
! EXECUTE COMMAND FUNCTION
! Main command dispatcher - handles all BASIC commands
! ================================================================
sub execute_command(cmd$, pc, line_map[])
    local result, jump_occurred
    local var_index, expr$

    result = 0
    jump_occurred = 0
    cmd$ = TRIM(0, cmd$)

    ! ============================================================
    ! LET COMMAND - Variable assignment
    ! ============================================================
    if LEFT(cmd$, 3) = "LET"
        local let_part$, eq_pos, var_name$

        ! Extract the part after LET
        let_part$ = TRIM(1, MID(cmd$, 4, LEN(cmd$) - 3))

        ! Find the equals sign
        eq_pos = FIND(let_part$, "=")

        if eq_pos = 0
            display_error("Syntax Error: Missing '=' in LET")
            rets
        else
            ! Extract variable name and expression
            var_name$ = TRIM(0, LEFT(let_part$, eq_pos - 1))
            expr$ = TRIM(1, MID(let_part$, eq_pos + 1, LEN(let_part$) - eq_pos))

            ! Check for INKEY assignment
            if expr$ = "INKEY"
                inkey
                var_index = ASC(var_name$) - 65
                vars[var_index] = V0
            else
                ! Validate variable name (A-Z)
                if LEN(var_name$) = 1 and INSET(var_name$, LETTERS$)
                    var_index = ASC(var_name$) - 65
                    vars[var_index] = eval_expr(expr$)
                else
                    display_error("Error: Invalid variable name '" + var_name$ + "'")
                    rets
                endif
            endif
        endif

    ! ============================================================
    ! PRINT COMMAND - Output to screen
    ! ============================================================
    elseif LEFT(cmd$, 5) = "PRINT"
        local print_part$
        print_part$ = TRIM(1, MID(cmd$, 6, LEN(cmd$) - 5))
        process_print(print_part$)

    ! ============================================================
    ! GOTO COMMAND - Unconditional jump
    ! Accepts line number expressions (e.g., GOTO X, GOTO X+10)
    ! ============================================================
    elseif LEFT(cmd$, 4) = "GOTO"
        local goto_part$, target_line

        ! Extract and evaluate target line expression
        goto_part$ = TRIM(1, MID(cmd$, 5, LEN(cmd$) - 4))
        target_line = eval_expr(goto_part$)

        ! Validate target line exists
        if target_line >= 1 and target_line <= MAX_LINES
            if line_map[target_line] < 0 then goto invalid_goto_target
            pc = line_map[target_line]
            jump_occurred = 1
        else
            invalid_goto_target#
            display_error("Error: Line " + STR(target_line) + " not found")
            rets
        endif


    ! ============================================================
    ! IF COMMAND - Conditional execution (robust THEN/ELSE matching)
    ! ============================================================
    elseif LEFT(cmd$, 2) = "IF"
        local if_part$, then_pos, else_pos, condition$, then_command$, else_command$
        local i, p, in_string, in_rem, nested_if, ch$, look$, prev_ch$

        if_part$ = TRIM(1, MID(cmd$, 3, LEN(cmd$) - 2))

        ! Find THEN position safely (respect strings and REM)
        then_pos = 0
        in_string = 0
        in_rem = 0

        for i = 1 to LEN(if_part$)
            ch$ = MID(if_part$, i, 1)

            ! Toggle string state when quote encountered (unless inside REM)
            if ch$ = CHR(34) and not in_rem
                in_string = 1 - in_string
            endif

            ! Start REM if we see REM outside strings
            if not in_string and not in_rem and MID(if_part$, i, 3) = "REM"
                in_rem = 1
            endif

            ! Detect THEN outside strings/comments with word-boundary check
            if not in_string and not in_rem and then_pos = 0
                look$ = MID(if_part$, i, 4)
                if look$ = "THEN"
                    ! ensure previous char is not a letter (word boundary)
                    if i = 1
                        then_pos = i
                    else
                        prev_ch$ = MID(if_part$, i-1, 1)
                        if not INSET(prev_ch$, LETTERS$)
                            then_pos = i
                        endif
                    endif
                endif
            endif

            if then_pos > 0 then break
        next

        if then_pos = 0
            display_error("Syntax Error: Missing THEN in IF")
            rets
        endif

        ! Extract condition (text before THEN)
        condition$ = TRIM(0, LEFT(if_part$, then_pos - 1))

        ! Find the matching ELSE for this IF (respect nested IFs)
        else_pos = 0
        nested_if = 0
        in_string = 0
        in_rem = 0
        p = then_pos + 4

        while p <= LEN(if_part$)
            ch$ = MID(if_part$, p, 1)

            ! Toggle string state
            if ch$ = CHR(34) and not in_rem
                in_string = 1 - in_string
            endif

            ! Start REM if encountered
            if not in_string and not in_rem and MID(if_part$, p, 3) = "REM"
                in_rem = 1
            endif

            if not in_string and not in_rem
                ! Look for IF to increment nesting
                look$ = MID(if_part$, p, 2)
                if look$ = "IF"
                    ! ensure previous char is not letter
                    ch$ = MID(if_part$, p-1, 1)
                    if p = 1 or not INSET(ch$, LETTERS$)
                        nested_if++
                        p++  ! advance a bit to avoid infinite loop
                        pass
                    endif
                endif

                ! Look for ELSE
                look$ = MID(if_part$, p, 4)
                if look$ = "ELSE"
                    ! ensure previous char is not letter
                    ch$ = MID(if_part$, p-1, 1)
                    if p = 1 or not INSET(ch$, LETTERS$)
                        if nested_if = 0
                            else_pos = p
                            break
                        else
                            nested_if--
                            p += 3
                            pass
                        endif
                    endif
                endif
            endif

            p++
        endw

        ! Extract then/else command strings
        if else_pos > 0
            then_command$ = TRIM(1, MID(if_part$, then_pos + 4, else_pos - then_pos - 4))
            else_command$ = TRIM(1, MID(if_part$, else_pos + 4, LEN(if_part$) - else_pos - 3))
        else
            then_command$ = TRIM(1, MID(if_part$, then_pos + 4, LEN(if_part$) - then_pos - 3))
            else_command$ = ""
        endif

        ! Evaluate condition
        cond_result = eval_expr(condition$)

        ! Execute appropriate branch: split branch on ':' and execute sub-commands
        if cond_result
            if LEN(then_command$) > 0
                local then_list$[64].ZERO
                num_then = split_commands(then_command$, ":", byref then_list$[])
                for t = 0 to num_then - 1
                    if jump_occurred then break
                    subcmd$ = TRIM(0, then_list$[t])
                    if LEN(subcmd$) > 0
                        jump_occurred = execute_command(subcmd$, byref pc, line_map[])
                        if fatal_error then break
                    endif
                next
            endif
        elseif else_command$ <> ""
            local else_list$[64].ZERO
            num_else = split_commands(else_command$, ":", byref else_list$[])
            for e = 0 to num_else - 1
                if jump_occurred then break
                subcmd$ = TRIM(0, else_list$[e])
                if LEN(subcmd$) > 0
                    jump_occurred = execute_command(subcmd$, byref pc, line_map[])
                    if fatal_error then break
                endif
            next
        endif

    ! ============================================================
    ! FOR COMMAND - Loop initialization
    ! ============================================================
    elseif LEFT(cmd$, 3) = "FOR"
        local for_part$, eq_pos, var_name$, rest$, to_pos, start_expr$, rest2$, step_pos, end_expr$, step_expr$
        local start_val, end_val, step_val

        for_part$ = TRIM(1, MID(cmd$, 4, LEN(cmd$) - 3))
        eq_pos = FIND(for_part$, "=")

        if eq_pos = 0
            display_error("Syntax Error: Missing '=' in FOR")
            rets
        endif

        ! Extract and validate variable name
        var_name$ = TRIM(0, LEFT(for_part$, eq_pos - 1))

        if LEN(var_name$) <> 1 or not INSET(var_name$, LETTERS$)
            display_error("Error: Invalid variable name in FOR")
            rets
        endif

        ! Parse loop parameters
        rest$ = TRIM(1, MID(for_part$, eq_pos + 1, LEN(for_part$) - eq_pos))
        to_pos = FIND(rest$, "TO")

        if to_pos = 0
            display_error("Syntax Error: Missing 'TO' in FOR")
            rets
        endif

        start_expr$ = TRIM(0, LEFT(rest$, to_pos - 1))
        rest2$ = TRIM(1, MID(rest$, to_pos + 2, LEN(rest$) - to_pos - 1))

        ! Check for optional STEP clause
        step_pos = FIND(rest2$, "STEP")

        if step_pos > 0
            end_expr$ = TRIM(0, LEFT(rest2$, step_pos - 1))
            step_expr$ = TRIM(1, MID(rest2$, step_pos + 4, LEN(rest2$) - step_pos - 3))
        else
            end_expr$ = rest2$
            step_expr$ = "1"
        endif

        ! Evaluate expressions
        start_val = eval_expr(start_expr$)
        end_val = eval_expr(end_expr$)
        step_val = eval_expr(step_expr$)

        ! Validate step value
        if step_val = 0
            display_error("Error: STEP value cannot be zero")
            rets
        endif

        ! Initialize loop variable
        var_index = ASC(var_name$) - 65
        vars[var_index] = start_val

        ! Validate loop body exists
        if pc + 1 >= line_count
            display_error("Error: No loop body after FOR")
            rets
        endif

        ! Check for maximum loop nesting
        if loop_count >= 10
            display_error("Error: Too many nested loops")
            rets
        endif

        ! Store loop information
        loop_var$[loop_count] = var_name$
        loop_end[loop_count] = end_val
        loop_step[loop_count] = step_val
        loop_pc[loop_count] = pc + 1
        loop_count++
        rets 0

    ! ============================================================
    ! NEXT COMMAND - Loop termination
    ! ============================================================
    elseif LEFT(cmd$, 4) = "NEXT"
        local next_part$, var_name$, step_val, current_val, end_val

        next_part$ = TRIM(1, MID(cmd$, 5, LEN(cmd$) - 4))

        ! Handle explicit or implicit variable name
        if LEN(next_part$) > 0
            var_name$ = TRIM(0, next_part$)

            ! Validate loop stack
            if loop_count = 0
                display_error("Error: NEXT without FOR")
                rets
            endif

            ! Validate variable matches current loop
            if var_name$ <> loop_var$[loop_count-1]
                display_error("Error: NEXT variable doesn't match FOR")
                rets
            endif
        else
            if loop_count = 0
                display_error("Error: NEXT without FOR")
                rets
            endif

            var_name$ = loop_var$[loop_count-1]
        endif

        ! Update loop variable
        var_index = ASC(var_name$) - 65
        vars[var_index] += loop_step[loop_count-1]

        ! Check loop condition
        step_val = loop_step[loop_count-1]
        current_val = vars[var_index]
        end_val = loop_end[loop_count-1]

        ! Continue or terminate loop based on step direction
        if step_val > 0
            if current_val <= end_val
                pc = loop_pc[loop_count-1]
                rets 1
            endif
        else
            if current_val >= end_val
                pc = loop_pc[loop_count-1]
                rets 1
            endif
        endif

        ! Loop finished - remove from stack
        loop_count--
        rets 0

    ! ============================================================
    ! WHILE COMMAND - Conditional loop start
    ! ============================================================
    elseif LEFT(cmd$, 5) = "WHILE"
        local while_condition$, condition_result, wend_found, temp_pc, depth, current_line$, space_pos, command$

        while_condition$ = TRIM(1, MID(cmd$, 6, LEN(cmd$) - 5))
        condition_result = eval_expr(while_condition$)

        if condition_result
            ! Condition true - store loop information
            if while_count >= 20
                display_error("Error: Too many nested WHILE loops")
                rets
            else
                while_pc[while_count] = pc
                while_count++
            endif
        else
            ! Condition false - skip to matching WEND
            wend_found = 0
            temp_pc = pc + 1
            depth = 1

            ! Search for matching WEND
            while temp_pc < line_count and not wend_found
                current_line$ = prog$[temp_pc]
                space_pos = FIND(current_line$, " ")

                if space_pos > 0
                    command$ = TRIM(1, MID(current_line$, space_pos + 1, LEN(current_line$) - space_pos))

                    ! Handle nested WHILE loops
                    if LEFT(command$, 5) = "WHILE"
                        depth++
                    elseif command$ = "WEND"
                        depth--

                        ! Found matching WEND
                        if depth = 0
                            wend_found = 1
                            pc = temp_pc + 1
                        endif
                    endif
                endif

                temp_pc++
            endw

            if not wend_found
                display_error("Error: WHILE without WEND")
                rets
            endif

            rets 1
        endif

    ! ============================================================
    ! WEND COMMAND - WHILE loop end
    ! ============================================================
    elseif cmd$ = "WEND"
        if while_count <= 0
            display_error("Error: WEND without WHILE")
            rets
        else
            ! Return to WHILE statement
            pc = while_pc[while_count - 1]
            while_count--
        endif

        rets 1

    ! ============================================================
    ! GOSUB COMMAND - Subroutine call
    ! Accepts a line number expression (e.g., GOSUB X, GOSUB X*2)
    ! ============================================================
    elseif LEFT(cmd$, 5) = "GOSUB"
        local gosub_part$, target_line

        ! Extract and evaluate target line expression
        gosub_part$ = TRIM(1, MID(cmd$, 6, LEN(cmd$) - 5))
        target_line = eval_expr(gosub_part$)

        ! Validate target line exists
        if target_line >= 1 and target_line <= MAX_LINES
            if line_map[target_line] < 0 then goto invalid_gosub_target

            ! Check stack overflow
            if gosub_sp >= 20
                display_error("Error: GOSUB stack overflow")
                rets
            endif

            ! Push return address and jump to subroutine
            gosub_stack[gosub_sp] = pc + 1
            gosub_sp++
            pc = line_map[target_line]
            rets 1
        else
            invalid_gosub_target#
            display_error("Error: Line " + STR(target_line) + " not found")
            rets
        endif

    ! ============================================================
    ! RETURN COMMAND - Subroutine return
    ! ============================================================
    elseif cmd$ = "RETURN"
        if gosub_sp <= 0
            display_error("Error: RETURN without GOSUB")
            rets
        else
            ! Pop return address from stack
            gosub_sp--
            pc = gosub_stack[gosub_sp]
            rets 1
        endif

    ! ============================================================
    ! LOCATE COMMAND - Set cursor position
    ! ============================================================
    elseif LEFT(cmd$, 6) = "LOCATE"
        local locate_part$, comma_pos, x_str$, y_str$

        locate_part$ = TRIM(1, MID(cmd$, 7, LEN(cmd$) - 6))
        comma_pos = FIND(locate_part$, ",")

        if comma_pos > 0
            ! Extract and validate coordinates
            x_str$ = TRIM(0, LEFT(locate_part$, comma_pos - 1))
            y_str$ = TRIM(0, MID(locate_part$, comma_pos + 1, LEN(locate_part$) - comma_pos))
            locate eval_expr(x_str$), eval_expr(y_str$)
        else
            display_error("Syntax Error: LOCATE requires two parameters (X,Y)")
            rets
        endif

    ! ============================================================
    ! COLOR COMMAND - Set text and background colors
    ! ============================================================
    elseif LEFT(cmd$, 5) = "COLOR"
        local color_part$, comma_pos, bg_str$, fg_str$

        color_part$ = TRIM(1, MID(cmd$, 6, LEN(cmd$) - 5))
        comma_pos = FIND(color_part$, ",")

        if comma_pos > 0
            ! Extract and validate color values
            bg_str$ = TRIM(0, LEFT(color_part$, comma_pos - 1))
            fg_str$ = TRIM(0, MID(color_part$, comma_pos + 1, LEN(color_part$) - comma_pos))
            color eval_expr(bg_str$), eval_expr(fg_str$)
        else
            display_error("Syntax Error: COLOR requires two parameters (background,foreground)")
            rets
        endif

    ! ============================================================
    ! INKEY COMMAND - Keyboard input with variable assignment
    ! ============================================================
    elseif RIGHT(cmd$, 5) = "INKEY" and FIND(cmd$, "=") > 0
        local eq_pos, var_name$

        eq_pos = FIND(cmd$, "=")
        var_name$ = TRIM(0, LEFT(cmd$, eq_pos - 1))

        ! Validate variable name
        if LEN(var_name$) = 1 and INSET(var_name$, LETTERS$)
            inkey
            var_index = ASC(var_name$) - 65
            vars[var_index] = V0
        else
            display_error("Error: Invalid variable name for INKEY")
            rets
        endif

    ! ============================================================
    ! INKEY COMMAND (standalone) - Keyboard input
    ! ============================================================
    elseif cmd$ = "INKEY"
        inkey
        ! Store key info in variables I, J, K
        vars[8] = V0
        vars[9] = V1
        vars[10] = V2

    ! ============================================================
    ! REM COMMAND - Comment (no operation)
    ! ============================================================
    elseif LEFT(cmd$, 3) = "REM"
        rets

    ! ============================================================
    ! INPUT COMMAND - User input
    ! ============================================================
    elseif LEFT(cmd$, 5) = "INPUT"
        local input_part$
        input_part$ = TRIM(1, MID(cmd$, 6, LEN(cmd$) - 5))
        process_input(input_part$)

    ! ============================================================
    ! CLS COMMAND - Clear screen
    ! ============================================================
    elseif cmd$ = "CLS"
        color 0, 7
        cls

    ! ============================================================
    ! WAIT COMMAND - Delay execution
    ! ============================================================
    elseif LEFT(cmd$, 4) = "WAIT"
        local wait_part$
        wait_part$ = TRIM(1, MID(cmd$, 5, LEN(cmd$) - 4))
        wait VAL(wait_part$)

    ! ============================================================
    ! END COMMAND - Program termination
    ! ============================================================
    elseif cmd$ = "END"
        print
        print "Program ended"
        goto program_end

    ! ============================================================
    ! UNKNOWN COMMAND - Error handling
    ! ============================================================
    else
        display_error("Unknown command: " + cmd$)
        goto program_end
    endif

    rets jump_occurred
ends

! ================================================================
! PROCESS PRINT FUNCTION
! Handles PRINT command formatting and output
! ================================================================
sub process_print(print_args$)
    local dim args$[30]     ! Array for print arguments
    local dim sep_type[30]  ! Array for separator types
    local num_args = 0      ! Number of arguments
    local in_string = 0     ! String mode flag
    local current_arg$ = "" ! Current argument being built
    local i, char$, temp$, pos, chr_result, expr$, rem_pos, depth

    ! Remove REM comments from print arguments, but ignore REM inside strings
    rem_pos = 0
    in_string = 0
    for i = 0 to LEN(print_args$)-1

        ! Toggle string mode on quotes
        if print_args$(i) = CHR(34)
            in_string = 1 - in_string
        endif

        ! If we find REM outside a string, record position and stop
        if not in_string and i + 2 <= LEN(print_args$) and MID(print_args$, i, 3) = "REM"
            rem_pos = i
            break
        endif
    next

    if rem_pos > 0
        print_args$ = LEFT(print_args$, rem_pos - 1)
    endif

    print_args$ = TRIM(0, print_args$)

    ! Handle empty PRINT command
    if LEN(print_args$) = 0 or print_args$ = "PRINT"
        print
        rets
    endif

    ! Parse print arguments
    i = 1
    while i <= LEN(print_args$)
        char$ = MID(print_args$, i, 1)

        ! Handle string literals
        if in_string
            current_arg$ = current_arg$ + char$
            if char$ = CHR(34)  ! Quote character
                in_string = 0
            endif
            i++
        else
            ! Start of string literal
            if char$ = CHR(34)  ! Quote character
                current_arg$ = current_arg$ + char$
                in_string = 1
                i++

            ! Handle CHR() function calls
            elseif MID(print_args$, i, 4) = "CHR("
                ! Optimized CHR() processing with character caching
                pos = i + 4
                depth = 1
                expr$ = ""

                while pos <= LEN(print_args$) and depth > 0
                    char$ = MID(print_args$, pos, 1)
                    if char$ = "("
                        depth++
                    elseif char$ = ")"
                        depth--
                    endif
                    if depth > 0
                        expr$ = expr$ + char$
                    endif
                    pos++
                endw

                if depth <> 0
                    display_error("Syntax Error: Unclosed CHR()")
                    rets
                endif

                expr$ = TRIM(0, expr$)
                chr_result = eval_expr(expr$)
                current_arg$ = CHR(34) + CHR(chr_result) + CHR(34)
                i = pos - 1  ! Skip past CHR()

            ! Handle separators
            elseif INSET(char$, ",;")
                args$[num_args] = TRIM(0, current_arg$)

                ! Comma = no space, Semicolon = tab
                if char$ = ","
                    sep_type[num_args] = 1
                else
                    sep_type[num_args] = 2
                endif

                num_args++
                current_arg$ = ""
                i++

            ! Regular characters
            else
                current_arg$ = current_arg$ + char$
                i++
            endif
        endif
    endw

   ! Check for unclosed string at the end of parsing
    if in_string
         display_error("Syntax Error: Unclosed string in PRINT statement")
        rets
    endif

    ! Add the last argument
    if current_arg$ <> ""
        args$[num_args] = TRIM(0, current_arg$)
        sep_type[num_args] = 0
        num_args++
    endif

    ! Process and print all arguments
    for i = 0 to num_args - 1
        arg$ = args$[i]

        ! Handle string literals (including CHR() results which are now wrapped in quotes)
        if arg$(0) = CHR(34)
            temp$ = MID(arg$, 2, LEN(arg$)-1)
            pos = FIND(temp$, CHR(34))

            if pos = 0
                display_error("Syntax Error: Unclosed string")
                rets
            else
                string_to_print$ = LEFT(temp$, pos-1)
                print string_to_print$,
            endif
        else
            ! Regular expression
            result = eval_expr(arg$)
            print result,
        endif

        ! Handle separators between arguments
        if i < num_args - 1
            if sep_type[i] = 1  ! Comma - no space
                pass
            elseif sep_type[i] = 2  ! Semicolon - tab
                print "        ",
            endif
        endif
    next

    ! Handle line ending
     last_char$ = RIGHT(print_args$, 1)
    if not INSET(last_char$, ",;")
        print
    endif
ends

! ================================================================
! PROCESS INPUT FUNCTION
! Handles INPUT command with optional prompt
! ================================================================
sub process_input(input_part$)
    local vars_list$[10]   ! List of variables to input
    local values[10]       ! Numeric array for values
    local i, pos, num_vars, var_index
    local temp$, rest$, input_vars$, current_var$, char$, single_value$, message$ = ""

    ! Check for prompt message
    if input_part$(0) = CHR(34)
        temp$ = MID(input_part$, 2, LEN(input_part$) - 1)
        pos = FIND(temp$, CHR(34))

        if pos = 0
            display_error("Syntax Error: Unclosed string in INPUT")
            rets
        else
            ! Extract prompt message
            message$ = LEFT(temp$, pos-1)
            rest$ = TRIM(1, MID(temp$, pos+1, LEN(temp$) - pos))

            ! Remove comma after prompt if present
            if rest$(0) = "," then rest$ = TRIM(1, MID(rest$, 2, LEN(rest$) - 1))

            input_vars$ = rest$
        endif
    else
        input_vars$ = input_part$
    endif

    ! Parse variable list
    vars_list$[].ZERO
    num_vars = 0
    current_var$ = ""

    for i = 0 to LEN(input_vars$)-1
        char$ = input_vars$(i)

        ! Comma separates variables
        if char$ = ","
            if LEN(current_var$) > 0
                vars_list$[num_vars] = TRIM(0, current_var$)
                num_vars++
                current_var$ = ""
            endif
        else
            current_var$ = current_var$ + char$
        endif
    next

    ! Add last variable
    if LEN(current_var$) > 0
        vars_list$[num_vars] = TRIM(0, current_var$)
        num_vars++
    endif

    ! Validate variables
    if num_vars = 0
        display_error("Syntax Error: No variables in INPUT")
        rets
    else
        ! Display prompt if provided
        if message$ <> "" then print message$,

        ! Single variable input
        if num_vars = 1
            input single_value$

            ! Validate and store variable
            var_name$ = TRIM(0, vars_list$[0])
            if LEN(var_name$) = 1 and INSET(var_name$, LETTERS$)
                var_index = ASC(var_name$) - 65
                vars[var_index] = VAL(single_value$)
            else
                display_error("Error: Invalid variable name '" + var_name$ + "'")
                rets
            endif

        ! Multiple variable input
        else
            input input_values$
            values[].ZERO
            num_values = 0
            current_val$ = ""

            ! Parse input values
            for i = 1 to LEN(input_values$)
                char$ = MID(input_values$, i, 1)

                if char$ = ","
                    if LEN(current_val$) > 0
                        values[num_values] = VAL(TRIM(0, current_val$))
                        num_values++
                        current_val$ = ""
                    endif
                else
                    current_val$ = current_val$ + char$
                endif
            next

            ! Add last value
            if LEN(current_val$) > 0
                values[num_values] = VAL(TRIM(0, current_val$))
                num_values++
            endif

            ! Validate value count matches variable count
            if num_values <> num_vars
                display_error("Error: Incorrect number of values. Expected " + STR(num_vars) + " but got " + STR(num_values))
                rets
            else
                ! Store values in variables
                for i = 0 to num_vars - 1
                    var_name$ = TRIM(0, vars_list$[i])

                    if LEN(var_name$) = 1 and INSET(var_name$, LETTERS$)
                        var_index = ASC(var_name$) - 65
                        vars[var_index] = values[i]
                    else
                        display_error("Error: Invalid variable name '" + var_name$ + "'")
                        rets
                    endif
                next
            endif
        endif
    endif
ends

! ================================================================
! EXPRESSION EVALUATION FUNCTIONS
! Recursive descent parser for mathematical expressions
! ================================================================

! Main expression evaluator
sub eval_expr(expr$)
    local result
    expr$ = TRIM(0, expr$)
    result = 0
    or_expr(byref result, byref expr$)
    rets result
ends

! OR expression handling
sub or_expr(result, expr$)
    local temp
    and_expr(byref result, byref expr$)

    while LEN(expr$) > 0
        expr$ = TRIM(0, expr$)

        if LEFT(expr$, 2) = "OR"
            expr$ = MID(expr$, 3, LEN(expr$) - 2)
            temp = 0
            and_expr(byref temp, byref expr$)
            result = result or temp
        else
            break
        endif
    endw
ends

! AND expression handling
sub and_expr(result, expr$)
    local temp
    comp_expr(byref result, byref expr$)

    while LEN(expr$) > 0
        expr$ = TRIM(0, expr$)

        if LEFT(expr$, 3) = "AND"
            expr$ = MID(expr$, 4, LEN(expr$) - 3)
            temp = 0
            comp_expr(byref temp, byref expr$)
            result = result and temp
        else
            break
        endif
    endw
ends

! Comparison operators (=, <>, <, >, <=, >=)
sub comp_expr(result, expr$)
    local temp, op_found$, op_pos, op_len
    add_sub(byref result, byref expr$)

    while LEN(expr$) > 0
        expr$ = TRIM(0, expr$)
        op_found$ = ""
        op_pos = 0

        ! Identify comparison operator
        if LEFT(expr$, 2) = "<>"
            op_found$ = "<>"
            op_len = 2
        elseif LEFT(expr$, 2) = "<="
            op_found$ = "<="
            op_len = 2
        elseif LEFT(expr$, 2) = ">="
            op_found$ = ">="
            op_len = 2
        elseif expr$(0) = "<"
            op_found$ = "<"
            op_len = 1
        elseif expr$(0) = ">"
            op_found$ = ">"
            op_len = 1
        elseif expr$(0) = "="
            op_found$ = "="
            op_len = 1
        endif

        ! Apply comparison if operator found
        if op_found$ <> ""
            expr$ = MID(expr$, op_len + 1, LEN(expr$) - op_len)
            temp = 0
            add_sub(byref temp, byref expr$)

            if op_found$ = "<"
                result = result < temp
            elseif op_found$ = ">"
                result = result > temp
            elseif op_found$ = "="
                result = result = temp
            elseif op_found$ = "<>"
                result = result <> temp
            elseif op_found$ = "<="
                result = result <= temp
            elseif op_found$ = ">="
                result = result >= temp
            endif
        else
            break
        endif
    endw
ends

! Addition and subtraction
sub add_sub(result, expr$)
    local temp
    term(byref result, byref expr$)

    while LEN(expr$) > 0
        expr$ = TRIM(0, expr$)

        if expr$(0) = "+"
            expr$ = MID(expr$, 2, LEN(expr$) - 1)
            temp = 0
            term(byref temp, byref expr$)
            result = result + temp

        elseif expr$(0) = "-"
            expr$ = MID(expr$, 2, LEN(expr$) - 1)
            temp = 0
            term(byref temp, byref expr$)
            result = result - temp

        else
            break
        endif
    endw
ends

! Multiplication, division, and modulo
sub term(result, expr$)
    local temp
    primary(byref result, byref expr$)

    while LEN(expr$) > 0
        expr$ = TRIM(0, expr$)

        if expr$(0) = "*"
            expr$ = MID(expr$, 2, LEN(expr$) - 1)
            temp = 0
            primary(byref temp, byref expr$)
            result = result * temp

        elseif expr$(0) = "/"
            expr$ = MID(expr$, 2, LEN(expr$) - 1)
            temp = 0
            primary(byref temp, byref expr$)

            if temp <> 0
                result = result / temp
            else
                print "Division by zero!"
                fatal_error = 1
                result = 0
                rets
            endif

        elseif expr$(0) = "%"
            expr$ = MID(expr$, 2, LEN(expr$) - 1)
            temp = 0
            primary(byref temp, byref expr$)

            if temp <> 0
                result = result % temp
            else
                print "Modulo by zero!"
                fatal_error = 1
                result = 0
                rets
            endif

        else
            break
        endif
    endw
ends

! Primary expressions (numbers, variables, parentheses)
sub primary(result, expr$)
    local char$, num_str$, i, char_code, sub_expr$, temp_result, depth, pos
    expr$ = TRIM(0, expr$)

    ! Handle parentheses
    if expr$(0) = "("
        depth = 1
        pos = 2

        ! Find matching closing parenthesis
        while pos <= LEN(expr$) and depth > 0
            char$ = MID(expr$, pos, 1)
            if char$ = "("
                depth++
            elseif char$ = ")"
                depth--
            endif
            pos++
        endw

        if depth <> 0
            display_error("Syntax Error: Unmatched parentheses")
            result = 0
            expr$ = ""
            rets
        endif

        ! Evaluate expression inside parentheses
        sub_expr$ = MID(expr$, 2, pos - 3)
        temp_result = eval_expr(sub_expr$)
        result = temp_result
        expr$ = MID(expr$, pos, LEN(expr$) - pos + 1)
        rets
    endif

    ! Check for RND() function call first
    if LEFT(expr$, 4) = "RND("
        ! Find the closing parenthesis for RND - must be immediately after
        if LEN(expr$) < 5 or expr$(4) <> ')'
            display_error("Syntax Error: RND takes no arguments")
            result = 0
            expr$ = ""
            rets
        endif

        result = RND()  ! Call Hobby BASIC's built-in RND function
        expr$ = MID(expr$, 6, LEN(expr$) - 5)  ! Skip "RND()"
        rets
    endif

    ! Extract numbers
    num_str$ = ""
    i = 1

    while i <= LEN(expr$)
        char$ = MID(expr$, i, 1)
        if not INSET(char$, DIGITS$) then break
        num_str$ = num_str$ + char$
        i++
    endw

    if LEN(num_str$) > 0
        result = VAL(num_str$)
        expr$ = MID(expr$, i, LEN(expr$) - i + 1)
        rets
    endif

    ! Extract variables
    if LEN(expr$) > 0
        char_code = ASC(expr$)

        if INSET(CHR(char_code), LETTERS$)
            result = vars[char_code - 65]
            expr$ = MID(expr$, 2, LEN(expr$) - 1)
            rets
        endif
    endif

    ! Default return if no valid expression found
    result = 0
ends