Forma is a small, statically-typed compiler language designed for educational and experimental compiler development.
Its goals are:
- Simple grammar
- Clear semantic rules
- Explicit typing
- Easy Intermediate Representation (IR) generation
- Minimal but structured design
Forma syntax is inspired by C but intentionally simplified.
A Forma program consists of one or more function definitions.
Example:
define add(int x, int y) -> int {
return x + y;
}
define main() -> int {
int a = 1;
int b = 2;
return add(a, b);
}define
return
int
Identifiers:
- Begin with a letter or underscore
- Followed by letters, digits, or underscores
- Case-sensitive
Example:
add
main
x
t0
Forma currently supports:
| Source Type | IR Type |
|---|---|
| int | i32 |
All integers are 32-bit signed integers.
define function_name(parameter_list) -> return_type {
statements
}
Parameters must include explicit types.
Example:
define add(int x, int y) -> int {Every function must declare a return type.
A return statement must match the declared return type.
Supported statements:
- Variable declaration
- Assignment
- Return statement
- Expression statement (future extension)
type identifier = expression;
Example:
int a = 1;Rules:
- Must declare before use
- Must include initialization
- Type must match expression type
identifier = expression;
The identifier must already be declared.
return expression;
The expression type must match the function return type.
Supported expressions:
- Integer literal
- Identifier
- Binary expression
- Function call
1
42
1000
Type: int
expression + expression
Currently supported operators:
+
Rules:
- Both operands must be
int - Result type is
int
Example:
x + yfunction_name(argument_list)
Rules:
- Function must be defined
- Argument count must match parameter count
- Argument types must match parameter types
Example:
add(a, b)Forma performs static semantic checking:
- Variables must be declared before use
- Functions must exist before calling
- Type checking enforced
- Return type must match function signature
- Parameter count and types must match
Forma compiles into a low-level three-address IR.
define [param_count], function_name() -> return_type
param:
type param_name
local:
type temp_or_local
entry:
instructions
Source:
define add(int x, int y) -> int {
return x + y;
}Generated IR:
define [2], add() -> i32
param:
i32 x
i32 y
local:
i32 t0
i32 t1
i32 t2
entry:
t0 = x
t1 = y
t2 = add t0, t1
ret t2
Source:
define main() -> int {
int a = 1;
int b = 2;
return add(a, b);
}Generated IR:
define [0], main() -> i32
local:
i32 t3
i32 a
i32 t4
i32 b
i32 t5
i32 t6
i32 t7
entry:
t3 = 1
a = t3
t4 = 2
b = t4
t5 = a
t6 = b
t7 = call add(t5, t6)
ret t7
- All functions are compiled before execution
mainis the entry point- Execution follows generated IR
- Each expression produces a temporary variable
- IR uses three-address code format
- Lexer
- Parser → AST
- Semantic Analysis
- IR Generation
- (Future) Optimization
- (Future) Code Generation
Forma is intentionally:
- Minimal
- Explicit
- Deterministic
- Educational
It avoids:
- Implicit type conversions
- Dynamic typing
- Complex control flow (for now)
The language is designed to make compiler implementation transparent and manageable.