2024-04-25 01:41:47 +01:00
|
|
|
const std = @import("std");
|
|
|
|
const builtin = @import("builtin");
|
|
|
|
const native_arch = builtin.cpu.arch;
|
|
|
|
const expect = std.testing.expect;
|
|
|
|
|
|
|
|
// Functions are declared like this
|
|
|
|
fn add(a: i8, b: i8) i8 {
|
|
|
|
if (a == 0) {
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
return a + b;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The export specifier makes a function externally visible in the generated
|
|
|
|
// object file, and makes it use the C ABI.
|
2024-05-04 19:29:17 +01:00
|
|
|
export fn sub(a: i8, b: i8) i8 {
|
|
|
|
return a - b;
|
|
|
|
}
|
2024-04-25 01:41:47 +01:00
|
|
|
|
|
|
|
// The extern specifier is used to declare a function that will be resolved
|
|
|
|
// at link time, when linking statically, or at runtime, when linking
|
|
|
|
// dynamically. The quoted identifier after the extern keyword specifies
|
|
|
|
// the library that has the function. (e.g. "c" -> libc.so)
|
|
|
|
// The callconv specifier changes the calling convention of the function.
|
|
|
|
const WINAPI: std.builtin.CallingConvention = if (native_arch == .x86) .Stdcall else .C;
|
|
|
|
extern "kernel32" fn ExitProcess(exit_code: u32) callconv(WINAPI) noreturn;
|
|
|
|
extern "c" fn atan2(a: f64, b: f64) f64;
|
|
|
|
|
|
|
|
// The @setCold builtin tells the optimizer that a function is rarely called.
|
|
|
|
fn abort() noreturn {
|
|
|
|
@setCold(true);
|
|
|
|
while (true) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The naked calling convention makes a function not have any function prologue or epilogue.
|
|
|
|
// This can be useful when integrating with assembly.
|
|
|
|
fn _start() callconv(.Naked) noreturn {
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
// The inline calling convention forces a function to be inlined at all call sites.
|
|
|
|
// If the function cannot be inlined, it is a compile-time error.
|
2024-05-04 19:29:17 +01:00
|
|
|
inline fn shiftLeftOne(a: u32) u32 {
|
2024-04-25 01:41:47 +01:00
|
|
|
return a << 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The pub specifier allows the function to be visible when importing.
|
|
|
|
// Another file can use @import and call sub2
|
2024-05-04 19:29:17 +01:00
|
|
|
pub fn sub2(a: i8, b: i8) i8 {
|
|
|
|
return a - b;
|
|
|
|
}
|
2024-04-25 01:41:47 +01:00
|
|
|
|
|
|
|
// Function pointers are prefixed with `*const `.
|
|
|
|
const Call2Op = *const fn (a: i8, b: i8) i8;
|
|
|
|
fn doOp(fnCall: Call2Op, op1: i8, op2: i8) i8 {
|
|
|
|
return fnCall(op1, op2);
|
|
|
|
}
|
|
|
|
|
|
|
|
test "function" {
|
|
|
|
try expect(doOp(add, 5, 6) == 11);
|
|
|
|
try expect(doOp(sub2, 5, 6) == -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// test
|