Interface Contracts
Interfaces define behavioral contracts — a set of method signatures that a type must implement. Forge provides dual syntax: power (natural) and interface (classic). Implementing an interface is verified at definition time when the give...the power or impl...for block is executed.
Syntax
InterfaceDef = ("power" | "interface") Identifier "{" MethodSig* "}"
MethodSig = ("fn" | "define") Identifier "(" ParamList ")" ("->" TypeAnnotation)?
ImplInterface = "give" TypeName "the" "power" InterfaceName "{" MethodDef* "}"
| "impl" InterfaceName "for" TypeName "{" MethodDef* "}"
Defining an Interface
The power keyword (or its classic alias interface) introduces a named interface. An interface body contains method signatures — method names with parameter lists and optional return type annotations.
power Greetable {
fn greet(it) -> String
}
Classic syntax:
interface Greetable {
fn greet(it) -> String
}
Both forms produce the same InterfaceDef AST node.
Interface Registration
When an InterfaceDef statement is executed, the interpreter:
- Builds an array of method specification objects. Each object contains:
name— the method name as aString.param_count— the number of parameters as anInt.return_type— the return type annotation as aString, if present.
- Creates an interface metadata object with fields
__kind__: "interface",name, andmethods. - Registers the interface in the environment under both its name and
__interface_Name__.
The interface object is a regular Object value and can be passed to functions like satisfies.
Implementing an Interface
To declare that a type fulfills an interface, use give...the power (natural) or impl...for (classic):
thing Cat {
name: String
}
power Greetable {
fn greet(it) -> String
}
give Cat the power Greetable {
define greet(it) {
return "Meow, I'm " + it.name
}
}
Classic syntax:
interface Named {
fn get_name(it) -> String
}
impl Named for Animal {
fn get_name(it) {
return it.name
}
}
Validation at Definition Time
When a give...the power or impl...for block is executed, the runtime validates that every method required by the interface is present in the type’s method table (including methods added by the current block and any previous give/impl blocks).
The validation checks method presence by name. It does not verify parameter counts, parameter types, or return types.
If a required method is missing, a runtime error is raised:
'Cat' does not implement 'greet' required by power 'Greetable'
This error occurs at the point where the give...the power block is executed, not at a later call site.
Interface Without Explicit Implementation
A type may satisfy an interface without ever using give...the power or impl...for. Forge supports Go-style structural typing through the satisfies function. See Structural Satisfaction.
The give...the power syntax provides two benefits over implicit satisfaction:
- Early validation — Errors are reported at the implementation site rather than at a distant call site.
- Documentation — The code explicitly declares the relationship between a type and an interface.
Multiple Interfaces
A type may implement multiple interfaces through separate give...the power blocks:
power Speakable {
fn speak(it) -> String
}
power Trainable {
fn train(it, command: String)
fn obey(it, command: String) -> Bool
}
thing Dog {
name: String
}
give Dog the power Speakable {
define speak(it) {
return "Woof!"
}
}
give Dog the power Trainable {
define train(it, command) {
say it.name + " is learning " + command
}
define obey(it, command) {
return true
}
}
Each give...the power block independently validates that its interface’s requirements are met. Methods from earlier blocks (including plain give blocks without an interface) count toward satisfaction.
Return Type Annotations
Return type annotations in interface method signatures are stored in the interface metadata but are not enforced at runtime. They serve as documentation:
power Hashable {
fn hash(it) -> String
}
The -> String annotation is recorded in the method specification but the runtime does not check that hash actually returns a String.