Language Fundamentals
Syntax, lexical grammar, variables, scoping, primitive data types, operators, control flow, functions, and first-class closures.
Syntax, Semicolon-Optional Model & Comments
BramandScript features a modern, semicolon-optional grammar. Semicolons (;) may be used to separate statements on the same line, but are never required at line endings.
// Single-line comments start with double slashes
/*
Multi-line comments can span
across multiple lines cleanly.
*/
// Clean, semicolon-free statements
let title = "BramandScript"
let version = 0.1
// Semicolons can be used for multi-statement single lines:
let a = 1; let b = 2; let c = a + b
print(c)
Variables (let), Constants (const), and Scoping
Identifiers are declared using let (for mutable bindings) or const (for immutable bindings). Variables are lexically scoped.
// Mutable variable
let score = 100
score = 150 // Direct reassignment
score += 25 // Compound addition (score is now 175)
score -= 10 // Compound subtraction
score *= 2 // Compound multiplication
score /= 4 // Compound division
// Immutable constant
const MAX_CONNECTIONS = 1024
// International Unicode Identifiers (Devanagari, CJK, Greek, Accented):
let संदेश = "नमस्ते ब्रह्माण्ड"
const संख्या = 108
let 変数 = 42
// Trying to reassign a const raises a CompileError:
// MAX_CONNECTIONS = 2048 // error[CompileError]: cannot reassign to constant variable 'MAX_CONNECTIONS'
Pattern Destructuring Bindings
BramandScript supports modern pattern destructuring for Arrays and Hashes directly in let and const declarations, including the rest operator (...):
// Array destructuring with rest operator
let [x, y, ...tail] = [10, 20, 30, 40, 50]
println("x:", x, "y:", y) // 10, 20
println("tail elements:", tail) // [30, 40, 50]
// Hash pattern destructuring
let point = { "x": 100, "y": 200, "z": 300 }
let { x, y } = point
println("Extracted point coordinates:", x, y)
// Immutable destructuring with const
const { host, port } = { "host": "127.0.0.1", "port": 8080 }
Top-level variables reside in the GlobalScope (indexed up to 65,536 globals). Variables declared inside functions belong to the LocalScope mapped to the VM frame's base pointer. Variables referenced from an enclosing function outer scope are converted into FreeScope closure cells!
Data Types & Literals (Int, Float, String, Boolean, Null)
BramandScript supports five primary primitive data types, all represented by dedicated runtime objects inside object/object.go:
| Type | Underlying Representation | Literal Syntax Examples | Hashable? |
|---|---|---|---|
INTEGER |
64-bit Signed Integer (int64) |
0, 42, -999, 1000000 |
YES |
FLOAT |
64-bit IEEE 754 Floating-Point (float64) |
3.14159, 0.05, -12.75 |
NO |
STRING |
UTF-8 Character String with escape sequences | "Hello", "Line\nTab\t" |
YES (FNV-1a 64) |
BOOLEAN |
Canonical Singleton Booleans | true, false |
YES |
NULL |
Canonical Null Object | null |
NO |
TUPLE |
Fixed-Length Immutable Sequence | (), (42,), (1, 2, 3) |
YES (FNV-1a 64) |
RESULT |
Algebraic Monad (Ok / Err) |
Ok(v), Err(e) |
NO |
OPTION |
Algebraic Monad (Some / None) |
Some(v), None() |
NO |
FUTURE |
Asynchronous Promise Container | Returned by async fn |
NO |
ACTOR |
Lightweight Isolated Process | Returned by actor(fn, init) |
NO |
let intVal = 42
let floatVal = 3.14159
let text = "Pure Go VM\nWith UTF-8 unicode support"
let flag = true
let empty = null
print("Type of int:", type(intVal)) // INTEGER
print("Type of float:", type(floatVal)) // FLOAT
print("Type of text:", type(text)) // STRING
String Manipulation Builtins
BramandScript includes robust Unicode-compliant string manipulation primitives for formatting, tokenization, and text processing:
let line = " brahmand,cosmos,universe "
// Trimming whitespace
let clean = trim(line) // "brahmand,cosmos,universe"
// Case conversion
println(to_upper(clean)) // "BRAHMAND,COSMOS,UNIVERSE"
println(to_lower("BRAMAND SCRIPT")) // "bramand script"
// Splitting and Joining
let parts = split(clean, ",") // ["brahmand", "cosmos", "universe"]
let joined = join(parts, " :: ") // "brahmand :: cosmos :: universe"
// Substring extraction (supports negative indexing)
println(substring(clean, 0, 8)) // "brahmand"
println(substring(clean, -8, len(clean))) // "universe"
// String replacement
let updated = replace(clean, "cosmos", "galaxy")
println(updated) // "brahmand,galaxy,universe"
| Function | Exact Signature | Return | Description |
|---|---|---|---|
split | split(str, sep) | ARRAY | Splits string by separator into an array of substrings. |
join | join(arr, sep) | STRING | Concatenates array of elements into a string delimited by separator. |
substring | substring(str, start, [end]) | STRING | Extracts substring between start and end indices with negative index support. |
trim | trim(str) | STRING | Strips leading and trailing whitespace characters. |
to_lower | to_lower(str) | STRING | Converts all UTF-8 characters to lowercase. |
to_upper | to_upper(str) | STRING | Converts all UTF-8 characters to uppercase. |
replace | replace(str, old, new) | STRING | Replaces all occurrences of old substring with new substring. |
String Interpolation & Template Literals
BramandScript provides native first-class string interpolation via f"..." format strings and backtick template literals (`...`). Expressions enclosed in {expr} or ${expr} are parsed directly into AST expressions and lowered by the compiler into efficient concatenated bytecode without runtime reflection overhead:
let user = "Devendra"
let role = "Lead Architect"
let year = 2026
// Python-style format string with {expr}
let greeting = f"Welcome {user}, role: {role} (v{year + 1})!"
println(greeting) // "Welcome Devendra, role: Lead Architect (v2027)!"
// JavaScript-style backtick template literal with ${expr}
let summary = `Architect: ${user} | System active: ${year}`
println(summary)
// Literal braces escaped with {{ and }}
let json_tmpl = f"{{\"user\": \"{user}\", \"status\": 200}}"
println(json_tmpl) // {"user": "Devendra", "status": 200}
Adaptive Numeric Core & Transparent BigInt Promotion
BramandScript automatically and transparently promotes standard 64-bit integer arithmetic (+, -, *, **) to arbitrary-precision BigInt when results exceed signed 64-bit limits (> 9,223,372,036,854,775,807). This completely eliminates silent integer overflow wrapping bugs, while retaining raw unboxed int64 speed on small numbers!
let max_int64 = 9223372036854775807
let promoted = max_int64 + 10
println("Type:", type(promoted)) // BIG_INT
println("Value:", promoted) // 9223372036854775817
// Gargantuan exponentiation without integer overflow
let huge = 2 ** 70
println("2^70:", huge) // 1180591620717411303424
// Fast modular exponentiation builtin (base^exp % mod)
let pm = pow_mod(7, 560, 561)
println("Modular exponentiation:", pm) // 1
Operators & Expressions (Arithmetic, Logical, Comparisons, Exponentiation)
BramandScript parses expressions using a Pratt parser with mathematically rigorous precedence hierarchies.
Operator Precedence Table
| Level | Operator | Associativity | Description |
|---|---|---|---|
| 1 (Lowest) | |> |
Left-to-Right | Pipeline Operator |
| 2 | <- |
Left-to-Right | Channel Send / Receive |
| 3 | ? : |
Right-to-Left | Ternary Conditional Operator (Short-Circuit) |
| 4 | ?? |
Left-to-Right | Null-Coalescing Operator (Short-Circuit) |
| 5 | || |
Left-to-Right | Logical OR (Value-Preserving Short-Circuit) |
| 6 | && |
Left-to-Right | Logical AND (Value-Preserving Short-Circuit) |
| 7 | | |
Left-to-Right | Bitwise OR |
| 8 | ^ |
Left-to-Right | Bitwise XOR |
| 9 | & |
Left-to-Right | Bitwise AND |
| 10 | ==, != |
Left-to-Right | Equality and Inequality |
| 11 | <, >, <=, >= |
Left-to-Right | Relational Comparisons |
| 12 | <<, >> |
Left-to-Right | Bitwise Left and Right Shifts |
| 13 | +, - |
Left-to-Right | Addition, Subtraction, String Concatenation |
| 14 | *, /, % |
Left-to-Right | Multiplication, Division, Modulo |
| 15 | ** |
Right-to-Left | Exponentiation / Power |
| 16 | !, -, ~ (prefix) |
Right-to-Left | Unary Bang, Negation, Bitwise NOT |
| 17 | () |
Left-to-Right | Function Call |
| 18 (Highest) | [], ., ?., ? (postfix) |
Left-to-Right | Index, Dot Access, Optional Chaining, Try-Propagation |
// Exponentiation is right-associative: 2 ** 3 ** 2 == 2 ** 9 == 512
let powVal = 2 ** 3 ** 2
print("2 ** 3 ** 2 =", powVal) // 512
// Mixed-type automatic numeric promotion
let mixed = 10 + 3.5
print("10 + 3.5 =", mixed) // 13.5 (FLOAT)
// String concatenation
let msg = "Bramand" + "Script" + " " + 2026
print(msg) // BramandScript 2026
Pipeline Operator (|>)
The pipeline operator (|>) allows data-first, fluent functional chaining without deeply nested parenthesized calls. At compile time, the bytecode compiler lowers pipeline expressions directly into standard nested function calls with zero intermediate stack or allocation overhead:
let inc = fn(x) { return x + 1; };
let sq = fn(x) { return x * x; };
let add = fn(x, y) { return x + y; };
// 3 |> inc |> sq is lowered directly to sq(inc(3)) -> 16
let res = 3 |> inc |> sq
println("Result:", res) // 16
// Supplying additional arguments to pipelined functions
let res2 = 5 |> add(10) |> inc // add(5, 10) -> 15 -> inc(15) -> 16
println("Result 2:", res2) // 16
Null-Coalescing (??) & Nullish Assignment (??=)
The null-coalescing operator (??) provides clean fallback semantics for null values. Unlike logical OR (||) which falls back on any falsey value (such as 0 or false), ?? evaluates its right operand only if the left operand evaluates strictly to null:
let user_input = null
let fallback = "default_user"
let name = user_input ?? fallback // "default_user"
// Preserves falsey non-null values (0, false, "")
let count = 0
let total = count ?? 100 // 0 (NOT replaced with 100)
// Nullish assignment (??=) assigns only if currently null
let config = {"host": "localhost", "port": null}
config["port"] ??= 8080 // Assigns 8080 because port was null
config["host"] ??= "example.com" // Preserved "localhost"
Optional Chaining Operator (?.)
Optional chaining safely traverses deeply nested property accesses, indexed collections, and method invocations without risking runtime null dereference errors. If any stage in the chain resolves to null, the entire expression immediately short-circuits and evaluates to null:
let account = {"profile": null}
// Safe property navigation: returns null instead of raising error
let city = account?.profile?.address?.city
println("City:", city) // null
// Safe index navigation (?.[idx])
let items = null
let first = items?.[0] // null
// Safe method / function invocation (?.())
let service = {"fetch": null}
let result = service.fetch?.("users") // null (fetch is never called)
Ternary Conditional Operator (? :)
BramandScript supports C-style ternary expressions with right-to-left associativity and guaranteed short-circuit evaluation:
let score = 85
let grade = score >= 90 ? "A" : score >= 80 ? "B" : "C"
println("Grade:", grade) // "B"
let is_admin = true
let access = is_admin ? "granted" : "denied"
println("Access:", access) // "granted"
Control Flow (if / else if / else with optional parens, while)
Conditionals in BramandScript do not require enclosing parentheses around their condition expressions, keeping syntax clean and readable. In addition to ternary conditional expressions (cond ? a : b), if blocks are first-class expressions that evaluate directly to a value (let x = if cond { a } else { b }).
if, else if, else
let speed = 75
// Clean syntax without parentheses:
if speed > 100 {
print("Extreme Velocity!")
} else if speed >= 60 {
print("Cruising Speed")
} else {
print("Idle or Slow")
}
// If expressions produce values:
let category = if speed >= 60 { "Fast" } else { "Slow" }
print("Category:", category)
while Loops with break and continue
Loops execute while their condition evaluates to a truthy value. Control jumps are backpatched directly in the bytecode instruction stream using OpJumpNotTruthy and OpJump.
let count = 0
let total = 0
while count < 10 {
count += 1
if count == 3 {
continue // Skip adding 3
}
if count == 8 {
break // Terminate loop early
}
total += count
}
print("Computed Total:", total)
Functions & Mutable Lexical Closures (fn)
Functions in BramandScript are first-class citizens. They can be defined as named functions or assigned as anonymous expressions. Crucially, closures capture free variables by reference, enabling mutable state encapsulation!
// Named function declaration
fn multiply(a, b) {
return a * b
}
// Higher-order function returning a stateful closure
fn createCounter(start) {
let count = start
return fn() {
count += 1 // Mutates free variable in outer lexical scope!
return count
}
}
let counterA = createCounter(10)
print(counterA()) // 11
print(counterA()) // 12
let counterB = createCounter(100)
print(counterB()) // 101
print(counterA()) // 13 (independent state!)
When a function references identifiers from an enclosing scope, the compiler emits OpClosure <constIndex> <numFree>. Free variables are pushed to the stack and captured into an array of object references inside the closure object. Access and mutation are performed via OpGetFree and OpSetFree.
Function Parameter Destructuring
Function signatures can directly destructure dictionary keys and array elements into scoped parameter bindings:
// Destructure object properties directly in parameters
fn distance({ x, y }) {
return sqrt((x * x) + (y * y))
}
println("Distance:", distance({ "x": 3.0, "y": 4.0 })) // 5.0
// Destructure array elements with rest parameter
fn sum_head([a, b, ...rest]) {
return a + b
}
println("Head sum:", sum_head([10, 20, 30, 40])) // 30
Default Parameters
Functions support default parameter values evaluated when the caller omits corresponding arguments or passes null:
let greet = fn(name = "World", punctuation = "!") {
return "Hello, " + name + punctuation
}
println(greet()) // "Hello, World!"
println(greet("Bramand")) // "Hello, Bramand!"
println(greet("Kiran", " :)")) // "Hello, Kiran :)"
Asynchronous Functions (async fn)
Declaring an async fn causes calls to execute concurrently on child VM fiber frames, returning an uncolored Future resolvable via await:
async fn load_resource(uri) {
sleep(10)
return "payload from " + uri
}
let fut = load_resource("https://example.com/api")
println("Resolved:", await fut) // "payload from https://example.com/api"
Generator Functions & yield
Generators enable stateful, resumable stream computation using lightweight coroutines. In conjunction with std/iter, functions yield successive values lazily without computing the entire dataset into memory:
import "std/iter" as iter
let fib_gen = iter.generator(fn(yield) {
let a = 0
let b = 1
while true {
yield a
let next = a + b
a = b
b = next
}
})
let first_six = iter.take(fib_gen, 6)
println("First 6 Fibonacci numbers:", first_six) // [0, 1, 1, 2, 3, 5]
Default Parameter Values (fn connect(host, port = 8080))
Functions support optional parameters with declarative default values. If omitted or passed as null, parameters evaluate to their default expressions. Default expressions can even reference preceding parameters:
// Parameters with defaults
fn connect(host, port = 8080, timeout = 30) {
return f"Connecting to {host}:{port} with timeout {timeout}s"
}
println(connect("localhost")) // "Connecting to localhost:8080 with timeout 30s"
println(connect("db.internal", 5432)) // "Connecting to db.internal:5432 with timeout 30s"
println(connect("api.prod", 443, 10)) // "Connecting to api.prod:443 with timeout 10s"
// Default expression referencing prior parameter
fn create_box(width, height = width) {
return width * height
}
println("Square area:", create_box(5)) // 25
LIFO defer Statement for Guaranteed Cleanup
The defer statement registers a function or method call to be executed immediately before the enclosing function returns, regardless of whether exit occurs via normal completion, early return, or uncaught exception unwinding. Multiple deferred calls execute in strict Last-In, First-Out (LIFO) order:
fn safe_transaction() {
let mu = mutex()
mu.lock()
defer mu.unlock() // Guaranteed to unlock even on early return or exception!
println("Acquired lock")
if error_condition {
return "failed" // mu.unlock() runs before this return!
}
return "success" // mu.unlock() runs before this return!
}
// LIFO Execution Ordering:
fn order_demo() {
defer println("Third")
defer println("Second")
defer println("First")
println("Body")
}
// Output: Body, First, Second, Third
Low-Level Primitives, Binary Bytes, Runes & Dynamic Eval
For binary protocol implementations, network packets, bytecode engines, and language toolchains, BramandScript provides first-class bitwise operators, high-performance raw byte buffers (bytes), Unicode code point introspection (ord, chr), and dynamic in-memory code execution (eval).
1. Bitwise Operators (&, |, ^, <<, >>, ~)
BramandScript natively supports standard bitwise integer manipulation directly in the compiler and virtual machine via dedicated bytecode opcodes (OpBitAnd, OpBitOr, OpBitXor, OpShiftLeft, OpShiftRight, and OpBitNot):
// Binary flag definitions using bit shifts
const FLAG_READ = 1 << 0 // 0b0001 (1)
const FLAG_WRITE = 1 << 1 // 0b0010 (2)
const FLAG_EXECUTE = 1 << 2 // 0b0100 (4)
// Bitwise OR combining flags
let permissions = FLAG_READ | FLAG_WRITE
println("Permissions mask:", permissions) // 3
// Bitwise AND testing flags
let canWrite = (permissions & FLAG_WRITE) != 0
println("Can write:", canWrite) // true
// Bitwise XOR toggling bits
let toggled = permissions ^ FLAG_WRITE
println("After toggle:", toggled) // 1 (only FLAG_READ remaining)
// Bitwise Shifts
println(16 >> 2) // 4
println(1 << 8) // 256
// Unary Bitwise NOT
println(~0) // -1
println(~1) // -2
2. Raw Byte Buffers & Binary I/O (bytes)
The bytes constructor allocates and wraps contiguous heap byte buffers ([]byte). Byte buffers support index mutations, hexadecimal export (to_hex()), string conversion (to_string() or str()), sub-slicing (slice()), and structured binary encoding for multi-byte integers with configurable endianness ("be" for Big-Endian, "le" for Little-Endian):
// 1. Allocate a zeroed buffer of 16 bytes
let buf = bytes(16)
println("Buffer capacity:", len(buf)) // 16
// 2. Direct byte indexing and mutations
buf[0] = 72 // ASCII 'H'
buf[1] = 101 // ASCII 'e'
buf[2] = 121 // ASCII 'y'
println(str(slice(buf, 0, 3))) // "Hey"
// 3. Structured Multi-Byte Binary I/O (Big-Endian & Little-Endian)
let packet = bytes(8)
packet.write_u8(0, 255) // 8-bit unsigned integer
packet.write_u16(1, 0xABCD, "be") // 16-bit Big-Endian
packet.write_u32(3, 12345678, "le") // 32-bit Little-Endian
println("Read u8:", packet.read_u8(0)) // 255
println("Read u16 (be):", packet.read_u16(1, "be")) // 43981 (0xABCD)
println("Read u32 (le):", packet.read_u32(3, "le")) // 12345678
// 4. Hexadecimal conversion & String ingestion
let raw = bytes([0xDE, 0xAD, 0xBE, 0xEF])
println("Hex representation:", raw.to_hex()) // "deadbeef"
3. Unicode Code Point & Rune Primitives (ord, chr)
For language parsers, text transformation pipelines, and character scanners, BramandScript includes built-in rune introspection:
// ord(char): returns Unicode code point integer
println(ord("A")) // 65
println(ord("z")) // 122
println(ord("✦")) // 10022
// chr(code): returns single UTF-8 rune string
println(chr(65)) // "A"
println(chr(122)) // "z"
println(chr(10022)) // "✦"
// Check if character is an ASCII uppercase letter
let isUpper = fn(ch) {
let code = ord(ch)
return code >= 65 && code <= 90
}
println("Is 'M' uppercase:", isUpper("M")) // true
4. In-Memory Dynamic Code Evaluation (eval)
The eval(code_str) builtin allows BramandScript programs to parse, compile, and execute code dynamically at runtime inside an isolated VM execution context. Syntax and compiler errors raise catchable runtime diagnostics:
// Dynamically evaluate mathematical expressions
let expr = "25 * 4 + 15"
let result = eval(expr)
println("Eval calculation:", result) // 115
// Dynamically execute logic scripts
let script = "let a = 50; let b = 75; if a < b { 'PASS' } else { 'FAIL' }"
let status = eval(script)
println("Script output:", status) // "PASS"
Exception Handling (try-catch-finally) & Permission Guards
BramandScript provides commercial-grade structured exception handling with first-class try, catch, finally, and throw statements, paired with a granular capability-based permission model.
1. Structured Exception Handling
Runtime errors (such as divide by zero or missing map keys) as well as explicitly thrown values can be safely intercepted using try { } catch err { } blocks:
// Catching runtime arithmetic faults
try {
let result = 100 / 0;
} catch err {
println("Safely caught:", err);
}
// Throwing and catching custom errors
try {
throw "User record not found";
} catch e {
println("Caught error:", e);
} finally {
println("Cleanup logic always runs");
}
2. Capability Permission Guards
To protect host environments, dangerous operations such as external process execution (exec), file system mutations (write_file, delete_file), and network listening (tcp_listen) are guarded behind explicit CLI permission flags:
| CLI Permission Flag | Protected Builtins | Behavior Without Flag |
|---|---|---|
--allow-run |
exec() |
Raises PermissionDenied: requires '--allow-run' |
--allow-write |
write_file(), append_file(), delete_file() |
Raises PermissionDenied: requires '--allow-write' |
--allow-net |
tcp_listen(), net sockets |
Raises PermissionDenied: requires '--allow-net' |
--allow-all |
All protected operations | Unrestricted full capability execution |
3. Enterprise Error Tracking & Call Stack Inspection
For enterprise debugging, observability, and diagnostics, BramandScript's VM automatically captures the full call stack upon any runtime fault or error(msg) instantiation. Caught errors expose structured stack introspection:
fn execute_payment(user_id, amount) {
if amount <= 0 {
throw error("InvalidPayment: amount must be strictly positive")
}
}
fn process_order(order) {
execute_payment(order["user"], order["amount"])
}
try {
process_order({"user": "usr_99", "amount": -10})
} catch err {
println("Error message:", err.message)
// Formatted multi-frame call stack:
println("Call trace:\n", err.stack_trace)
// Structured frame objects: [{"fn": "execute_payment", "line": 3}, ...]
println("Frame count:", len(err.frames))
}
Compile-Time Metaprogramming Sandbox (comptime { ... })
BramandScript provides native compile-time evaluation via the comptime { ... } language primitive. The AST compiler spins up an isolated, deterministic Go VM sandbox during compilation to execute arbitrary statements, compute lookup tables, and unroll loops—directly inlining the resulting values into the bytecode constant pool (OpConstant) with zero runtime latency.
// Precompute factorial lookup table entirely during compilation
let factorials = comptime {
let t = [];
let val = 1;
let i = 1;
while i <= 6 {
val = val * i;
push(t, val);
i = i + 1;
}
return t;
}; // Compiled directly to: OpConstant [1, 2, 6, 24, 120, 720]
// Inlined compile-time configuration and string transformations
let greeting = comptime {
let prefix = "WELCOME TO";
let name = "BRAMAND";
return prefix + " " + name + " VM";
};
println("Factorials table:", factorials)
println("Banner:", greeting)
- Zero Runtime Overhead: Evaluated strictly at compile time; runtime opcode stream contains only instant constant pushes.
- Isolated VM Context: Comptime blocks execute inside a clean, sandbox VM without polluting the parent compilation frame or outer variable scope.
- Full Language Expressiveness: Supports loops, conditionals, arrays, hashes, math builtins, and string operations within the block.