Skip to content

Standard Library Overview

The Nic standard library provides essential functionality for systems programming: memory management, string handling, collections, I/O, threading, and more.

Installation

The standard library is installed to ~/.nicc/ when you run:

bash
make install

For development, you can use the local std/ directory:

bash
NIC_STD_PATH=. cabal run nicc -- run myfile.nic

Import Conventions

Prelude (Auto-imported)

The prelude is automatically imported into every Nic program. It provides core types:

nic
// These are available without explicit import:
let maybe: Option[i32] = Some(42);
let result: Result[i32, string] = Ok(10);
let s = String::from("hello");
let v = Vec::empty[i32]();

Standard Modules

Standard library modules use the std. prefix:

nic
import std.io;           // File I/O
import std.mem;          // Memory allocation
import std.args;         // Command-line arguments
import std.parse;        // String parsing
import std.async.thread; // Threading
import std.async.mutex;  // Synchronization
import std.flags;        // CLI flag parsing

Selective Imports

Import specific items to avoid namespace pollution:

nic
import std.io(File, FileMode, open, close);
import std.mem(alloc, dealloc);
import std.parse(parse_i32, parse_bool);

Glob Imports

Import everything from a module:

nic
import std.flags(*);

Module Overview

ModuleDescription
PreludeCore types: Option, Result, String, Vec, StringMap, IntMap
std.memMemory allocation and manipulation
std.argsCommand-line argument handling
std.parseString parsing utilities
std.ioFile I/O operations
std.asyncThreading and synchronization
std.flagsCLI flag parsing with subcommands

Design Principles

Explicit Resource Management

Nic avoids garbage collection. Resources are managed explicitly:

nic
let file = open("data.txt", FileMode::Read);
defer close(file);  // Cleanup when scope exits

// Use the file...

Error Handling with Result

Fallible operations return Result[T, E]:

nic
import std.parse(parse_i32);

fn read_number(s: string) -> Result[i32, string] {
    return parse_i32(s);
}

match read_number("42") {
    Ok(n) => println("Got: " + int_to_string(n)),
    Err(e) => println("Error: " + e),
}

Optional Values with Option

Values that may be absent use Option[T]:

nic
fn find_user(id: i64) -> Option[User] {
    // Returns Some(user) or None
}

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

Generic Collections

Collections are generic and type-safe:

nic
let numbers = Vec::empty[i32]();
numbers.push(1);
numbers.push(2);
numbers.push(3);

let map = StringMap::empty[bool]();
map.insert("enabled", true);

Directory Structure

~/.nicc/
├── prelude.nic     # Auto-imported core types
└── std/
    ├── io/         # File I/O module
    │   ├── mod.nic
    │   └── file.nic
    ├── async/      # Threading module
    │   ├── mod.nic
    │   ├── thread.nic
    │   └── mutex.nic
    ├── flags/      # CLI parsing module
    │   ├── mod.nic
    │   ├── types.nic
    │   ├── parser.nic
    │   ├── result.nic
    │   └── help.nic
    ├── mem.nic     # Memory module
    ├── args.nic    # Arguments module
    └── parse.nic   # Parsing module

Released under the MIT License.