1
0
Fork 0
forked from fun/fun

Added lot more example code. (0.39.8).

This commit is contained in:
Johannes Findeisen 2026-03-25 23:38:04 +01:00
commit 564999709c
32 changed files with 1353 additions and 53 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
project(fun VERSION 0.39.7 LANGUAGES C)
project(fun VERSION 0.39.8 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)

24
examples/README.md Normal file
View file

@ -0,0 +1,24 @@
# Fun Examples
This directory contains small, pure Fun examples organized by topic.
How to run:
- Build the interpreter once: `cmake --build ./build_debug --target fun`
- Execute an example: `./build_debug/fun ./examples/<path>.fun`
- For CGI examples under `examples/data/htdocs`, start one of the blocking HTTP servers from `examples/blocking/` and visit the URL noted in the file headers.
Categories:
- basics: hello_world, fizzbuzz, fibonacci, collections
- strings: split_join_trim, templating_min, urlencode_decode
- io: read_write_file, csv_reader (uses examples/io/sample.csv), word_count
- algos: sort_and_search, deduplicate, stack_queue
- cli: env_echo, args_parse (parse ARGS env)
- net: tcp_echo_server, tcp_echo_client, http_static_server (blocking)
- data/htdocs (CGI): hello.fun, info.fun, counter.fun, form_post.fun, redirect.fun, json_like_api.fun
- compose: run_other_fun, pipeline
- patterns: assert_like, logging_min
- snippets: escape_html_demo, maps_iterate
Notes:
- Scripts that start servers (tcp_echo_server, http_static_server, http_server_cgi*.fun) are blocking; run them in a separate terminal.
- Some examples rely on stdlib includes; if needed, set `FUN_LIB_DIR=./lib` before running.

26
examples/algos/deduplicate.fun Executable file
View file

@ -0,0 +1,26 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// De-duplicate an array using a map as a set
arr = [1,2,2,3,1,4]
seen = {}
out = []
for x in arr
if (!has(seen, to_string(x)))
seen[to_string(x)] = 1
push(out, x)
print(to_string(out))
/* Expected output:
[array n=4]
*/

View file

@ -0,0 +1,60 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Selection sort + linear/binary search
fun sel_sort(a)
n = len(a)
i = 0
while (i < n)
m = i
j = i + 1
while (j < n)
if (a[j] < a[m]) m = j
j = j + 1
tmp = a[i]
a[i] = a[m]
a[m] = tmp
i = i + 1
return a
fun lin_find(a, x)
i = 0
while (i < len(a))
if (a[i] == x) return i
i = i + 1
return -1
fun bin_find(a, x)
lo = 0
hi = len(a) - 1
while (lo <= hi)
mid = (lo + hi) / 2
v = a[mid]
if (v == x) return mid
if (v < x)
lo = mid + 1
else
hi = mid - 1
return -1
arr = [5,1,4,2,3]
print("sorted: " + to_string(sel_sort(arr)))
print("lin_find 4: " + to_string(lin_find(arr, 4)))
print("bin_find 4: " + to_string(bin_find(arr, 4)))
/* Expected output:
sorted: [array n=5]
lin_find 4: 2
bin_find 4: 2
*/

44
examples/algos/stack_queue.fun Executable file
View file

@ -0,0 +1,44 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Array helpers
#include <arrays.fun>
// Stack via array push/pop
stack = []
push(stack, 1)
push(stack, 2)
push(stack, 3)
print("stack pop: " + to_string(stack[len(stack)-1]))
pop = stack[len(stack)-1]
// Use array_slice(arr, start, count) to drop the last element
stack = array_slice(stack, 0, len(stack)-1)
print("stack now: " + to_string(stack))
// Queue via array push/shift
queue = []
push(queue, "a")
push(queue, "b")
push(queue, "c")
head = queue[0]
// Keep all but the first element
queue = array_slice(queue, 1, len(queue)-1)
print("queue head: " + to_string(head))
print("queue now: " + to_string(queue))
/* Expected output:
stack pop: 3
stack now: [array n=2]
queue head: a
queue now: [array n=2]
*/

30
examples/basics/collections.fun Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Arrays and maps basics
arr = [1, 2, 3]
push(arr, 4)
print("arr size=" + to_string(len(arr)) + ", last=" + to_string(arr[3]))
user = {"name": "Lin", "age": 29}
user["city"] = "Paris"
for k in keys(user)
print(k + ": " + to_string(user[k]))
/* Expected output:
arr size=4, last=4
age: 29
name: Lin
city: Paris
*/

38
examples/basics/fibonacci.fun Executable file
View file

@ -0,0 +1,38 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Fibonacci: iterative and recursive
fun fib_iter(n)
if (n <= 1) return n
a = 0
b = 1
i = 2
while (i <= n)
t = a + b
a = b
b = t
i = i + 1
return b
fun fib_rec(n)
if (n <= 1) return n
return fib_rec(n - 1) + fib_rec(n - 2)
print("fib_iter(10) = " + to_string(fib_iter(10)))
print("fib_rec(10) = " + to_string(fib_rec(10)))
/* Expected output:
fib_iter(10) = 55
fib_rec(10) = 55
*/

125
examples/basics/fizzbuzz.fun Executable file
View file

@ -0,0 +1,125 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Classic FizzBuzz from 1..100
i = 1
while (i <= 100)
out = ""
if (i % 3 == 0) out = out + "Fizz"
if (i % 5 == 0) out = out + "Buzz"
if (len(out) == 0) out = to_string(i)
print(out)
i = i + 1
/* Expected output:
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
*/

19
examples/basics/hello_world.fun Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Minimal Hello World in Fun
print("Hello, World!")
/* Expected output:
Hello, World!
*/

41
examples/cli/args_parse.fun Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Parse env-style args: ARGS="key=val foo=bar" (since argv is not available here)
// String helpers
#include <strings.fun>
line = env("ARGS")
if (len(line) == 0)
line = "name=Fun color=blue"
parts = str_split(line, " ")
cfg = {}
for p in parts
if (len(p) == 0) continue
eq = find(p, "=")
if (eq > 0)
k = substr(p, 0, eq)
v = substr(p, eq + 1, len(p) - eq - 1)
cfg[k] = v
for k in keys(cfg)
print(k + ": " + to_string(cfg[k]))
/* Expected output (order of keys may vary):
name: Fun
color: blue
With ARGS overridden, e.g.: ARGS="x=1 y=2"
x: 1
y: 2
*/

23
examples/cli/env_echo.fun Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
keys_to_show = ["HOME", "USER", "SHELL", "PATH"]
for k in keys_to_show
print(k + "=" + env(k))
/* Expected output (values depend on your environment):
HOME=/home/youruser
USER=youruser
SHELL=/bin/bash
PATH=/usr/local/bin:... (truncated)
*/

23
examples/compose/pipeline.fun Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <strings.fun>
res1 = proc_run("echo one")
res2 = proc_run("echo two")
out = str_trim(res1["out"]) + "," + str_trim(res2["out"])
print(out)
/* Expected output:
one,two
*/

View file

@ -0,0 +1,25 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
cmd = "./build_debug/fun ./examples/basics/hello_world.fun"
res = proc_run(cmd)
print("exit: " + to_string(res["code"]))
print("out: " + to_string(res["out"]))
print("err: " + to_string(res["err"]))
/* Expected output (with build_debug/fun present):
exit: 0
out: Hello, World!\n
err: nil
*/

View file

@ -0,0 +1,31 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <net/cgi.fun>
cgi = CGI()
v = to_number(cgi.cookie("visits"))
if (v <= 0) v = 0
v = v + 1
cgi.header("Set-Cookie", "visits=" + to_string(v) + "; Path=/; HttpOnly")
cgi.content_type("text/html; charset=utf-8")
body = "<html><body><p>Visits: " + to_string(v) + "</p></body></html>"
cgi.send(body)
/* Expected output (first visit, no existing cookie):
Status: 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: visits=1; Path=/; HttpOnly
<html><body><p>Visits: 1</p></body></html>
*/

View file

@ -0,0 +1,36 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <net/cgi.fun>
cgi = CGI()
cgi.content_type("text/html; charset=utf-8")
pmap = cgi.params()
html = "<html><body><h1>POST fields</h1><ul>"
for k in keys(pmap)
vals = cgi.param_all(k)
i = 0; n = len(vals); joined = ""
while (i < n)
if (i > 0) joined = joined + ", "
joined = joined + cgi.escape_html(vals[i])
i = i + 1
html = html + "<li><b>" + cgi.escape_html(k) + "</b>: " + joined + "</li>"
html = html + "</ul></body></html>"
cgi.send(html)
/* Expected output (POST with body: "a=1&b=two&b=2"):
Status: 200 OK
Content-Type: text/html; charset=utf-8
<html><body><h1>POST fields</h1><ul><li><b>a</b>: 1</li><li><b>b</b>: two, 2</li></ul></body></html>
*/

View file

@ -52,3 +52,11 @@ html = html + "</body></html>"
// Send CGI headers + body
cgi.send(html)
/* Expected output (GET /hello.fun?name=Fun with no ua cookie):
Status: 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: ua=FunClient; Path=/; HttpOnly
<html><head><title>Fun CGI</title></head><body><h1>Hello, Fun!</h1><p>REQUEST_METHOD: GET</p><p>QUERY_STRING: name=Fun</p><p>User-Agent cookie: </p><h2>Params</h2><ul><li><b>name</b>: Fun</li></ul></body></html>
*/

View file

@ -0,0 +1,21 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <net/cgi.fun>
cgi = CGI()
cgi.content_type("application/json; charset=utf-8")
name = cgi.param("name")
if (len(name) == 0) name = "World"
body = "{\n \"greeting\": \"Hello, " + cgi.escape_html(name) + "!\",\n \"method\": \"" + cgi.escape_html(cgi.env["REQUEST_METHOD"]) + "\"\n}"
cgi.send(body)

View file

@ -0,0 +1,19 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <net/cgi.fun>
cgi = CGI()
cgi.redirect("/hello.fun?name=Fun", 302)
cgi.content_type("text/html; charset=utf-8")
cgi.send("<html><body>Redirecting...</body></html>")

4
examples/data/sample.csv Normal file
View file

@ -0,0 +1,4 @@
name,age,city
Ada,37,London
Lin,29,Paris
Max,42,Berlin
1 name age city
2 Ada 37 London
3 Lin 29 Paris
4 Max 42 Berlin

37
examples/io/csv_reader.fun Executable file
View file

@ -0,0 +1,37 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <strings.fun>
path = "./examples/data/sample.csv"
// Very small CSV reader (no quotes/escapes) for demo purposes
fun parse_csv_line(line)
return str_split(str_trim(line), ",")
data = read_file(path)
if (len(data) == 0)
print("No CSV content at: " + path)
else
rows = str_split(data, "\n")
for row in rows
if (len(str_trim(row)) == 0) continue
cols = parse_csv_line(row)
print("ROW: " + to_string(cols))
/* Expected output (from examples/io/sample.csv):
ROW: [array n=3]
ROW: [array n=3]
ROW: [array n=3]
ROW: [array n=3]
*/

25
examples/io/read_write_file.fun Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <strings.fun>
path = "./tmp/example.txt"
print("Writing to: " + path)
write_file(path, "Hello from Fun!\n")
txt = read_file(path)
print("Read back: " + str_trim(txt))
/* Expected output:
Writing to: ./tmp/example.txt
Read back: Hello from Fun!
*/

412
examples/io/word_count.fun Executable file
View file

@ -0,0 +1,412 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// String helpers
#include <strings.fun>
path = "./README.md"
txt = read_file(path)
if (len(txt) == 0)
print("no content: " + path)
return 0
txt = str_to_lower(txt)
txt = str_replace_all(txt, "\n", " ")
parts = str_split(txt, " ")
freq = {}
for w in parts
w = str_trim(w)
if (len(w) == 0) continue
c = to_number(freq[w])
if (c <= 0) c = 0
freq[w] = c + 1
for k in keys(freq)
print(k + ": " + to_string(freq[k]))
/* Possible output (first 10 lines; counts depend on README.md contents):
#: 1
fun: 19
([https://fun-lang.xyz](https://fun-lang.xyz)): 1
##: 9
what: 2
is: 16
fun?: 1
a: 9
small,: 1
strict,: 1
and: 15
simple: 3
programming: 5
language: 5
that: 4
runs: 1
on: 3
compact: 1
stack-based: 1
virtual: 1
machine.: 1
the: 24
c: 2
core: 3
intentionally: 1
minimal;: 1
most: 6
functionality: 1
standard: 2
libraries: 2
are: 6
implemented: 2
in: 19
itself.: 2
emphasizes: 1
simplicity,: 1
consistency,: 1
joy: 3
coding.: 2
an: 1
experiment,: 1
just: 2
for: 6
fun,: 3
but: 5
works!: 1
highly: 2
strict: 1
language,: 1
also: 1
simple.: 1
it: 2
looks: 2
like: 4
python: 1
(my: 1
favorite: 1
language),: 1
there: 2
differences.: 1
influenced: 1
by: 2
**[bash](https://www.gnu.org/software/bash/)**,: 1
**[c](https://en.wikipedia.org/wiki/the_c_programming_language)**,: 1
**[lua](https://www.lua.org/)**,: 1
php,: 1
**[python](https://www.python.org/)**,: 1
rust: 1
(most: 1
influences: 1
came: 1
from: 2
linked: 1
languages).: 1
will: 4
ever: 1
be: 5
100%: 1
free: 1
under: 1
terms: 1
of: 3
[apache-2.0: 1
license](https://opensource.org/license/apache-2-0).: 1
idea: 1
-: 48
simplicity: 2
consistency: 2
to: 7
extend: 1
hackable: 1
coding: 2
fun!: 1
characteristics: 1
dynamic: 1
optionally: 1
statically: 1
typed: 1
type: 1
safety: 1
written: 6
(c99): 1
internal: 1
libs: 2
with: 2
no_camel_case: 1
even: 1
when: 1
except: 1
class: 1
names: 1
only: 2
minimal: 1
function: 1
set: 1
c,: 1
other: 1
functions: 1
manifesto: 1
built: 2
idea:: 1
should: 6
enjoyable,: 1
elegant,: 1
consistent.: 1
###: 5
philosophy: 1
**fun: 2
fun**<br>: 1
spark: 1
creativity,: 1
not: 4
frustration.: 1
code: 3
feels: 3
light,: 1
playful,: 1
rewarding.: 1
uses: 1
nothing**<br>: 1
minimalism: 1
power.: 1
no: 7
unnecessary: 1
features,: 1
endless: 1
syntax: 1
variations,: 1
formatting: 1
debates.: 1
clean,: 1
uniform: 1
code.: 1
**indentation: 1
truth**<br>: 1
two: 1
spaces,: 1
always.: 1
tabs,: 1
four-space: 1
wars.: 1
look: 1
same: 2
everywhere,: 1
your: 1
laptop: 1
/usr/bin/fun.: 1
**one: 1
way: 1
do: 1
it**<br>: 1
clutter,: 1
15: 1
ways: 1
writing: 1
thing.: 1
means: 1
clarity.: 1
**hackable: 1
nature**<br>: 1
small: 1
embeddable,: 1
lua.: 1
easy: 1
understand,: 1
extend,: 1
tinker: 1
—: 2
true: 1
hacker: 1
spirit.: 1
**beautiful: 1
defaults**<br>: 1
doesnt: 1
need: 1
linters,: 1
formatters,: 1
or: 3
style: 1
guides.: 1
beauty: 1
in.: 1
community: 3
about: 2
being: 1
fastest: 1
feature-rich.: 1
its: 1
sharing: 1
be:: 1
respectful: 1
curious: 1
creative: 1
open: 1
everyone: 1
name: 1
says:: 1
unites: 1
nerds.: 1
please: 1
visit: 1
[fun: 1
page](https://fun-lang.xyz/community/): 1
get: 1
touch.: 1
goal: 1
home: 1
developers: 1
who:: 1
love: 1
minimal,: 1
elegant: 1
tools: 1
believe: 1
freedom: 1
want: 1
write: 1
good: 2
may: 2
change: 1
world: 1
make: 1
little: 1
more: 1
fun.: 1
features: 2
functions/classes/objects: 1
if/else: 2
try/catch/finally: 1
lib: 1
(./lib/): 1
see: 2
[./lib/](https://git.xw3.org/fun/fun/src/branch/main/lib): 2
library: 1
provides.: 1
optional: 1
extensions: 1
(build-time: 1
selectable: 1
/: 2
testing: 1
this: 1
linux: 1
actually):: 1
[cgi](https://en.wikipedia.org/wiki/common_gateway_interface): 1
support: 1
builtin: 1
using: 1
[kcgi](https://kristaps.bsd.lv/kcgi/): 1
(optional): 11
&#9744;: 2
[curl: 1
(libcurl)](./docs/external/curl.md): 1
&#9745;: 11
[ini: 1
(iniparser)](./docs/external/ini.md): 1
[json: 1
(json-c)](./docs/external/json.md): 1
[libsql](./docs/external/libsql.md): 1
[pcre2](./docs/external/pcre2.md): 1
[pcsc: 1
(smart: 1
cards)](./docs/external/pcsc.md): 1
[openssl](./docs/external/openssl.md): 1
[sqlite](./docs/external/sqlite.md): 1
[tk: 1
(tcl/tk: 1
gui)](./docs/external/tcltk.md): 1
[xml: 1
(libxml2)](./docs/external/xml2.md): 1
=: 2
done: 1
planned: 1
progress.: 1
note:: 2
all: 1
above: 1
implemented.: 1
those: 1
who: 1
marked: 1
"done": 1
probaly: 1
remain: 1
i: 1
don't: 1
know: 1
actually...: 1
;): 1
some: 2
available: 1
diretory.: 1
future: 1
enhancements: 1
openssl: 1
quickstart: 1
(md5): 1
dedicated: 1
page:: 1
./docs/external/openssl.md: 1
documentation: 2
looking: 1
docs?: 1
start: 1
here:: 1
local: 1
index:: 1
[docs/readme.md](./docs/readme.md): 1
handbook:: 1
[docs/handbook.md](./docs/handbook.md): 1
types: 1
overview:: 1
[docs/types.md](./docs/types.md): 1
repl: 1
guide:: 1
[docs/repl.md](./docs/repl.md): 1
testing:: 1
[docs/testing.md](./docs/testing.md): 1
troubleshooting:: 1
[docs/troubleshooting.md](./docs/troubleshooting.md): 1
additional: 1
references:: 1
specification:: 1
[spec/v0.3.md](./spec/v0.3.md): 1
(work: 1
progress): 1
examples: 1
demonstrating: 1
features:: 1
[examples/](./examples/): 1
internals: 1
vm: 1
opcodes: 1
live: 1
[src/](./src/): 1
(see: 1
[src/vm/](./src/vm): 1
opcode: 1
implementations): 1
project: 1
evolving;: 1
documents: 1
lag: 1
behind.: 1
docs: 1
index: 1
`./docs/readme.md`: 1
uptodate: 1
entry: 1
point.: 1
author: 1
johannes: 1
findeisen: 1
<you@hanez.org>: 1
*/

View file

@ -0,0 +1,40 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <io/socket.fun>
port = 8088
srv = TcpServer(port, 10)
if (srv.listen() <= 0)
print("HTTP static server: listen failed on :" + to_string(port))
return 0
print("HTTP static server on :" + to_string(port))
while true
fd = srv.accept()
if (fd > 0)
_ = sock_recv(fd, 4096) // ignore request
body = "<html><body><h1>Hello from Fun static server</h1></body></html>"
b = to_string(body)
resp = "HTTP/1.1 200 OK\r\n"
resp = resp + "Content-Type: text/html; charset=utf-8\r\n"
resp = resp + "Content-Length: " + to_string(len(b)) + "\r\n"
resp = resp + "Connection: close\r\n\r\n" + b
sock_send(fd, resp)
sock_close(fd)
/* Expected output (on start):
HTTP static server on :8088
Then open http://127.0.0.1:8088/ in a browser; it will render:
<html><body><h1>Hello from Fun static server</h1></body></html>
*/

View file

@ -0,0 +1,27 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <io/socket.fun>
fd = sock_connect("127.0.0.1", 9090)
if (fd <= 0)
print("connect failed")
return 0
sock_send(fd, "ping\n")
resp = sock_recv(fd, 4096)
print("response: " + resp)
sock_close(fd)
/* Expected output (with tcp_echo_server.fun running):
response: ping
*/

View file

@ -0,0 +1,33 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <io/socket.fun>
port = 9090
srv = TcpServer(port, 10)
if (srv.listen() <= 0)
print("listen failed on :" + to_string(port))
return 0
print("Echo server on :" + to_string(port))
while true
fd = srv.accept()
if (fd > 0)
msg = sock_recv(fd, 4096)
if (len(msg) > 0) sock_send(fd, msg)
sock_close(fd)
/* Expected output (on start):
Echo server on :9090
Then, from another shell: `nc 127.0.0.1 9090` and type "ping" the server echoes it back.
*/

View file

@ -0,0 +1,25 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
fun assert_like(cond, msg)
if (!cond)
print("ASSERT FAILED: " + to_string(msg))
return 0
return 1
ok = assert_like(1 + 1 == 2, "math broke")
print("assert returned: " + to_string(ok))
/* Expected output:
assert returned: 1
*/

View file

@ -0,0 +1,37 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Minimal helper: remove trailing newline from a string (no full strings lib needed)
fun chomp(s)
t = to_string(s)
if (len(t) > 0 && substr(t, len(t) - 1, 1) == "\n")
return substr(t, 0, len(t) - 1)
return t
fun now()
// Very rough timestamp using system 'date' for demo
r = proc_run("date +%Y-%m-%dT%H:%M:%S%z")
return chomp(r["out"])
fun log_line(level, msg)
print("[" + now() + "] [" + to_string(level) + "] " + to_string(msg))
log_line("INFO", "Service starting")
log_line("DEBUG", "Config loaded")
log_line("INFO", "Service running")
/* Expected output (timestamps will vary):
[2026-03-25T23:00:00+0000] [INFO] Service starting
[2026-03-25T23:00:00+0000] [DEBUG] Config loaded
[2026-03-25T23:00:00+0000] [INFO] Service running
*/

View file

@ -0,0 +1,24 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <net/cgi.fun>
cgi = CGI()
raw = "<script>alert('xss') & more</script>"
print("raw: " + raw)
print("escaped:" + cgi.escape_html(raw))
/* Expected output:
raw: <script>alert('xss') & more</script>
escaped:&lt;script&gt;alert(&#39;xss&#39;) &amp; more&lt;/script&gt;
*/

View file

@ -0,0 +1,29 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <strings.fun>
txt = " one, two , three "
parts = str_split(txt, ",")
i = 0
while (i < len(parts))
parts[i] = str_trim(parts[i])
i = i + 1
print("parts: " + to_string(parts))
joined = join(parts, ";")
print("joined: " + joined)
/* Expected output:
parts: [array n=3]
joined: one;two;three
*/

View file

@ -0,0 +1,30 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
// Micro templating: replace {{key}} with map values
#include <strings.fun>
tpl = "Hello, {{name}} from {{city}}!"
ctx = {"name": "Fun", "city": "Cyberspace"}
fun render(template, data)
out = to_string(template)
for k in keys(data)
needle = "{{" + to_string(k) + "}}"
out = str_replace_all(out, needle, to_string(data[k]))
return out
print(render(tpl, ctx))
/* Expected output:
Hello, Fun from Cyberspace!
*/

View file

@ -0,0 +1,24 @@
#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-25
*/
#include <net/cgi.fun>
cgi = CGI()
s = "name=Fun+Lang&msg=Hello%2C+World%21"
print("raw: " + s)
print("decod: " + cgi.url_decode(s))
/* Expected output:
raw: name=Fun+Lang&msg=Hello%2C+World%21
decod: name=Fun Lang&msg=Hello%2C World%21
*/

View file

@ -16,7 +16,7 @@ fun str_ltrim(s)
src = to_string(s)
number i = 0
ws = " \t\r\n"
while i < len(src)
while (i < len(src))
ch = substr(src, i, 1)
if (find(ws, ch) < 0)
break
@ -28,7 +28,7 @@ fun str_rtrim(s)
src = to_string(s)
number i = len(src) - 1
ws = " \t\r\n"
while i >= 0
while (i >= 0)
ch = substr(src, i, 1)
if (find(ws, ch) < 0)
break
@ -69,7 +69,7 @@ fun str_split(s, delim)
buf = []
number i = 0
number n = len(src)
while i < n
while (i < n)
ch = substr(src, i, 1)
if (ch == dd)
push(parts, join(buf, ""))
@ -92,7 +92,7 @@ fun str_replace_all(s, from, to)
return src
out = []
number i = 0
while i < n
while (i < n)
if ((i + lf <= n) && (substr(src, i, lf) == f))
push(out, t)
i = i + lf
@ -109,7 +109,7 @@ fun str_to_lower(s)
out = []
number i = 0
number n = len(src)
while i < n
while (i < n)
ch = substr(src, i, 1)
idx = find(U, ch)
if (idx >= 0)
@ -127,7 +127,7 @@ fun str_to_upper(s)
out = []
number i = 0
number n = len(src)
while i < n
while (i < n)
ch = substr(src, i, 1)
idx = find(L, ch)
if (idx >= 0)
@ -145,59 +145,19 @@ fun str_repeat(s, count)
return ""
parts = []
number i = 0
while i < c
while (i < c)
push(parts, src)
i = i + 1
return join(parts, "")
/*
// ASCII string to bytes (printable ASCII 0x20..0x7E)
// Temporarily disabled due to parser incompatibilities with certain string
// literals in this function on some environments. Re-enable after the
// language parser updates to support these cases.
fun string_to_bytes_ascii(s)
str = to_string(s)
out = []
number i = 0
// ASCII printable ranges
P1 = " !\"#$%&'()*+,-./" // 32..47
P2 = "0123456789" // 48..57
P3 = ":;<=>?@" // 58..64
P4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 65..90
P5 = "[\\]^_`" // 91..96
P6 = "abcdefghijklmnopqrstuvwxyz" // 97..122
P7 = "{|}~" // 123..126
while true
ch = substr(str, i, 1)
if (typeof(ch) != "String" || ch == "")
break
number code = -1
idx = find(P1, ch)
if (idx >= 0)
code = 32 + idx
else
idx = find(P2, ch)
if (idx >= 0)
code = 48 + idx
else
idx = find(P3, ch)
if (idx >= 0)
code = 58 + idx
else
idx = find(P4, ch)
if (idx >= 0)
code = 65 + idx
else
idx = find(P5, ch)
if (idx >= 0)
code = 91 + idx
else
idx = find(P6, ch)
if (idx >= 0)
code = 97 + idx
else
idx = find(P7, ch)
if (idx >= 0)
code = 123 + idx
else
// non-printable -> 0
code = 0
push(out, code)
i = i + 1
return out
*/