Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/boblio-max/origin/llms.txt

Use this file to discover all available pages before exploring further.

Origin provides first-class support for both procedural and object-oriented programming. Functions let you encapsulate reusable logic with named parameters and return values. Classes let you bundle related data (fields) and behavior (methods) into typed objects, following a compact declaration style where fields are listed directly in the class signature. This page walks through defining and calling both, including how the interpreter compiles them under the hood.

Defining Functions

Use the def keyword to declare a function. Parameters are listed inside parentheses without type annotations, and the body is wrapped in curly braces:
def greet(name) {
    print "Hello, " + name
}
Call a function by name with arguments in parentheses:
greet("Origin")    # → Hello, Origin

Return Values

Use return to send a value back to the caller:
def add(a, b) {
    return a + b
}

let result: int = add(3, 7)
print result    # → 10

Recursive Functions

Functions can call themselves recursively. Here is a classic factorial example:
def factorial(n) {
    if n <= 1 {
        return 1
    }
    return n * factorial(n - 1)
}

print factorial(5)    # → 120

Defining Classes

Classes are declared with the class keyword. Fields are listed as a comma-separated list inside parentheses after the class name — this is the class signature, not a base-class list. Methods are defined inside the curly-brace body using def:
class Sensor (pin, type) {
    def read() {
        return pin
    }
}
Fields in the class signature must be separated by commas, exactly like function parameters. Writing class Sensor (pin type) without the comma will cause a parse error.

How Classes Compile

The interpreter automatically generates a Python __init__ method from the field list. Each field becomes a parameter that defaults to None, and the body assigns them to self:
# What the interpreter generates:
class Sensor:
    def __init__(self, pin=None, type=None):
        self.pin = pin
        self.type = type

    def read(self):
        return self.pin
Inside methods, refer to fields using self.field_name. The self binding is injected by the interpreter — you do not need to declare it explicitly in your Origin method signature.

Creating Instances

Instantiate a class by calling it like a function, passing values for each field in declaration order:
let s: Sensor = Sensor(12, "digital")

Accessing Fields and Methods

Use dot notation to read fields and call methods:
print s.pin      # → 12
print s.type     # → digital
print s.read()   # → 12
Fields can also be updated via dot assignment:
s.pin = 18
print s.pin      # → 18

Complete Class Example

The following example demonstrates a full class definition alongside instance creation and method invocation:
class Sensor (pin, type) {
    def read() {
        return pin
    }
}

let s: Sensor = Sensor(12, "digital")
print s.pin      # → 12
print s.type     # → digital
print s.read()   # → 12

A Note on yield

The yield keyword is reserved in Origin’s lexer and has an AST node (YieldNode) defined in classes.py, but generator semantics are not yet fully implemented in the interpreter. Avoid using yield in production scripts until this feature is officially released.

Reserved but Unimplemented Keywords

Several keywords appear in the lexer but are not yet wired to interpreter handlers. Do not use them in production scripts:
The following keywords are reserved for future use and will raise a parse or runtime error if used outside of a py { } block: match, case, macro, inline, struct, enum, interface, pub, priv, async, await, when, unless, loop, until, do.

Build docs developers (and LLMs) love