# Fun Language Specification v0.3 This document describes Fun (Fun Uses Nothing) as of version 0.3. It supersedes v0.2 by formalizing classes/objects, inheritance, namespaced includes, richer collections and builtins, concurrency primitives, networking and OS integration, as reflected by the examples. --- ## 1) Overview and Goals - Readable: strict, indentation-based syntax (2 spaces), no semicolons. - Safe: explicit types, no implicit numeric coercions, bounds-checked operations, controlled side effects. - Hackable: pragmatic stdlib, process I/O, sockets, threads. What’s new in v0.3 (high level): - Classes and objects with methods, constructors, and inheritance (`extends`). - Dot-call sugar for method calls, and explicit `this` in method definitions. - Namespaced `#include ... as alias` for module imports. - Maps (dictionaries) with literals and helpers. - Control-flow additions: `break` and `continue`. - Threads: `thread_spawn`, `thread_join` and `sleep`. - Expanded system and network APIs (TCP/Unix sockets, serial, env, timers). - Bitwise helpers (`band`, `bor`, `bxor`, `bnot`, `shl`). - Exception syntax (`try/catch/finally`) is defined; runtime throwing/handling may be partial. --- ## 2) Lexical Structure - Case-sensitive identifiers: letters, digits, `_`; must not start with a digit. - Comments: - Single-line: `// comment` - Multi-line: `/* ... */` - Whitespace and newlines: - Indentation is exactly 2 spaces; tabs are forbidden. - Newline terminates statements; no semicolons. Reserved keywords (cannot be redefined): - `if`, `else`, `for`, `while`, `break`, `continue` - `fun`, `return` - `class`, `extends` - `global`, `private` - `true`, `false` - `try`, `catch`, `finally` Notes: - `#include` is a directive, not an expression; `as` is part of the include alias syntax (see Modules & Includes). --- ## 3) Types Scalar types: - `number`: 64-bit signed integer. - `float`: 64-bit IEEE-754 floating point. - `string` - `boolean`: `true` / `false` (in conditionals `0` and `1` are accepted where noted). - `byte`: 8-bit value (see conversions and overflow rules). Fixed-width integers (signed/unsigned): - `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64` Aggregate types: - `array` and typed arrays: `array` - `map` (dictionary / associative array) - `object` (instances of `class`) Examples: ```fun number n = 42 float pi = 3.14159 string s = 'He said: "Fun!"' boolean ok = true byte b = 0x41 array nums = [1, 2, 3] array mixed = [1, "two", true, [3, 4]] m = { "a": 1, "b": 2 } // map ``` Dynamic typing escape hatch (discouraged; use when interacting with unknown data): ```fun dynamic string x = 42 // allowed by spec; runtime performs dynamic checks x = "Now I'm a string" ``` --- ## 4) Variables and Scope - `global` variables are visible program-wide. - `private` variables are file-local (module private). - Rebinding a global or shadowing a name is a compile-time error. ```fun global string message = "Hello" private number count = 42 number local = 23 ``` --- ## 5) Operators and Builtins Arithmetic: `+`, `-`, `*`, `/`, `%` Comparison: `==`, `!=`, `>`, `<`, `>=`, `<=` Boolean: `&&`, `||`, `!` Assignment: `=` Bitwise helpers (functions): - `band(a, b)`, `bor(a, b)`, `bxor(a, b)`, `bnot(a)`, `shl(a, n)` ```fun print(bxor(0x80000000, 0x00000001)) // 2147483649 print(shl(0x80, 24)) // 2147483648 ``` Collection helpers (selected): - Arrays: `push(arr, v)`, `join(arr, sep)`, `map(arr, f)`, `filter(arr, pred)`, `reduce(arr, init, f)` - Maps: `has(m, key)`, `keys(m)`, `values(m)` Type/convert helpers (selected): - `typeof(x) -> string` - `to_string(x)` and numeric casts (see examples for `cast_demo.fun` and `conversions_showcase.fun`) --- ## 6) Control Flow If/Else: ```fun if (x != y) print(x) else if (a == b || h != i) print(a + b) else if (k < 1 && l > 1) print("Buh!") ``` While: ```fun number i = 0 while i < 10 if i % 2 == 0 i = i + 1 continue if i > 5 break i = i + 1 ``` For: - Range iteration: `for i in range(start, end)` - Array iteration: `for x in arr` - Map iteration: `for k in keys(m)` then `m[k]` ```fun for i in range(0, 5) print(i) for x in [1, 2, 3] print(x) ``` Loop control: - `break` exits the innermost loop. - `continue` skips to next iteration of the current loop. Try/Catch/Finally (syntax defined; runtime throwing may be incomplete): ```fun try // protected section risky() catch err print("caught error:") print(err) finally print("cleanup") ``` --- ## 7) Functions Built-in/runtime functions (selected): - Basic: `print(x)`, `range(a, b)`, `sleep(ms)` - Processes: `exec(cmd) -> string`, `system(cmd) -> number` - Async processes: `nexec(cmd) -> pid/object`, `nsystem(cmd) -> number`, `nspawn(cmd) -> pid`, `wait(pid)`, `read(pid)`, `kill(pid)` - Threads: `thread_spawn(fn, argOrArgs) -> thread_id`, `thread_join(thread_id) -> any` User-defined functions: ```fun fun add(a, b) return a + b fun divide(a, b) if b == 0 return 0, "division by zero" return a / b, "" ``` Higher-order helper (example pattern): ```fun fun call(f, arg) return f(arg) ``` Multiple return values are supported syntactically; use tuple-like unpacking via arrays as needed in user code patterns. --- ## 8) Classes and Objects Definition: ```fun class Name(/* optional ctor params with types */) // field defaults field1 = 0 field2 = "" // method: first parameter must be `this` fun method(this, arg1, arg2) // ... return 0 ``` Constructors: - Default constructor maps the class header parameters to fields of the same names. - Optional explicit constructor hook: define `fun _construct(this, ...params...)` to customize initialization. It is invoked automatically on instantiation. Fields and methods: - Fields are created/initialized with simple assignments in the class body. - Methods are functions declared inside the class; the first parameter must be `this`. - Private members: any field or method whose name starts with `_` is considered private to the class. Accessing them from outside should raise an access error. Instantiation and method calls: ```fun p = Point(10, -2) print(p.x) // field access via `.` or indexing print(p["x"]) // map-like field access is supported // Dot-call sugar: p.method(a, b) is equivalent to method(p, a, b) print(p.toString()) ``` Method references: ```fun move_fn = p["move"] move_fn(p, 3, 5) // call with explicit `this` ``` Inheritance: ```fun class Parent(number start) value = 0 fun _construct(this, s) this.value = s fun describe(this) return "Parent(value=" + to_string(this.value) + ")" class Child(number start) extends Parent bonus = 5 fun _construct(this, s) // runs after parent fields merged this.value = this.value + this.bonus fun describe(this) return "Child(value=" + to_string(this.value) + ", bonus=" + to_string(this.bonus) + ")" ``` `typeof` on classes and instances: - `typeof(Point) == "Class"` - `typeof(p) == "Point(10, -2)"` (implementation-specific descriptive form) --- ## 9) Modules and Includes Include sources: - System/stdlib: angle brackets search the Fun library path (e.g., `FUN_LIB_DIR`). ```fun #include ``` - Local file: quoted, relative to the current working directory or file. ```fun #include "./utils/file.fun" ``` - Absolute path is supported. Namespaced includes: - Use `as` to bind a module into a namespace alias. ```fun #include as m #include "examples/namespaced_mod.fun" as mod print(m.add(2, 3)) g = mod.Greeter("Hi") g.say("World") ``` Aliased access uses `alias.symbol` or `alias.ClassName`. Global/private at file scope control symbol exports from a module. --- ## 10) Collections Arrays: - Literals with `[ ... ]`; may be heterogeneous unless `array` is declared. - Helpers: `push`, `join`, `map`, `filter`, `reduce`, iteration via `for x in arr`. Maps: - Literal: `{ key: value, ... }` - Indexing: `m["a"]`, assignment `m["c"] = 5` - Introspection: `has(m, key)`, `keys(m)`, `values(m)` - Iterate keys/values using arrays returned by `keys`/`values`. --- ## 11) Concurrency (Threads) - `thread_spawn(fn, args)` starts `fn` in a new thread. `args` may be a single value or an array for multiple arguments. - `thread_join(id)` waits for the thread and returns its result. - `sleep(ms)` suspends current thread. Example: ```fun fun square(n) sleep(100) return n * n ids = [] for x in [1, 2, 3] push(ids, thread_spawn(square, x)) results = [] for id in ids push(results, thread_join(id)) print(results) ``` --- ## 12) System, Files, Environment, and Networking Processes: - Blocking: `exec(cmd) -> string` (stdout), `system(cmd) -> number` (exit code) - Non-blocking: `nexec`, `nspawn`, `nsystem`, with `wait(pid)`, `read(pid)`, `kill(pid)` helpers Environment and CLI: - `env(NAME) -> string` to read env variables (see `os_env.fun`) - `argv() -> array` from ``; also `FUN_ARGC`/`FUN_ARGS` environment interoperability in examples Files: - Basic file I/O helpers exist in the stdlib; see `file_io.fun`, `file_print_for_file_line_by_line.fun` Time: - Date/time and timers (see `datetime_basic.fun`, `datetime_extended.fun`, `datetime_timer.fun`) Random: - `random` helpers (see `random_demo.fun`, `random_number_example.fun`) Regex: - Regex operations via stdlib (see `regex_demo.fun`, `regex_procedural.fun`) Networking: - TCP client helpers: `tcp_connect(host, port) -> fd`, `sock_send(fd, data)`, `sock_recv(fd, nbytes)`, `sock_close(fd)` - Unix domain sockets (see `unix_socket_echo.fun`) Serial: - Serial port helpers (see `serial_demo.fun`) Progress/UI: - Helper functions to render CLI progress (see `progress.fun`, `progress_inline.fun`) Note: function names may live in stdlib modules; import accordingly (system-dependent availability). --- ## 13) Error Handling and Type Safety - No implicit type coercion between numeric types; explicit casts or constructors are required. - Overflow/underflow on fixed-width types is an error. - Accessing undefined variables or re-defining globals is a compile-time error. - Shadowing internal/runtime functions is forbidden. - Exception syntax `try/catch/finally` is standardized in v0.3; throwing and catching at runtime may be partially implemented depending on the feature (see examples like `byte_overflow_try_catch.fun` and notes within). --- ## 14) Examples (from the repository) Hello: ```fun print("Hello, World!") ``` Namespaced includes: ```fun #include as m print(m.add(2, 3)) ``` Classes: ```fun class Counter value = 0 fun inc(this) this.value = this.value + 1 return this.value c = Counter() print(c.inc()) ``` Inheritance: ```fun class Parent(number start) value = 0 fun _construct(this, s) this.value = s class Child(number start) extends Parent bonus = 5 fun _construct(this, s) this.value = this.value + this.bonus ``` Threads: ```fun tid = thread_spawn(add3, [10, 20, 30]) print(thread_join(tid)) // 60 ``` TCP GET: ```fun fd = tcp_connect("example.org", 80) req = "GET / HTTP/1.0\r\nHost: example.org\r\n\r\n" sent = sock_send(fd, req) print(sock_recv(fd, 8192)) sock_close(fd) ``` --- ## 15) Versioning and Compatibility - v0.3 keeps v0.2 syntax intact and adds new features. Where runtime support is evolving (exceptions, some stdlib facets), the syntax is stable and forward-compatible. - Examples are authoritative for idioms and available helpers; consult `examples/` and `lib/` modules. --- ## 16) Appendix: Notation and Conventions - Use backticks for code identifiers in prose (`fun`, `class`, `extends`, etc.). - All code blocks are in `fun` pseudolanguage. - Indentation is always 2 spaces; tabs will cause errors. --- ## Changelog (from v0.2 to v0.3) - Added: `class`, methods with explicit `this`, default and custom constructors via `_construct`. - Added: inheritance with `extends`. - Added: private members by leading underscore naming convention. - Added: dot-call sugar `obj.method(a, b)` ≡ `method(obj, a, b)`. - Added: namespaced includes: `#include as alias`, `#include "path" as alias`. - Added: `map` type with literals `{ key: value }` and helpers. - Added: loop control `break`, `continue`. - Added: threads (`thread_spawn`, `thread_join`), sleep. - Added: socket helpers (TCP/Unix), serial devices, CLI argv, env helpers, timers. - Added: bitwise helper functions: `band`, `bor`, `bxor`, `bnot`, `shl`. - Added: exception syntax `try/catch/finally` (runtime handling is evolving). --- ## How to use this file - Save this content as `./spec/v0.3.md` in the repository. - Keep `examples/` in sync with this spec. When adding a new feature, provide an example and update the spec accordingly.