./examples/features.fun and ./web/features/features.md update. (0.41.16)
This commit is contained in:
parent
751dd61da9
commit
6a39862787
3 changed files with 599 additions and 136 deletions
|
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(fun VERSION 0.41.15 LANGUAGES C)
|
||||
project(fun VERSION 0.41.16 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
|
|
|||
|
|
@ -10,48 +10,120 @@ print("")
|
|||
// ============================================
|
||||
print("1. Strong Type System:")
|
||||
string name = "Fun Language"
|
||||
float version = 0.3
|
||||
float version = 0.41
|
||||
boolean is_awesome = true
|
||||
number meaning = 42
|
||||
items = [1, 2, 3, 4, 5]
|
||||
config = {"debug": true, "port": 8080}
|
||||
nil_val = nil
|
||||
|
||||
print(" Language: " + name + " v" + to_string(version))
|
||||
print(" Language: " + name + " v" + fun_version())
|
||||
print(" Awesome: " + to_string(is_awesome))
|
||||
print(" Nil: " + to_string(nil_val))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 2. Modern Array Operations
|
||||
// 2. Type Introspection
|
||||
// ============================================
|
||||
print("2. Array Operations:")
|
||||
print("2. Type Introspection:")
|
||||
number check_int = 42
|
||||
string check_str = "hello"
|
||||
check_arr = [1, 2, 3]
|
||||
check_map = {"key": "value"}
|
||||
check_float = 3.14
|
||||
|
||||
print(" typeof(42) = " + typeof(check_int))
|
||||
print(" typeof(\"hello\") = " + typeof(check_str))
|
||||
print(" typeof([1,2,3]) = " + typeof(check_arr))
|
||||
print(" typeof(map) = " + typeof(check_map))
|
||||
print(" typeof(3.14) = " + typeof(check_float))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 3. Conversion & Casting
|
||||
// ============================================
|
||||
print("3. Conversion & Casting:")
|
||||
print(" to_string(42) = " + to_string(42))
|
||||
print(" to_number(\"99\") = " + to_string(to_number("99")))
|
||||
casted = cast(1, "boolean")
|
||||
print(" cast(1, \"boolean\") = " + to_string(casted))
|
||||
casted2 = cast("42", "number")
|
||||
print(" cast(\"42\", \"number\") = " + to_string(casted2))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 4. String Manipulation
|
||||
// ============================================
|
||||
print("4. String Operations:")
|
||||
string text = "Hello, Fun Language!"
|
||||
print(" Original: " + text)
|
||||
print(" Length: " + to_string(len(text)))
|
||||
print(" Substr(0,5): " + substr(text, 0, 5))
|
||||
print(" Find(\"Fun\"): " + to_string(find(text, "Fun")))
|
||||
parts = split(text, " ")
|
||||
print(" Split by space: " + to_string(parts))
|
||||
joined = join(parts, "-")
|
||||
print(" Join with '-': " + joined)
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 5. Modern Array Operations
|
||||
// ============================================
|
||||
print("5. Array Operations:")
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
print(" Original: " + to_string(numbers))
|
||||
print(" Length: " + to_string(len(numbers)))
|
||||
print(" Index 0: " + to_string(numbers[0]))
|
||||
print(" Index last: " + to_string(numbers[len(numbers) - 1]))
|
||||
|
||||
// Array helpers from spec: push, join, map, filter, reduce
|
||||
joined = join([10, 20, 30], ", ")
|
||||
print(" Joined: " + joined)
|
||||
// Slice syntax arr[start:end]
|
||||
sliced = numbers[2:7]
|
||||
print(" Slice [2:7]: " + to_string(sliced))
|
||||
|
||||
// Iterate arrays
|
||||
print(" Iteration:")
|
||||
for item in ["apple", "banana", "cherry"]
|
||||
print(" " + item)
|
||||
// Mutating array ops
|
||||
arr = [10, 20, 30]
|
||||
push(arr, 40)
|
||||
print(" After push(40): " + to_string(arr))
|
||||
removed = pop(arr)
|
||||
print(" Popped: " + to_string(removed) + ", arr: " + to_string(arr))
|
||||
insert(arr, 1, 15)
|
||||
print(" After insert(1, 15): " + to_string(arr))
|
||||
removed = remove(arr, 0)
|
||||
print(" Removed at 0: " + to_string(removed) + ", arr: " + to_string(arr))
|
||||
|
||||
// Search & utility
|
||||
print(" Contains 20? " + to_string(contains(arr, 20)))
|
||||
print(" Index of 20? " + to_string(indexOf(arr, 20)))
|
||||
print(" Enumerate: " + to_string(enumerate(["a", "b", "c"])))
|
||||
print(" Zip: " + to_string(zip([1, 2, 3], ["x", "y", "z"])))
|
||||
clear(arr)
|
||||
print(" After clear: " + to_string(arr))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 3. Maps (Dictionaries)
|
||||
// 6. Maps (Dictionaries)
|
||||
// ============================================
|
||||
print("3. Map Operations:")
|
||||
print("6. Map Operations:")
|
||||
person = {"name": "Alice", "age": 30, "role": "Developer"}
|
||||
|
||||
print(" Person: " + to_string(person))
|
||||
print(" Has 'age' key: " + to_string(has(person, "age")))
|
||||
print(" Keys: " + to_string(keys(person)))
|
||||
print(" Values: " + to_string(values(person)))
|
||||
|
||||
// Bracket access and assignment
|
||||
print(" person[\"name\"]: " + person["name"])
|
||||
person["age"] = 31
|
||||
print(" Updated age: " + to_string(person["age"]))
|
||||
|
||||
// Object property access (dot notation)
|
||||
print(" person.name: " + person.name)
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 4. Object-Oriented Programming
|
||||
// 7. Object-Oriented Programming
|
||||
// ============================================
|
||||
print("4. Classes & Objects:")
|
||||
print("7. Classes & Objects:")
|
||||
|
||||
class Counter(number initial, string label)
|
||||
count = 0
|
||||
|
|
@ -78,9 +150,9 @@ counter.display()
|
|||
print("")
|
||||
|
||||
// ============================================
|
||||
// 5. Inheritance
|
||||
// 8. Inheritance
|
||||
// ============================================
|
||||
print("5. Inheritance:")
|
||||
print("8. Inheritance:")
|
||||
|
||||
class Animal(string type)
|
||||
species = ""
|
||||
|
|
@ -107,9 +179,9 @@ print(" Species: " + dog.species)
|
|||
print("")
|
||||
|
||||
// ============================================
|
||||
// 6. Error Handling
|
||||
// 9. Error Handling & Exceptions
|
||||
// ============================================
|
||||
print("6. Exception Handling:")
|
||||
print("9. Exception Handling:")
|
||||
|
||||
try
|
||||
print(" Attempting risky operation...")
|
||||
|
|
@ -122,51 +194,63 @@ finally
|
|||
print("")
|
||||
|
||||
// ============================================
|
||||
// 7. String Manipulation
|
||||
// 10. Comparison & Logical Operators
|
||||
// ============================================
|
||||
print("7. String Features:")
|
||||
string text = "Hello, Fun Language!"
|
||||
print(" Original: " + text)
|
||||
// Note: Using stdlib functions (assumed to exist in utils modules)
|
||||
// len, substr, find, split would come from stdlib
|
||||
print("10. Comparison & Logical Operators:")
|
||||
number a = 10
|
||||
number b = 20
|
||||
print(" a=10, b=20")
|
||||
print(" a < b: " + to_string(a < b))
|
||||
print(" a <= b: " + to_string(a <= b))
|
||||
print(" a > b: " + to_string(a > b))
|
||||
print(" a >= b: " + to_string(a >= b))
|
||||
print(" a == b: " + to_string(a == b))
|
||||
print(" a != b: " + to_string(a != b))
|
||||
print(" a < b && a > 0: " + to_string(a < b && a > 0))
|
||||
print(" a > b || a > 0: " + to_string(a > b || a > 0))
|
||||
print(" !true: " + to_string(!true))
|
||||
print(" Ternary (a < b ? \"yes\" : \"no\"): " + (a < b ? "yes" : "no"))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 8. Mathematical Operations
|
||||
// 11. Control Flow: if/else if/else
|
||||
// ============================================
|
||||
print("8. Math Functions:")
|
||||
float x = 16.7
|
||||
print(" x = " + to_string(x))
|
||||
// Note: Math functions like sqrt, floor, ceil, abs, gcd, lcm
|
||||
// would come from stdlib <utils/math.fun> or similar
|
||||
print("11. If/Else If/Else:")
|
||||
number score = 85
|
||||
|
||||
if score >= 90
|
||||
print(" Grade: A")
|
||||
else if score >= 80
|
||||
print(" Grade: B")
|
||||
else if score >= 70
|
||||
print(" Grade: C")
|
||||
else
|
||||
print(" Grade: F")
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 9. Bitwise Operations
|
||||
// 12. Control Flow: Loops
|
||||
// ============================================
|
||||
print("9. Bitwise Operations:")
|
||||
number bits1 = 12
|
||||
number bits2 = 10
|
||||
print(" 12 & 10 = " + to_string(band(bits1, bits2)))
|
||||
print(" 12 | 10 = " + to_string(bor(bits1, bits2)))
|
||||
print(" 12 ^ 10 = " + to_string(bxor(bits1, bits2)))
|
||||
print(" 12 << 2 = " + to_string(shl(bits1, 2)))
|
||||
print(" ~12 = " + to_string(bnot(bits1)))
|
||||
print("")
|
||||
print("12. Loop Variants:")
|
||||
|
||||
// ============================================
|
||||
// 10. Control Flow
|
||||
// ============================================
|
||||
print("10. Control Flow:")
|
||||
// For-each with array
|
||||
print(" For-each array:")
|
||||
for item in ["apple", "banana", "cherry"]
|
||||
print(" " + item)
|
||||
|
||||
// For loop with array
|
||||
print(" Countdown:")
|
||||
for i in [5, 4, 3, 2, 1]
|
||||
print(" " + to_string(i) + "...")
|
||||
print(" Liftoff!")
|
||||
// For-range loop
|
||||
print(" For-range 0..4:")
|
||||
for i in range(0, 5)
|
||||
print(" " + to_string(i))
|
||||
|
||||
// For-map loop
|
||||
print(" For-map key, value:")
|
||||
config_map = {"a": 1, "b": 2, "c": 3}
|
||||
for (k, v) in config_map
|
||||
print(" " + k + " = " + to_string(v))
|
||||
|
||||
// While with break/continue
|
||||
print(" Skip evens:")
|
||||
print(" While with break/continue:")
|
||||
number n = 0
|
||||
while n < 10
|
||||
n = n + 1
|
||||
|
|
@ -178,24 +262,55 @@ while n < 10
|
|||
print("")
|
||||
|
||||
// ============================================
|
||||
// 11. Type Introspection
|
||||
// 13. Mathematical Operations
|
||||
// ============================================
|
||||
print("11. Type Introspection:")
|
||||
number check_int = 42
|
||||
string check_str = "hello"
|
||||
check_arr = [1, 2, 3]
|
||||
check_map = {"key": "value"}
|
||||
print("13. Math Functions:")
|
||||
number mx = -16
|
||||
print(" abs(-16) = " + to_string(abs(mx)))
|
||||
print(" min(10, 20) = " + to_string(min(10, 20)))
|
||||
print(" max(10, 20) = " + to_string(max(10, 20)))
|
||||
print(" clamp(50, 0, 10) = " + to_string(clamp(50, 0, 10)))
|
||||
print(" pow(2, 10) = " + to_string(pow(2, 10)))
|
||||
print(" sqrt(144) = " + to_string(sqrt(144)))
|
||||
print(" floor(3.7) = " + to_string(floor(3.7)))
|
||||
print(" ceil(3.2) = " + to_string(ceil(3.2)))
|
||||
print(" round(3.5) = " + to_string(round(3.5)))
|
||||
print(" trunc(3.9) = " + to_string(trunc(3.9)))
|
||||
print(" sin(0) = " + to_string(sin(0)))
|
||||
print(" cos(0) = " + to_string(cos(0)))
|
||||
print(" gcd(12, 8) = " + to_string(gcd(12, 8)))
|
||||
print(" lcm(12, 8) = " + to_string(lcm(12, 8)))
|
||||
print(" isqrt(50) = " + to_string(isqrt(50)))
|
||||
print(" sign(-42) = " + to_string(sign(-42)))
|
||||
print(" fmin(3.1, 2.9) = " + to_string(fmin(3.1, 2.9)))
|
||||
print(" fmax(3.1, 2.9) = " + to_string(fmax(3.1, 2.9)))
|
||||
|
||||
print(" typeof(42) = " + typeof(check_int))
|
||||
print(" typeof(\"hello\") = " + typeof(check_str))
|
||||
print(" typeof([1,2,3]) = " + typeof(check_arr))
|
||||
print(" typeof(map) = " + typeof(check_map))
|
||||
// Random (deterministic for demo)
|
||||
random_seed(42)
|
||||
print(" random_int(1, 100) = " + to_string(random_int(1, 100)))
|
||||
print(" random_number(8) = " + random_number(8))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 12. Functional Programming
|
||||
// 14. Bitwise Operations
|
||||
// ============================================
|
||||
print("12. Higher-Order Functions:")
|
||||
print("14. Bitwise Operations:")
|
||||
number bits1 = 12 // 1100
|
||||
number bits2 = 10 // 1010
|
||||
print(" 12 & 10 = " + to_string(band(bits1, bits2)))
|
||||
print(" 12 | 10 = " + to_string(bor(bits1, bits2)))
|
||||
print(" 12 ^ 10 = " + to_string(bxor(bits1, bits2)))
|
||||
print(" ~12 = " + to_string(bnot(bits1)))
|
||||
print(" 12 << 2 = " + to_string(shl(bits1, 2)))
|
||||
print(" 12 >> 2 = " + to_string(shr(bits1, 2)))
|
||||
print(" rol(0x80000001, 1) = " + to_string(rol(0x80000001, 1)))
|
||||
print(" ror(0x80000001, 1) = " + to_string(ror(0x80000001, 1)))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 15. Functional & Higher-Order Programming
|
||||
// ============================================
|
||||
print("15. Higher-Order Functions:")
|
||||
|
||||
fun double(n)
|
||||
return n * 2
|
||||
|
|
@ -208,28 +323,112 @@ print(" apply_twice(5, double) = " + to_string(result))
|
|||
print("")
|
||||
|
||||
// ============================================
|
||||
// 13. Array Operations with Spec Functions
|
||||
// 16. Array Higher-Order Functions
|
||||
// ============================================
|
||||
print("13. Array Higher-Order Functions:")
|
||||
print("16. Array Higher-Order Functions:")
|
||||
nums = [1, 2, 3, 4, 5]
|
||||
|
||||
fun square(x)
|
||||
return x * x
|
||||
|
||||
squared = map(nums, square)
|
||||
print(" Squared: " + to_string(squared))
|
||||
print(" map(nums, square): " + to_string(squared))
|
||||
|
||||
fun is_even(x)
|
||||
return x % 2 == 0
|
||||
|
||||
evens = filter(nums, is_even)
|
||||
print(" Evens: " + to_string(evens))
|
||||
print(" filter(nums, is_even): " + to_string(evens))
|
||||
|
||||
fun sum(acc, x)
|
||||
return acc + x
|
||||
|
||||
total = reduce(nums, 0, sum)
|
||||
print(" Sum: " + to_string(total))
|
||||
print(" reduce(nums, 0, sum): " + to_string(total))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 17. File I/O
|
||||
// ============================================
|
||||
print("17. File I/O:")
|
||||
write_file("/tmp/fun_demo.txt", "Hello from Fun!")
|
||||
content = read_file("/tmp/fun_demo.txt")
|
||||
print(" Written and read back: " + content)
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 18. Environment & OS
|
||||
// ============================================
|
||||
print("18. Environment & OS:")
|
||||
print(" HOME: " + env("HOME"))
|
||||
print(" Version: " + fun_version())
|
||||
|
||||
// List directory (non-empty /tmp assumed)
|
||||
listing = os_list_dir("/tmp")
|
||||
print(" /tmp has " + to_string(len(listing)) + " entries")
|
||||
|
||||
// Run a command and capture output
|
||||
proc_result = proc_run("echo hello from fun")
|
||||
print(" proc_run output: " + proc_result["out"])
|
||||
|
||||
// System call exit code
|
||||
sys_code = system("true")
|
||||
print(" system(\"true\") exit: " + to_string(sys_code))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 19. Date, Time & Sleep
|
||||
// ============================================
|
||||
print("19. Date, Time & Sleep:")
|
||||
now = time_now_ms()
|
||||
print(" Now (epoch ms): " + to_string(now))
|
||||
print(" Date formatted: " + date_format(now, "%Y-%m-%d %H:%M:%S"))
|
||||
|
||||
mono = clock_mono_ms()
|
||||
print(" Monotonic ms: " + to_string(mono))
|
||||
|
||||
// Short sleep to demonstrate
|
||||
sleep(10)
|
||||
after = clock_mono_ms()
|
||||
diff = after - mono
|
||||
print(" Slept 10 ms, elapsed: " + to_string(diff) + " ms")
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 20. Echo (print without newline)
|
||||
// ============================================
|
||||
print("20. Echo (no newline):")
|
||||
echo(" Hello, ")
|
||||
echo("world")
|
||||
print("!")
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 21. Threading
|
||||
// ============================================
|
||||
print("21. Threading:")
|
||||
|
||||
fun worker(id)
|
||||
print(" Thread " + to_string(id) + " says hi!")
|
||||
return id * 2
|
||||
|
||||
t1 = thread_spawn(worker, [1])
|
||||
t2 = thread_spawn(worker, [2])
|
||||
r1 = thread_join(t1)
|
||||
r2 = thread_join(t2)
|
||||
print(" Joined thread results: " + to_string(r1) + ", " + to_string(r2))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
// 22. Type-Safe Integer Clamping
|
||||
// ============================================
|
||||
print("22. Integer Clamping:")
|
||||
byte val = 300
|
||||
print(" byte val = 300 -> clamped to " + to_string(val))
|
||||
int8 signed = 200
|
||||
print(" int8 val = 200 -> clamped to " + to_string(signed))
|
||||
uint16 big = 70000
|
||||
print(" uint16 val = 70000 -> clamped to " + to_string(big))
|
||||
print("")
|
||||
|
||||
// ============================================
|
||||
|
|
|
|||
|
|
@ -24,103 +24,367 @@ tags:
|
|||
- cgi
|
||||
---
|
||||
|
||||
This page summarizes the core capabilities of Fun: the language, its virtual machine/runtime, tooling, build options, and the surrounding ecosystem. For in‑depth pages, see also:
|
||||
This page summarizes the core capabilities of Fun: the language, its virtual machine/runtime, tooling, build options, and the surrounding ecosystem.
|
||||
|
||||
- VM opcodes overview: /documentation/opcodes/
|
||||
- Optional extensions catalog: /documentation/extensions/
|
||||
---
|
||||
|
||||
## Language
|
||||
|
||||
- Simple, expressive syntax designed for scripting and embedding
|
||||
- First‑class functions and function calls
|
||||
- Variables, locals and globals with stack‑based execution model
|
||||
- Control flow: conditional jumps, returns, and basic boolean operators
|
||||
- Arrays and maps as primary collection types (literal construction, indexing, slicing, membership)
|
||||
- Strings with common operations (substring, find, split, join)
|
||||
- Arithmetic and bitwise integer operations (add, sub, mul, div, mod; band, bor, bxor, shifts, rotations)
|
||||
- Exceptions and error handling primitives (throw/try semantics at VM level)
|
||||
- Regular expressions support via optional PCRE2 extension (see Extensions)
|
||||
### Syntax & Structure
|
||||
- Indentation-based block structure (strict 2-space indent)
|
||||
- Line comments (`//`) and block comments (`/* */`)
|
||||
- Optional shebang (`#!`) line for script execution
|
||||
- Unicode string support via UTF-8 throughout
|
||||
- `exit` statement with optional exit code
|
||||
|
||||
Notes:
|
||||
### Type System
|
||||
- **Dynamic typing** with optional **static type annotations**
|
||||
- **Value types:** Integer (signed 64-bit), Float (double), Boolean, String, Array, Map, Function, Nil
|
||||
- **Type annotations:** `number`, `string`, `boolean`, `float`, `nil`, `array`, `map`, `class`
|
||||
- **Fixed-width integer types:** `byte` / `uint8`, `uint16`, `uint32`, `uint64`, `int8`, `int16`, `int32`, `int64` — with automatic range clamping
|
||||
- **Type aliases:** `sint8`–`sint64` as synonyms for `int8`–`int64`
|
||||
- `typeof()` runtime type introspection
|
||||
- `to_string()` and `to_number()` conversion functions
|
||||
- `cast(value, typeName)` explicit type casting
|
||||
|
||||
- See the opcode index for the precise stack behavior of each operation: /documentation/opcodes/
|
||||
### Variables & Scope
|
||||
- Global and local (per-function) variable scoping
|
||||
- Auto-declaration on first assignment
|
||||
- Typed variable declarations: `string name = "Fun"`
|
||||
- Up to 128 globals, 64 locals per frame, 128 call frames
|
||||
|
||||
### Operators
|
||||
|
||||
**Arithmetic:** `+`, `-`, `*`, `/`, `%` (addition also concatenates strings)
|
||||
|
||||
**Comparison:** `<`, `<=`, `>`, `>=`, `==`, `!=`
|
||||
|
||||
**Logical:** `&&` (and), `||` (or), `!` (not) — short-circuit evaluation
|
||||
|
||||
**Bitwise (32-bit):** `band()`, `bor()`, `bxor()`, `bnot()`, `shl()`, `shr()`, `rol()`, `ror()`
|
||||
|
||||
**Ternary:** `condition ? true_expr : false_expr`
|
||||
|
||||
### Data Structures
|
||||
|
||||
**Arrays:**
|
||||
- Literal syntax: `[1, 2, 3]`
|
||||
- Index get/set: `arr[0]`, `arr[0] = value`
|
||||
- Slice syntax: `arr[start:end]`
|
||||
- Negative indices for end-relative access
|
||||
- Built-in operations: `len()`, `push()`, `pop()`, `insert()`, `remove()`, `slice()`, `contains()`, `indexOf()`, `clear()`, `enumerate()`, `zip()`, `join()`, `map()`, `filter()`, `reduce()`
|
||||
|
||||
**Maps (dictionaries):**
|
||||
- Literal syntax: `{"key": value, ...}`
|
||||
- Bracket access/assignment: `map["key"]`, `map["key"] = value`
|
||||
- Dot property access: `map.key`
|
||||
- Built-in operations: `has()`, `keys()`, `values()`
|
||||
|
||||
### Strings
|
||||
- Double and single-quoted string literals
|
||||
- Concatenation with `+`
|
||||
- Built-in operations: `len()`, `substr()`, `find()`, `split()`, `join()`
|
||||
|
||||
### Control Flow
|
||||
- `if` / `else if` / `else` conditional chains
|
||||
- `while` loops with `break` and `continue`
|
||||
- `for var in array` — array iteration
|
||||
- `for var in range(start, end)` — numeric range iteration (`[start, end)`)
|
||||
- `for (key, value) in map` — map key-value iteration
|
||||
- `match` expression (stdlib `lib/utils/match.fun`)
|
||||
|
||||
### Functions
|
||||
- Named function definitions: `fun name(params) body`
|
||||
- Anonymous function literals: `fn(params) body`
|
||||
- First-class functions (pass as arguments, store in variables)
|
||||
- Recursion support
|
||||
- Return with `return expr` (or implicit nil)
|
||||
|
||||
### Object-Oriented Programming
|
||||
- Class definitions: `class Name(typed params) body`
|
||||
- Constructor method: `_construct(this, ...)` — auto-invoked on instantiation
|
||||
- Methods: `fun method(this, ...)` inside class body
|
||||
- Field access and mutation via `this.field`
|
||||
- Property access via dot notation: `obj.field`
|
||||
- Method call sugar: `obj.method(args)` (auto-binds `this`)
|
||||
- Single inheritance: `class Child(...) extends Parent`
|
||||
- Method overriding in subclasses
|
||||
|
||||
### Error Handling
|
||||
- `try` / `catch` / `finally` blocks
|
||||
- Error variable binding: `catch err`
|
||||
- `throw` opcode for raising exceptions
|
||||
- Per-frame try-stack for nested exception handlers
|
||||
|
||||
### Pattern Matching & Regex (Built-in POSIX)
|
||||
- `regex_match(str, pattern)` — full match test (returns 1/0)
|
||||
- `regex_search(str, pattern)` — first match with groups (returns map)
|
||||
- `regex_replace(str, pattern, replacement)` — global search and replace
|
||||
|
||||
### Functional Programming
|
||||
- First-class and anonymous functions
|
||||
- `map(array, fn)` — transform each element
|
||||
- `filter(array, fn)` — keep matching elements
|
||||
- `reduce(array, init, fn)` — accumulate values
|
||||
- Higher-order functions (functions that accept or return functions)
|
||||
- `enumerate()` and `zip()` iteration helpers
|
||||
|
||||
### Concurrency
|
||||
- `thread_spawn(fn, args)` — spawn a thread, returns thread ID
|
||||
- `thread_join(id)` — join a thread, returns its result
|
||||
- Cooperative async scheduler (stdlib `lib/async/scheduler.fun`)
|
||||
|
||||
---
|
||||
|
||||
## Virtual Machine & Runtime
|
||||
|
||||
- Compact stack‑based bytecode VM implemented in C (C99)
|
||||
- Deterministic execution model with explicit opcodes for core language features
|
||||
- Efficient array and map primitives with indexing and mutation opcodes
|
||||
- Built‑in string operations and regex integration (with extension)
|
||||
- Minimal error model integrated with VM (throw/try handlers)
|
||||
### Architecture
|
||||
- Compact stack-based bytecode VM written in **C99**
|
||||
- Tagged union value type supporting 8 runtime types
|
||||
- ~220 opcodes covering all language features
|
||||
- Separate operand stack (1024 entries), call frames (128 max), and globals (128)
|
||||
- Each frame has 64 local slots and a 16-entry try/catch stack
|
||||
|
||||
## Standard Library (Core)
|
||||
### Memory & Performance
|
||||
- Deterministic execution model
|
||||
- Reference-counted arrays and maps
|
||||
- Function/data sectioning with linker GC for small binaries
|
||||
- LTO (Link-Time Optimization) support for Release builds
|
||||
|
||||
Core functionality available out of the box in the VM and library modules:
|
||||
### Debugging & Tracing
|
||||
- Built-in debugger with breakpoints (up to 64)
|
||||
- Step, next, finish, and continue commands
|
||||
- `--trace` / `-t` flag for opcode-level execution tracing
|
||||
- Per-opcode execution counters (compile-time `FUN_TRACE`)
|
||||
- `--repl-on-error` flag: drops into interactive REPL on runtime error with stack preserved
|
||||
- Stack trace printing on errors
|
||||
- Source line mapping in error messages (includes include-file resolution)
|
||||
|
||||
- Arrays: create, push/pop, insert/remove, slice, contains, join, enumerate
|
||||
- Maps: create, has_key, keys, values
|
||||
- Strings: substr, find, split, replace (with regex), join
|
||||
- Math and bitwise ops over fixed‑width integers used by the VM
|
||||
### I/O & Platform
|
||||
- `print()` — output with newline
|
||||
- `echo()` — output without newline (immediate flush)
|
||||
- `read_file(path)` — read entire file into string
|
||||
- `write_file(path, data)` — write string to file
|
||||
- `input_line()` — read a line from stdin (with optional prompt)
|
||||
- `env(name)` / `env_all()` — get environment variables
|
||||
- `proc_run(cmd)` — run command, capture stdout+exit code
|
||||
- `system(cmd)` — run command via shell, returns exit code
|
||||
- `os_list_dir(path)` — list directory entries
|
||||
|
||||
See the opcode list for the canonical reference: /documentation/opcodes/
|
||||
### Date, Time & Random
|
||||
- `time_now_ms()` — wall clock in milliseconds since Unix epoch
|
||||
- `clock_mono_ms()` — monotonic clock for interval measurement
|
||||
- `date_format(ms, fmt)` — format timestamps via strftime
|
||||
- `sleep(ms)` — suspend execution
|
||||
- `random_seed(seed)` — seed the PRNG
|
||||
- `random_int(lo, hi)` — random integer in `[lo, hi)`
|
||||
- `random_number(len)` — cryptographically random hex string
|
||||
|
||||
### Networking (Built-in, Unix)
|
||||
- `sock_tcp_listen(port, backlog)` — TCP server socket
|
||||
- `sock_tcp_accept(listen_fd)` — accept client connection
|
||||
- `sock_tcp_connect(host, port)` — TCP client connection
|
||||
- `sock_send(fd, data)` / `sock_recv(fd, maxlen)` — send/receive data
|
||||
- `sock_unix_listen(path, backlog)` / `sock_unix_connect(path)` — Unix domain sockets
|
||||
- `sock_close(fd)` — close socket
|
||||
- `fd_set_nonblock(fd, on)` — non-blocking mode
|
||||
- `fd_poll_read(fd, timeout_ms)` / `fd_poll_write(fd, timeout_ms)` — I/O readiness polling
|
||||
|
||||
### Serial Communication (Unix)
|
||||
- `serial_open(path, baud_rate)` — open serial port
|
||||
- `serial_config(fd, data_bits, parity, stop_bits, flow_control)` — configure
|
||||
- `serial_send(fd, data)` / `serial_recv(fd, maxlen)` — send/receive
|
||||
- `serial_close(fd)` — close
|
||||
|
||||
### Integer Utilities
|
||||
- `sclamp(value, bits)` / `uclamp(value, bits)` — signed/unsigned bit-width clamping
|
||||
- Integer type declarations (`byte`, `uint8`–`uint64`, `int8`–`int64`) with automatic range clamping
|
||||
- `gcd(a, b)`, `lcm(a, b)` — greatest common divisor, least common multiple
|
||||
- `isqrt(x)` — integer square root
|
||||
- `sign(x)` — signum (-1, 0, 1)
|
||||
|
||||
---
|
||||
|
||||
## Standard Library
|
||||
|
||||
The standard library is written primarily in **Fun itself** and lives in `lib/`:
|
||||
|
||||
### Strings (`lib/strings.fun`)
|
||||
- `str_ltrim`, `str_rtrim`, `str_trim` — whitespace trimming
|
||||
- `str_starts_with`, `str_ends_with` — prefix/suffix checking
|
||||
- `str_split` — single-character delimiter splitting
|
||||
- `str_replace_all` — global substring replacement
|
||||
- `str_to_lower`, `str_to_upper` — ASCII case conversion
|
||||
- `str_repeat` — string repetition
|
||||
- `string_to_bytes_ascii` — ASCII string to byte array
|
||||
|
||||
### Arrays (`lib/arrays.fun`)
|
||||
- `array_slice`, `array_reverse`, `array_concat` — slicing and combining
|
||||
- `array_index_of`, `array_contains` — searching
|
||||
- `array_unique` — deduplication
|
||||
- `array_flatten1` — flatten one level of nesting
|
||||
|
||||
### Math (`lib/math.fun`)
|
||||
- `abs`, `clamp`, `gcd`, `lcm`, `powi` (integer exponentiation)
|
||||
- `min3`, `max3`, `array_min`, `array_max`
|
||||
|
||||
### Hex (`lib/hex.fun`)
|
||||
- `hex_to_dec`, `dec_to_hex`, `hex_to_bytes`, `bytes_to_hex`
|
||||
|
||||
### Encoding (`lib/encoding/base64.fun`)
|
||||
- `b64_encode_bytes`, `b64_decode_to_bytes` — Base64 encoding/decoding
|
||||
|
||||
### Cryptography (Pure Fun implementations in `lib/crypt/`)
|
||||
- **MD5** — `MD5` class (`lib/crypt/md5.fun`)
|
||||
- **SHA-1** — `SHA1` class (`lib/crypt/sha1.fun`)
|
||||
- **SHA-256** — `SHA256` class (`lib/crypt/sha256.fun`)
|
||||
- **SHA-384** — `SHA384` class (`lib/crypt/sha384.fun`)
|
||||
- **SHA-512** — `SHA512` class (`lib/crypt/sha512.fun`)
|
||||
- **CRC-32** — `CRC32` class (IEEE 802.3)
|
||||
- **CRC-32C** — `CRC32C` class (Castagnoli)
|
||||
- **AES-256** — `AES256` class (ECB mode)
|
||||
|
||||
### Functional Utilities
|
||||
- **Option type** (`lib/utils/option.fun`): `some()`, `none()`, `is_some`, `is_none`, `unwrap`, `unwrap_or`, `option_map`, `and_then`, `or_else`, `try_get`
|
||||
- **Result type** (`lib/utils/result.fun`): `ok()`, `err()`, `is_ok`, `is_err`, `unwrap`, `unwrap_or`, `result_map`, `map_err`, `and_then`, `or_else`, `to_option`
|
||||
- **Pattern matching** (`lib/utils/match.fun`): `match(value, cases)` with `is`, `when`, `else` patterns
|
||||
|
||||
### Range Utilities (`lib/utils/range.fun`)
|
||||
- `range(n)` — `[0, n)`
|
||||
- `range2(start, end)` — `[start, end)`
|
||||
- `range3(start, end, step)` — stepped range
|
||||
|
||||
### Date/Time (`lib/utils/datetime.fun`)
|
||||
- `DateTime` class with `now_ms`, `mono_ms`, `format`, `iso_now`, `iso_from`, `date_str`, `time_str`, `today_str`, `start_timer`, `elapsed_ms`, `sleep_ms`, `sleep_s`
|
||||
|
||||
### CLI (`lib/cli.fun`)
|
||||
- `argv()` — retrieve command-line arguments
|
||||
- `parse_args(args)` — parse flags and positional arguments
|
||||
|
||||
### Console (`lib/io/console.fun`)
|
||||
- `Console` class with `prompt`, `ask`, `ask_hidden`, `ask_yes_no`, `term_cols`, `progress` (progress bar)
|
||||
|
||||
### Process (`lib/io/process.fun`)
|
||||
- `Process` class wrapping `proc_run` and `system`
|
||||
|
||||
### Thread (`lib/io/thread.fun`)
|
||||
- `Thread` class wrapping `thread_spawn` / `thread_join`
|
||||
|
||||
### Socket Classes (`lib/io/socket.fun`)
|
||||
- `TcpClient` — TCP client with connect/send/recv/close/recv_all
|
||||
- `TcpServer` — TCP server with listen/accept/close
|
||||
- `UnixClient` — Unix domain socket client
|
||||
|
||||
### Serial (`lib/io/serial.fun`)
|
||||
- `Serial` class wrapping serial port operations
|
||||
|
||||
### Async Scheduler (`lib/async/scheduler.fun`)
|
||||
- Cooperative multitasking with `task_spawn`, `co_yield`, `run_once`, `run_until_done`
|
||||
- I/O readiness polling: `await_read`, `await_write`
|
||||
|
||||
### Networking / Web
|
||||
- **CGI** (`lib/net/cgi.fun`): full CGI request parsing, response generation, URL encoding/decoding
|
||||
- **HTTP Server** (`lib/net/http_server.fun`): static file serving with `.fun` script execution
|
||||
- **HTTP CGI Server** (`lib/net/http_cgi_server.fun`): CGI-based HTTP server
|
||||
- **IRC Client** (`lib/net/irc.fun`): IRC protocol client with message parsing
|
||||
|
||||
---
|
||||
|
||||
## Optional Extensions (Build-time)
|
||||
|
||||
Enabled via CMake flags; each wraps a mature C library:
|
||||
|
||||
| Extension | CMake Flag | Library | Features |
|
||||
|-----------|-----------|---------|----------|
|
||||
| **JSON** | `FUN_WITH_JSON` | json-c | `json_parse()`, `json_stringify()`, `json_from_file()`, `json_to_file()` |
|
||||
| **cURL** | `FUN_WITH_CURL` | libcurl | `curl_get()`, `curl_post()`, `curl_download()` |
|
||||
| **SQLite** | `FUN_WITH_SQLITE` | libsqlite3 | `sqlite_open()`, `sqlite_close()`, `sqlite_exec()`, `sqlite_query()` |
|
||||
| **PCRE2** | `FUN_WITH_PCRE2` | libpcre2 | `pcre2_test()`, `pcre2_match()`, `pcre2_find_all()` — with flags (i, m, s, u, x) |
|
||||
| **OpenSSL** | `FUN_WITH_OPENSSL` | libcrypto | `openssl_md5()`, `openssl_sha256()`, `openssl_sha512()`, `openssl_ripemd160()` |
|
||||
| **INI** | `FUN_WITH_INI` | iniparser 4.2.6 | `ini_load()`, `ini_get_string/int/double/bool()`, `ini_set()`, `ini_unset()`, `ini_save()` |
|
||||
| **XML** | `FUN_WITH_XML2` | libxml2 | `xml_parse()`, `xml_root()`, `xml_name()`, `xml_text()` |
|
||||
| **PC/SC** | `FUN_WITH_PCSC` | libpcsclite | `pcsc_establish()`, `pcsc_list_readers()`, `pcsc_connect()`, `pcsc_transmit()`, etc. |
|
||||
| **KCGI** | `FUN_WITH_KCGI` | libkcgi | `kcgi_parse()`, `kcgi_reply_start()`, `kcgi_write()`, `kcgi_end()` |
|
||||
|
||||
Each extension also has a corresponding **stdlib wrapper class** in `lib/io/` or `lib/net/`:
|
||||
- `JSON` class (`lib/io/json.fun`)
|
||||
- `INI` class (`lib/io/ini.fun`)
|
||||
- `XML` class (`lib/io/xml.fun`)
|
||||
- `PCSC` / `PCSC2` classes (`lib/io/pcsc.fun`)
|
||||
- `PCRE2` class (`lib/regex/pcre2.fun`)
|
||||
- `KCGI` class (`lib/net/kcgi.fun`)
|
||||
|
||||
---
|
||||
|
||||
## FFI / Interop (Experimental)
|
||||
|
||||
### Rust FFI (`FUN_WITH_RUST`)
|
||||
- Cargo-based Rust static library linked into the VM
|
||||
- Demo opcodes: `rust_hello()`, `rust_hello_args()`, `rust_hello_args_return()`, `rust_get_sp()`, `rust_set_exit()`
|
||||
- Rust has unsafe access to VM internals via raw pointer and struct offset APIs
|
||||
|
||||
### C++ FFI (`FUN_WITH_CPP`)
|
||||
- C++ static library linked into the VM
|
||||
- Demo opcode: `cpp_add(a, b)`
|
||||
|
||||
---
|
||||
|
||||
## Tooling
|
||||
|
||||
- Fun interpreter/runtime executable (target: fun)
|
||||
- REPL and small tools (targets: repl, funstx, examples under examples/)
|
||||
- Test binaries (target: fun_test, test_opcodes)
|
||||
- Formatting helper target (target: format) using clang‑format
|
||||
- Make‑like aggregate build target (target: build)
|
||||
- **`fun`** — Interpreter/REPL. Runs `.fun` scripts or starts interactive REPL
|
||||
- **`funstx`** — Syntax checker with optional `--fix` mode
|
||||
- **REPL** — Interactive shell with history (1000 lines), multi-line input, tab completion, and commands: `:help`, `:env`, `:load`, `:run`, `:edit`, `:save`, `:clear`, `:exit`, `:quit`, `:debug`, `:import`, `:export`, `:type`, `:trace`, `:reload`
|
||||
- **Test harnesses** — `fun_test` (bytecode-level tests) and `test_opcodes` (opcode exercisers)
|
||||
- **CTest integration** — crypto example scripts run as automated tests
|
||||
- **clang-format** target for consistent C source formatting
|
||||
|
||||
## Build System & Options
|
||||
---
|
||||
|
||||
Fun uses CMake and exposes toggles that mirror the project’s optionality at build time:
|
||||
## Build System
|
||||
|
||||
- FUN_DEBUG — enable extra diagnostics in builds
|
||||
- FUN_USE_MUSL — build against musl when available
|
||||
- FUN_WITH_CPP — enable C++ interop/components where applicable
|
||||
- FUN_WITH_RUST — build and link an optional Rust static library with opcode examples
|
||||
- FUN_BUILD_DOCS — generate documentation (Doxygen/website pipelines)
|
||||
- FUN_WITH_* — per‑extension toggles (see Extensions section)
|
||||
- **CMake** 3.10+ with C99 standard
|
||||
- Build toggles: `FUN_DEBUG`, `FUN_USE_MUSL`, `FUN_WITH_REPL`, `FUN_WITH_CPP`, `FUN_WITH_RUST`, `FUN_BUILD_DOCS`
|
||||
- Per-extension toggles for all optional libraries
|
||||
- Release builds with LTO, function/data sectioning, and `--gc-sections`
|
||||
- Doxygen documentation generation
|
||||
- Install targets for binaries, libraries, examples, man pages
|
||||
- Uninstall target with safe directory cleanup
|
||||
|
||||
Targets available for CI/workflows include Experimental/Continuous/Nightly aggregates, plus unit tests and coverage helpers (see CMake targets).
|
||||
---
|
||||
|
||||
## Portability
|
||||
|
||||
- Written in portable C99
|
||||
- Designed to build on common Linux environments; musl support available
|
||||
- Written in **C99** with POSIX extensions
|
||||
- Primary target: **Linux** (glibc and musl)
|
||||
- Partial **Windows** support
|
||||
- Platform abstraction for threading, sockets, serial I/O
|
||||
- Builds with GCC and Clang
|
||||
|
||||
## Extensions (Optional, Build‑time)
|
||||
|
||||
Fun ships with optional integrations that can be enabled per environment. Highlights include:
|
||||
|
||||
- cURL (HTTP client)
|
||||
- INI (iniparser)
|
||||
- JSON (json‑c)
|
||||
- libxml2 (XML)
|
||||
- SQLite
|
||||
- PCRE2 (Perl‑compatible regex)
|
||||
- PC/SC (Smart cards)
|
||||
- OpenSSL (crypto/TLS)
|
||||
- kcgi (CGI/web helper)
|
||||
|
||||
See the full catalog with enable/requirement notes: /documentation/extensions/
|
||||
|
||||
## Web/CGI
|
||||
|
||||
- Optional kcgi integration for building CGI‑style programs and simple web endpoints (see Extensions)
|
||||
- Website sources under web/ with Jekyll layouts; generated site in web/_site/
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit and VM‑level opcode tests (targets: fun_test, test_opcodes)
|
||||
- Example scripts under examples/ exercised by CI and manual runs
|
||||
- Unit tests for VM opcodes and bytecode execution
|
||||
- CTest integration runs example scripts as automated tests
|
||||
- Example scripts in `examples/` (90+ files) cover all language features
|
||||
- Crypto self-tests for MD5, SHA-1/256/384/512, CRC-32/CRC-32C, AES-256
|
||||
- Include-line mapping regression test
|
||||
- KCGI smoke test (when enabled)
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
- Doxygen configuration for API references (Doxyfile)
|
||||
- Human‑readable docs under web/documentation/ (opcodes, extensions, etc.)
|
||||
- Jekyll-based website under `web/` with full documentation
|
||||
- Doxygen API reference
|
||||
- Language specification documents (`spec/`)
|
||||
- Over 90 annotated example scripts
|
||||
- Handbook, type system guide, REPL guide, testing guide
|
||||
- Opcode reference with stack effect documentation
|
||||
- Changelog and semantic versioning
|
||||
|
||||
---
|
||||
|
||||
## Licensing
|
||||
|
||||
- Licensed under an OSI‑approved license; see LICENSE at the repository root
|
||||
- **Apache 2.0** — fully open source, freely usable and modifiable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue