NSL Language Overview
NSL Language Overview
Section titled “NSL Language Overview”What is NSL?
Section titled “What is NSL?”NSL (Nox Scripting Language) is the programming language executed by the Nox runtime. It is intentionally familiar — borrowing syntax from C, Java, and JavaScript — but its semantics are strictly controlled by the sandbox.
Every .nox file represents a single program that can optionally import other .nox files as namespaced libraries.
Design Goals
Section titled “Design Goals”| Goal | How NSL Achieves It |
|---|---|
| Easy to learn and generate | C-family syntax, no unusual constructs which makes it familiar to developers and trivial for code generators |
| Safe by default | Static types, no implicit permissions, no escape hatches |
| Developer-friendly | Rich error messages with suggestions, string interpolation, UFCS for ergonomic APIs |
| Expressive enough | Structs, flexible json type, UFCS, streaming with yield |
| No unnecessary complexity | No classes, no inheritance, no generics, no closures |
A Complete Example
Section titled “A Complete Example”@tool:name "data_processor"@tool:description "Downloads a JSON report, validates it, and yields progress."@tool:author "Data Engineering"
type ReportItem { double value; string name;}
boolean isSignificant(ReportItem item, double threshold) { return item.value > threshold;}
main(string url, double minThreshold = 10.5) { yield `Initializing connection to ${url}`;
try { json data = Http.getJson(url);
int totalProcessed = 0; double sumValues = 0.0;
for (int i = 0; i < data.size(); i++) { ReportItem item = data[i] as ReportItem;
if (item.isSignificant(minThreshold)) { sumValues = sumValues + item.value; totalProcessed = totalProcessed + 1; }
if (i % 10 == 0) { yield `Analyzed ${i + 1} items...`; } }
return `Processed ${totalProcessed} significant items. Total value: ${sumValues}`;
} catch (err) { yield `Error during processing: ${err}`; return "Task Failed"; }}Language Structure
Section titled “Language Structure”A .nox file follows a strict top-down structure:
┌─────────────────────────────┐│ 1. Metadata Headers │ @tool:name, @tool:description, etc.│ (optional) │├─────────────────────────────┤│ 2. Import Declarations │ import "math.nox" as m;│ (optional) │├─────────────────────────────┤│ 3. Type Definitions │ type Point { int x; int y; }│ (optional) │├─────────────────────────────┤│ 4. Helper Functions │ int add(int a, int b) { ... }│ (optional) │├─────────────────────────────┤│ 5. main() Entry Point │ main(string arg1) { ... }│ (optional for libraries)│└─────────────────────────────┘Key Language Features
Section titled “Key Language Features”Static Typing
Section titled “Static Typing”Every variable has a known type at compile time. Type mismatches are caught during semantic validation, before any code runs.
int x = 42; // Correctint y = "hello"; // SemanticError: Cannot assign 'string' to 'int'String Interpolation
Section titled “String Interpolation”Template literals with backticks are the idiomatic way to build strings:
int count = 42;string msg = `Found ${count} items.`; // "Found 42 items."Unified Function Call Syntax (UFCS)
Section titled “Unified Function Call Syntax (UFCS)”Functions can be called as if they were methods of their first argument:
double dist1 = calculateDistance(origin); // Standard calldouble dist2 = origin.calculateDistance(); // UFCS, identical semanticsStreaming with yield
Section titled “Streaming with yield”Programs can send intermediate results, enabling progress updates for long-running operations:
yield "Step 1 complete...";yield "Step 2 complete...";return "All done.";Capability-Based I/O
Section titled “Capability-Based I/O”All external operations go through namespaced libraries with permission checks:
string content = File.read("/data/input.txt"); // Requires file.read permissionjson response = Http.getJson("https://api.com"); // Requires http.get permissiondouble root = Math.sqrt(144); // No permission neededScript Imports (Tier 2)
Section titled “Script Imports (Tier 2)”Reuse code across files by importing other .nox files as namespaced libraries:
import "utils/math_helpers.nox" as mh;import "formatting.nox" as fmt;
main() { double result = mh.calculate(42); yield fmt.prettyPrint(result);}Imported files can have their own main() for standalone testing, it is simply not exported when imported. The namespace must be explicitly specified and cannot clash with built-in library names (Math, File, Http, etc.).
Reserved Words
Section titled “Reserved Words”int, double, boolean, string, json, void,true, false, null,if, else, while, for, foreach, in,return, yield, break, continue,try, catch, throw,type, main, as, importOperator Precedence
Section titled “Operator Precedence”| Precedence | Operators | Associativity |
|---|---|---|
| 1 (highest) | !, -, ~ (unary), ++, -- | Right |
| 2 | *, /, % | Left |
| 3 | +, - | Left |
| 4 | <<, >>, >>> | Left |
| 5 | <, <=, >, >= | Left |
| 6 | ==, != | Left |
| 7 | & | Left |
| 8 | ^ | Left |
| 9 | | | Left |
| 10 | && | Left |
| 11 (lowest) | || | Left |
Assignment operators: =, +=, -=, *=, /=, %=
Comments
Section titled “Comments”// Single-line comment
/* Multi-line comment*/