WSTRING64 & WinAPI V14 compiler V16 WinAPI

V13: WSTRING64 runtime library created (20+ helper functions). V14: Compiler now lowers WSTRING expressions through the full pipeline: lexer -> parser -> semantic -> codegen -> PE.

WSTRING Variable Declarations

Syntax: LOCAL w AS WSTRING | STATIC w AS WSTRING | GLOBAL w AS WSTRING

V14 allocates WSTRING descriptors in the stack frame or static storage. The descriptor contains: data pointer, length (UTF-16 code units), capacity, and flags.

STRING / WSTRING Cross-Assignment

Syntax: w$ = s$ (STRING to WSTRING) | s$ = w$ (WSTRING to STRING)
LOCAL s AS STRING, w AS WSTRING
s = "Hello"
w = s          ' MultiByteToWideChar (CP_ACP -> UTF-16)
s = w          ' WideCharToMultiByte (UTF-16 -> CP_ACP)

Generated Assembly (STRING -> WSTRING)

; Get source STRING pointer -> RCX
; WideCharToMultiByte or MultiByteToWideChar
mov    rcx, 65001                       ; CP_UTF8 / CP_ACP
xor    rdx, rdx                         ; dwFlags = 0
mov    r8, [rbp - src_ptr]              ; source
mov    r9, -1                           ; null-terminated
call   [__imp_MultiByteToWideChar]      ; returns required buffer size

PRINT WSTRING

Syntax: PRINT w$

Lowered through a temporary narrow conversion buffer (WideCharToMultiByte), then output via the existing WriteFile console path.

LEN(WSTRING) / STRPTR(WSTRING)

Syntax: LEN(w$) | STRPTR(w$)

LEN returns UTF-16 code-unit count from the descriptor. STRPTR returns the raw WCHAR* data pointer.

LOCAL w AS WSTRING
w = "Hello"
PRINT LEN(w)       ' 5 (code units)
PRINT STRPTR(w)    ' address of wchar_t data

WSTRING Comparison

Syntax: w1$ = w2$ | w1$ <> w2$ | w1$ < w2$

Mixed STRING/WSTRING expressions auto-promote to WSTRING. Comparison uses memcmp on UTF-16 byte spans.

WSTRING Concatenation

Syntax: w$ = w1$ + w2$ | w$ = s$ + w$ (mixed)

Uses pb_wstr64_concat runtime. Mixed STRING/WSTRING operands are promoted to WSTRING before concatenation.

FUNCTION AS WSTRING

Syntax: FUNCTION name(BYVAL w AS WSTRING) AS WSTRING

Full scalar return path. Parameters can be BYVAL or default BYREF WSTRING.

FUNCTION Greet(BYVAL name AS WSTRING) AS WSTRING
    LOCAL w AS WSTRING
    w = "Hello, " + name
    FUNCTION = w
END FUNCTION

Still Pending

WSTRING64 Functions

WSPACE$(count)

Syntax: w$ = WSPACE$(n)
Runtime: pb_wstr64_space (pb_wstring64.c)

Returns a WSTRING containing n space characters.

LOCAL w AS WSTRING
w = WSPACE$(10)    ' 10 spaces

WSTRING$(count, fill)

Syntax: w$ = WSTRING$(n, fill$)
Runtime: pb_wstr64_string (pb_wstring64.c)

Returns a WSTRING by repeating the fill character or string n times.

LOCAL w AS WSTRING
w = WSTRING$(5, "*")     ' "*****"
w = WSTRING$(3, "AB")    ' "ABABAB"

WREMOVE$(source, substring)

Syntax: result$ = WREMOVE$(w$, remove$)
Runtime: pb_wstr64_remove (pb_wstring64.c)

Removes all occurrences of remove$ from w$.

LOCAL w AS WSTRING, r AS WSTRING
w = "Hello World"
r = WREMOVE$(w, "o")    ' "Hell Wrld"

WEXTRACT$(source, delimiter, index)

Syntax: result$ = WEXTRACT$(w$, delim$, n)
Runtime: pb_wstr64_extract (pb_wstring64.c)

Extracts the nth field from w$ split by delim$. Index is 1-based.

LOCAL w AS WSTRING, r AS WSTRING
w = "one,two,three"
r = WEXTRACT$(w, ",", 2)    ' "two"

ASCII/WSTRING Bridge Functions

WSTR_FROM_ASCII(ascii$)

Runtime: pb_wstr64_from_ascii (pb_wstring64.c)

Converts an ASCII/ANSI STRING to a WSTRING (UTF-16). Each byte maps to a wide character.

WSTR_TO_ASCII_LOSSY(w$)

Runtime: pb_wstr64_to_ascii_lossy (pb_wstring64.c)

Converts a WSTRING back to ASCII, truncating characters above U+00FF to '?'.

WinAPI WSTRING Interop V16

BYVAL WSTRING in DECLARE

Syntax: DECLARE FUNCTION MsgBoxW LIB "user32.dll" ALIAS "MessageBoxW" (BYVAL hWnd AS QUAD, BYVAL lpText AS WSTRING, BYVAL lpCaption AS WSTRING, BYVAL uType AS LONG) AS LONG

V16 fixes BYVAL WSTRING to pass LPWSTR data pointers (not descriptors) to external DLLs. STRING literals are auto-widened via MultiByteToWideChar into per-call temporaries, freed after the call.

DECLARE FUNCTION MessageBoxW LIB "user32.dll" ALIAS "MessageBoxW" ( _
    BYVAL hWnd AS QUAD, BYVAL lpText AS WSTRING, _
    BYVAL lpCaption AS WSTRING, BYVAL uType AS LONG) AS LONG

CALL MessageBoxW(0, "Hello", "Title", 0)   ' STRING literal auto-widened

Console PRINT WSTRING

Syntax: PRINT w$ uses WriteConsoleW
LOCAL w AS WSTRING
w = "Hello Unicode"
PRINT w       ' WriteConsoleW with UTF-16 code-unit length

File I/O with WSTRING

Syntax: OPEN w$ FOR ... AS #n uses CreateFileW

WSTRING filenames call CreateFileW (narrow filenames keep CreateFileA). INPUT/LINE INPUT into WSTRING reads the byte stream and widens into the descriptor.

LOCAL w AS WSTRING
w = "unicode_file.txt"
OPEN w FOR OUTPUT AS #1
PRINT #1, "data"
CLOSE #1

VARPTR(WSTRING) Fix

Syntax: VARPTR(w$) | VARPTR(type.wstringField)

V16 fixes VARPTR to return the descriptor-slot address (matching PowerBASIC behavior). Previously returned the string-data pointer.

Limitations