From 4039abd10db42e9b673441a53c163e3fcf9fe61a Mon Sep 17 00:00:00 2001 From: hanez Date: Thu, 11 Dec 2025 22:51:23 +0100 Subject: [PATCH] Added new example that shows the usage of random_int() and random_seed(). Related parser fixes. (0.37.6) --- CMakeLists.txt | 2 +- examples/builtins_extended.fun | 6 +-- examples/random_demo.fun | 81 ++++++++++++++++++++++++++++++++++ src/parser.c | 11 ++--- 4 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 examples/random_demo.fun diff --git a/CMakeLists.txt b/CMakeLists.txt index 142212e..45f83ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(fun VERSION 0.37.5 LANGUAGES C) +project(fun VERSION 0.37.6 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/examples/builtins_extended.fun b/examples/builtins_extended.fun index 7c9fe9f..aac791e 100755 --- a/examples/builtins_extended.fun +++ b/examples/builtins_extended.fun @@ -45,9 +45,9 @@ print(max(5, 9)) // -> 9 print(clamp(15, 0, 10)) // -> 10 print(abs(-7)) // -> 7 print(pow(2, 8)) // -> 256 -random(123) // seed RNG -print(randomInt(0, 3)) // -> 0..2 (deterministic for seed 123) -print(randomInt(5, 6)) // -> 5 +random_seed(123) // seed RNG +print(random_int(0, 3)) // -> 0..2 (deterministic for seed 123) +print(random_int(5, 6)) // -> 5 /* Expected output: a-b-c diff --git a/examples/random_demo.fun b/examples/random_demo.fun new file mode 100644 index 0000000..6ec0a36 --- /dev/null +++ b/examples/random_demo.fun @@ -0,0 +1,81 @@ +#!/usr/bin/env fun + +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-12-11 + */ + +// Demonstrates usage of RANDOM_SEED and RANDOM_INT opcodes via +// the built-ins: random_seed(seed) and random_int(lo, hiExclusive). + +print("-- Random demo: seed reproducibility and bounds --") + +// Seed with a fixed value and produce a short sequence +seed = 123456 +random_seed(seed) +a1 = random_int(0, 10) // in [0,10) +a2 = random_int(0, 10) +a3 = random_int(5, 8) // in [5,8) + +print("First run:") +print(a1) +print(a2) +print(a3) + +// Re-seed with the same value: the sequence should repeat +random_seed(seed) +b1 = random_int(0, 10) +b2 = random_int(0, 10) +b3 = random_int(5, 8) + +print("Second run (after re-seed):") +print(b1) +print(b2) +print(b3) + +print("Reproducible? (a1==b1, a2==b2, a3==b3)") +print(a1 == b1) +print(a2 == b2) +print(a3 == b3) + +// Show that the upper bound is exclusive by sampling multiple times +// and tracking the maximum seen value; it should never reach hi. +lo = 10 +hi = 20 +max_seen = lo +i = 0 +while i < 100 + v = random_int(lo, hi) + if (v > max_seen) max_seen = v + i = i + 1 + +print("Max seen in [" + to_string(lo) + "," + to_string(hi) + ") over 100 samples:") +print(max_seen) +print("Is max_seen < hi? ") +print(max_seen < hi) + +/* Expected output: +-- Random demo: seed reproducibility and bounds -- +First run: +9 +3 +5 +Second run (after re-seed): +9 +3 +5 +Reproducible? (a1==b1, a2==b2, a3==b3) +true +true +true +Max seen in [10,20) over 100 samples: +19 +Is max_seen < hi? +1 +*/ diff --git a/src/parser.c b/src/parser.c index 17f1eca..b665f16 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1632,17 +1632,18 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos) free(name); return 1; } - if (strcmp(name, "random") == 0) { + + if (strcmp(name, "random_seed") == 0) { (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "random expects 1 arg"); free(name); return 0; } + if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "random_seed expects 1 arg"); free(name); return 0; } bytecode_add_instruction(bc, OP_RANDOM_SEED, 0); free(name); return 1; } - if (strcmp(name, "randomInt") == 0) { + if (strcmp(name, "random_int") == 0) { (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ',')) { parser_fail(*pos, "randomInt expects 2 args"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "randomInt expects 2 args"); free(name); return 0; } + if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ',')) { parser_fail(*pos, "random_int expects 2 args"); free(name); return 0; } + if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "random_int expects 2 args"); free(name); return 0; } bytecode_add_instruction(bc, OP_RANDOM_INT, 0); free(name); return 1;