Sessions
Sessions are HypnoScript's object-oriented building blocks. They bundle related state and behaviour while keeping the hypnotic syntax you already know. This page explains how to declare sessions, control visibility, wire constructors, and work with static members.
Declaring a session
A session groups fields and methods inside a dedicated block:
session Account {
conceal balance: number = 0;
expose suggestion constructor(initialBalance: number) {
this.balance = initialBalance;
}
expose suggestion deposit(amount: number) {
this.balance = this.balance + amount;
}
conceal suggestion snapshot(): number {
awaken this.balance;
}
}
Key points:
session Name { ... }declares the type.- Fields require an explicit visibility keyword (
exposefor public,concealfor private). Initialisers are optional. - Methods use
suggestion,imperativeSuggestion, ordominant suggestiondepending on the style you prefer. The parser treatsimperativeSuggestionas an instance method anddominant suggestionas static. - The optional
constructorkeyword aftersuggestionmarks a constructor. Constructors cannot be static and always return an instance of the surrounding session. The type checker enforces those rules.
Field visibility
Visibility determines where a member can be accessed:
exposemarks a field or method as public. Public members can be used from any script.concealrestricts access to the defining session. Both the interpreter and the type checker reject external reads, writes, or calls.
Attempting to reach a concealed member outside its session triggers a type error:
Focus {
session Vault {
conceal pin: number = 1234;
expose suggestion reveal(): number {
awaken this.pin;
}
}
induce vault = Vault();
induce leak = vault.pin; // Field 'pin' of session 'Vault' is not visible here
} Relax
Methods and constructors
Instance methods rely on this, which the runtime binds automatically when you call them on an instance. Mark a constructor with suggestion constructor(...) and optionally accept parameters:
session Timeline {
conceal events: number = 0;
expose suggestion constructor(initial: number) {
this.events = initial;
}
expose suggestion record(amount: number) {
this.events = this.events + amount;
}
conceal suggestion current(): number {
awaken this.events;
}
}
Focus {
induce timeline = Timeline(5);
timeline.record(3);
induce count = timeline.current();
} Relax
The type checker validates constructor arity and ensures returns inside methods agree with the declared return type.
Static members
Use the dominant modifier to mark members as static. Static fields belong to the session itself, not to individual instances, and must be accessed through the session name:
session Config {
dominant expose version: string = "1.0";
dominant suggestion setVersion(next: string) {
Config.version = next;
}
}
Focus {
Config.setVersion("2.1");
induce activeVersion: string = Config.version;
} Relax
Static rules enforced by the compiler:
- Assign static fields via the session (
Config.version = ...), not through an instance. - Do not call instance methods on the session type (
Config.update()fails unlessupdateis static). - Constructors are always instance members and cannot be declared
dominant.
Summary of type checker guarantees
The extended type checker performs the following validations for sessions:
- Detects duplicate fields, methods, or constructors inside a session.
- Ensures private members stay hidden outside the declaring session.
- Verifies constructors are unique, non-static, and called with the correct number of arguments.
- Differentiates static and instance members for both access and assignment.
- Catches
thisusage in static methods and invalid member assignments (for example, writing to methods).
Further reading
Head over to Basic Examples for end-to-end snippets that combine constructors, static members, and visibility. The interpreter and runtime design notes in /docs/reference/interpreter.md highlight how the execution engine enforces the same constraints at runtime.