Portable: Linux (getrandom + pthread) and Windows (BCryptGenRandom + CRITICAL_SECTION); thread-safe with mutex; lazy auto-seed on first call.
Introduction
The random plugin provides a fast, modern pseudo-random number generator callable from scripts. The algorithm is xoshiro256++ (Blackman & Vigna) with a 256-bit internal state and a period of 2^256-1; seeding uses SplitMix64. One global generator lives in the process behind a mutex (Linux: pthread, Windows: CRITICAL_SECTION) -- safe to call from multiple threads.
Range conventions
The integer range (random.Int) is CLOSED: [min, max] with both endpoints inclusive -- for dice rolls (1..6) or array indices (0..N-1). The floating-point output (random.Double, random.Range) is HALF-OPEN: [min, max) -- the upper bound NEVER appears, which is the standard U(0,1) convention (Java, Python, Lua, JavaScript).
Determinism and reproducibility
Given the same seed, output is platform-independent. Two functions support reproducibility: random.Seed(i64) for simple seeding (good for tests and demos), and random.SaveState / random.LoadState which serialize the FULL 256-bit internal state to a 32-byte blob (exact snapshot).
When NOT to use
This is NOT a cryptographically secure generator -- do NOT use it for key material, password-hash salt, or token generation. Use crypto.RandomBytes / crypto.RandomHex instead -- those call the OS CSPRNG (BCryptGenRandom / getrandom) on every call.
Loading the plugin
plugin "../plugins/print/PrintPlugin"; plugin "../plugins/random/RandomPlugin";
A typical flow
// reproducible (for tests) random.Seed(42); i64 $d = random.Int(1, 6); // fresh sequence on every run random.AutoSeed(); double $u = random.Double();
What to know about every function
Every function is thread-safe; one global generator behind a mutex.
First call auto-seeds from OS entropy if random.Seed/AutoSeed has not been called.
Rejection sampling makes random.Int uniform across the full [min, max] (no modulo bias).
random.Double fills [0,1) with full 53-bit mantissa precision.
Errors come only from wrong arguments -- runtime error, script stops.
Seeding and state
Seeding the generator from an integer, from OS entropy, or restoring a previous snapshot.
random.Seed
random.Seed(seed) -> int
Sets the global PRNG seed from an i64 value. The implementation uses a SplitMix64 recipe to expand the seed into the 4*u64 internal state words. The same seed always produces the same sequence on any platform.
| Parameter | Type | Description |
|---|---|---|
| seed | i64 | The seed value. Any 64-bit integer; 0 is valid. |
Always 0 on success. The only error cases are wrong argument count/type.
random.Seed(42);
printf("%lld\n", random.Int(0, 99));
printf("%lld\n", random.Int(0, 99));51 53
For tests and reproducible demos. If you want a different sequence on every run, call random.AutoSeed() instead.
random.AutoSeed
random.AutoSeed() -> int
Seeds the generator from OS entropy (Linux: getrandom/urandom; Windows: BCryptGenRandom) and returns the i64 seed that was used. A single call guarantees a different sequence on every run.
This function takes no arguments.
The seed that was used (i64). Following random.Int / random.Double calls will produce a fresh sequence every time the program runs.
i64 $s = random.AutoSeed();
printf("seed used: %lld\n", $s);
printf("first: %lld\n", random.Int(1, 100));seed used: -3829416751029348176 first: 42
For real applications: games, simulations -- anywhere you want a fresh experience on every start.
random.SaveState
random.SaveState() -> blob
Snapshot of the current 256-bit PRNG state in a 32-byte blob (4 little-endian u64 words). For storage and later restoration.
This function takes no arguments.
32-byte blob; the contents are the full internal state.
random.Seed(100);
random.Int(0, 1000000);
blob $s[32];
$s = random.SaveState();
printf("%d bytes\n", $s.Length);32 bytes
Reproducible replay: e.g. a demo's 'snapshot' button captures the PRNG in a moment; later restoring it makes the following draws identical.
random.LoadState
random.LoadState(state) -> int
Restores a previously-saved 32-byte state. Rejects the all-zero blob (the xoshiro256++ system would collapse there).
| Parameter | Type | Description |
|---|---|---|
| state | blob | Exactly 32 bytes, output of a previous SaveState. |
0 on success. Errors on a wrong-sized blob or all-zero state.
blob $s[32];
random.Seed(100);
random.Int(0, 999999);
$s = random.SaveState();
int $a = random.Int(0, 999999);
random.LoadState($s);
int $b = random.Int(0, 999999);
printf("%lld == %lld\n", $a, $b);862054 == 862054
Deterministic algorithm testing; pausing a long simulation and resuming it later with identical draws.
Number drawing
Integer, double, range, and fair bool -- the typical user-facing surface.
random.Int
random.Int(min, max) -> int
Integer in the CLOSED interval [min, max] (BOTH endpoints inclusive). Uses rejection sampling to avoid modulo bias, so the distribution is uniform across the full range.
| Parameter | Type | Description |
|---|---|---|
| min | i64 | Lower bound (inclusive). |
| max | i64 | Upper bound (inclusive). min <= max is required. |
Integer in [min, max].
random.Seed(42);
printf("dice: %lld\n", random.Int(1, 6));
printf("d100: %lld\n", random.Int(1, 100));dice: 4 d100: 53
Dice rolls (1..6), array indices (0..N-1), percentages (1..100) -- any classic integer range.
random.Double
random.Double() -> float
Floating-point value in the HALF-OPEN interval [0.0, 1.0) (0.0 is possible, 1.0 is NEVER reached). The full 53-bit mantissa is filled exactly from the top 53 bits of the PRNG output.
This function takes no arguments.
Double in [0.0, 1.0).
random.Seed(1);
printf("u: %f\n", random.Double());u: 0.811612
For probabilistic decisions (if u < 0.3 -> 30%), interpolation alphas, and any U(0,1)-derived quantity.
random.Range
random.Range(min, max) -> float
Floating-point value in the half-open interval [min, max). min == max is NOT accepted (min < max is required).
| Parameter | Type | Description |
|---|---|---|
| min | number | Lower bound (inclusive). |
| max | number | Upper bound (NOT inclusive). min < max is required. |
Double in [min, max).
random.Seed(7);
printf("pos: (%f, %f)\n", random.Range(-1.0, 1.0), random.Range(-1.0,
1.0));pos: (-0.889279, -0.477181)
For mixed positive/negative float ranges: 2D positions, durations, physical parameters (weight, speed) for random init.
random.Bool
random.Bool() -> int
Fair 0 or 1 value (50/50). Uses the topmost bit of the PRNG output, which is the highest-quality bit of xoshiro256++.
This function takes no arguments.
0 or 1 (DominScript has no native bool, hence i32).
random.Seed(2024);
for i in 1..5 { printf("%d ", random.Bool()); }
printf("\n");1 0 1 1 0
Coin flips and fair binary decisions. For weighted bool (e.g. 70/30), use random.Double() and compare against 0.7.
Practical notes
Reproducible demos
For demos and test scripts, prefer a fixed random.Seed: this keeps the system tests deterministic, and the output can be diff-checked after each run. For live use (game, application), use random.AutoSeed() instead -- it produces a different internal state on every run.
Weighted choices with Double
For weighted bool (e.g. 70%/30%): `if (random.Double() < 0.7) { ... } else { ... }`. For more buckets, use cumulative thresholds: 60%/30%/10% -> 0.0..0.6, 0.6..0.9, 0.9..1.0.
Error handling
A wrong argument count/type, an invalid range (random.Int min > max, random.Range min >= max), a LoadState blob with size != 32 bytes, or the all-zero state are reported by the runtime as a runtime error and the script stops.
Built-in runtime functions
The 61 functions the DominScript runtime offers natively — exposed via five builtin plugins (os, blob, string, struct, plugin)
These functions do not live in separate plugin files; they are part of the runtime itself (Source/DominExecBuiltin.c and Source/DominExecPlugin.c). They require an explicit `plugin "builtin:os";` (and friends) directive — the runtime does NOT register them automatically. (Exception: `builtin:struct` helpers are invoked implicitly from the parser/binder for `struct` declarations and the `assign` operator, so language-level schema building works without loading.)
1. builtin:os — command line, script paths, runtime eval
Helpers for command-line handling and script environment. os.Eval and os.ValidateScript run/validate source in an isolated child runtime.
os.ArgCount
os.ArgCount() -> int
Number of command-line arguments. For `./domin script.dom a b c` returns 5 (the `./domin` and `script.dom` count as well).
This function takes no arguments.
Total number of arguments.
printf("argc = %d\n", os.ArgCount());argc = 5 Note: Index 0 is the domin binary path; index 1 is the script path; the rest are user args.
os.Arg
os.Arg(int $index) -> string
Returns the command-line argument at the given index as a string. Range: 0 .. os.ArgCount()-1.
| Parameter | Type | Description |
|---|---|---|
| $index | i32 | 0-based index of the argument. |
The argument as a string.
i32 $i = 0;
while ($i < os.ArgCount()) {
printf(" argv[%d] = %s\n", $i, os.Arg($i));
$i = $i + 1;
}
Note: Out-of-range index raises a runtime error.os.HasFlag
os.HasFlag(string $flag) -> int
Checks whether the given flag (e.g. `--help`, `-v`) is present in the command line. Returns 1 if present, 0 otherwise.
| Parameter | Type | Description |
|---|---|---|
| $flag | string | Exact flag string in the command line (leading `-` or `--` required). |
1 if present, 0 otherwise.
if (os.HasFlag("--help") == 1) {
printf("usage: ...\n");
}
Note: Only exact matches — `-h` and `--help` are
different flags.os.FindArg
os.FindArg(string $needle) -> int
Searches for `$needle` in the argument list and returns its index. -1 if not found.
| Parameter | Type | Description |
|---|---|---|
| $needle | string | Exact argument string to search for. |
Index (0-based) or -1.
i32 $pos = os.FindArg("--port");
if ($pos != -1) {
printf("--port at argv[%d]\n", $pos);
}
Note: Unlike `os.HasFlag`, this gives the index, so
the following argument (value) can be retrieved.os.GetOption
os.GetOption(string $name) -> string
Returns the value of an option in the form `--name value` or `--name=value`. Empty string if not present or no value.
| Parameter | Type | Description |
|---|---|---|
| $name | string | The option name including the leading `--`. |
Option value as string, or empty string.
string $port[16] = os.GetOption("--port");
printf("port=[%s]\n", $port);port=[19090] Note: Handles both `--port 8080` and `--port=8080` styles.
os.GetOptionOrDefault
os.GetOptionOrDefault(string $name, string $default) -> string
Same as `os.GetOption`, but returns `$default` if the option is absent.
| Parameter | Type | Description |
|---|---|---|
| $name | string | Option name including leading `--`. |
| $default | string | Default if not provided. |
Option value, or the default.
string $host[64] = os.GetOptionOrDefault("--host", "localhost");
Note: Ideal for config-style options where a default
is always needed.os.GetEnv
os.GetEnv(string $name) -> string
Returns the value of an environment variable. Empty string if unset.
| Parameter | Type | Description |
|---|---|---|
| $name | string | The environment variable name. |
The value string, or empty string.
string $home[256] = os.GetEnv("HOME");os.ScriptPath
os.ScriptPath() -> string
Absolute path of the currently running script.
This function takes no arguments.
Absolute path as string.
printf("script: %s\n", os.ScriptPath());os.ScriptDir
os.ScriptDir() -> string
Absolute directory of the currently running script (no trailing `/`).
This function takes no arguments.
Absolute directory path.
printf("base dir: %s\n", os.ScriptDir());
Note: Useful for resolving relative paths (e.g.
bundled assets).os.ExePath
os.ExePath() -> string
Absolute path of the `domin` executable. On Linux via `/proc/self/exe`.
This function takes no arguments.
Absolute path of the domin binary.
printf("interp: %s\n", os.ExePath());os.ValidateScript
os.ValidateScript(string $source) -> int
Validates a script source syntactically and semantically without running it. 0 = success, non-zero = error. Use the `os.LastValidation*` family to inspect details.
| Parameter | Type | Description |
|---|---|---|
| $source | string | The DominScript source to validate. |
0 on success, non-zero on error.
if (os.ValidateScript("int $x = 1;") != 0) {
printf("error: %s\n", os.LastValidationError());
}
Note: For plugin development and REPL-style tools:
validate user code before running it.os.Eval
os.Eval(string $source) -> int
Evaluates a script source at runtime in an isolated child runtime. Parent script variables are NOT visible inside. 0 = success, non-zero = error.
| Parameter | Type | Description |
|---|---|---|
| $source | string | The DominScript source to run. |
0 on success; on error the `os.LastValidation*` family provides details.
os.Eval("plugin \"builtin:os\"; printf(\"hi\\n\");");
Note: Dynamic script loading, script templates,
plug-in-like extensions. Be careful with untrusted source!os.LastValidationCategory
os.LastValidationCategory() -> string
Category of the last `ValidateScript`/`Eval` error: `"parse"`, `"bind"`, `"runtime"`, or empty if no error.
This function takes no arguments.
The error category name (lowercase string), or empty.
os.LastValidationLine
os.LastValidationLine() -> int
Line number of the last validation error (1-based), or 0 if no error.
This function takes no arguments.
Line number (1-based), or 0.
os.LastValidationColumn
os.LastValidationColumn() -> int
Column number of the last validation error (1-based), or 0.
This function takes no arguments.
Column number (1-based), or 0.
os.LastValidationOffset
os.LastValidationOffset() -> int
Byte offset of the last validation error in the source (0-based).
This function takes no arguments.
Byte offset.
os.LastValidationError
os.LastValidationError() -> string
Human-readable description of the last validation error.
This function takes no arguments.
Error text, or empty.
os.LastValidationWarnings
os.LastValidationWarnings() -> string
Warnings collected during the last validation, newline-separated.
This function takes no arguments.
Warnings text.
2. builtin:blob — blob overflow flag
A single function: whether the latest blob assignment overflowed.
blob.Overflow
blob.Overflow(blob $value) -> int
Returns 1 if the most recent assignment to the blob overflowed (was truncated due to declared size). 0 otherwise. The blob counterpart of `string.Overflow`.
| Parameter | Type | Description |
|---|---|---|
| $value | blob | A blob variable. |
1 = truncated, 0 = succeeded.
blob $small[8];
$small = blob.FromText("longer than eight");
if (blob.Overflow($small) == 1) {
printf("blob was truncated\n");
}blob was truncated Note: The flag persists until the next assignment.
3. builtin:string — string helpers and string.Format
Three functions: capacity query, overflow flag, and C printf-style format string into a string.
string.Capacity
string.Capacity(string $value) -> int
Declared capacity of a string variable (the N value from the `string $name[N]` declaration).
| Parameter | Type | Description |
|---|---|---|
| $value | string | A string variable. |
Capacity (N) in characters.
string $s[64] = "hello";
printf("cap=%d, len=%d\n", string.Capacity($s), $s.Length);cap=64, len=5 Note: Useful for buffer-size accounting; does NOT return the length — use the `.Length` property for that.
string.Overflow
string.Overflow(string $value) -> int
Returns 1 if the most recent assignment to the string overflowed (was truncated due to capacity). 0 otherwise.
| Parameter | Type | Description |
|---|---|---|
| $value | string | A string variable. |
1 = truncated, 0 = full assignment succeeded.
string $tiny[8];
$tiny = "this is too long";
if (string.Overflow($tiny) == 1) {
printf("truncated to: [%s]\n", $tiny);
}truncated to: [this is] Note: The flag persists until the next assignment — check it right after the risky assignment.
string.Format
string.Format(string $format, ...) -> string
C `printf`-style format string evaluation, returning the result as a string (does NOT write to stdout). Supports all standard specifiers (`%d %i %u %o %x %X %f %F %e %E %g %G %s %%`), flags (`+ - 0 space #`), width, precision, and length modifiers (`l ll h hh z j t`).
| Parameter | Type | Description |
|---|---|---|
| $format | string | The format string. |
| ... | any | Values to be substituted. |
The substituted string. The target variable's capacity may limit it (check with string.Overflow).
string $msg[256];
$msg = string.Format("%s = %d (0x%08x)", "value", 255, 255);
printf("%s\n", $msg);value = 255 (0x000000ff) Note: The `printf` function (in the `print` plugin) uses the same logic but writes to stdout. `string.Format` is essentially the same, but into a string.
4. builtin:struct — the struct/assign backend (global names)
These functions are the BACKEND helpers for the language's `struct` declaration and the `$blob assign StructName;` operator — the parser/binder calls them while building the schema tree. They are reachable by their global names (NULL namespace), e.g. `AddStructMember(...)`. Separate blob variants (`AddBlobMember`, `SchemaBlobMember*`) exist because a `struct Foo packet { ... }` declaration with the `packet` modifier asks for byte-exact, alignment-free layout — the runtime keeps those members in the schema descriptor's BLOB segment (ideal for network packets, file headers). Members without `packet` go into the normal segment. The registered plugin path is `"builtin:struct"` — `"builtin:assign"` does NOT exist (the C-side variable name `gBuiltinAssignPluginExport` is just an internal convention referring to the `assign` operator).
AddStructMember
AddStructMember(int $schemaId, string $name, int $type, int $offset) -> int
Adds a new member to a runtime-built schema descriptor.
AddBlobMember
AddBlobMember(int $schemaId, string $name, int $type, int $offset, int $size) -> int
Adds a new blob member to a runtime-built schema descriptor.
DelStructMember
DelStructMember(int $schemaId, string $name) -> int
Removes a named member from the schema descriptor.
DelBlobMember
DelBlobMember(int $schemaId, string $name) -> int
Removes a named blob member from the schema descriptor.
SchemaMemberCount
SchemaMemberCount(int $schemaId) -> int
Number of normal members in a schema.
SchemaBlobMemberCount
SchemaBlobMemberCount(int $schemaId) -> int
Number of blob members in a schema.
SchemaMemberName
SchemaMemberName(int $schemaId, int $index) -> string
Name of the normal member at the given index.
SchemaBlobMemberName
SchemaBlobMemberName(int $schemaId, int $index) -> string
Name of the blob member at the given index.
SchemaMemberType
SchemaMemberType(int $schemaId, int $index) -> int
Type code of the normal member at the given index.
SchemaBlobMemberType
SchemaBlobMemberType(int $schemaId, int $index) -> int
Type code of the blob member at the given index.
5. builtin:plugin — plugin introspection
For inspecting loaded plugins and their functions at runtime. Useful for REPL-style tools, documentation generators, and tooling. Type and mode constants are exposed via the `plugin.Type*` and `plugin.Mode*` getters.
plugin.Count
plugin.Count() -> int
Number of loaded plugins (including `builtin:*` plugins).
plugin.Path
plugin.Path(int $index) -> string
A plugin's load path or `builtin:` URL.
plugin.IsBuiltin
plugin.IsBuiltin(int $index) -> int
1 if the plugin is built-in (`builtin:*`), 0 if external (`.so`/`.dll`).
plugin.FunctionCount
plugin.FunctionCount(int $index) -> int
Number of functions exported by the plugin.
plugin.FindPath
plugin.FindPath(string $path) -> int
Finds a plugin by its path, returning its index; -1 if not found.
plugin.FunctionNamespace
plugin.FunctionNamespace(int $pluginIndex, int $funcIndex) -> string
Namespace of a plugin's function (empty string if NULL).
plugin.FunctionName
plugin.FunctionName(int $pluginIndex, int $funcIndex) -> string
Short name of a plugin's function (without namespace).
plugin.FunctionFullName
plugin.FunctionFullName(int $pluginIndex, int $funcIndex) -> string
Full name of a plugin's function (`namespace.Name` or just `Name`).
plugin.FindFunction
plugin.FindFunction(int $pluginIndex, string $fullName) -> int
Finds a function within a plugin by full name; -1 if not found.
plugin.Signature
plugin.Signature(int $pluginIndex, int $funcIndex) -> string
The function's full human-readable signature.
plugin.ParamCount
plugin.ParamCount(int $pluginIndex, int $funcIndex) -> int
Number of named parameters of the function (variadic not counted).
plugin.MinArgs
plugin.MinArgs(int $pluginIndex, int $funcIndex) -> int
Minimum number of arguments the function requires.
plugin.MaxArgs
plugin.MaxArgs(int $pluginIndex, int $funcIndex) -> int
Maximum number of arguments; `plugin.ArgCountUnlimited()` if unlimited.
plugin.ParamName
plugin.ParamName(int $pluginIndex, int $funcIndex, int $paramIndex) -> string
Name of the parameter at the given index.
plugin.ParamMode
plugin.ParamMode(int $pluginIndex, int $funcIndex, int $paramIndex) -> int
Parameter passing mode: `plugin.ModeValue()` or `plugin.ModeRef()`.
plugin.ParamType
plugin.ParamType(int $pluginIndex, int $funcIndex, int $paramIndex) -> int
Parameter type code (plugin.TypeInt, TypeFloat, ...).
plugin.VariadicMode
plugin.VariadicMode(int $pluginIndex, int $funcIndex) -> int
Mode of variadic arguments, if any.
plugin.VariadicType
plugin.VariadicType(int $pluginIndex, int $funcIndex) -> int
Type code of variadic arguments.
plugin.ModeValue
plugin.ModeValue() -> int
Constant value for `value` passing mode (for comparison).
plugin.ModeRef
plugin.ModeRef() -> int
Constant value for `ref` passing mode.
plugin.TypeAny
plugin.TypeAny() -> int
Constant value for the `any` type.
plugin.TypeInt
plugin.TypeInt() -> int
Constant value for the `int` type.
plugin.TypeFloat
plugin.TypeFloat() -> int
Constant value for the `float` type.
plugin.TypeString
plugin.TypeString() -> int
Constant value for the `string` type.
plugin.TypeBlob
plugin.TypeBlob() -> int
Constant value for the `blob` type.
plugin.TypeNumber
plugin.TypeNumber() -> int
Constant value for the `number` type (int or float).
plugin.ArgCountUnlimited
plugin.ArgCountUnlimited() -> int
Constant value for unlimited max-arg (for comparison with MaxArgs).
plugin.ModeText
plugin.ModeText(int $code) -> string
Converts a mode code to text form (`"value"`/`"ref"`).
plugin.TypeText
plugin.TypeText(int $code) -> string
Converts a type code to text form (`"int"`, `"float"`, ...).