484 lines
13 KiB
Markdown
484 lines
13 KiB
Markdown
# 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<T>`
|
||
- `map<K, V>` (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<number> nums = [1, 2, 3]
|
||
array mixed = [1, "two", true, [3, 4]]
|
||
|
||
m = { "a": 1, "b": 2 } // map<string, number>
|
||
```
|
||
|
||
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 <utils/math.fun>
|
||
```
|
||
- 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 <utils/math.fun> 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<T>` 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<string>` from `<cli.fun>`; 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 <utils/math.fun> 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 <path> 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.
|