builtins
Builtins are always available without importing any module.
Output Functions
Section titled “Output Functions”| Function | Signature | Description |
|---|---|---|
println |
(value T) |
Print value with newline. Accepts any type. |
print |
(value T) |
Print value without newline. Accepts any type. |
eprintln |
(value T) |
Print to stderr with newline. Accepts any type. |
eprint |
(value T) |
Print to stderr without newline. Accepts any type. |
flush |
() |
Flush buffered stdout so partial-line output appears immediately. |
All types are printable: string, i64, f64, bool, arrays, maps, structs, and pointers.
stdout is buffered. print output may not appear until a newline is written (on a
terminal) or the buffer fills (on a pipe or file); call flush() to force it out for
prompts, progress indicators, and spinners. system flushes stdout and stderr before
running the child so output is not reordered.
Input Functions
Section titled “Input Functions”| Function | Signature | Description |
|---|---|---|
input |
() -> string |
Read line from stdin. Flushes stdout first so a preceding print prompt is visible. |
Wide Integer Conversions
Section titled “Wide Integer Conversions”| Function | Description |
|---|---|
i128, i256 |
Convert to wide signed integers (struct-based, 128/256-bit) |
u128, u256 |
Convert to wide unsigned integers (struct-based, 128/256-bit) |
Utility Functions
Section titled “Utility Functions”| Function | Signature | Description |
|---|---|---|
len |
(collection T) -> i64 |
Length of array, map, or string (byte length for strings, not character count) |
type_of |
(value T) -> string |
Returns the Grayscale type name as a string (e.g. "i64", "u64", "f64", "string", "i128", "u256"). Accepts any type. |
size_of |
(Type) -> i64 |
Size of type in bytes |
fields |
(instance T) -> [string] |
Returns the field names of a struct as an array of strings in declaration order. Accepts struct instances and pointers to structs. |
copy |
(value T) -> T |
Create deep copy. Accepts any type. |
new |
(Type) -> ^Type |
Allocate zero-initialized value of any type on the heap arena |
ref |
(variable T) -> T |
Create a transparent reference (alias) to a variable. The return type is inferred and cannot be explicitly annotated. Reads and writes through the reference affect the original. Mutability is determined by the declaration (mut or const). |
addr |
(variable T) -> ^T |
Get memory address of a variable |
raw |
(variable T) -> ^T |
Get unchecked pointer — skips nil-check panics and const-source write protection |
error |
(code ErrorCode, message string = "") -> Error |
Create error value |
assert |
(condition bool, message string = "") |
Terminate with P0075 if condition is false. Message is optional. |
panic |
(message string) |
Terminate with error message |
exit |
(code i64) |
Exit program with code |
range |
(start i64, end i64, step i64 = 1) -> Range |
Create integer range; step defaults to 1 |
cast |
(value T, Type) -> Type |
Explicit type conversion |
to_char |
(s string, index i64) -> char |
Return the char at character position index (not byte position). The char is a 32-bit Unicode codepoint; use cast(c, i64) on the result for its numeric value. Panics if index is out of bounds. |
char_count |
(s string) -> i64 |
Return the number of Unicode characters (codepoints) in a string. Unlike len(), which returns byte count, char_count() counts decoded UTF-8 characters. |
c_string |
(ptr ^u8) -> string |
Convert a C char* return value to a Grayscale string (for C interop) |
embed |
(path string) -> string |
Read a file at compile time and return its contents as a string literal baked into the binary |
system |
(command string) -> i64 |
Run a shell command and return its exit code. Returns -1 if killed by signal. |
Reference behavior with ref():
The ref() function creates a reference to an existing value. The mutability of the reference depends on the variable declaration:
import @arrays
do main() { mut arr [i64] = {1, 2, 3}
// mut ref is mutable - can modify through the reference mut r1 = ref(arr) arrays.append(r1, 4) // OK - modifies arr
// const ref is read-only - can read but not modify const r2 = ref(arr) mut val = r2[0] // OK - can read // arrays.append(r2, 5) // ERROR - cannot modify through const ref
// const ref sees changes made to the original arrays.append(arr, 6) println(r2[4]) // Prints 6 - r2 sees the change}Mutability rules:
| Reference declaration | Source | Allowed? |
|---|---|---|
mut r = ref(x) |
mut |
yes |
const r = ref(x) |
mut |
yes, read-only view of a mutable source |
const r = ref(x) |
const |
yes |
mut r = ref(x) |
const |
no; you cannot get a mutable reference to a const source. Use copy(x) to obtain an independent mutable instance. |
Argument requirement: ref() requires a variable, struct field, array index, or pointer dereference; anything with a stable address. Literals, call results, and arithmetic expressions are rejected. The same rule applies to addr() and raw(), and the check recurses through member/index chains, so ref(some_call().field) is validated end-to-end. Indexing a dynamic [T] array is also rejected for all three (addr(arr[i]), raw(arr[i]), ref(arr[i])) — the backing store relocates when the array grows, leaving the pointer dangling. A fixed-size [T,N] array element is allowed, since its storage never moves.
assert() — runtime assertion
assert() checks a condition at runtime. If the condition is false, the program terminates immediately with error code P0075 and prints "panic[P0075]: assertion failed" to stderr. An optional second argument provides a message appended to the output.
do main() { mut x i64 = 1 mut items [i64] = {1} mut connected bool = true assert(x > 0, "x must be positive") assert(len(items) > 0, "list cannot be empty") assert(connected) // message is optional}assert() is a global builtin — no import required.
Rules:
- The condition must be a
bool. Passing a non-bool is a compile-time error (E5026). - The optional message must be a
string. Passing any other type is a compile-time error (E5026). - If the condition is
true, the program continues normally.assert()has no return value.
Runtime error code: P0075
Sleep Functions
Section titled “Sleep Functions”| Function | Signature | Description |
|---|---|---|
sleep_s |
(seconds i64) |
Sleep for seconds |
sleep_ms |
(ms i64) |
Sleep for milliseconds |
sleep_ns |
(ns i64) |
Sleep for nanoseconds |
Compile-time Functions
Section titled “Compile-time Functions”embed(path string) -> string
embed() reads a file from disk at compile time and bakes its entire contents into the binary as a string literal. The resulting value is available as a string at runtime with no file I/O overhead.
The path is resolved relative to the directory of the source file containing the embed() call. Absolute paths are also accepted. The argument must be a string literal; variables and expressions are rejected at compile time. If the file does not exist or cannot be read when the compiler runs, it is a compile-time error.
embed() is valid at file scope (as a const initializer) or inside a function body.
// Embed a file at file scope, baked into the binary at compile time// const LICENSE string = embed("../../LICENSE")// const DEFAULT_CONFIG string = embed("config/defaults.json")
// do main() {// // Also valid inside a function// const shader string = embed("shaders/vertex.glsl")// println(LICENSE)// }
do main() {}The embedded file is read once during compilation. Changes to the file after compilation have no effect on the binary. The compiler resolves the path relative to the .gray source file, not the current working directory when running grayc.