Documentation Index
Fetch the complete documentation index at: https://mintlify.com/elfrask/cls/llms.txt
Use this file to discover all available pages before exploring further.
CLS has a full object-oriented programming system built into the language core. Classes are declared with class, use function main as the constructor, reference the current instance with me, and support single inheritance, visibility modifiers, operator overloading via magic methods, generics, and compile-time interfaces — all without a new keyword in sight.
Declaring a Class
A class body contains field declarations (var) and method definitions (function). The special method function main serves as the constructor: it is called automatically when the class is instantiated. Inside any method, me refers to the current instance — equivalent to this in other languages.
class Persona {
var nombre: String;
var edad: int = 0;
function main(nombre: String, edad: int) {
me.nombre = nombre;
me.edad = edad;
}
function saludar() -> String {
return "Hola, " + me.nombre;
}
static function crear(nombre: String) -> Persona {
return Persona(nombre, 0);
}
};
main is the constructor — not a lifecycle hook or entry-point method. It is invoked automatically the moment you instantiate the class with ClassName(args).
Instantiation
Classes are instantiated by calling the class name as if it were a function. There is no new keyword.
var p = Persona("Ana", 30);
print(p.saludar()); # → "Hola, Ana"
print(Persona.crear("Bea")); # static method call
The me Reference
me is available inside every instance method and always points to the object on which the method was called. Use me.field to read or write instance fields, and me.method() to call other methods on the same object.
class Contador {
var valor: int = 0;
function incrementar() {
me.valor = me.valor + 1;
}
function obtener() -> int {
return me.valor;
}
};
var c = Contador();
c.incrementar();
print(c.obtener()); # → 1
Static Members
Static fields and methods belong to the class itself, not to any instance. Declare them with static var or static function, and access them through the class name.
class Cuenta {
static var tasa: float = 0.05;
static function obtenerTasa() -> float {
return Cuenta.tasa;
}
};
print(Cuenta.tasa); # → 0.05
print(Cuenta.obtenerTasa()); # → 0.05
Inheritance
CLS supports single inheritance. The primary syntax uses a colon (:); the keywords extends and parentheses (Parent) are also accepted.
class Animal {
var name: String;
function main(name: String) {
me.name = name;
}
function speak() -> String {
return me.name + " hace un sonido";
}
};
# Primary syntax
class Dog: Animal {
function speak() -> String {
return super.speak() + " y ladra";
}
};
# Parentheses syntax — equivalent
class Cat (Animal) {
function speak() -> String {
return me.name + " maúlla";
}
};
Subclasses inherit all fields and methods from the parent. The child can override any method — accessing the parent’s original version through super.
Using super
| Expression | Effect |
|---|
super.method(args) | Calls the parent’s version of method, bypassing the override. |
super.field | Reads a field defined in the parent class. |
super.main(args) | Calls the parent constructor explicitly. |
class CuentaVip: Cuenta {
function main(titular: String, saldo: float) {
super.main(titular, saldo); # delegate to parent constructor
}
function descripcion() -> String {
return "Vip " + me.numero; # me.numero inherited from Cuenta
}
};
The is Operator
is tests whether an object is an instance of a given class. It returns true for the direct class and any ancestor class in the inheritance chain.
var d = Dog("Rex");
print(d is Dog); # true — direct instance
print(d is Animal); # true — inherited
print(d is String); # false — unrelated type
Visibility Modifiers
CLS enforces access control at runtime (and at type-check time). Both fields and methods can carry a visibility modifier. Without any modifier, members are accessible from anywhere (effectively public).
| Modifier | Access rule |
|---|
private | Only from inside the same class, via me. or super.. |
protected | From the class and all its subclasses. Never from outside. |
public | From anywhere — inside the class, subclasses, and external code. |
static | Lives on the class itself; accessed with ClassName.member. |
readonly | External code can read the value, but only internal code (via me.) can write it. |
class Cuenta {
private var saldo: float;
public var titular: String;
protected var numero: String;
readonly var creadoEn: int;
static var tasa: float = 0.05;
function main(titular: String, saldo: float) {
me.titular = titular;
me.saldo = saldo;
me.numero = "001-0001";
me.creadoEn = 2026;
}
private function auditar() -> bool { return me.saldo >= 0; }
public function depositar(monto: float) { me.saldo = me.saldo + monto; }
public function verSaldo() -> float { return me.saldo; }
protected function verNumero() -> String { return me.numero; }
static function obtenerTasa() -> float { return Cuenta.tasa; }
};
Attempting to access a private or protected member from outside its allowed scope produces a runtime error:
var c = Cuenta("Ana", 100.0);
print(c.titular); # OK — public
try {
var x = c.saldo; # ERROR — private
} catch (e) {
print("c.saldo blocked (ok)");
};
try {
c.creadoEn = 1999; # ERROR — readonly
} catch (e) {
print("c.creadoEn is readonly (ok)");
};
Magic Methods
Magic methods let objects define how they respond to built-in operators, type conversions, and protocol functions like len(), print(), and for each. They follow a __name naming convention. If a magic method is absent, the interpreter falls back to default behavior without raising an error.
class Number {
var value: int;
function main(v: int) { me.value = v; }
function __toString() -> String {
return "Num(" + toString(me.value) + ")";
}
function __equals(other) -> bool {
return me.value == other.value;
}
function __compare(other) -> int {
if (me.value < other.value) { return -1; }
if (me.value > other.value) { return 1; }
return 0;
}
function __add(other) -> Number {
return Number(me.value + other.value);
}
function __neg() -> Number {
return Number(-me.value);
}
function __len() -> int {
return len(toString(me.value));
}
function __get(index: int) -> int {
return [me.value, me.value * 2, me.value * 3][index];
}
function __iter() -> Array {
return [me.value, me.value + 1, me.value + 2];
}
function __call(x: int) -> int {
return me.value + x;
}
};
var a = Number(5);
var b = Number(7);
print(a); # → "Num(5)" — __toString
print(a == Number(5));# → true — __equals
print(a < b); # → true — __compare
print(a + b); # → Num(12) — __add
print(-a); # → Num(-5) — __neg
print(len(a)); # → 1 — __len
print(a[0]); # → 5 — __get
print(a(10)); # → 15 — __call
for each item in (a) { # __iter
print(item); # 5, 6, 7
}
Full Magic Method Reference
| Magic method | Triggered by |
|---|
__toString() | print(x), toString(x), string interpolation "$x" |
__equals(other) | == and != operators |
__compare(other) | <, <=, >, >= (return -1, 0, or 1) |
__add(other) | x + y |
__sub(other) | x - y |
__mul(other) | x * y |
__div(other) | x / y |
__mod(other) | x % y |
__pow(other) | x ** y |
__neg() | Unary -x |
__not() | Unary !x |
__int() | int(x) |
__float() | float(x) |
__bool() | bool(x) |
__len() | len(x) |
__get(index) | x[i] (index read) |
__set(index, value) | x[i] = v (index write) |
__contains(value) | value in x |
__iter() | for each item in (x) — return iterable |
__next() | Manual iterator advancement |
__call(...) | x(...) — callable object |
__type() | type(x) — return a custom type name string |
__toJson() | json.stringify(x) |
__clone() | User-defined clone convention (called explicitly) |
Generic Classes
Classes can be parameterised with one or more type parameters declared in angle brackets. The type variable (T) can be used for field types, parameter types, and return types.
class Caja<T> {
var contenido: T;
function main(contenido: T) {
me.contenido = contenido;
}
function obtener() -> T {
return me.contenido;
}
};
var cajaNum = Caja(42);
print(cajaNum.obtener()); # → 42
var cajaTxt = Caja("hola");
print(cajaTxt.obtener()); # → "hola"
At runtime, generic classes work without explicit type annotations — Caja(42) infers T = int automatically. Full static verification of Caja<String> member types is planned as a future improvement to the type checker.
Interfaces
Interfaces define a structural contract — a set of method signatures a class must satisfy. They exist only at compile time and do not generate any runtime code.
interface Printable {
print(): void
};
interface Serializable {
serialize(): String,
deserialize(data: String): void
};
Use interfaces as type annotations to let the type checker verify structural compatibility across unrelated class hierarchies without requiring a shared base class.