Arrays & REDIM

Description

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.

Fixed Arrays

Syntax: LOCAL a(size) AS type  |  LOCAL a(lower TO upper) AS type

Description

Fixed 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.

Parameters

ParameterDescription
aArray variable name
sizeNumber of elements (0-based: 0 TO size-1)
lowerLower bound (any integer constant)
upperUpper bound (any integer constant, >= lower)
typeElement type: LONG, STRING, etc.

Example

LOCAL a(10) AS LONG       ' 0 TO 10 (11 elements)
LOCAL b(1 TO 5) AS LONG   ' 5 elements
a(5) = 42

Generated Assembly

; 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 (Dynamic Arrays)

Syntax: REDIM array(lower TO upper) AS type
Source: pb_cg_emit_redim (pb_codegen.c:5975)

Description

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.

Note: REDIM PRESERVE is partially supported. Heap-backed arrays and STRING/UDT arrays are not yet implemented.

Parameters

ParameterDescription
arrayDynamic array variable name
lowerLower bound (integer expression, evaluated at runtime)
upperUpper bound (integer expression, evaluated at runtime)
typeElement type

Example

LOCAL n AS LONG
n = 100
REDIM myArray(1 TO n) AS LONG
myArray(50) = 999

Allocation

; 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)

PRESERVE Copy (overlapping elements)

; 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

Finalize (swap pointers)

; 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 Element Access

Syntax: array(index) (read or write)

Example

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)