← Back to AILP Home

Strings in Nitpick

Overview

Nitpick strings are immutable UTF-8 byte sequences with explicit length. The string type is a first-class type with compiler-level support for operations, comparisons, and template interpolation.

string:greeting = "Hello, Nitpick!";

String Literals

Regular Strings

string:s = "Hello\nWorld";        // escape sequences processed

Escape Sequences

Escape Meaning Hex
\n Newline 0x0A
\t Tab 0x09
\r Carriage Return 0x0D
\\ Backslash 0x5C
\" Double Quote 0x22
\0 Null Byte 0x00
\a Bell 0x07
\b Backspace 0x08
\xNN Hex Byte 0xNN
\u{NNNN} Unicode Codepoint U+NNNN

Raw Strings (planned)

string:regex = r"^\d+\.\d+$";    // no escape processing

Template Literals

string:name = "world";
string:msg = `hello &{name}`;    // interpolation with &{expr}

Known limitation: Function calls inside &{...} produce garbage output. Pre-compute values into variables first.

Byte vs Codepoint Semantics

Nitpick strings are byte-indexed, not character-indexed:

Function Operates On
string_length(s) Bytes
string_byte_length(s) Bytes (explicit alias)
string_char_count(s) UTF-8 codepoints
string_substring(s, start, end) Byte indices
string_index_of(s, needle) Byte index returned

This means for ASCII strings, byte and character operations are identical. For multi-byte UTF-8, you must use string_char_count for accurate character counting.

Compiler Builtins

These are compiler intrinsics — available without imports:

Creation & Conversion

Function Signature Description
string_from_int(val) int64 → string Integer to string
string_to_int(str) string → int64 Parse string as integer
string_from_int_hex(val) int64 → string Integer to hex (no prefix)
string_from_char(byte) uint8 → string Single byte to string
string_format_float(val, prec) flt64, int32 → string Float with precision

Querying

Function Signature Description
string_length(s) string → int64 Byte length
string_byte_length(s) string → int64 Byte length (explicit)
string_char_count(s) string → int64 UTF-8 codepoint count
string_is_empty(s) string → bool True if length is 0
string_is_valid_utf8(s) string → bool UTF-8 validation

Searching

Function Signature Description
string_contains(s, needle) string, string → bool Substring search
string_starts_with(s, prefix) string, string → bool Prefix check
string_ends_with(s, suffix) string, string → bool Suffix check
string_index_of(s, needle) string, string → int64 First occurrence (-1 if not found)
string_last_index_of(s, needle) string, string → int64 Last occurrence (-1 if not found)
string_count(s, needle) string, string → int64 Non-overlapping count

Manipulation

Function Signature Description
string_concat(a, b) string, string → string Concatenation
string_substring(s, start, end) string, int64, int64 → string Byte substring [start, end)
string_replace(s, needle, repl) string, string, string → string Replace all occurrences
string_trim(s) string → string Trim ASCII whitespace
string_trim_start(s) string → string Trim leading whitespace
string_trim_end(s) string → string Trim trailing whitespace
string_to_upper(s) string → string ASCII uppercase
string_to_lower(s) string → string ASCII lowercase
string_repeat(s, n) string, int64 → string Repeat n times
string_pad_left(s, len, ch) string, int64, uint8 → string Left-pad to length
string_pad_right(s, len, ch) string, int64, uint8 → string Right-pad to length

Comparison

Function Signature Description
string_equals(a, b) string, string → bool Byte equality

Strings also support all comparison operators: ==, !=, <, <=, >, >=, <=>.

Stdlib Functions

These require use "string.npk".*;:

Function Description
str_replace(s, needle, repl) Replace (stdlib version, superseded by builtin)
str_count(s, needle) Count occurrences (superseded by builtin)
str_byte_at(s, idx) Get byte at index
str_char_at(s, idx) Get character at index
str_reverse(s) Reverse string
str_split(s, delim) Split by delimiter
str_join(arr, delim) Join array with delimiter

StringBuilder

For building strings in loops, use StringBuilder from string_builder.npk:

use "string_builder.npk".*;

StringBuilder:sb = StringBuilder_new(1024i64) ? empty;
sb = sb.append("Hello") ? sb;
sb = sb.append(" World") ? sb;
string:result = sb.build() ? "";
drop sb.free();

Operators

Operator Meaning
+ Concatenation (with overflow check)
== / != Byte equality
< / <= / > / >= Lexicographic byte ordering
<=> Spaceship (returns -1, 0, 1)