Turbo Language Specification
Turbo is a statically-typed, compiled language designed to be simple enough to compile to a custom ISA while still supporting useful constructs like functions, recursion, loops, and conditional branching. This document defines the source language that turbo-compiler accepts.
File Extension
Turbo source files use the .turbo extension.
Types
| Type | Description |
|---|---|
int | 32-bit signed integer |
bool | Boolean value (true or false) |
void | No return value |
Variables and Mutability
letintroduces a new mutable variable.- Function parameters are mutable within the function body.
- Variables are block scoped.
let x: int = 10;
x = x + 1;Program Structure
A Turbo program is a sequence of function definitions.
fn main() -> int {
return 0;
}Rules:
- A program must define
main. mainmust returnint.
Grammar
The syntax of Turbo is described below using an extended Backus-Naur form (EBNF), which is a standardized way to describe how a programming language is written. In this notation:
- Words in quotes (
"fn") are exact literal characters you must type. - Capitalized words (
IDENT) refer to lexical tokens defined at the bottom. - Curly braces (
{ ... }) mean the contents can be repeated zero or more times. - Square brackets (
[ ... ]) mean the contents are optional. - A vertical bar (
|) means "or" (choose one of the options).
Program & Functions
A file consists of multiple function definitions. At least one must be named main.
program = { fn_def } ;
fn_def = "fn" , IDENT , "(" , [ params ] , ")" , "->" , type , block ;
params = param , { "," , param } ;
param = IDENT , ":" , type ;
type = "int" | "bool" | "void" ;
block = "{" , { statement } , "}" ;Statements
Inside a function block, you can write these different kinds of statements.
statement = let_stmt
| return_stmt
| if_stmt
| while_stmt
| for_stmt
| expr_stmt ;
let_stmt = "let" , IDENT , ":" , type , "=" , expr , ";" ;
return_stmt = "return" , [ expr ] , ";" ;
if_stmt = "if" , expr , block , [ "else" , block ] ;
while_stmt = "while" , expr , block ;
for_stmt = "for" , IDENT , "in" , expr , ".." , expr , block ;
expr_stmt = expr , ";" ;Expressions
Expressions are things that evaluate to a value (like math or function calls). The order below dictates the operator precedence (assignment is evaluated last, logic next, then math, then single items).
expr = assignment ;
assignment = IDENT , "=" , expr
| logic_or ;
logic_or = logic_and , { "||" , logic_and } ;
logic_and = comparison , { "&&" , comparison } ;
comparison = addition , { ( "==" | "!=" | "<" | ">" | "<=" | ">=" ) , addition } ;
addition = multiply , { ( "+" | "-" ) , multiply } ;
multiply = unary , { ( "*" | "/" | "%" ) , unary } ;
unary = ( "!" | "-" ) , unary
| call ;
call = IDENT , "(" , [ args ] , ")"
| primary ;
args = expr , { "," , expr } ;
primary = INT_LIT | "true" | "false" | IDENT | "(" , expr , ")" ;Lexical Tokens
These are the smallest building blocks of the language, defining how to type names and numbers.
IDENT = letter , { letter | digit | "_" } ;
INT_LIT = digit , { digit }
| "0x" , hex_digit , { hex_digit } ;
letter = "a".."z" | "A".."Z" | "_" ;
digit = "0".."9" ;
hex_digit = digit | "a".."f" | "A".."F" ;Control Flow
if ... { ... } else { ... }while cond { ... }for i in start .. end { ... }— range is half-open[start, end).
Operators
- Arithmetic:
+-*/%(onint) - Comparison:
==!=<><=>= - Logical:
&&||!(onbool) - Assignment:
=
Operator Precedence
From lowest to highest binding strength:
| Level | Operators | Assoc. | Operand Types | Result |
|---|---|---|---|---|
| 1 | = | Right | varies | varies |
| 2 | || | Left | bool | bool |
| 3 | && | Left | bool | bool |
| 4 | == != < > <= >= | Left | int | bool |
| 5 | + - | Left | int | int |
| 6 | * / % | Left | int | int |
| 7 | ! - (prefix) | Right | bool / int | bool / int |
| 8 | function call | Left | — | return type |
Function Calls
- Positional arguments.
- Current compiler supports up to 4 call arguments.
- Return value is an expression.
Comments
- Line comments:
// comment - Line comments:
# comment
Examples
Fibonacci
fn fibonacci(n: int) -> int {
if n <= 1 { return n; }
return fibonacci(n - 1) + fibonacci(n - 2);
}
fn main() -> int {
return fibonacci(10);
}GCD
fn gcd(a: int, b: int) -> int {
while b != 0 {
let t: int = b;
b = a % b;
a = t;
}
return a;
}
fn main() -> int {
return gcd(48, 18);
}