PowerBASIC supports both fixed-size arrays (allocated on the stack) and dynamic arrays (allocated on the heap via REDIM). Fixed arrays are declared with a constant size at compile time. Dynamic arrays use REDIM to allocate and resize at runtime. Both support custom lower bounds via the lower TO upper syntax.
LOCAL a(size) AS type | LOCAL a(lower TO upper) AS typeFixed arrays are allocated inline in the stack frame. The size must be a compile-time constant. Element access uses direct index arithmetic: base + (index - lbound) * stride.
| Parameter | Description |
|---|---|
a | Array variable name |
size | Number of elements (0-based: 0 TO size-1) |
lower | Lower bound (any integer constant) |
upper | Upper bound (any integer constant, >= lower) |
type | Element type: LONG, STRING, etc. |
LOCAL a(10) AS LONG ' 0 TO 10 (11 elements) LOCAL b(1 TO 5) AS LONG ' 5 elements a(5) = 42
; Fixed array: allocated inline in stack frame ; Element access: base + (index - lbound) * stride ; Example: a(5) = 42 ; pb_cg_emit_array_address computes [rbp - base + (5-lbound)*stride] mov [rbp - array_base + (5-lbound)*stride], 42
REDIM array(lower TO upper) AS typepb_cg_emit_redim (pb_codegen.c:5975)REDIM allocates (or reallocates) a dynamic array on the heap via malloc. The lower and upper bounds can be runtime expressions. If the array was previously allocated, the old heap memory is freed before the new allocation.
| Parameter | Description |
|---|---|
array | Dynamic array variable name |
lower | Lower bound (integer expression, evaluated at runtime) |
upper | Upper bound (integer expression, evaluated at runtime) |
type | Element type |
LOCAL n AS LONG n = 100 REDIM myArray(1 TO n) AS LONG myArray(50) = 999
; Compute bounds mov rax, upper_bound sub rax, lower_bound add rax, 1 ; count = upper - lower + 1 cmp rax, 1 jl __pb_redim_fail ; count < 1 -> error mov [rbp - count_offset], rax mov rcx, rax imul rcx, element_size ; bytes = count * stride call [__imp_malloc] ; allocate test rax, rax je __pb_redim_fail ; OOM -> exit mov [rbp - new_ptr_offset], rax ; Zero-initialize mov rcx, rax xor rdx, rdx mov r8, [rbp - bytes_offset] call [__imp_memset] ; memset(ptr, 0, bytes)
; For each element that exists in both old and new arrays: ; source offset = (i - old_lower) * stride + old_ptr ; dest offset = (i - new_lower) * stride + new_ptr mov rcx, dest_ptr mov rdx, src_ptr mov r8, stride call [__imp_memcpy] ; copy element ; For STRING elements: copy descriptor
; Free old array if exists mov rcx, [rbp - old_ptr_offset] test rcx, rcx je __pb_redim_old_null call [__imp_free] __pb_redim_old_null: ; Update local descriptor mov rax, [rbp - new_ptr_offset] mov [rbp - local_ptr_offset], rax ; ptr = new_ptr mov rax, [rbp - new_lower] mov [rbp - local_lower_offset], rax ; lbound = new_lower mov rax, [rbp - new_upper] mov [rbp - local_upper_offset], rax ; ubound = new_upper mov rax, [rbp - new_count] mov [rbp - local_count_offset], rax ; count = new_count
array(index) (read or write)LOCAL a(10) AS LONG a(3) = 42 ' write LOCAL x AS LONG x = a(3) ' read -> x = 42
; Read: x = a(index) ; Write: a(index) = expr ; Both compute: r11 = base + (index - lbound) * stride ; Then: mov rax, [r11] (read) or mov [r11], rax (write)