Skip to content

nnlgsakib/nlang

Repository files navigation

Nlang — Modern Systems Programming Language

Nlang logo

Nlang is a statically typed language that combines approachable syntax with systems-level performance. It provides compile-time memory safety, rigorous type checking, an interpreter for rapid iteration, and a C transpiler for portable binaries.

Key Features

  • Intuitive syntax and clear blocks
  • Static typing with practical inference
  • Compile-time memory safety with immutability-by-default, ownership, borrowing, lifetimes, and move semantics
  • Standard library for I/O, strings, math, and data structures
  • Multiple execution modes: interpreter and C code generation
  • LSP tooling with diagnostics, quick fixes, completion, and formatting

Installation

Prerequisites:

  • Rust 1.70+
  • GCC or Clang (for compiling generated C; path configurable via env or API)

Build:

cargo build --release
cargo test

Usage

Project Management

Create a new project:

cargo run --bin nlang -- create my_project
cd my_project

Or initialize in existing directory:

mkdir my_project && cd my_project
cargo run --bin nlang -- init

Update module registry (after adding/removing files):

cargo run --bin nlang -- mod-rec

Running and Compiling

Direct execution (interpreter):

cargo run --bin nlang -- run path/to/program.nlang
# Or inside a project directory:
cargo run --bin nlang -- run

C code generation and compilation:

cargo run --bin nlang -- generate-c path/to/program.nlang -o program.c
gcc program.c -o program.exe

# Or compile directly via the CLI wrapper
cargo run --bin nlang -- compile path/to/program.nlang
# Inside a project, output goes to bin/ with project name:
cargo run --bin nlang -- compile

Compiler Selection (custom GCC/Clang path)

  • Via environment variables (resolution order: NLANG_GCCCC → system gcc):
    • Windows PowerShell:
      $env:NLANG_GCC = 'C:\\msys64\\usr\\bin\\gcc.exe'
      cargo run --bin nlang -- compile path\to\program.nlang
    • Unix shells:
      NLANG_GCC=/usr/local/bin/gcc cargo run --bin nlang -- compile path/to/program.nlang
  • Via the Rust API:
    use nlang::execution_engine::ExecutionEngine;
    use std::path::Path;
    
    let engine = ExecutionEngine::new_with_gcc_path("C\\msys64\\usr\\bin\\gcc.exe");
    // or set later
    // let mut engine = ExecutionEngine::new();
    // engine.set_gcc_path("C\\mingw64\\bin\\gcc.exe");
    engine.compile_to_executable("def main() {}", "demo", Path::new("demo.exe")).unwrap();

Language Essentials

Variables:

store x :i32 = 42;       // immutable by default
@mut store y :i32 = 5;   // mutable variable
y = y + 1;               // ok
x = 10;                  // error: x is immutable

Ownership and borrowing:

store v = create_vector();
store v2 = v;            // v moved; use-after-move is a compile error

@mut store a :i32 = 5;
store r1 = &a;           // immutable borrow
store r2 = &@mut a;      // mutable borrow; error if r1 is active

References and lifetimes:

// Reference types can appear in signatures
def head(xs: [int; 3]) -> &int { return &xs[0]; }

def bad() -> &int {
    store x :i32 = 5;
    return &x;          // error: returns reference to local
}

Arrays and indexing:

@mut store arr: [int; 3] = [1, 2, 3];
arr[0] = 100;            // ok: arr is mutable
store first = arr[1];    // reading is always fine

Control flow:

@mut store i = 0;
while (i < 3) { i = i + 1; }
for (@mut store j = 2; j >= 0; j = j - 1) { println(j); }
repeat { i = i + 1; } until i >= 10;
loop { break; }

Imports:

import std;                 // lazy-loads only called std functions
from std { sin, cos, tan }  // eager import of specific functions

Memory Safety System

  • Immutability by default; @mut required for mutation
  • Single ownership; moves invalidate the source binding
  • Borrowing rules:
    • Multiple immutable borrows
    • One mutable borrow; no other borrows concurrently
  • Lifetimes inferred; references cannot outlive their data
  • Move semantics tracked across control flow
  • All checks happen at compile time (no GC, no ref-count overhead)

Tooling

LSP (src/nscan/):

  • Diagnostics include memory-safety hints and spans
  • Quick fix to convert store@mut store on immutability errors
  • Completion includes @mut, std functions, and string/array methods
  • Formatting, goto-definition, rename, and workspace symbols

Syntax Highlighting:

  • TextMate grammar (nscan-ext/syntaxes/nlang.tmLanguage.json) supports @mut, borrows (&, &@mut), and bitwise operators

Standard Library

Location: src/std_lib/

  • I/O: print, println, input
  • Conversions: str, int, float
  • Strings: upper, lower, trim, contains, split, replace, substring, regex
  • Math: pi, e, exp, ln, log10, log2, sqrt, pow_float, sin, cos, tan, asin, acos, atan, floor, ceil, round, fmod, gcd, lcm, factorial, nPr, nCr, stats (sum_float, mean_float, median_float, variance_float, stddev_float)
  • Collections: reverse, sort
  • Time: time_now, time_elapsed, sleep_ms, format_duration
  • Environment: env_get, env_set, env_remove, env_exists
  • Crypto: sha256, sha256_random

Compilation Pipeline

Source (.nlang)
  ↓
Lexer → Parser → Semantic (type checking)
  ↓
MemManager (immutability/ownership/borrowing/lifetimes/moves)
  ↓
Interpreter         C Codegen
  ↓                    ↓
Direct run          C source → GCC/Clang → Executable

Project Structure

src/
├── ast/              # AST definitions
├── lexer/            # Tokenizer and errors
├── parser/           # Declarations, statements, expressions, types
├── semantic/         # Type checking and analysis
├── memmanager/       # Ownership, borrowing, lifetimes, moves, drops
├── interpreter/      # Execution engine
├── c_codegen/        # C transpiler (portable runtime helpers)
├── execution_engine/ # Unified orchestration for run/compile
├── module_sys/       # Module resolution and registry (mod-rec.toml)
├── nlang_libs/       # Built-in libraries (std_lib, env_man, etc.)
├── diagnostics/      # Error reporting and formatting
├── nscan/            # LSP server and tooling
├── cli.rs            # CLI subcommands
├── lib.rs            # Public API exports
└── main.rs           # Application entry point

Project Structure

A typical NLang project:

my_project/
├── mod-rec.toml      # Module registry (auto-generated)
├── src/
│   └── main.nlang    # Entry point
└── bin/              # Compiled output

Examples

See nlang_examples/ for runnable samples:

  • Hello world, loops, control flow, functions
  • Arrays and multi-dimensional arrays (13_comprehensive_array_test.nlang)
  • String library demos (25_string_library_advanced.nlang)
  • Math std lib demo (26_math_std_lib_demo.nlang)
  • Time library demo (28_time_library_demo.nlang)
  • Environment variables (29_test_env_man.nlang)
  • SHA-256 (pure nlang and built-in) (21_sha256.nlang)
  • Memory safety showcase (27_memory_safety_showcase.nlang)

Testing

cargo test

License

MIT License. See LICENSE.

Acknowledgments

  • Rust community
  • Contributors and users of Nlang

About

Rust implementation of Nlang - A modern systems programming language with Python-like syntax and multi-backend compilation

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors