module hello_world;
import std::io;
fn void main()
{
io::printn("Hello, world!");
}
// Simple variable declarations (type inference)
int count = 42; // Integer
double price = 19.99; // Floating point
String name = "Alice"; // String type
bool is_active = true; // Boolean
// Multiple declarations
int x = 1, y = 2, z = 3; // Declare multiple variables
// If statements
fn void check_value(int x)
{
if (x > 10)
{
io::printn("Greater than 10");
}
else if (x > 5)
{
io::printn("Between 6 and 10");
}
else
{
io::printn("5 or less");
}
}
// For loop (C-style)
fn void count_to_ten()
{
for (int i = 0; i < 10; i++)
{
io::printfn("%d", i); // Print current number
}
}
// While loop
fn void countdown(int n)
{
while (n > 0)
{
io::printfn("%d", n);
n--;
}
}
// Foreach with index and value
fn void iterate_array(int[] numbers)
{
foreach (index, value : numbers)
{
io::printfn("Index %d: %d", index, value);
}
}
// Foreach by reference (modify values)
fn void double_values(int[] numbers)
{
foreach (&num : numbers)
{
*num *= 2; // Modify original array
}
}
// Switches have implicit break (no fallthrough)
enum Status
{
PENDING,
PROCESSING,
COMPLETE,
FAILED
}
fn void handle_status(Status s)
{
switch (s)
{
case PENDING:
io::printn("Waiting to start");
// Implicit break
case PROCESSING:
io::printn("Currently processing");
case COMPLETE:
io::printn("Done!");
case FAILED:
io::printn("Error occurred");
}
}
// Using nextcase for explicit fallthrough
fn void categorize(int value)
{
switch (value)
{
case 1:
io::printn("One");
nextcase; // Continue to next case
case 2:
io::printn("Small number");
nextcase;
case 3:
io::printn("Less than four");
}
}
// Basic function
fn int add(int a, int b)
{
return a + b;
}
// Function with optional result (error handling)
fn double? divide(int a, int b)
{
if (b == 0) return DIVISION_BY_ZERO?;
return (double)a / (double)b;
}
// Function pointer type alias
alias Calculator = fn int(int, int);
fn int multiply(int a, int b)
{
return a * b;
}
fn void use_callback()
{
Calculator calc = &multiply; // Get function pointer
int result = calc(5, 3); // Call through pointer
}
// Struct definition
struct Person
{
String name;
int age;
double height;
// Nested anonymous struct (fields accessed directly)
struct
{
String street;
String city;
}
// Named sub-struct
struct contact
{
String email;
String phone;
}
}
// Struct initialization
fn void create_person()
{
Person p = {
.name = "Bob",
.age = 30,
.height = 5.9,
.street = "123 Main St", // Anonymous struct field
.city = "Springfield",
.contact.email = "bob@example.com"
};
}
// Struct methods (dot syntax)
fn void Person.greet(Person* this)
{
io::printfn("Hello, I'm %s", this.name);
}
fn void Person.have_birthday(Person* this)
{
this.age++; // Increment age
}
fn void test_methods()
{
Person p = { .name = "Alice", .age = 25 };
p.greet(); // Call method with dot syntax
p.have_birthday();
}
// Basic enum
enum Color
{
RED,
GREEN,
BLUE
}
// Enum with explicit values
enum HttpStatus : int
{
OK = 200,
NOT_FOUND = 404,
SERVER_ERROR = 500
}
// Enum reflection
fn void enum_info()
{
Color[] all_colors = Color.values; // Get all enum values
usz count = Color.elements; // Number of values (3)
String[] names = Color.names; // ["RED", "GREEN", "BLUE"]
Color first = Color.values[0]; // Access specific value
}
// Define custom fault types
faultdef FILE_NOT_FOUND;
faultdef PERMISSION_DENIED;
// Function returning optional result
fn String? read_file(String path)
{
// Return fault on error
if (!file_exists(path)) return FILE_NOT_FOUND?;
if (!has_permission(path)) return PERMISSION_DENIED?;
return load_file_contents(path);
}
// Handling optional results
fn void process_file(String path)
{
String? content = read_file(path);
// Check for error
if (catch err = content)
{
switch (err)
{
case FILE_NOT_FOUND:
io::printn("File doesn't exist");
case PERMISSION_DENIED:
io::printn("Access denied");
default:
io::printn("Unknown error");
}
return;
}
// After if-catch, content is unwrapped to String
io::printfn("File content: %s", content);
}
// Propagate errors with ! suffix
fn void? process_multiple_files()
{
read_file("config.txt")!; // Return error if read fails
read_file("data.txt")!;
}
// Defer runs on scope exit (cleanup)
fn void example_defer()
{
defer io::printn("3 - Cleanup");
defer io::printn("2 - Second defer");
io::printn("1 - Main code");
// Prints: "1 - Main code", "2 - Second defer", "3 - Cleanup"
}
// Conditional defer (error handling)
fn void? process_with_cleanup()
{
defer io::printn("Always runs");
defer try io::printn("Only on success");
defer catch io::printn("Only on error");
defer (catch err) io::printfn("Error was: %s", err);
// If error occurs, only catch defers run
do_risky_operation()!;
}
// Simple macro
macro square(x)
{
return x * x;
}
// Macro with compile-time execution
macro long factorial(long $n)
{
$if $n <= 1:
return 1;
$else
return $n * factorial($n - 1);
$endif
}
// Computed at compile time
const long FACT_10 = factorial(10); // = 3628800 at compile time
// Macro with type checking
<*
@require types::is_numerical($typeof(x))
*>
macro abs(x)
{
return x < 0 ? -x : x;
}
// Generic module (similar to templates)
module list {Type};
struct List
{
Type* items;
usz length;
usz capacity;
}
fn void List.add(List* this, Type item)
{
if (this.length >= this.capacity)
{
this.capacity = this.capacity ? this.capacity * 2 : 8;
this.items = realloc(this.items, Type.sizeof * this.capacity);
}
this.items[this.length++] = item;
}
fn Type List.get(List* this, usz index)
{
assert(index < this.length);
return this.items[index];
}
// Using the generic type
alias IntList = List {int};
alias StringList = List {String};
fn void test_generic()
{
IntList numbers;
numbers.add(10);
numbers.add(20);
io::printfn("First: %d", numbers.get(0));
}
// Struct for 2D vector
struct Vec2
{
float x, y;
}
// Overload + operator
fn Vec2 Vec2.add(self, Vec2 other) @operator(+)
{
return { self.x + other.x, self.y + other.y };
}
// Overload - operator
fn Vec2 Vec2.subtract(self, Vec2 other) @operator(-)
{
return { self.x - other.x, self.y - other.y };
}
// Overload * operator (scalar multiplication)
fn Vec2 Vec2.scale(self, float scalar) @operator(*)
{
return { self.x * scalar, self.y * scalar };
}
fn void test_operators()
{
Vec2 a = { 2.0, 3.0 };
Vec2 b = { 1.0, 4.0 };
Vec2 sum = a + b; // Uses overloaded +
Vec2 diff = a - b; // Uses overloaded -
Vec2 scaled = a * 2.0; // Uses overloaded *
}
// Pre and post conditions
<*
@param value : "input value"
@require value >= 0 // Precondition: non-negative
@return "square root"
@ensure return >= 0 // Postcondition: result non-negative
*>
fn double sqrt_wrapper(double value)
{
return math::sqrt(value);
}
// Array bounds checking
<*
@param arr : "array to search"
@param index : "index to access"
@require index >= 0, index < arr.len
*>
fn int get_element(int[] arr, int index)
{
return arr[index];
}
// Define interface
interface Drawable
{
fn void draw();
fn String get_name();
}
// Struct implementing interface
struct Circle (Drawable)
{
float radius;
}
fn void Circle.draw(Circle* this) @dynamic
{
io::printfn("Drawing circle with radius %f", this.radius);
}
fn String Circle.get_name(Circle*) @dynamic
{
return "Circle";
}
// Polymorphic function
fn void render(any obj)
{
Drawable d = (Drawable)obj;
if (&d.draw) // Check if draw method exists
{
d.draw();
}
}
// Loop over struct fields at compile time
struct Config
{
int port;
String host;
bool debug;
}
macro print_struct_info($Type)
{
$foreach $field : $Type.membersof:
io::printfn("Field: %s, Type: %s, Offset: %s",
$field.nameof,
$field.typeid.nameof,
$field.offsetof);
$endforeach
}
fn void test_reflection()
{
print_struct_info(Config); // Prints info about each field
}