Skip to content

Prelude

The prelude is automatically imported into every Nic program. It provides the core types and functions that form the foundation of Nic programming.

Core Types

Option[T]

Represents an optional value - either Some(value) or None:

nic
enum Option[T] {
    Some(T),
    None,
}

// Usage
let maybe_number: Option[i32] = Some(42);
let nothing: Option[i32] = None;

match maybe_number {
    Some(n) => println("Got: " + int_to_string(n)),
    None => println("No value"),
}

Helper Functions:

nic
fn is_some[T](opt: Option[T]) -> bool;
fn is_none[T](opt: Option[T]) -> bool;
fn unwrap_or[T](opt: Option[T], default: T) -> T;

Result[T, E]

Represents success or failure - either Ok(value) or Err(error):

nic
enum Result[T, E] {
    Ok(T),
    Err(E),
}

// Usage
fn divide(a: i32, b: i32) -> Result[i32, string] {
    if b == 0 {
        return Err("division by zero");
    }
    return Ok(a / b);
}

match divide(10, 2) {
    Ok(result) => println("Result: " + int_to_string(result)),
    Err(msg) => println("Error: " + msg),
}

Helper Functions:

nic
fn is_ok[T, E](res: Result[T, E]) -> bool;
fn is_err[T, E](res: Result[T, E]) -> bool;
fn unwrap_ok[T, E](res: Result[T, E]) -> T;  // Panics if Err

String Class

A growable, heap-allocated string with copy-on-write semantics.

Creating Strings

nic
// From string literal (shared, no copy until mutation)
let s1 = String::from("hello");

// Copy a string literal
let s2 = String::from_copy("hello");

// Empty string
let s3 = String::empty();

// With pre-allocated capacity
let s4 = String::with_capacity(100);

String Methods

nic
class String {
    // Accessors
    pub fn len(self) -> u64;
    pub fn capacity(self) -> u64;
    pub fn is_empty(self) -> bool;

    // Mutation (copy-on-write)
    pub fn concat(self, other: string) -> unit;
    pub fn concat_string(self, other: *String) -> unit;
    pub fn clear(self) -> unit;

    // Comparison
    pub fn equals(self, other: *String) -> bool;
    pub fn equals_literal(self, other: string) -> bool;

    // Lifecycle
    pub fn init(self) -> unit;
    pub fn deinit(self) -> unit;
}

Example

nic
let greeting = String::from("Hello");
greeting.concat(", ");
greeting.concat("World!");
println(greeting.as_str());  // "Hello, World!"

// Don't forget cleanup
defer greeting.deinit();

Vec[T] Class

A generic growable array.

Creating Vectors

nic
// Empty vector
let v1 = Vec::empty[i32]();

// With pre-allocated capacity
let v2 = Vec::with_capacity[i32](100);

Vector Methods

nic
class Vec[T] {
    // Accessors
    pub fn len(self) -> u64;
    pub fn capacity(self) -> u64;
    pub fn is_empty(self) -> bool;

    // Element access
    pub fn get(self, index: u64) -> Option[T];
    pub fn get_unchecked(self, index: u64) -> T;
    pub fn set(self, index: u64, value: T) -> unit;
    pub fn first(self) -> Option[T];
    pub fn last(self) -> Option[T];

    // Mutation
    pub fn push(self, value: T) -> unit;
    pub fn pop(self) -> Option[T];
    pub fn clear(self) -> unit;
    pub fn reserve(self, additional: u64) -> unit;
}

Example

nic
let numbers = Vec::empty[i32]();
defer numbers.deinit();

numbers.push(1);
numbers.push(2);
numbers.push(3);

for i in 0..numbers.len() {
    match numbers.get(i) {
        Some(n) => println(int_to_string(n)),
        None => {},
    }
}

StringMap[V]

A hash map with string keys. Uses DJB2 hash algorithm with linear probing.

nic
let config = StringMap::empty[bool]();
defer config.deinit();

config.insert("debug", true);
config.insert("verbose", false);

match config.get("debug") {
    Some(val) => println("debug = " + bool_to_string(val)),
    None => println("not set"),
}

if config.contains("verbose") {
    println("verbose mode available");
}

Methods

nic
class StringMap[V] {
    pub fn empty() -> *StringMap[V];
    pub fn with_capacity(cap: u64) -> *StringMap[V];

    pub fn insert(self, key: string, value: V) -> unit;
    pub fn get(self, key: string) -> Option[V];
    pub fn contains(self, key: string) -> bool;
    pub fn remove(self, key: string) -> bool;
    pub fn clear(self) -> unit;
}

IntMap[V]

A hash map with 64-bit integer keys. Uses Knuth's multiplicative hash.

nic
let users = IntMap::empty[*User]();
defer users.deinit();

users.insert(1001, user1);
users.insert(1002, user2);

match users.get(1001) {
    Some(user) => println("Found: " + user.name),
    None => println("User not found"),
}

I/O Functions

nic
pub fn print(s: string) -> unit;
pub fn println(s: string) -> unit;

Conversion Functions

nic
pub fn int_to_string(n: i64) -> *String;
pub fn uint_to_string(n: u64) -> *String;

Libc Bindings

The prelude exposes common C library functions for low-level operations:

nic
// Memory
extern fn malloc(size: u64) -> opaque;
extern fn calloc(count: u64, size: u64) -> opaque;
extern fn realloc(ptr: opaque, size: u64) -> opaque;
extern fn free(ptr: opaque) -> unit;

// Strings
extern fn strlen(s: string) -> u64;
extern fn strcmp(a: string, b: string) -> i32;
extern fn memcpy(dst: opaque, src: opaque, n: u64) -> opaque;
extern fn memset(ptr: opaque, val: i32, n: u64) -> opaque;

// I/O
extern fn puts(s: string) -> i32;
extern fn printf(fmt: string, ...) -> i32;

These are available for advanced use cases but prefer the higher-level abstractions when possible.

Released under the MIT License.