Skip to content

Latest commit

 

History

History
427 lines (310 loc) · 8.87 KB

File metadata and controls

427 lines (310 loc) · 8.87 KB

ROX Language Reference

ROX is a minimal, clarity-first programming language built on a simple belief:

Programming logic should not have to fight the language.

ROX removes implicit behavior, hidden conversions, and syntactic tricks so that expressing logic feels direct and mechanical rather than negotiated.

First Principles

  • We no longer write code that must fit on a punch card — readability wins over brevity.
  • Code is read far more than it is written. Optimize for the reader, not the writer.
  • Code is written in calm and read in crisis.
  • Cleverness is often the enemy of clarity.

Language Guarantees (v0)

  • No implicit type conversions
  • No bracket indexing ([] only for list literals)
  • No exceptions — errors are explicit values (rox_result[T])
  • A single loop construct (for)
  • Explicit control flow only
  • Strict compile-time type checking
  • Reserved Prefix: roxv26_ is reserved for internal namespacing. User variables must not start with this prefix.

Namespacing (v0)

ROX automatically namespaces all user-defined identifiers to prevent collisions with C++ keywords and standard library symbols.

  • User variable x becomes roxv26_x in generated C++.
  • Reserved Components: The following are NOT namespaced:
    • main function (entry point)
    • Built-in functions (print, isOk, etc.)
    • Standard library constants (true, false, none)

Rule: User identifiers must not begin with roxv26_. This prefix is reserved for the compiler.

Operators

Arithmetic

  • +, -, *: Standard arithmetic.
  • /: Division. Returns rox_result[T].
  • %: Modulo. Returns rox_result[T].

Comparison

  • ==: Equal
  • <, <=, >, >=
  • Note: != is not supported. Use not (a == b).

Logical

  • and
  • or
  • not: Replaces ! and !=. e.g., not (a == b).

Types

ROX is a statically typed language. All types must be explicit.

Primitive Types

  • int64: 64-bit Signed Integer. The default integer type.

    int64 x = 42;
    
    
    
  • float64: 64-bit Floating Point.

    float64 f = 3.14;
    
  • bool: Boolean (true or false).

  • char: Single ASCII character.

    char c = 'A';
    
  • string: Immutable sequence of UTF-8 bytes.

    string s = "Hello";
    
  • none: Unit type (similar to void).

Composite Types

  • list[T]: Dynamic Array. Ordered collection of elements of type T.
    list[int64] numbers = [1, 2, 3];
    
  • dictionary[K, V]: Hash Map. Key-value pairs.
    dictionary[string, int64] scores;
    

Record Types

User-defined types with named, typed fields.

type User {
    id: int64
    name: string
}

Construction — all fields are required, using named-field initializers:

User u = User{ id: 7, name: "Taman" };

Field Access & Assignment:

print(u.name);      // field access
u.name = "Apon";     // field mutation

Copy Semantics — assignment copies the entire record:

User b = a;  // b is an independent copy

Nested Records:

type Address {
    city: string
    country: string
}

type User {
    id: int64
    address: Address
}

Functions on Records — no methods, just functions:

function label(User u) -> string {
    return u.name;
}

Compile-time errors:

  • Missing required field
  • Unknown field name
  • Duplicate field
  • Field type mismatch
  • Unknown field access
  • Uninitialized record declaration (User u;)

Result Type

  • rox_result[T]: Explicit error handling type.

    rox_result[int64] result = list.at(5);
    if (isOk(result)) {
        // Safe to call getValue(result) here
        int64 val = getValue(result);
    } else {
        print("Error: ", getError(result), "\n");
    }
    

    Safety Note: getValue(result) can only be called when the result is proven to be ok. The compiler enforces this via flow-sensitive analysis.

    Supported patterns:

    1. If-Check:
      if (isOk(result)) {
          int64 val = getValue(result);
      }
      
    2. Early Return:
      if (not(isOk(result))) {
          return; // or break/continue
      }
      // Safe to use here
      int64 val = getValue(result);
      

    Reassigning result invalidates these checks.

Control Flow

Conditionals

Standard if / else if / else.

if (x > 10) {
    print("Big\n");
} else {
    print("Small\n");
}

Loops

ROX has a single loop construct: for.

// range(start, end, step) - all 3 arguments required
for i in range(0, 5, 1) { ... }

// Backwards
for i in range(10, 0, -1) { ... }

Notes:

  • ROX has no unbounded loop construct.
  • Every for loop iterates over:
    • a finite range(start, end, step), or
    • a finite collection (e.g., list[T]).
  • range is bounded by int64 arithmetic. Practical termination is guaranteed for well-formed inputs.

Iterating Collections

list[int64] nums = [1, 2, 3];
for n in nums {
    print(n, " ");
}

The for item in collection form works with any list[T].

Loop Control

  • break: Terminates the loop.
  • continue: Skips to next iteration.

## Collections

### Lists

Access is strictly checked and returns `rox_result[T]`.

**Methods:**

- `.size() -> int64`
- `.append(item) -> none`
- `.pop() -> none`
- `.at(index) -> rox_result[T]`

### Dictionaries

Key-value maps. Access returns `rox_result[V]`.

**Methods:**

- `.set(key, value) -> none`
- `.remove(key) -> none`
- `.has(key) -> bool`
- `.size() -> int64`
- `.get(key) -> rox_result[V]`
- `.getKeys() -> list[K]`

### Strings

Immutable sequence of bytes.

**Methods:**

- `.size() -> int64`
- `.at(index) -> rox_result[char]`

## Functions

Functions are first-class citizens in ROX. They must specify parameter types and return types explicitly.

```rox
function add(int64 a, int64 b) -> int64 {
    return a + b;
}
```

### Syntax

```rox
function name(type name, ...) -> return_type {
    // body
    return value;
}
```

- **Parameters**: Must have explicit types.
- **Return Type**: Must be explicit. Use `none` if no value is returned.
- **Recursion**: Supported.
- **Type Matching**: Function types must match exactly. No implicit conversions or variance are allowed.

### Return Values

Functions returning `none` can omit the return statement or use `return;` or `return none;`.

```rox
function log(string msg) -> none {
    print(msg);
    // Implicit return none
}
```

**Rule**: If a function has return type `none`, reaching the end of the function body implicitly returns `none`.

### Functions as Values

Functions can be assigned to variables, passed as arguments, and returned from other functions.

**Syntax for Function Types:** `function(paramType1, paramType2,...) -> returnType`

```rox
function add(int64 a, int64 b) -> int64 {
    return a + b;
}

// Assignment
function(int64, int64) -> int64 op = add;

// Passing as argument
function apply(function(int64, int64) -> int64 f, int64 a, int64 b) -> int64 {
    return f(a, b);
}

// Returning functions
function log(string msg) -> none {
    print(msg);
}

function get_logger() -> function(string) -> none {
    return log;
}

function(string)->none logger = get_logger();
logger("Log this message\n");
```

## Built-in Functions

- `print(val...) -> none`: Variadic. Accepts one or more arguments.

- `isOk(rox_result[T]) -> bool`
- `getValue(rox_result[T]) -> T`
- `getError(rox_result[T]) -> string`

- `default(T) -> T`: Returns the zero/empty value for any type.
  - `default(int64)` → `0`
  - `default(float64)` → `0.0`
  - `default(bool)` → `false`
  - `default(string)` → `""`
  - `default(list[T])` → `[]`
  - `default(dict[K,V])` → `{}`
  - `default(Record)` → fieldwise defaults (recursive)

- `read_line() -> rox_result[string]`
  - Reads one line from standard input.
  - The returned string does not include the newline character.
  - On end-of-file, returns err(EOF).
  - On I/O failure, returns err(<error_message>).

**Example: Echo stdin**

```rox
function main() -> none {
    for i in range(0, 1000000, 1) {
        rox_result[string] line = read_line();
        if (isOk(line)) {
            print(getValue(line), "\n");
        } else if (getError(line) == EOF) {
            break;
        } else {
            print("error: ", getError(line), "\n");
            break;
        }
    }
}
```

### Built-in Constants

- `pi` (float64)
- `e` (float64)
- `EOF` (string) — error returned by `read_line()` on end of input

## Math Library

### `int64` (64-bit)

- `int64_abs(n)`
- `int64_min(a, b)`
- `int64_max(a, b)`
- `int64_pow(base, exp) -> rox_result[int64]`



### `float64` (double)

- `float64_abs(n)`
- `float64_min(a, b)`
- `float64_max(a, b)`
- `float64_pow(base, exp)`
- `float64_sqrt(n) -> rox_result[float64]`
- `float64_sin, float64_cos, float64_tan`
- `float64_log, float64_exp`
- `float64_floor, float64_ceil`

## Comments

Single-line comments starting with `//`.

```rox
// This is a comment
int64 x = 10;