Fahrenheit 0.4.0

Structures

Defining Structures

Use the structure keyword to define data shapes. Fields can have optional types and default initialization expressions.


structure Person {
    String name;
    int age = 0;

    function void greet() {
        print("Hello, my name is " + this.name);
    }
}

p = Person("Alice", 30);
p.greet(); # Prints: Hello, my name is Alice
    

Constructors

You can define an initialization method named constructor.


structure User {
    name;
    role;

    function constructor(name, role) {
        this.name = name;
        this.role = role;
    }
}

u = User("Bob", "Admin");
    

Inheritance

Structures can inherit fields and methods using extends.


structure Animal {
    name;
    function speak() { print("Generic noise"); }
}

structure Dog extends Animal {
    breed;
    function speak() { print("Woof!"); }
}

d = Dog("Buddy", "Golden Retriever");
d.speak(); # Prints: Woof!
    

Calculated Parent Fields

You can pass expressions to the parent in the extends clause, evaluated using the child's field arguments.


structure Shape { area; }

# Square passes (width * width) as the value for Shape's 'area' field
structure Square extends Shape(width * width) {
    width;
}

s = Square(5);
print(s.area); # 25
    

Super Constructor

Use super(...) inside a child constructor to call the parent structure's constructor.


structure User {
    name; role;
    function constructor(name, role) {
        this.name = name;
        this.role = role;
    }
}

structure Admin extends User {
    level;
    function constructor(name) {
        super(name, "Admin"); # Call parent constructor
        this.level = 1;
    }
}

a = Admin("Alice");
print(a.role);  # Admin
print(a.level); # 1
    

Access Modifiers

Use private and protected modifiers on fields and methods within structures.


structure BankAccount {
    private double balance = 0.0;

    function void deposit(double amount) { this.balance += amount; }
    function double getBalance() { return this.balance; }
}

acc = BankAccount();
acc.deposit(100.5);
print(acc.getBalance()); # 100.5
# acc.balance = 999;      # Error: access denied
    

Threaded Structures

Structures can be declared as threaded to run on their own background thread. This makes them Active Objects: all method calls and field access/assignments are executed sequentially on a dedicated thread, ensuring thread safety.


threaded structure Counter {
    int count = 0;

    function void increment() {
        this.count = this.count + 1;
    }
}

c = Counter(); # Runs on its own thread
c.increment(); # Executed asynchronously on c's thread
    

Reactive Triggers

Triggers are reactive blocks inside a structure that fire automatically when a field is assigned. They are useful for reactive programming and UI updates.

FormDescription
on (boolExpr) { ... }Fires after any field write if boolExpr is truthy.
on (field changed) { ... }Fires only if the value of field actually changed.

structure Tracker {
    any state;
    int changeCount = 0;

    # Fires whenever 'state' value actually changes
    on (state changed) {
        this.changeCount += 1;
        print("State changed to: " + this.state);
    }

    # Fires if changeCount exceeds 10
    on (changeCount > 10) {
        print("Threshold reached!");
    }
}
    

Static Members

Use the static keyword for fields and methods belonging to the structure type rather than instances.


structure MathUtils {
    static double PI = 3.14159;

    static function double circleArea(double r) {
        return MathUtils.PI * r * r;
    }
}

area = MathUtils.circleArea(5);
    

Dynamic Method Addition

Methods can be added to structures or instances at runtime using addMethod.


structure User { String name; }
function String sayHello() { return "Hello, " + this.name; }

# Add to structure type (affects all new instances)
User.addMethod("hello", sayHello);

# Add to a specific instance only
u = User("Alice");
function String farewell() { return "Goodbye from " + this.name; }
u.addMethod("bye", farewell);

print(u.hello()); # Hello, Alice
print(u.bye());   # Goodbye from Alice