1
0
Fork 0
forked from fun/fun

Documentation fixes. No code changes. (0.40.5)

This commit is contained in:
Johannes Findeisen 2026-04-11 02:38:47 +02:00
commit 02f0c07bce
28 changed files with 271 additions and 496 deletions

View file

@ -8,7 +8,7 @@ layout: default
<p class="post-meta" style="padding: 0px 0px 0px 0px;">{% if page.date %}{{ page.date | date: "%b %-d, %Y %H:%M:%S" }}{% endif %}
{% if page.date and page.date_updated %} - {% endif %}
{% if page.date_updated %}Edited: {{ page.date_updated | date: "%b %-d, %Y %H:%M:%S" }}{% endif %}
{% if page.date or page.date_updated %} ({{ page.date | date: "%Z" }}){% endif %}{% if page.author %}, <a href="{{ site.git_short }}/{{ page.author }}" target="_blank" class="user">{{ page.author }}</a>{% endif %}</p>
{% if page.date or page.date_updated %} ({{ page.date | date: "%Z" }}){% endif %}{% if page.author %}, <a href="{{ page.author_url }}" target="_blank" class="user">{{ page.author }}</a>{% endif %}</p>
</header>
<article class="post-content">
{{ content }}

View file

@ -2,6 +2,8 @@
layout: post
published: true
author: hanez
author_email: you@hanez.org
author_url: https://hanez.org
title: Init Fun!
description: Blog - Init Fun!
date: 2025-10-05

View file

@ -2,11 +2,13 @@
layout: post
published: true
author: hanez
author_email: you@hanez.org
author_url: https://hanez.org
noToc: false
title: Announcing Fun 0.37.62
description: Homepage and Blog
date: 2026-01-25
date_updated: 2026-01-31 21:45:03
date_updated: 2026-04-11 00:56:03
categories:
- news
- project
@ -54,26 +56,22 @@ This release brings Fun closer to its vision with significant language enhanceme
- Private members by convention (leading underscore)
- Dot-call syntax sugar for clean method invocations: obj.method(a, b)
<pre>
class Counter
<pre>class Counter
value = 0
fun inc(this)
this.value = this.value + 1
return this.value
c = Counter()
print(c.inc()) // 1
</pre>
print(c.inc()) // 1</pre>
### Module System
- Namespaced includes with #include <path> as alias for clean imports
- Organize code into reusable modules without naming conflicts
<pre>
#include <utils/math.fun> as m
print(m.add(2, 3)) // 5
</pre>
<pre>#include <utils/math.fun> as m
print(m.add(2, 3)) // 5</pre>
### Enhanced Type System
@ -87,14 +85,12 @@ print(m.add(2, 3)) // 5
- Thread primitives: thread_spawn, thread_join, and sleep
- Write concurrent programs with ease
<pre>
fun square(n)
<pre>fun square(n)
sleep(100)
return n * n
tid = thread_spawn(square, 5)
print(thread_join(tid)) // 25
</pre>
print(thread_join(tid)) // 25</pre>
### Control Flow Improvements
@ -146,22 +142,21 @@ Important: Fun is not developed on third-party Git servers like GitHub or GitLab
If you're curious about Fun, check out:
- [Website](https://fun-lang.xyz)
- [Git Repository](https://git.xw3.org/fun/fun){:class="git"}
- [Fun Handbook](https://fun-lang.xyz/documentation/handbook/){:class="git"}
- [Fun REPL Guide](https://fun-lang.xyz/documentation/repl/){:class="git"}
- [Fun Handbook](/documentation/handbook/)
- [Fun REPL Guide](/documentation/repl/)
- [Specification v0.3](https://git.xw3.org/fun/fun/src/branch/main/spec/v0.3.md){:class="git"}
- [Examples](https://git.xw3.org/fun/fun/src/branch/main/examples){:class="git"}
- [Standard Library](https://git.xw3.org/fun/fun/src/branch/main/lib){:class="git"}
- [Community](https://fun-lang.xyz/community/)
- [Community](/community/)
The examples directory contains demonstrations of most Fun features, from basic "Hello, World!" to threading, networking, classes, and more. The lib directory includes modules written in Fun itself — and in the future, most enhancements will be written in Fun rather than C.
### For Developers
- [Fun Internals](https://fun-lang.xyz/documentation/internals/){:class="git"}
- [Fun Opcodes](https://fun-lang.xyz/documentation/opcodes/){:class="git"}
- [Basic Rust Opcodes Support](https://fun-lang.xyz/documentation/rust/){:class="git"}
- [Fun Internals](/documentation/internals/){:class="git"}
- [Fun Opcodes](/documentation/opcodes/){:class="git"}
- [Basic Rust Opcodes Support](/documentation/rust/){:class="git"}
### The Road Ahead
@ -173,5 +168,4 @@ Fun is and will always be 100% free under the terms of the [Apache-2.0 License](
Happy hacking, and remember: Fun is Fun!
Johannes Findeisen (hanez) - [hanez@fun-lang.org](mailto:hanez@fun-lang.org){:class="mail"}
Johannes Findeisen (hanez) - [hanez@fun-lang.xyz](mailto:hanez@fun-lang.xyz){:class="mail"}

View file

@ -2,6 +2,8 @@
layout: post
published: true
author: hanez
author_email: you@hanez.org
author_url: https://hanez.org
noToc: false
title: Moving the Website to the Project Root
description: Relocating the fun-lang.xyz source code for easier maintenance.
@ -23,6 +25,7 @@ We've recently completed a significant change to our project structure: the sour
The main reason for merging this code into the root of the Fun project is that it is much easier for me to maintain the whole project this way.
Having everything in one place simplifies our development workflow:
- **Unified Versioning:** All project components, including the website and its documentation, now share the same version control history.
- **Simplified Maintenance:** Updating documentation and the website together ensures that the online presence stays in sync with the language's development.
- **Streamlined Workflow:** It's now possible to update the language, its libraries, the documentation, and the blog in a single commit if needed.
@ -31,7 +34,7 @@ Having everything in one place simplifies our development workflow:
You can now find the website source in the `./web/` directory of the repository. It continues to use the [Jekyll](https://jekyllrb.com/){:class="ext"} static site generator.
For those interested in the technical details or looking to contribute to the website, we have added a new documentation file: [docs/website.md](https://git.xw3.org/fun/fun/src/branch/main/docs/website.md){:class="git"}. This document covers the technology stack, the directory structure, and the available `Makefile` targets for local development and deployment.
For those interested in the technical details or looking to contribute to the website, we have added a new documentation file: [/web/documentation/website/](../documentation/website/){:class="git"}. This document covers the technology stack, the directory structure, and the available `Makefile` targets for local development and deployment.
### What changes for you?

View file

@ -15,7 +15,7 @@ $background-color: #565656;
$headline-color: #bc6c21; //#b40000;
$hover-color: #bc6c21;
$topbutton-color: $headline-color;
$brand-color: #1fa2af;
$brand-color: #3d0e51;
$brand-color-light: lighten($brand-color, 40%);
$grey-color: #828282;
$grey-color-light: #e8e8e8;

View file

@ -31,8 +31,7 @@ This guide focuses on arrays: creation, indexing, mutation, iteration, slicing,
## Creating arrays
```
// literals
<pre>// literals
a = [1, 2, 3]
b = ["alpha", "beta"]
empty = []
@ -42,30 +41,27 @@ grid = [[1,2], [3,4]]
print(typeof(a)) // "array"
print(len(a)) // 3
```
</pre>
Tip: Prefer squarebracket literals for clarity and performance versus building via repeated push in a hot loop.
## Indexing (0based) and assignment
```
a = [10, 20, 30]
<pre>a = [10, 20, 30]
print(a[0]) // 10
print(a[2]) // 30
// update in place
a[1] = 42
print(a) // [10, 42, 30]
```
</pre>
Notes:
- Valid indices are 0..len(a)-1. Using an invalid index raises a runtime error.
- Assignment updates the existing array; references pointing to it observe the change.
## Appending, popping, inserting, removing
```
a = [1]
<pre>a = [1]
// append to end; returns new length
push(a, 7) // => 2, a is now [1, 7]
@ -79,12 +75,10 @@ insert(a, 1, 99) // a => [1, 99, 2, 3]
// remove at index (shifts left)
remove(a, 2) // a => [1, 99, 3]
```
</pre>
## Slicing and concatenation
```
a = [0,1,2,3,4]
<pre>a = [0,1,2,3,4]
// slice(startInclusive, endExclusive)
head = slice(a, 0, 3) // [0,1,2]
@ -93,14 +87,12 @@ mid = slice(a, 1, 4) // [1,2,3]
// concat: join two arrays
b = ["x", "y"]
ab = concat(a, b) // [0,1,2,3,4,"x","y"]
```
</pre>
Slicing returns a new array. The original is unchanged.
## Iteration patterns
```
a = ["a", "b", "c"]
<pre>a = ["a", "b", "c"]
// indexbased loop
for i = 0; i < len(a); i = i + 1 {
@ -114,14 +106,12 @@ for pair in it.enumerate(a) {
val = pair[1]
print(to_string(idx) + ":" + val)
}
```
</pre>
## Copying vs. referencing
Arrays are reference types. Assigning just copies the reference, not the contents:
```
orig = [1, 2]
<pre>orig = [1, 2]
alias = orig // points to the same array
alias[0] = 9
print(orig) // [9, 2]
@ -131,17 +121,14 @@ copy = slice(orig, 0, len(orig))
copy[1] = 7
print(orig) // [9, 2]
print(copy) // [9, 7]
```
</pre>
Shallow copies duplicate the toplevel array but not nested structures.
## Equality
```
print([1,2] == [1,2]) // true
<pre>print([1,2] == [1,2]) // true
print([1,2] == [2,1]) // false
```
</pre>
Array equality compares length and elementwise equality recursively.
## Common utilities
@ -160,19 +147,16 @@ Check your lib directory (e.g., lib/utils) for additional helpers.
## Error handling and bounds
```
a = [0]
<pre>a = [0]
// a[1] is out of range → runtime error
```
</pre>
Tips:
- Guard indices: if i < 0 or i >= len(a) { /* handle */ }
- Use remove/insert carefully inside loops; indices of following items change.
## Interop with maps and strings
```
// arrays of maps
<pre>// arrays of maps
users = [ {"name":"Ada"}, {"name":"Lin"} ]
print(users[1]["name"]) // Lin
@ -180,8 +164,7 @@ print(users[1]["name"]) // Lin
#include <utils/strings.fun> as su // adjust if present in your tree
parts = su.split("a,b,c", ",") // ["a","b","c"]
csv = su.join(parts, ",") // "a,b,c"
```
</pre>
## Performance tips
- Preallocate by building from literals or chunked appends rather than onebyone in very tight loops.
@ -190,8 +173,7 @@ csv = su.join(parts, ",") // "a,b,c"
## Examples
```
// filter even numbers
<pre>// filter even numbers
src = [0,1,2,3,4,5]
dst = []
for i = 0; i < len(src); i = i + 1 {
@ -210,8 +192,7 @@ for i = 0; i < len(nested); i = i + 1 {
}
}
print(flat) // [1,2,3,4,5]
```
</pre>
## See also
- types.md — broader overview of core types with quick array examples.

View file

@ -57,18 +57,15 @@ Tip: Always check return values. In non-blocking mode, partial writes and short
## Typical patterns
1) Connect and switch to non-blocking
```
fd = tcp_connect(host, port)
<pre>fd = tcp_connect(host, port)
if (fd == 0)
// handle connect error
ok = fd_set_nonblock(fd, 1)
if (ok == 0)
// handle mode switch error
```
</pre>
2) Non-blocking write loop with readiness polling
```
remaining = req
<pre>remaining = req
while (len(remaining) > 0)
wr = fd_poll_write(fd, 1000) // wait up to 1s
if (wr < 0)
@ -79,11 +76,9 @@ while (len(remaining) > 0)
if (n < 0)
// send error; abort
remaining = substr(remaining, n, len(remaining) - n)
```
</pre>
3) Non-blocking read-until-close
```
buf = ""
<pre>buf = ""
while (true)
rd = fd_poll_read(fd, 2000) // wait up to 2s
if (rd < 0)
@ -99,8 +94,7 @@ while (true)
if (len(data) == 0)
break // closed
buf = buf + data
```
</pre>
## Timeouts and responsiveness
- timeout_ms controls how long poll waits. Use small timeouts inside loops to interleave work across multiple sockets or tasks.
@ -125,20 +119,14 @@ Because Fun keeps the primitives low-level and explicit, you can build simple co
- lib/net/http_cgi_server.fun — Library helpers used by the server examples
Run client example from a build tree:
```
FUN_LIB_DIR=./lib ./build/fun examples/io/async_http_client.fun
```
<pre>FUN_LIB_DIR=./lib ./build/fun examples/io/async_http_client.fun
</pre>
If installed system-wide, just:
```
fun /usr/share/fun/examples/io/async_http_client.fun
```
<pre>fun /usr/share/fun/examples/io/async_http_client.fun
</pre>
Or to try the await-style client using the cooperative scheduler:
```
FUN_LIB_DIR=./lib ./build/fun examples/io/await_http_client.fun
```
<pre>FUN_LIB_DIR=./lib ./build/fun examples/io/await_http_client.fun
</pre>
## Cooperative scheduler helpers (library-level)
The file lib/async/scheduler.fun provides a minimal cooperative scheduler built on the existing primitives. There is no VM-level suspension: each task is a small state machine advanced one step per tick. API summary:
@ -159,8 +147,7 @@ The file lib/async/scheduler.fun provides a minimal cooperative scheduler built
- Mark the task to be skipped for roughly ms milliseconds; cleared automatically when it wakes.
Example skeleton using the scheduler:
```
#include <async/scheduler.fun>
<pre>#include <async/scheduler.fun>
fun my_task_step(t)
if (t.phase == nil)
@ -205,8 +192,7 @@ fun my_task_step(t)
task = task_spawn(my_task_step, {})
run_until_done()
```
</pre>
This approach is 100% compatible with current runtimes and serves as a stepping stone towards potential future VM-level async/await opcodes.
## Error handling and cleanup

View file

@ -61,45 +61,35 @@ These are defined as `CACHE` variables, so they will persist in your `CMakeCache
When configuring, the build prints a summary like:
```
==== Fun build options ====
<pre>==== Fun build options ====
FUN_DEBUG: ENABLED|DISABLED
FUN_USE_MUSL: ENABLED|DISABLED
FUN_WITH_CPP: ENABLED|DISABLED
FUN_WITH_RUST: ENABLED|DISABLED
===========================
```
</pre>
## Example commands
Use the CLion-provided build directories or your own. Typical invocations:
### Debug
```
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
<pre>cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
-DFUN_DEBUG=ON -DFUN_WITH_RUST=OFF
cmake --build build --target build
```
</pre>
### Release
```
cmake -S . -B build_release -DCMAKE_BUILD_TYPE=Release \
<pre>cmake -S . -B build_release -DCMAKE_BUILD_TYPE=Release \
-DFUN_DEBUG=OFF -DFUN_WITH_RUST=OFF
cmake --build build_release --target build
```
</pre>
### Enabling optional extensions
```
cmake -S . -B build_release -DCMAKE_BUILD_TYPE=Release \
<pre>cmake -S . -B build_release -DCMAKE_BUILD_TYPE=Release \
-DFUN_WITH_CPP=ON -DFUN_WITH_RUST=ON -DFUN_WITH_OPENSSL=ON
cmake --build build_release --target build
```
</pre>
### Customizing VM limits
```
cmake -S . -B build_custom -DSTACK_SIZE=4096 -DMAX_GLOBALS=512
<pre>cmake -S . -B build_custom -DSTACK_SIZE=4096 -DMAX_GLOBALS=512
cmake --build build_custom --target fun
```
</pre>
If `FUN_WITH_RUST` is enabled, ensure `cargo` is available in PATH; the build will invoke it and link the produced static library.
If `FUN_WITH_OPENSSL` is enabled, CMake must detect your system OpenSSL (libcrypto).

View file

@ -29,10 +29,8 @@ Reference for the `fun` command-line interface.
For a complete usage guide (including REPL details, environment variables, include paths, examples, and install locations), see [fun.md](./fun/).
## Synopsis
```
fun [options] <script.fun> [-- args...]
```
<pre>fun [options] <script.fun> [-- args...]
</pre>
If no script is supplied and interactive mode is available, `fun` starts a REPL (see [repl.md](./repl/)).
## Common options
@ -54,11 +52,8 @@ See also: [includes.md](./includes/) for namespaced includes and search order.
## Examples
Run a script:
```
FUN_LIB_DIR=./lib ./build/fun examples/hello.fun
```
<pre>FUN_LIB_DIR=./lib ./build/fun examples/hello.fun
</pre>
Start the REPL:
```
./build/fun -i
```
<pre>./build/fun -i
</pre>

View file

@ -5,7 +5,7 @@ noToc: false
noComments: false
noDate: false
title: Fun - Documentation
subtitle: Detailed documentation for the Fun programming language.
subtitle: Detailed documentation for the Fun programming language.<br><br><span style="color:red;">The documentation is always a work in progress! It will always be behind the development of the code. It will be 100% aligned with a 1.0 release... ;)</span>
description: The Fun Documentation Index
permalink: /documentation/
lang: en
@ -68,7 +68,7 @@ The examples directory contains demonstrations of most Fun features, from basic
## Examples
- [examples/README/](./examples/README/) - Catalog of all example scripts under ./examples/: what each area contains, how to run them, required env vars, and extension requirements.
- [examples/](./examples/) - Catalog of all example scripts under [https://git.xw3.org/fun/fun/src/branch/main/examples](https://git.xw3.org/fun/fun/src/branch/main/examples){:class="git"}: what each area contains, how to run them, required env vars, and extension requirements.
## External extensions

View file

@ -33,35 +33,27 @@ All commands assume you are in the repository root.
Example (Linux/macOS/BSD):
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun examples/include_lib.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun examples/include_lib.fun
</pre>
Windows (PowerShell):
```
$env:FUN_LIB_DIR = "$PWD/lib"
<pre>$env:FUN_LIB_DIR = "$PWD/lib"
./build/fun.exe .\examples\include_lib.fun
```
</pre>
## Interactive showcase: play.fun
The script `./play.fun` discovers all `.fun` files under `./examples` and offers to run them one by one:
```
./play.fun
```
<pre>./play.fun
</pre>
Notes:
- The script auto-picks your interpreter (FUN_BIN env or `fun` in PATH) and ensures `FUN_LIB_DIR=./lib` so examples resolve includes correctly.
- It shows the exit code for each run and summarizes failures at the end.
Tip: you can run specific examples directly too:
```
FUN_LIB_DIR="$(pwd)/lib" fun examples/crypto/openssl_md5.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" fun examples/crypto/openssl_md5.fun
</pre>
## Example categories
Browse the `examples/` tree for areas of interest:
@ -77,9 +69,7 @@ Browse the `examples/` tree for areas of interest:
Place your `.fun` files anywhere under `examples/` to have them picked up by `play.fun`. Use quoted includes for project-local helpers and angle brackets for stdlib modules:
```
#include "examples/my_lib/common.fun"
<pre>#include "examples/my_lib/common.fun"
#include <io/console.fun>
```
</pre>
If you add an example showcasing a new feature, also consider adding a brief note to the relevant doc (types.md, includes.md, opcodes.md, etc.).

View file

@ -18,24 +18,27 @@ tags:
- quick
---
Answers to common questions.
## I built Fun but includes aren't found
Set `FUN_LIB_DIR` to the repository's `./lib` directory when running without installation:
```
FUN_LIB_DIR=./lib ./build/fun examples/hello.fun
```
See [includes.md](./includes/).
<pre>FUN_LIB_DIR=./lib ./build/fun examples/hello.fun
</pre>
See [includes/](../includes/).
## How do I start the REPL?
Run `fun -i` (or run `fun` without a script, depending on version). See [repl.md](./repl/).
Run `fun -i` (or run `fun` without a script, depending on version). See [repl/](../repl/).
## Which build target should I use?
Use the aggregate `build` target to build `fun`, `fun_test`, and `test_opcodes`. See [build.md](./build/).
Use the aggregate `build` target to build `fun`, `fun_test`, and `test_opcodes`. See [build/](../build/).
## Where are the standard libraries?
Under [`./lib/`](../lib/). See [stdlib.md](./stdlib/) for an overview.
Under [https://git.xw3.org/fun/fun/src/branch/main/lib](https://git.xw3.org/fun/fun/src/branch/main/lib){:class="git"}. See [stdlib/](../stdlib/) for an overview.
## Where can I find internals and opcodes?
Browse [src/vm](../src/vm/) and [internals.md](./internals/) / [opcodes.md](./opcodes/).
Browse [https://git.xw3.org/fun/fun/src/branch/main/src/vm](https://git.xw3.org/fun/fun/src/branch/main/src/vm/) and [internals/](../internals/) / [opcodes/](../opcodes/).

View file

@ -27,10 +27,8 @@ tags:
This document explains how to use the `fun` binary after building or installing it: invocation patterns, options, environment variables, include/search paths, REPL, and examples.
## Synopsis
```
fun [options] [<script.fun>] [-- args...]
```
<pre>fun [options] [<script.fun>] [-- args...]
</pre>
- If `<script.fun>` is provided, `fun` runs the script.
- If omitted and the build enables the REPL, `fun` starts an interactive session.
@ -66,20 +64,14 @@ Useful commands/patterns in REPL:
## Running scripts
Basic run (installed systemwide):
```
fun /usr/share/fun/examples/hello.fun
```
<pre>fun /usr/share/fun/examples/hello.fun
</pre>
Running from a build tree (not installed):
```
FUN_LIB_DIR=./lib /path/to/build_dir/fun examples/hello.fun
```
<pre>FUN_LIB_DIR=./lib /path/to/build_dir/fun examples/hello.fun
</pre>
Passing arguments to scripts (arguments after `--` are forwarded to the script environment):
```
fun myscript.fun -- arg1 arg2
```
<pre>fun myscript.fun -- arg1 arg2
</pre>
## Build and install locations
- Build targets: `fun` is produced by the `fun` target. In CLion/CMake, typical build directories are `build_debug` or `build_release`.
- Install locations (by default):
@ -88,11 +80,9 @@ fun myscript.fun -- arg1 arg2
- Examples (optional): `/usr/share/fun/examples`
To stage an install without touching the system:
```
DESTDIR=./tmp/stage cmake --build <build_dir> --target install
<pre>DESTDIR=./tmp/stage cmake --build <build_dir> --target install
./tmp/stage/usr/bin/fun ./examples/hello.fun
```
</pre>
## See also
- `documentation/cli.md` — concise CLI reference (synopsis/options/exit codes)
- `documentation/funstx.md` — syntax checker for `.fun` files with optional `--fix`

View file

@ -36,10 +36,8 @@ funstx is a small commandline tool that parses .fun source files to verify sy
## Usage
```
funstx [--fix] <file1.fun> [file2.fun ...]
```
<pre>funstx [--fix] <file1.fun> [file2.fun ...]
</pre>
- Provide one or more .fun files to check.
- Add `--fix` to attempt safe, automatic corrections before rechecking.

View file

@ -64,16 +64,12 @@ Linux/UNIX and Cygwin are covered here.
Clone repository:
```
git clone https://git.xw3.org/fun/fun.git
<pre>git clone https://git.xw3.org/fun/fun.git
cd fun
```
</pre>
Configure and build (examples shown with several optional features enabled):
```
cmake -S . -B build \
<pre>cmake -S . -B build \
-DFUN_DEBUG=OFF \
-DFUN_WITH_REPL=ON \
-DFUN_WITH_JSON=ON \
@ -82,32 +78,23 @@ cmake -S . -B build \
-DFUN_WITH_PCSC=OFF \
-DFUN_WITH_SQLITE=OFF
cmake --build build --target fun
```
</pre>
Run the demo (without installing):
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./demo.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./demo.fun
</pre>
Tracing execution:
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun --trace ./demo.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun --trace ./demo.fun
</pre>
Drop into the REPL when an error occurs:
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun --repl-on-error --trace ./demo.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun --repl-on-error --trace ./demo.fun
</pre>
Start the REPL directly (build with -DFUN_WITH_REPL=ON):
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun
</pre>
#### CMake options
Pass all options as -DNAME=VALUE. The most relevant toggles are:
@ -124,10 +111,8 @@ Pass all options as -DNAME=VALUE. The most relevant toggles are:
You can also set the default search path for the bundled stdlib with DEFAULT_LIB_DIR:
```
cmake -S . -B build -DDEFAULT_LIB_DIR="/usr/share/fun/lib" -DFUN_WITH_REPL=ON
```
<pre>cmake -S . -B build -DDEFAULT_LIB_DIR="/usr/share/fun/lib" -DFUN_WITH_REPL=ON
</pre>
If you encounter a CMake error such as:
CMake Error: Parse error in command line argument: FUN_WITH_JSON
@ -139,8 +124,7 @@ it means you passed a -D option without a value. Always use the form -DNAME=VALU
SQLite support is optional and disabled by default. To build with it and run the example:
```
cmake -S . -B build -DFUN_WITH_SQLITE=ON
<pre>cmake -S . -B build -DFUN_WITH_SQLITE=ON
cmake --build build --target fun
@ -148,20 +132,17 @@ sqlite3 ./database.sqlite < ./examples/data/database.sql
FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./examples/sqlite_example.fun
```
</pre>
#### XML example (optional feature)
XML support (via libxml2) is optional and disabled by default. To build with it and run the example:
```
cmake -S . -B build -DFUN_WITH_XML2=ON
<pre>cmake -S . -B build -DFUN_WITH_XML2=ON
cmake --build build --target fun
FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./examples/xml_class_example.fun
```
</pre>
Available VM builtins when built with -DFUN_WITH_XML2=ON:
- xml_parse(text: string) -> doc_handle (int > 0) or 0 on error
- xml_root(doc_handle: int) -> node_handle (int > 0) or 0 if missing
@ -177,8 +158,7 @@ Standard library wrapper (lib/io/xml.fun):
- text(node: int): string
Example Fun code:
```
include <io/xml.fun>
<pre>include <io/xml.fun>
xml = XML()
doc = xml.from_file("./examples/data/example.xml")
@ -188,8 +168,7 @@ else
root = xml.root(doc)
print(xml.name(root))
print(xml.text(root))
```
</pre>
Notes:
- Handles are simple integers managed by the VM; nodes are owned by their document.
- This initial integration focuses on parsing and basic navigation. Attributes, children iteration, and XPath may be added later.
@ -198,20 +177,16 @@ Notes:
Not recommended during early development, but supported:
```
sudo cmake --build build --target install
```
<pre>sudo cmake --build build --target install
</pre>
After installation, FUN_LIB_DIR usually isnt needed because libs are placed in the system default directory (e.g., /usr/share/fun/lib).
## Usage
Run a script:
```
fun ./demo.fun
```
<pre>fun ./demo.fun
</pre>
## Table of contents
- Language overview and VM internals
@ -470,8 +445,7 @@ Stdlib wrapper:
- class JSON (lib/io/json.fun) — convenience methods mirroring the VM API.
Example:
```
include <io/json.fun>
<pre>include <io/json.fun>
j = JSON()
data = j.parse('{"name":"Fun","year":2026,"ok":true,"tags":["vm","lang"]}')
@ -480,8 +454,7 @@ print(data["name"])
ok = j.to_file("./tmp/out.json", data, 1) // pretty = 1
print("saved:", ok)
```
</pre>
Notes:
- JSON types map to Fun types: object -> map, array -> array, string -> string, number -> number/float, true/false -> 1/0, null -> nil.
- When writing, prettyFlag=1 enables pretty printing.
@ -499,15 +472,13 @@ Stdlib wrapper:
- None (call built-ins directly). See examples in examples/extra/.
Example:
```
url = "https://httpbin.org/get"
<pre>url = "https://httpbin.org/get"
resp = curl_get(url)
if (len(resp) == 0)
print("GET failed")
else
print(substr(resp, 0, 60), "...")
```
</pre>
Examples:
- curl_get_json.fun, curl_post.fun, curl_download.fun
@ -526,8 +497,7 @@ Stdlib wrapper:
- class PCSC (lib/io/pcsc.fun) — higher-level helpers for listing readers, connecting, and APDU I/O.
Example:
```
include <io/pcsc.fun>
<pre>include <io/pcsc.fun>
sc = PCSC()
ctx = pcsc_establish()
@ -544,8 +514,7 @@ else
res = pcsc_transmit(h, [0x00, 0xC0, 0x00, 0x00, 0x00])
print("SW:", res["sw1"], res["sw2"], "code:", res["code"])
pcsc_disconnect(h)
```
</pre>
Examples:
- examples/extra/pcsc_example.fun, examples/extra/pcsc_demo.fun
@ -596,8 +565,7 @@ Notes:
- Always free handles with ini_free when done.
Example:
```
h = ini_load("./examples/data/example.ini")
<pre>h = ini_load("./examples/data/example.ini")
if (h == 0)
print("Failed to load INI")
else
@ -608,8 +576,7 @@ else
if (ok)
ini_save(h, "./tmp/updated.ini")
ini_free(h)
```
</pre>
### XML (optional)
Build flag: -DFUN_WITH_XML2=ON; requires libxml2.
@ -629,8 +596,7 @@ Stdlib wrapper:
- text(node): string
Example:
```
include <io/xml.fun>
<pre>include <io/xml.fun>
xml = XML()
doc = xml.from_file("./examples/data/example.xml")
@ -640,8 +606,7 @@ else
root = xml.root(doc)
print(xml.name(root))
print(xml.text(root))
```
</pre>
Notes:
- Handles are integers managed by the VM; nodes belong to their document.

View file

@ -4,7 +4,7 @@ published: true
noToc: false
noComments: false
noDate: false
title: Fun - Includes in Fun: local vs. system and the FUN_LIB_DIR environment variable
title: Fun - Includes in Fun, local vs. system and the FUN_LIB_DIR environment variable
subtitle: Using local vs. system includes, FUN_LIB_DIR, DEFAULT_LIB_DIR, and namespaced includes with `as`.
description: Using local vs. system includes, FUN_LIB_DIR, DEFAULT_LIB_DIR, and namespaced includes with `as`.
permalink: /documentation/includes/
@ -39,8 +39,7 @@ This document explains how to use local and system includes in Fun source files
Use double quotes to include files relative to the directory you execute `fun` from.
Example:
```
#include "examples/include_local_util.fun"
<pre>#include "examples/include_local_util.fun"
print("== include local demo ==")
greet("Fun")
@ -48,8 +47,7 @@ greet("Fun")
number a = 2
number b = 3
print("sum(" + to_string(a) + ", " + to_string(b) + ") = " + to_string(sum(a, b)))
```
</pre>
- Resolution rule: quoted includes are read directly from the given path relative to `$PWD`.
- Typical use: including helper modules that live within your project tree.
@ -58,8 +56,7 @@ print("sum(" + to_string(a) + ", " + to_string(b) + ") = " + to_string(sum(a, b)
Use angle brackets to include modules from the Fun standard library or any library directory you point `FUN_LIB_DIR` to.
Example:
```
#include <hello.fun>
<pre>#include <hello.fun>
#include <utils/math.fun>
print("== include lib demo ==")
@ -69,8 +66,7 @@ number x = 10
number y = 32
print("add(" + to_string(x) + ", " + to_string(y) + ") = " + to_string(add(x, y)))
print("times(" + to_string(x) + ", " + to_string(y) + ") = " + to_string(times(x, y)))
```
</pre>
Resolution order for `#include <...>`:
1) `FUN_LIB_DIR` (environment variable), with automatic handling of trailing `/` or `\`
@ -84,8 +80,7 @@ If the file cannot be read from any location, an "Include error" is printed with
You can import a module into a namespace to avoid symbol collisions or to make intent explicit.
Examples:
```
// Import stdlib helpers under alias 'm'
<pre>// Import stdlib helpers under alias 'm'
#include <utils/math.fun> as m
print("m.add(2, 3) = " + to_string(m.add(2, 3)))
print("m.times(4, 5) = " + to_string(m.times(4, 5)))
@ -95,8 +90,7 @@ print("m.times(4, 5) = " + to_string(m.times(4, 5)))
print(mod.hello("Fun"))
g = mod.Greeter("Hi")
g.say("World")
```
</pre>
Rules:
- `as` must be followed by a valid identifier (letters, digits, underscore, starting with a letter or underscore).
- Works for both local (`"..."`) and system (`<...>`) includes.

View file

@ -351,8 +351,7 @@ This provides zerocopy handoff without coupling VMs or their collectors.
#### Minimal API (illustrative)
```c
// Zero-copy shared buffers (immutable inside VMs)
<pre>// Zero-copy shared buffers (immutable inside VMs)
fun_shared_buffer_t* fun_shared_buffer_new(size_t n);
void* fun_shared_buffer_data(fun_shared_buffer_t*);
void fun_shared_buffer_retain(fun_shared_buffer_t*);
@ -362,8 +361,7 @@ void fun_shared_buffer_release(fun_shared_buffer_t*);
fun_port_t* fun_port_create(fun_vm_t*);
int fun_send(fun_port_t*, fun_value_t value); // can carry a shared buffer handle
int fun_recv(fun_port_t*, fun_value_t* out, uint64_t timeout_ms);
```
</pre>
#### Practical usage tips
- Default to isolates + ports for logic; use `fun_shared_buffer` only for large payloads (images, tensors, blobs).
@ -393,8 +391,7 @@ We dont expose shared mutability to VMs. The trick is: publishasimmutab
#### Typical pattern (no locks needed)
```c
fun_shared_buffer_t* b = fun_shared_buffer_new(n);
<pre>fun_shared_buffer_t* b = fun_shared_buffer_new(n);
void* p = fun_shared_buffer_data(b);
memcpy(p, src, n); // fill while private
@ -411,8 +408,7 @@ if (fun_recv(port, &v, 1000) == 0) {
fun_shared_buffer_release(r);
}
```
</pre>
#### When would the host ever sync?
- Only if you choose shared mutability outside the VM (e.g., a lockfree ring buffer you manage). For that, we expose optional helpers (`fun_atomic_*`, `fun_mutex_t`, `fun_rwlock_t`), but theyre not required for the standard zerocopy path.
@ -477,8 +473,7 @@ It depends on what “shared” means. Our design keeps perVM GCs independent
### Minimal API surface (illustrative)
```c
// Create/destroy VMs
<pre>// Create/destroy VMs
fun_vm_t* vm = fun_vm_create(const fun_vm_config_t*);
void fun_vm_destroy(fun_vm_t*);
@ -500,8 +495,7 @@ fun_shared_buffer_t* fun_shared_buffer_new(size_t n);
void* fun_shared_buffer_data(fun_shared_buffer_t*);
void fun_shared_buffer_retain(fun_shared_buffer_t*);
void fun_shared_buffer_release(fun_shared_buffer_t*);
```
</pre>
### Glossary
- GC: garbage collection. In our context, each `fun_vm_t` isolate has its own GC (stoptheworld, perVM). There is no global stoptheworld and no global lock; a GC pause in one VM does not affect others.

View file

@ -33,29 +33,24 @@ This guide focuses on maps: creation, reading/writing by key, checking key prese
## Creating maps
```
// literals
<pre>// literals
user = { "name": "Ada", "age": 37 }
empty = {}
print(typeof(user)) // "map"
```
</pre>
Nested structures are natural and common:
```
book = {
<pre>book = {
"title": "Fun Handbook",
"meta": { "pages": 120, "isbn": "123-456" },
"tags": ["lang", "vm"]
}
print(book["meta"]["pages"]) // 120
```
</pre>
## Getting and setting by key
```
profile = { "name": "Lin" }
<pre>profile = { "name": "Lin" }
// read existing key
print(profile["name"]) // Lin
@ -67,35 +62,29 @@ print(profile["email"]) // nil
profile["email"] = "lin@example.org"
profile["name"] = "Linus"
print(profile) // {"name":"Linus","email":"lin@example.org"}
```
</pre>
Notes:
- Using a nonstring key is allowed only if your build/runtime supports it; most code uses string keys for portability.
- Missing keys produce nil. Compare against nil before converting or indexing:
```
v = profile["phone"]
<pre>v = profile["phone"]
if v == nil { print("no phone on file") }
```
</pre>
## Checking key existence
Use has(m, key) to check if a key is present (returns 1 or 0):
```
cfg = { "debug": 1 }
<pre>cfg = { "debug": 1 }
print(has(cfg, "debug")) // 1
print(has(cfg, "port")) // 0
if has(cfg, "port") { print(cfg["port"]) } else { print("using default port") }
```
</pre>
## Iterating maps
Maps are not inherently ordered. To iterate, first obtain an array of keys or values.
```
user = { "name": "Ada", "age": 38 }
<pre>user = { "name": "Ada", "age": 38 }
// iterate known keys (explicit order you choose)
order = ["name", "age"]
@ -114,8 +103,7 @@ for i = 0; i < len(ks); i = i + 1 {
// values only
vs = values(user) // -> ["Ada", 38]
for i = 0; i < len(vs); i = i + 1 { print(to_string(vs[i])) }
```
</pre>
Tip:
- If you need deterministic output, either define the order array explicitly or sort the result of keys(user) using your available utilities before looping.
@ -123,8 +111,7 @@ Tip:
Maps are reference types. Assigning copies the reference, not the contents:
```
orig = { "a": 1 }
<pre>orig = { "a": 1 }
alias = orig
alias["a"] = 9
print(orig["a"]) // 9
@ -138,17 +125,14 @@ for i = 0; i < len(ks); i = i + 1 { k = ks[i]; dst[k] = src[k] }
dst["x"] = 7
print(src["x"]) // 1
print(dst["x"]) // 7
```
</pre>
Shallow copies duplicate only the toplevel mapping; nested arrays/maps inside are still shared unless you clone them manually.
## Equality
```
print({"a":1,"b":2} == {"b":2,"a":1}) // true
<pre>print({"a":1,"b":2} == {"b":2,"a":1}) // true
print({"a":1} == {"a":2}) // false
```
</pre>
Map equality compares sets of keys and their corresponding values for equality (order does not matter).
## Common utilities
@ -164,8 +148,7 @@ Check your lib or VM docs (e.g., src/vm/maps) and documentation/types.md for ava
## Interop with arrays and strings
```
// maps inside arrays
<pre>// maps inside arrays
users = [ {"name":"Ada"}, {"name":"Lin"} ]
for i = 0; i < len(users); i = i + 1 {
print(users[i]["name"]) // Ada, Lin
@ -180,8 +163,7 @@ print(m["nums"]) // [1,2,3,4]
// JSON interop is typically via lib/io/json.fun (if enabled in your build)
#include <io/json.fun> as json // adjust to your tree and build flags
s = json.stringify({"ok":1}) // "{"ok":1}"
```
</pre>
## Error handling and edge cases
- Accessing a missing key returns nil. Guard before arithmetic or nested indexing.
@ -196,8 +178,7 @@ s = json.stringify({"ok":1}) // "{"ok":1}"
## Examples
```
// merge defaults into config (without overwriting explicit keys)
<pre>// merge defaults into config (without overwriting explicit keys)
defaults = { "host":"127.0.0.1", "port":8080, "debug":0 }
cfg = { "port": 9000 }
@ -216,8 +197,7 @@ for i = 0; i < len(rows); i = i + 1 {
by_id[r["id"]] = r
}
print(by_id["u2"]["name"]) // Lin
```
</pre>
## See also
- types.md — broader overview of core types with quick map examples.

View file

@ -38,96 +38,79 @@ This guide covers the numeric types in Fun, with a focus on the integer "number"
- number: signed integer (implementationdefined width; use uclamp/sclamp for fixedwidth interop)
- float: IEEE754 double precision (64bit)
```
an = 42 // number
<pre>an = 42 // number
af = 3.14159 // float
print(typeof(an)) // "number"
print(typeof(af)) // "float"
```
</pre>
## Literals
- Integer (number): 0, 1, -7, 120
- Floating point (float): 0.0, 1.5, -2.75, 1e3, -4.2e-1
```
x = 10
<pre>x = 10
y = 2.5
z = -3
```
</pre>
## Arithmetic
Basic arithmetic works as youd expect:
```
a = 7
<pre>a = 7
b = 2
print(a + b) // 9
print(a - b) // 5
print(a * b) // 14
print(a % b) // 1 (modulo)
```
</pre>
Division and result type:
```
// If you need a fractional result, ensure a float is involved
<pre>// If you need a fractional result, ensure a float is involved
print(7 / 2) // implementation may yield 3 or 3.5 depending on numeric rules
print(cast(7, "float") / 2) // 3.5 (recommended when you need fractions)
print(7 / 2.0) // 3.5
```
</pre>
Mixing numbers and floats promotes the operation to float semantics:
```
print(2 + 0.5) // 2.5
```
<pre>print(2 + 0.5) // 2.5
</pre>
## Comparisons
```
print(3 < 5) // 1 (true)
<pre>print(3 < 5) // 1 (true)
print(3 == 3) // 1
print(3 != 4) // 1
// Be explicit when comparing ints vs floats if types matter
print(1 == 1.0) // may be true, but types differ
print(cast(1.0, "number") == 1) // 1 (true) with explicit cast
```
</pre>
## Conversions and parsing
```
n = to_number("123") // 123 (number)
<pre>n = to_number("123") // 123 (number)
f = cast(n, "float") // 123.0 (float)
n2 = cast(3.9, "number") // 3 (truncation semantics)
print(to_string(f)) // "123"
```
</pre>
If parsing fails (e.g., to_number("abc")), expect a runtime error; guard accordingly.
## Clamping to fixed widths
When interoperating with bytecode, C APIs, or binary formats, clamp integers to a specific bit width.
```
// Unsigned clamp to N bits
<pre>// Unsigned clamp to N bits
u8 = uclamp(300, 8) // 44
u16 = uclamp(70000, 16)
// Signed clamp to N bits
s8 = sclamp(-130, 8) // wraps into signed 8bit range
```
</pre>
Choose the bits according to the target field (8, 16, 32, 64). See your interop API docs for exact ranges.
## Bitwise operations (numbers)
Bitwise operators apply to the integer number type.
```
a = 0b0110 // if binary literals arent supported in your setup, use decimals: a = 6
<pre>a = 0b0110 // if binary literals arent supported in your setup, use decimals: a = 6
b = 0b0011 // or b = 3
print(a & b) // 0b0010 -> 2
@ -136,41 +119,34 @@ print(a ^ b) // 0b0101 -> 5
print(~a) // bitwise NOT (twos complement rules)
print(a << 1) // 12
print(a >> 1) // 3
```
</pre>
Note: Bitwise ops are defined for numbers, not floats. Cast floats to numbers first when needed.
## Common patterns
Ensuring float math to avoid unintended truncation:
```
avg = cast(sum, "float") / cast(count, "float")
```
<pre>avg = cast(sum, "float") / cast(count, "float")
</pre>
Safe division with guard against zero:
```
num = 10
<pre>num = 10
den = 0
if den == 0 {
print("division by zero")
} else {
print(num / den)
}
```
</pre>
Parsing user input with fallback:
```
raw = "not-a-number"
<pre>raw = "not-a-number"
val = 0
// simplistic guard pattern; adapt to your error handling style
if find(raw, "0") >= 0 || find(raw, "1") >= 0 { // crude pre-check
val = to_number(raw)
}
```
</pre>
## Gotchas
- Integer division vs float division: promote to float when you need fractional results.

View file

@ -29,55 +29,41 @@ The REPL is optional at build time. It provides a fast feedback loop for experim
- Build flag: -DFUN_WITH_REPL=ON
- Typical CMake configuration example:
```
cmake -S . -B build \
<pre>cmake -S . -B build \
-DFUN_WITH_REPL=ON
cmake --build build --target fun
```
</pre>
You can also set a default search path for the bundled stdlib using DEFAULT_LIB_DIR at configure time (used for completions and library loading):
```
cmake -S . -B build -DFUN_WITH_REPL=ON -DDEFAULT_LIB_DIR="/usr/share/fun/lib"
```
<pre>cmake -S . -B build -DFUN_WITH_REPL=ON -DDEFAULT_LIB_DIR="/usr/share/fun/lib"
</pre>
## Launching the REPL
- Directly run the main executable (ensure FUN_WITH_REPL=ON):
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun
</pre>
- With the CMake “repl” convenience target (available only if built with FUN_WITH_REPL=ON):
```
cmake --build build --target repl
```
<pre>cmake --build build --target repl
</pre>
On startup, you should see something like:
```
Fun X.Y.Z REPL
<pre>Fun X.Y.Z REPL
Type :help for commands. Submit an empty line to run.
```
</pre>
Environment variable FUN_LIB_DIR can be used to point the REPL to the standard library directory for symbol completion and library loading. If not set, a compile-time DEFAULT_LIB_DIR (if provided) or "lib" is used.
## Running scripts and REPL-on-error
- Run a script file normally:
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./demo.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./demo.fun
</pre>
- Enable tracing, and drop into a REPL automatically when a runtime error occurs:
```
FUN_LIB_DIR="$(pwd)/lib" ./build/fun --repl-on-error --trace ./demo.fun
```
<pre>FUN_LIB_DIR="$(pwd)/lib" ./build/fun --repl-on-error --trace ./demo.fun
</pre>
Inside REPL-on-error, you can inspect frames, locals, disassembly, set breakpoints, and continue or step. Use :help to see available commands.
## Prompts and input model

View file

@ -77,8 +77,7 @@ Example: integer addition opcode implemented in Rust.
In src/rust/src/lib.rs:
```
#![no_std]
<pre>#![no_std]
#[repr(C)]
pub struct Vm;
@ -100,8 +99,7 @@ In src/rust/src/lib.rs:
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} }
```
</pre>
What this does:
- Pops two 64-bit integers from the VM stack.
- Pushes back their sum.
@ -115,8 +113,7 @@ To make the VM call your Rust opcode, add a small C-side case that invokes the e
String demo wiring (already present): src/vm/rust/hello.c
```
case OP_RUST_HELLO: {
<pre>case OP_RUST_HELLO: {
#ifdef FUN_WITH_RUST
const char *s = fun_rust_get_string();
if (!s) s = "";
@ -127,12 +124,10 @@ case OP_RUST_HELLO: {
#endif
break;
}
```
</pre>
For a stack-based math opcode (like fun_op_radd), you would declare and call the Rust function similarly:
```
#ifdef FUN_WITH_RUST
<pre>#ifdef FUN_WITH_RUST
extern int fun_op_radd(void* vm); // or use the proper VM type if available
#endif
@ -145,8 +140,7 @@ case OP_RADD: {
#endif
break;
}
```
</pre>
Notes:
- Follow the existing opcode conventions for your module (core, math, strings, etc.).

View file

@ -80,11 +80,9 @@ The stdlib is written in Fun and organized by domain. Below is the current layou
Note: Availability of some modules can depend on optional extensions selected at build time (see [build.md](./build/)). For instance, `regex/pcre2.fun` requires PCRE2 support; `ui/*` depends on chosen UI backends.
## Using modules
```fun
#include <strings.fun>
<pre>#include <strings.fun>
let s = trim(" hello ")
print(s)
```
</pre>
For search paths and namespacing details, see [includes.md](./includes/) and [cli.md](./cli/) (FUN_LIB_DIR and DEFAULT_LIB_DIR).

View file

@ -33,14 +33,12 @@ This guide covers string literals, common operations (length, concatenation, sub
## Literals and escaping
```
s1 = "hello"
<pre>s1 = "hello"
s2 = "line1\nline2" // newline
s3 = "quote: \" and backslash: \\" // escaped quote and backslash
print(s1) // hello
```
</pre>
Notes:
- Strings are immutable; operations return new strings rather than modifying in place.
- Use to_string(x) when concatenating non-string values.
@ -49,66 +47,54 @@ Notes:
Length and concatenation:
```
name = "Ada"
<pre>name = "Ada"
greet = "Hello, " + name + "!" // "Hello, Ada!"
print(len(greet)) // 12
```
</pre>
Substring (start, length) and search:
```
s = "hello, world"
<pre>s = "hello, world"
print(substr(s, 7, 5)) // world
idx = find(s, ",") // 5, or -1 if not found
if idx >= 0 { print("comma at index " + to_string(idx)) }
```
</pre>
Splitting into arrays:
```
parts = split("a,b,c", ",") // ["a","b","c"]
<pre>parts = split("a,b,c", ",") // ["a","b","c"]
for i = 0; i < len(parts); i = i + 1 {
print(parts[i])
}
```
</pre>
## Conversions and formatting
```
n = 42
<pre>n = 42
pi = 3.14
msg = "n=" + to_string(n) + ", pi=" + to_string(pi)
print(msg)
// parsing (may error if the string is not numeric)
n2 = to_number("123") // 123
```
</pre>
If you need a specific type, you can use cast for advanced cases, e.g. cast("123", "number").
## Common patterns
- Guard on find results before slicing:
```
email = "user@example.org"
<pre>email = "user@example.org"
at = find(email, "@")
if at >= 0 {
user = substr(email, 0, at)
host = substr(email, at + 1, len(email) - at - 1)
print(user + " on " + host)
}
```
</pre>
- Building paths or messages:
```
base = "/tmp"
<pre>base = "/tmp"
file = "log.txt"
path = base + "/" + file
```
</pre>
## Gotchas
- Strings are immutable: repeated concatenation in big loops can be costly; consider collecting pieces in an array and joining at the end if you have a helper for that in your setup.

View file

@ -41,29 +41,21 @@ To list targets with CMake directly, consult your IDE or run the build system
Debug profile example:
```
cmake --build build --target test_opcodes && ./build/test_opcodes
```
<pre>cmake --build build --target test_opcodes && ./build/test_opcodes
</pre>
Release profile example:
```
cmake --build build_release --target test_opcodes && ./build/test_opcodes
```
<pre>cmake --build build_release --target test_opcodes && ./build/test_opcodes
</pre>
If `fun_test` exists in your configuration:
```
cmake --build build --target fun_test && ./build/fun_test
```
<pre>cmake --build build --target fun_test && ./build/fun_test
</pre>
You can also invoke CTest to run any tests registered with `add_test()`:
```
cmake --build build --target test
<pre>cmake --build build --target test
ctest --test-dir build -j
```
</pre>
## Adding new tests
- C/C++/VM-side tests: look for existing tests under `src` or `spec` and mirror the structure. Add a new source and register it in CMake with an executable or via `add_test()`.

View file

@ -26,27 +26,21 @@ This page lists common issues when building and running Fun from a source checko
Error example:
```
Include error: cannot read '<io/console.fun>'
```
<pre>Include error: cannot read '<io/console.fun>'
</pre>
Fix:
- When running from the repository without installing, set `FUN_LIB_DIR` to the local `./lib` directory so anglebracket includes resolve correctly.
Linux/macOS/BSD:
```
export FUN_LIB_DIR="$(pwd)/lib"
<pre>export FUN_LIB_DIR="$(pwd)/lib"
./build/fun examples/include_lib.fun
```
</pre>
Windows (PowerShell):
```
$env:FUN_LIB_DIR = "$PWD/lib"
<pre>$env:FUN_LIB_DIR = "$PWD/lib"
./build/fun.exe .\examples\include_lib.fun
```
</pre>
If `FUN_LIB_DIR` is not set, the interpreter tries a compiletime `DEFAULT_LIB_DIR`, and finally falls back to `./lib` relative to the current working directory. Be mindful of where you run the `fun` binary from.
See includes.md for more details.
@ -59,12 +53,10 @@ Symptoms:
Fix:
- Build with `-DFUN_WITH_REPL=ON` and rebuild the `fun` target. Then launch without arguments:
```
cmake -S . -B build -DFUN_WITH_REPL=ON
<pre>cmake -S . -B build -DFUN_WITH_REPL=ON
cmake --build build --target fun
FUN_LIB_DIR="$(pwd)/lib" ./build/fun
```
</pre>
See repl.md for usage tips and features.
## Linker errors for optional libraries (JSON, PCRE2, CURL, SQLite, etc.)

View file

@ -56,8 +56,7 @@ Helpers used throughout:
Create arrays with square brackets and commaseparated elements.
```
// creation
<pre>// creation
a = [1, 2, 3]
b = ["alpha", "beta"]
c = [] // empty array
@ -96,8 +95,7 @@ for pair in it.enumerate(["x", "y"]) {
val = pair[1]
print(idx + ":" + val)
}
```
</pre>
Notes:
- Indexing is boundschecked; invalid indices cause a runtime error that you can inspect with --trace or REPLonerror.
- Arrays are mutable; operations modify in place unless documented otherwise.
@ -106,8 +104,7 @@ Notes:
Create maps with curly braces. Keys are typically strings; values can be any type.
```
// creation
<pre>// creation
user = { "name": "Ada", "age": 37 }
cfg = {}
@ -134,57 +131,48 @@ for i = 0; i < len(keys); i = i + 1 {
k = keys[i]
print(k + " = " + to_string(user[k]))
}
```
</pre>
Notes:
- Accessing a nonexisting key returns nil; write a guard before using it as another type.
- Maps are mutable; assigning with map["k"] = v updates in place.
## Strings (brief)
```
s = "hello, world"
<pre>s = "hello, world"
print(len(s)) // 12
print(substr(s, 7, 5)) // world
print(find(s, ",")) // 5 (index) or -1 if not found
parts = split("a,b,c", ",") // ["a","b","c"]
print(join(parts, ";")) // a;b;c
```
</pre>
## Numbers and floats (brief)
```
n = 10
<pre>n = 10
f = 3.14
print(n + 2) // 12
print(f * 2) // 6.28
// clamp to widths when needed
print(uclamp(300, 8)) // 44 (300 mod 256)
```
</pre>
## Booleans and nil
```
ok = 1 // true
<pre>ok = 1 // true
no = 0 // false
none = nil
if ok && !no { print("yay") }
if none == nil { print("is nil") }
```
</pre>
## Conversions and typing
```
x = "42"
<pre>x = "42"
print(to_number(x) + 1) // 43
print(typeof([1,2,3])) // "array"
print(typeof({})) // "map"
```
</pre>
## Common patterns
- Accumulate values:

View file

@ -5,8 +5,8 @@ noToc: false
noComments: false
noDate: false
title: Fun - Website Documentation (fun-lang.xyz)
subtitle: Documentation for the [fun-lang.xyz](https,//fun-lang.xyz) website in the `./web/` directory.
description: Documentation for the [fun-lang.xyz](https,//fun-lang.xyz) website in the `./web/` directory.
subtitle: Documentation for the fun-lang.xyz website in the `./web/` directory.
description: Documentation for the fun-lang.xyz website in the `./web/` directory.
permalink: /documentation/website/
lang: en
tags:
@ -93,9 +93,7 @@ To run the website locally for development:
The website can be deployed using the Makefile:
```bash
cd web/
<pre>cd web/
make release
```
</pre>
The `release` target builds the site, minifies the assets, and syncs the files to [fun-lang.xyz](https://fun-lang.xyz) via `rsync`. Ensure you have the necessary SSH permissions for the sync to succeed.

View file

@ -37,7 +37,7 @@ permalink: /
<article class="post-content">
<h2><a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a> <span style="cursor:help; float: right;" title="Pinned Post!">📌</span></h2>
<p class="post-meta">{{ post.date | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }})
{% if post.date_updated %} - Edited: {{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}){% endif %}{% if post.author %}, <a href="{{ site.git_short }}/{{ post.author }}" target="_blank" class="user">{{ post.author }}</a>{% endif %}</p>
{% if post.date_updated %} - Edited: {{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}){% endif %}{% if post.author %}, <a href="{{ post.author_url }}" target="_blank" class="user">{{ post.author }}</a>{% endif %}</p>
{{ post.content | truncatewords: site.truncatewords_length }}
<p style="text-align:right;"><a href="{{ post.url }}" title="{{ post.url }}">[Read post]</a></p>
</article>
@ -48,7 +48,7 @@ permalink: /
<article class="post-content">
<h2><a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a></h2>
<p class="post-meta">{{ post.date | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }})
{% if post.date_updated %} - Edited: {{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}){% endif %}{% if post.author %}, <a href="{{ site.git_short }}/{{ post.author }}" target="_blank" class="user">{{ post.author }}</a>{% endif %}</p>
{% if post.date_updated %} - Edited: {{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}){% endif %}{% if post.author %}, <a href="{{ post.author_url }}" target="_blank" class="user">{{ post.author }}</a>{% endif %}</p>
{{ post.content | truncatewords: site.truncatewords_length }}
<p style="text-align:right;"><a href="{{ post.url }}" title="{{ post.url }}">[Read post]</a></p>
</article>