Strings are valid UTF-8 independent values. Default parameters borrow without copying; results own their storage. Positions, lengths and padding widths below count Unicode scalar values, starting at zero. A combining sequence or emoji may contain several scalars. Equality and search are exact and case-sensitive. No implicit normalization, locale tailoring, or numeric conversion occurs.
Functions
All integer arguments/results use INTEGER (signed 64-bit). Fallible calls are checked automatically, including calls whose successful results are discarded; inline TRY is optional.
| Function | Result and behavior | Declared error |
|---|---|---|
| LEN(text), ByteCount(text) | Scalar count; UTF-8 byte count | None |
| ByteAt(text, offset) | Encoded byte at zero-based byte offset; invalid offset is fatal | None |
| LEFT(text, count), RIGHT(text, count) | At most count scalars from either end | StringError |
| MID(text, start, count) | At most count scalars starting at start; start may equal LEN | StringError |
| INSTR(text, needle) | First scalar position, or -1; empty needle gives 0 | None |
| INSTRFROM(text, needle, start) | First scalar position at/after start; empty needle gives start | StringError |
| RINSTR(text, needle) | Last scalar position, or -1; empty needle gives LEN | None |
| CHR(value) | One Unicode scalar encoded as UTF-8, including NUL | StringError |
| ASC(text) | First Unicode scalar’s integer value | StringError |
| STR(value) | Canonical integer or shortest round-tripping DOUBLE spelling, no leading space | None |
| VAL(text) | Strict signed decimal integer after Unicode whitespace trimming | NumericError |
| SPACE(count), REPEAT(text, count) | Repeated spaces or text; zero gives empty string | StringError |
| UPPER(text), LOWER(text), CASEFOLD(text) | Full Unicode 17 default mapping; may expand characters | None |
| UCASE(text), LCASE(text) | Aliases for UPPER and LOWER | None |
| TRIM(text), LTRIM(text), RTRIM(text) | Remove Unicode White_Space from both/start/end | None |
| CONTAINS(text, needle) | BOOLEAN substring test | None |
| STARTSWITH(text, prefix), ENDSWITH(text, suffix) | BOOLEAN boundary test | None |
| REMOVEPREFIX(text, prefix), REMOVESUFFIX(text, suffix) | Remove one matching boundary; otherwise return independent unchanged value | None |
| REPLACE(text, old, replacement) | Replace all nonoverlapping matches; empty old inserts at scalar boundaries, including both ends | None |
| SPLIT(text, separator="") | LIST OF STRING; empty separator splits Unicode code points, nonempty separators preserve empty fields | StringError (legacy contract) |
| LINES(text) | LIST OF STRING, splitting line boundaries without retaining separators | None |
| JOIN(parts, separator) | Join a LIST OF STRING | None |
| PADLEFT(text, width), PADRIGHT(text, width) | Space padding to width; shorter/negative widths leave text unchanged | StringError |
| PADLEFTWITH(text, width, fill), PADRIGHTWITH(text, width, fill) | Padding with exactly one scalar | StringError |
| FORMAT(template, values) | Replace {} with successive strings from LIST OF STRING; {{ and }} escape braces | StringError |
| CODEPOINTS(text) | LIST OF INTEGER containing Unicode scalar values | None |
| UNICODEVERSION() | “17.0.0” | None |
MID/INSTRFROM reject negative starts and starts beyond LEN. LEFT/RIGHT/MID reject negative counts; excessive nonnegative counts clamp to available text. SPACE/REPEAT reject negative counts. Padding widths and slicing positions are not display-column measurements.
VAL requires the entire trimmed input to be optional ASCII + or - followed by ASCII decimal digits. Empty input, embedded whitespace, fractional/exponent/radix notation, and trailing characters fail. The full signed 64-bit range is accepted. VAL parses INTEGER; STR also formats DOUBLE. Use checked CDBL(text) / VALDOUBLE(text) for floating-point parsing; see the math reference .
LINES recognizes CRLF as one boundary, plus LF, CR, vertical tab, form feed, U+001C–U+001E, NEL, line separator and paragraph separator. Empty input yields an empty list; a trailing line boundary does not add a final empty element. SPLIT with a nonempty separator preserves final empty fields. Its separator is optional and defaults to “”: omitted/empty separators split into Unicode code points, with empty input producing an empty list. Combining marks remain separate entries.
FORMAT requires exactly as many values as {} placeholders, and balanced/escaped braces. Values are strings: use STR explicitly for numeric values. Width/precision/type format specifications are deferred.
Traditional string-result spellings with a trailing dollar are optional call aliases, such as LEFT$(text, count), UCASE$(text) and STR$(value). They are recognized for the string-result functions listed above except UNICODEVERSION; they do not introduce typed variable suffixes or arbitrary dollar-named functions. INSTR/ASC/VAL/SPLIT/LINES return other types and have no dollar alias. This is modern BASIL behavior, not complete QuickBASIC compatibility: positions are zero-based, not-found is -1, CHR/ASC use Unicode scalars, and VAL is checked and strict.
Recoverable errors
NumericError and StringError are distinct built-in typed records with an INTEGER Code field. Construction is an ordinary value operation. User functions declare escaping types in FAILS, and RETURN ERROR explicitly forwards a caught error.
| Error | Code | Meaning |
|---|---|---|
| NumericError | 1 | Invalid decimal integer syntax |
| NumericError | 2 | Integer outside the signed 64-bit range |
| StringError | 1 | Invalid Unicode scalar (negative, surrogate, or above U+10FFFF) |
| StringError | 2 | Invalid position or negative count |
| StringError | 3 | Reserved legacy split error code; empty separators now succeed |
| StringError | 4 | ASC called on empty text |
| StringError | 5 | Invalid template or mismatched format argument count |
| StringError | 6 | Padding fill is not exactly one scalar |
| StringError | 7 | Invalid byte sequence supplied to DecodeUtf8/ReadFileText |
TRY
PRINT UPPER("Straße")
PRINT TRY LEFT("café 🌍", 4)
PRINT JOIN(TRY SPLIT("one,two,three", ","), " | ")
PRINT TRY VAL("42")
CATCH err AS StringError
PRINT "String error code: " + STR(err.Code)
CATCH err AS NumericError
PRINT "Number error code: " + STR(err.Code)
END TRYErrors inside a catch target an outer matching catch or propagate from the function, never another clause of the same handler. Partial expressions and owned locals are cleaned on recoverable exit. Allocation failure remains fatal, separate from these errors, with no normal application-cleanup guarantee. Integer arithmetic overflow and invalid ByteAt access are also fatal.