Skip to content

Language Basics

This guide covers the core features of Kōdo that are available today.

Every .ko file contains exactly one module. A module has a name, a meta block, and one or more functions:

module my_program {
meta {
purpose: "What this module does",
version: "0.1.0",
author: "Your Name"
}
fn main() {
println("Hello!")
}
}

The meta block is mandatory. It makes every module self-describing — any reader (human or AI) can immediately understand the module’s purpose.

FieldDescription
purposeWhat this module does (required)
versionSemantic version string
authorWho wrote it

Functions are declared with fn, followed by a name, parameters, and an optional return type:

fn add(a: Int, b: Int) -> Int {
return a + b
}
  • Parameters must have explicit type annotations
  • Return type is declared with -> after the parameter list
  • Functions without a return type return nothing
  • The main function is the program’s entry point
fn double(x: Int) -> Int {
return x * 2
}
fn main() {
let result: Int = double(21)
print_int(result)
}

Functions can call themselves:

fn factorial(n: Int) -> Int {
if n <= 1 {
return 1
}
return n * factorial(n - 1)
}

Kōdo supports the following primitive types:

TypeDescriptionExample
Int64-bit integer42, -7, 0
Float6464-bit floating point3.14, -0.5, 1.0
BoolBoolean valuestrue, false
StringString literals"hello"

The full type system also includes Int8, Int16, Int32, Int64, Float32, and Byte — see the Language Specification for details.

Variables can have explicit type annotations or use local type inference:

// Explicit type annotations
let x: Int = 42
let pi: Float64 = 3.14159
let name: String = "Kōdo"
let active: Bool = true
// Type inference — the compiler infers the type from the initializer
let y = 42 // inferred as Int
let greeting = "hi" // inferred as String
let flag = true // inferred as Bool
let tau = 6.28 // inferred as Float64

Note: Function signatures always require explicit type annotations. Type inference is local to let bindings only.

By default, variables are immutable:

let x: Int = 10
// x = 20 — this would be an error

Use let mut to create a mutable variable. Mutable variables can be reassigned using =:

let mut counter: Int = 0
counter = counter + 1

Reassignment requires the variable to have been declared with mut. The new value must match the variable’s type. Only simple variable names can be reassigned — field assignment is not yet supported.

OperatorDescriptionExample
+Addition (Int, Float64, or String concatenation)a + b, "hi" + name
-Subtractiona - b
*Multiplicationa * b
/Divisiona / b
%Moduloa % b
-Negation (unary)-x

Arithmetic operators work on both Int and Float64 values. The + operator also supports String concatenation — "hello " + "world" produces "hello world".

OperatorDescriptionExample
==Equala == b
!=Not equala != b
<Less thana < b
>Greater thana > b
<=Less or equala <= b
>=Greater or equala >= b
OperatorDescriptionExample
&&Logical ANDa && b
||Logical ORa || b
!Logical NOT!a
if x > 0 {
println("positive")
} else {
println("non-positive")
}

if/else blocks can be nested:

if x > 100 {
println("large")
} else {
if x > 0 {
println("small positive")
} else {
println("non-positive")
}
}

Use while to repeat a block while a condition is true:

let mut i: Int = 5
while i > 0 {
print_int(i)
i = i - 1
}

The condition must be a Bool expression. The loop body executes repeatedly until the condition becomes false.

Here’s a complete example with a countdown function:

fn countdown(n: Int) {
let mut i: Int = n
while i > 0 {
print_int(i)
i = i - 1
}
println("Liftoff!")
}

Use return to exit a function with a value:

fn abs(x: Int) -> Int {
if x < 0 {
return -x
}
return x
}

Kōdo provides builtin functions for output:

FunctionParameterDescription
println(s)StringPrint a string followed by a newline
print(s)StringPrint a string without a newline
print_int(n)IntPrint an integer followed by a newline
print_float(f)Float64Print a float without a newline
println_float(f)Float64Print a float followed by a newline
fn main() {
println("The answer is:")
print_int(42)
println_float(3.14)
}

Here’s a program that combines everything covered in this guide:

module demo {
meta {
purpose: "Demonstrate Kōdo language basics",
version: "0.1.0",
author: "Kōdo Team"
}
fn is_even(n: Int) -> Bool {
return n % 2 == 0
}
fn fizzbuzz_single(n: Int) {
if n % 15 == 0 {
println("FizzBuzz")
} else {
if n % 3 == 0 {
println("Fizz")
} else {
if n % 5 == 0 {
println("Buzz")
} else {
print_int(n)
}
}
}
}
fn main() {
let x: Int = 42
let mut counter: Int = 1
if is_even(x) {
println("42 is even")
}
fizzbuzz_single(3)
fizzbuzz_single(5)
fizzbuzz_single(15)
fizzbuzz_single(7)
}
}