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

TypeDescription
int32-bit signed integer
boolBoolean value (true or false)
voidNo return value

Variables and Mutability

  • let introduces 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.
  • main must return int.

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: + - * / % (on int)
  • Comparison: == != < > <= >=
  • Logical: && || ! (on bool)
  • Assignment: =

Operator Precedence

From lowest to highest binding strength:

LevelOperatorsAssoc.Operand TypesResult
1=Rightvariesvaries
2||Leftboolbool
3&&Leftboolbool
4== != < > <= >=Leftintbool
5+ -Leftintint
6* / %Leftintint
7! - (prefix)Rightbool / intbool / int
8function callLeftreturn 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);
}