FREAKV3 docs freak 0.14.2 (Maverick)

Standard library#

> Every callable V3 recognises: the compiler builtins, and the FREAK-source modules linked into your build.

There are two distinct surfaces, and the difference matters.

Compiler builtins are known to the type checker itself. They always exist, need no import, and work under freak check.

Standard-library tasks live in std/*.fk as ordinary FREAK source. The CLI concatenates those files ahead of yours during freak build and freak run. They are global tasks in the same flat namespace as your own.

Careful

freak check compiles your file alone. Anything from std/ reports unknown callable. Use freak build or freak run to type-check code that uses the standard library.

How modules are loaded#

use lines are rewritten to comments before parsing, so they never reach the grammar. They survive only as a textual trigger telling the build to link an optional module.

ModuleLoaded
std/math.fk, std/string.fk, std/convert.fk, std/algorithm.fk, std/json.fk, std/version.fkAlways
std/runtime.fk, std/http.fkAlways, LLVM backend only
std/math3d.fkOnly if the source text contains use std::math3d
std/zip.fkOnly if the source text contains use std::zip
std/ui/window.fkOnly if the source text contains use std::ui
packages/cockpit/src/*.fkOnly if the source text contains use cockpit

So use std::ui is not an import — it is a build flag written in import syntax. Everything else is already in scope without it.

Prelude builtins#

CallSignatureNotes
say(value)scalar -> voidPrints with a newline. Accepts int, num, word, boolnot a shape
ask(prompt)word -> wordReads a line from stdin
panic(message)word -> voidAborts the process

say takes a statement form as well as a call form — say "x" and say("x") are identical, because ("x") is just a parenthesised expression.

Conversion builtins#

CallSignature
word_from_int(i)int -> word
word_from_bool(b)bool -> word
word_to_int(w)word -> int
word_concat(a, b)word, word -> word
word_join(handle)int -> word
char_to_word(code)int -> word
format_num(f)num -> word
parse_num(w)word -> num
parse_status()-> int — non-zero if the last checked parse failed
parse_clear_status()-> void

word methods#

Covered in full in Words & interpolation: .length(), .trim(), .to_upper(), .to_lower(), .contains(), .starts_with(), .ends_with(), .replace(), .substring(), .char_at(), .to_int(), .to_num(), .parse_int(), .parse_num(), .checksum(), .repeated(n), plus seven internal snapshot_* helpers.

Scalar methods: int.to_num(), int.to_word(), num.to_int(), num.to_word(), bool.to_word().

Lists and arrays#

Typed List<T>: List::new(), List::with_capacity(n), List::filled(v, n), indexing, .length(), .push(), .pop(), .capacity(), .reserve(n), .clear().

Legacy handle: array_new, array_push, array_get, array_set, array_len, array_release, word_join.

Both, and when each applies — see Lists & arrays.

WordBuilder#

word_builder::new, with_capacity, reserve, append, append_char, append_int, length, capacity, clear, finish, discard — see Words & interpolation.

ByteBuffer#

The only builtin type with real method syntax. Constructed with ByteBuffer::new() or ByteBuffer::with_capacity(n).

examples/bytebuffer.fk compilesruns
-- `ByteBuffer` is a real builtin type with methods, unlike the `int`
-- handles used elsewhere. It is a seekable binary read/write cursor.
task main() -> void {
    pilot buf: ByteBuffer = ByteBuffer::new()

    buf.write_word("hi")
    buf.write_int(7)
    buf.write_byte(255)

    say word_from_int(buf.length())
    say word_from_int(buf.position())

    -- Rewind and read the same values back.
    buf.seek(0)
    say buf.read_word(2)
    say word_from_int(buf.read_int())
    say word_from_int(buf.read_byte())
    say word_from_int(buf.remaining())

    -- status() reports the last failure; 0 means clean.
    say word_from_int(buf.status())

    buf.release()
}
Program output
11
0
hi
7
255
0
0
MethodSignatureNotes
.length()-> intBytes written
.capacity()-> int
.position()-> intThe read/seek cursor
.remaining()-> intBytes from the cursor to the end
.reserve(n)int -> void
.seek(pos)int -> voidMove the read cursor
.clear()-> void
.truncate(n)int -> void
.write_byte(b)int -> void
.write_int(n)int -> void
.write_int_be(n)int -> voidBig-endian
.write_word(w)word -> void
.read_byte()-> int
.read_int()-> int
.read_int_be()-> int
.read_word(len)int -> word
.slice(from, len)int, int -> ByteBuffer
.to_word()-> word
.status()-> intLast failure code; 0 is clean
.clear_status()-> void
.release()-> voidFree the buffer
Note

Writes append to the end; position() is the read cursor, so it stays at 0 until you read or seek. Errors are reported out-of-band through status() rather than by return value, since V3 has no result<T, E>.

This is the closest thing V3 has to the bible's std::bytes §7.14.

math:: builtins#

Floating point, over num.

examples/stdlib_math.fk compilesruns
-- Two numeric surfaces exist side by side:
--   `math::*` are compiler builtins over `num` (floating point).
--   `std_*` come from std/math.fk and work on `int`.
task main() -> void {
    -- builtins, num
    say format_num(math::sqrt(144.0))
    say format_num(math::pow(2.0, 10.0))
    say format_num(math::floor(3.9))
    say format_num(math::ceil(3.1))
    say format_num(math::sin(0.0))
    say format_num(math::cos(0.0))

    -- std/math.fk, int
    say word_from_int(std_abs(0 - 9))
    say word_from_int(std_max(3, 8))
    say word_from_int(std_min(3, 8))
    say word_from_int(std_clamp(42, 0, 10))
    say word_from_int(std_pow(2, 8))
    say word_from_int(std_gcd(84, 30))
    say word_from_int(std_lcm(4, 6))
    say word_from_int(std_factorial(6))
    say word_from_int(std_fibonacci(12))
    say word_from_bool(std_is_even(4))
    say word_from_int(std_sign(0 - 3))
}
Program output
12
1024
3
4
0
1
9
8
3
10
256
6
12
720
144
true
-1
CallSignature
math::sqrt(x)num -> num
math::pow(base, exp)num, num -> num
math::sin(x) / math::cos(x) / math::tan(x)num -> num
math::floor(x) / math::ceil(x)num -> num

That is the entire math:: namespace. No log, exp, asin, atan2, abs, gcd, simd — those bible entries are V4.

fs:: builtins#

examples/files.fk compilesruns
-- `fs::*` are compiler builtins. Paths are plain `word` values.
task main() -> void {
    fs::write("sortie.log", "launch\n")
    fs::append("sortie.log", "engage\n")

    if fs::exists("sortie.log") {
        say fs::read("sortie.log").trim()
    }

    fs::make_dir("hangar_out")
    say word_from_bool(fs::exists("hangar_out"))

    -- `fs::delete` is file-only in V3, and reports true when the file is
    -- gone -- whether this call removed it or it was already absent.
    say word_from_bool(fs::delete("sortie.log"))
    say word_from_bool(fs::exists("sortie.log"))
}
Program output
launch
engage
true
true
false
CallSignatureNotes
fs::read(path)word -> wordEmpty word on failure
fs::write(path, content)word, word -> void
fs::append(path, content)word, word -> void
fs::exists(path)word -> bool
fs::delete(path)word -> boolFile only. true when the file was removed or was already absent; false when it could not be unlinked
fs::list_dir(path)word -> wordEncoded listing
fs::make_dir(path)word -> void

There is no fs::copy, fs::move, fs::is_file, fs::is_dir, dir::create_all or dir::delete, and no result<T, E> — errors surface as empty words or false.

process:: builtins#

examples/process_time.fk compilesruns
-- Process and clock builtins.
-- Note: `process::args()` is deliberately rejected by V3. Use the
-- indexed pair `process::args_count()` / `process::arg(i)` instead.
task main() -> void {
    pilot argc: int = process::args_count()
    say word_from_int(argc)

    pilot mut i: int = 0
    repeat argc times {
        say "arg {i}: " + process::arg(i)
        i += 1
    }

    pilot started: int = time::now_ms()
    pilot mut spin: int = 0
    repeat 1000 times {
        spin += 1
    }
    pilot elapsed: int = time::now_ms() - started
    say word_from_bool(elapsed >= 0)
    say word_from_bool(process::env("PATH").length() > 0)
}
Program output
3
arg 0: C:\Users\cozor\AppData\Local\Temp\fkdocs_e8et7pyk\process_time.exe
arg 1: alpha
arg 2: bravo
true
true
CallSignature
process::args_count()-> int
process::arg(i)int -> word
process::env(name)word -> word
process::exec(cmd)word -> int
process::exec_capture(cmd)word -> word
process::exit(code)int -> void
process::input()-> word
process::pid()-> int
process::set_env(name, value)word, word -> void
Careful

process::args() is deliberately rejected by V3 rather than exposing the runtime's raw argv pointer as a fake array handle. Use the indexed pair process::args_count() and process::arg(i). Argument 0 is the executable path.

time:: builtins#

CallSignature
time::now_ms()-> int — milliseconds since the epoch
time::monotonic_ns()-> int — nanoseconds from a monotonic clock

Use monotonic_ns() for measuring elapsed time; it does not jump when the wall clock is adjusted.

There is no sleep, no Instant, no Duration, and no duration literals like 500.milliseconds.

tcp:: builtins#

CallSignature
tcp::connect(host, port)word, int -> int — socket handle
tcp::send(sock, data)int, word -> int
tcp::recv(sock, max)int, int -> word
tcp::recv_all(sock, max)int, int -> word
tcp::close(sock)int -> void

std/http.fk builds on these and is linked automatically on the LLVM backend.

The newer socket API#

A second, lower-level socket surface exists alongside the calls above. It adds listening, accepting, timeouts and ByteBuffer-based transfer.

CallSignature
tcp::socket_connect(host, port)word, int -> int
tcp::socket_listen(host, port)word, int -> int
tcp::socket_accept(listener)int -> int
tcp::socket_local_port(sock)int -> int
tcp::socket_status(sock)int -> int
tcp::socket_eof(sock)int -> bool
tcp::socket_set_timeout(sock, ms)int, int -> void
tcp::socket_send(sock, buf, off, len)int, ByteBuffer, int, int -> int
tcp::socket_send_all(sock, buf, off, len)int, ByteBuffer, int, int -> int
tcp::socket_receive(sock, buf, max)int, ByteBuffer, int -> int
tcp::socket_close(sock)int -> void
Note

This is the first V3 API that can write a server, since socket_listen and socket_accept have no equivalent in the older tcp::connect family. Like ByteBuffer, it reports failure through a status()-style code rather than a result<T, E>.

ui:: builtins#

A raw, indexed windowing API: ui::create_window, ui::destroy_window, ui::poll_events, ui::begin_frame, ui::end_frame, ui::clear, ui::fill_rect, ui::stroke_rect, ui::fill_circle, ui::draw_line, ui::draw_text, ui::measure_text, ui::get_width, ui::get_height, ui::set_clip, ui::reset_clip, and an ui::event_* family (kind, key, pressed, character, mouse_x, mouse_y, button, repeat, scroll_dy, width, height, gained).

Careful

std::ui runs on the LLVM backend, on Windows, through the Win32/GDI runtime only. There is no macOS or Linux native backend, and the C backend has no executable shape storage for UI programs. WindowConfig.vsync is retained but ignored, events use the raw indexed API rather than an owned event list, and COCKPIT is a source preview, not a frozen package.

Geometry crosses this ABI as pixel-addressed int. Convert from num before calling.

std::math — integer maths#

examples/stdlib_math.fk compilesruns
-- Two numeric surfaces exist side by side:
--   `math::*` are compiler builtins over `num` (floating point).
--   `std_*` come from std/math.fk and work on `int`.
task main() -> void {
    -- builtins, num
    say format_num(math::sqrt(144.0))
    say format_num(math::pow(2.0, 10.0))
    say format_num(math::floor(3.9))
    say format_num(math::ceil(3.1))
    say format_num(math::sin(0.0))
    say format_num(math::cos(0.0))

    -- std/math.fk, int
    say word_from_int(std_abs(0 - 9))
    say word_from_int(std_max(3, 8))
    say word_from_int(std_min(3, 8))
    say word_from_int(std_clamp(42, 0, 10))
    say word_from_int(std_pow(2, 8))
    say word_from_int(std_gcd(84, 30))
    say word_from_int(std_lcm(4, 6))
    say word_from_int(std_factorial(6))
    say word_from_int(std_fibonacci(12))
    say word_from_bool(std_is_even(4))
    say word_from_int(std_sign(0 - 3))
}
TaskSignature
std_abs(x)int -> int
std_sign(x)int -> int
std_min(a, b) / std_max(a, b)int, int -> int
std_clamp(x, lo, hi)int, int, int -> int
std_pow(base, exp)int, int -> int
std_gcd(a, b) / std_lcm(a, b)int, int -> int
std_factorial(n)int -> int
std_fibonacci(n)int -> int
std_is_even(x) / std_is_odd(x)int -> bool
int_to_word(n)int -> word

std::string#

Listed in full in Words & interpolation.

std::convert#

examples/stdlib_convert.fk compilesruns
-- std/convert.fk: base conversion and safe parsing.
task main() -> void {
    say int_to_hex(255)
    say int_to_bin(10)
    say int_to_oct(64)
    say word_from_int(char_to_digit("7"))
    say word_from_int(word_to_int_safe("not a number"))
    say word_from_int(word_to_int_safe("123"))
    say bool_to_word(true)
}
Program output
ff
1010
100
7
0
123
true
TaskSignature
int_to_hex(n) / int_to_bin(n) / int_to_oct(n)int -> word
char_to_digit(c)word -> int
word_to_int_safe(s)word -> int0 on failure, never panics
bool_to_word(b)bool -> word

std::algorithm#

See Arrays, including the two functions that are broken.

std::json#

A complete JSON parser in pure FREAK. Values are int handles.

examples/stdlib_json.fk compilesruns
-- std/json.fk is a pure-FREAK parser. Values are `int` handles.
task main() -> void {
    json_init()

    pilot doc: int = json_parse("{\"unit\":\"Valkyries\",\"members\":4,\"ready\":true}")

    say json_get_type(doc)
    say word_from_int(json_obj_len(doc))
    say word_from_bool(json_obj_has(doc, "unit"))

    say json_get_str(json_obj_get(doc, "unit"))
    say word_from_int(json_get_int(json_obj_get(doc, "members")))
    say word_from_bool(json_get_bool(json_obj_get(doc, "ready")))

    pilot list: int = json_parse("[10, 20, 30]")
    say word_from_int(json_arr_len(list))
    say word_from_int(json_get_int(json_arr_get(list, 1)))
}
Program output
o
3
true
Valkyries
4
true
3
20
TaskSignature
json_init()-> void — call once before parsing
json_parse(source)word -> int
json_stringify(handle)int -> word
json_get_type(h)int -> wordo, a, s, n, b, z
json_get_str(h) / json_get_int(h) / json_get_bool(h)int -> word / int / bool
json_is_null(h)int -> bool
json_obj_len(h) / json_obj_has(h, key) / json_obj_get(h, key) / json_obj_key_at(h, i)object access
json_arr_len(h) / json_arr_get(h, i)array access

std::version#

Semantic-version parsing and constraint matching — the machinery behind Hangar's dependency resolution.

examples/stdlib_version.fk compilesruns
-- std/version.fk implements semver parsing and constraint matching.
task main() -> void {
    pilot parsed: word = ver_parse("2.14.1-rc.1+build7")

    say word_from_int(ver_major(parsed))
    say word_from_int(ver_minor(parsed))
    say word_from_int(ver_patch(parsed))
    say ver_pre(parsed)
    say ver_build(parsed)
    say ver_to_string(parsed)

    say word_from_bool(ver_lt("1.2.3", "1.10.0"))
    say word_from_bool(ver_gt("2.0.0", "1.9.9"))
    say word_from_bool(ver_eq("1.0.0", "1.0.0"))
    say word_from_bool(ver_satisfies("1.4.2", "^1.4"))
    say word_from_bool(ver_satisfies("2.0.0", "^1.4"))
}
Program output
2
14
1
rc.1
build7
2.14.1-rc.1+build7
false
true
true
true
false
TaskSignature
ver_parse(version)word -> word — an encoded parse result
ver_major / ver_minor / ver_patchword -> int
ver_pre / ver_build / ver_to_stringword -> word
ver_compare(a, b)word, word -> int
ver_eq / ver_lt / ver_gt / ver_lte / ver_gteword, word -> bool
ver_bump_major / ver_bump_minor / ver_bump_patchword -> word
ver_satisfies(version, constraint)word, word -> bool
version_matches_constraint(version, constraint)word, word -> bool

Modules that do not exist#

The bible's Section 7 lists many more. None of these are in V3:

std::iter (.map, .filter, .fold, …), Map<K,V>, Set<T> and Lineup<T> from std::collections, std::io beyond say / ask, std::random, std::thread, std::anime, std::narrative, std::test, std::mem (Shared, Weak, size_of, alloc), std::ffi, std::os, std::panic, std::regex, std::crypto.

Partially covered, in a V3-specific shape rather than the bible's:

Bible moduleV3 equivalent
std::collections List<T>Typed List<T> with indexing and List::filled — no push/pop/sort
std::bytes ByteBufferThe builtin ByteBuffer type
std::word WordBuilderword_builder::* over an int handle
std::nettcp::socket_*, including listen and accept

Every FREAK snippet on this site was compiled by freak 0.14.2 (Maverick), built from source with a verified self-host fixed point. 45/45 examples compile; regenerate with python tools/verify.py then python tools/build_docs.py.