more correct syntax and AI instructions

This commit is contained in:
2026-02-09 11:00:23 -06:00
parent d0c68d7a7d
commit 872cd6ab51
28 changed files with 998 additions and 453 deletions

134
CLAUDE.md
View File

@@ -1,25 +1,123 @@
# Code style
All code is done with 2 spaces for indentation.
# ƿit (pit) Language Project
For cell script and its integration files, objects are preferred over classes, and preferrably limited use of prototypes, make objects sendable between actors (.ce files).
## Building
## cell script format
Cell script files end in .ce or .cm. Cell script is similar to Javascript but with some differences.
Recompile after changes: `make`
Bootstrap from scratch (first time): `make bootstrap`
Run `cell --help` to see all CLI flags.
Variables are delcared with 'var'. Var behaves like let.
Constants are declared with 'def'.
!= and == are strict, there is no !== or ===.
There is no undefined, only null.
There are no classes, only objects and prototypes.
Prefer backticks for string interpolation. Otherwise, convering non strings with the text() function is required.
Everything should be lowercase.
## Code Style
There are no arraybuffers, only blobs, which work with bits. They must be stoned like stone(blob) before being read from.
All code uses 2 spaces for indentation. K&R style for C and Javascript.
## c format
For cell script integration files, everything should be declared static that can be. Most don't have headers at all. Files in a package are not shared between packages.
## ƿit Script Quick Reference
There is no undefined, so JS_IsNull and JS_NULL should be used only.
ƿit script files: `.ce` (actors) and `.cm` (modules). The syntax is similar to JavaScript with important differences listed below.
## how module loading is done in cell script
Within a package, a c file, if using the correct macros (CELL_USE_FUNCS etc), will be loaded as a module with its name; so png.c inside ac package is loaded as <package>/png, giving you access to its functions.
### Key Differences from JavaScript
- `var` (mutable) and `def` (constant) — no `let` or `const`
- `==` and `!=` are strict (no `===` or `!==`)
- No `undefined` — only `null`
- No classes — only objects and prototypes (`meme()`, `proto()`, `isa()`)
- No `for...in`, `for...of`, spread (`...`), rest params, or default params
- No named function declarations — use `var fn = function() {}` or arrow functions
- Variables must be declared at function body level only (not in if/while/for/blocks)
- All variables must be initialized at declaration (`var x` alone is an error; use `var x = null`)
- No `try`/`catch`/`throw` — use `disrupt`/`disruption`
- No arraybuffers — only `blob` (works with bits; must `stone(blob)` before reading)
- Identifiers can contain `?` and `!` (e.g., `nil?`, `set!`, `is?valid`)
- Prefer backticks for string interpolation; otherwise use `text()` to convert non-strings
- Everything should be lowercase
### Intrinsic Functions (always available, no `use()` needed)
The creator functions are **polymorphic** — behavior depends on argument types:
- `array(number)` — create array of size N filled with null
- `array(number, value_or_fn)` — create array with initial values
- `array(array)` — copy array
- `array(array, fn)` — map
- `array(array, array)` — concatenate
- `array(array, from, to)` — slice
- `array(record)` — get keys as array of text
- **`array(text)` — split text into individual characters** (e.g., `array("hello")``["h","e","l","l","o"]`)
- `array(text, separator)` — split by separator
- `array(text, length)` — split into chunks of length
- `text(array, separator)` — join array into text
- `text(number)` or `text(number, radix)` — number to text
- `text(text, from, to)` — substring
- `number(text)` or `number(text, radix)` — parse text to number
- `number(logical)` — boolean to number
- `record(record)` — copy
- `record(record, another)` — merge
- `record(array_of_keys)` — create record from keys
Other key intrinsics: `length()`, `stone()`, `is_stone()`, `print()`, `filter()`, `find()`, `reduce()`, `sort()`, `reverse()`, `some()`, `every()`, `starts_with()`, `ends_with()`, `meme()`, `proto()`, `isa()`, `splat()`, `apply()`, `extract()`, `replace()`, `search()`, `format()`, `lower()`, `upper()`, `trim()`
Sensory functions: `is_array()`, `is_text()`, `is_number()`, `is_object()`, `is_function()`, `is_null()`, `is_logical()`, `is_integer()`, `is_stone()`, etc.
### Standard Library (loaded with `use()`)
- `blob` — binary data (bits, not bytes)
- `time` — time constants and conversions
- `math` — trig, logarithms, roots (`math/radians`, `math/turns`)
- `json` — JSON encoding/decoding
- `random` — random number generation
### Actor Model
- `.ce` files are actors (independent execution units, don't return values)
- `.cm` files are modules (return a value, cached and frozen)
- Actors never share memory; communicate via `$send()` message passing
- Actor intrinsics start with `$`: `$me`, `$stop()`, `$send()`, `$start()`, `$delay()`, `$receiver()`, `$clock()`, `$portal()`, `$contact()`, `$couple()`, `$unneeded()`, `$connection()`, `$time_limit()`
### Requestors (async composition)
`sequence()`, `parallel()`, `race()`, `fallback()` — compose asynchronous operations. See docs/requestors.md.
### Error Handling
```javascript
var fn = function() {
disrupt // bare keyword, no value
} disruption {
// handle error; can re-raise with disrupt
}
```
### Push/Pop Syntax
```javascript
var a = [1, 2]
a[] = 3 // push: [1, 2, 3]
var v = a[] // pop: v is 3, a is [1, 2]
```
## C Integration
- Declare everything `static` that can be
- Most files don't have headers; files in a package are not shared between packages
- No undefined in C API: use `JS_IsNull` and `JS_NULL` only
- A C file with correct macros (`CELL_USE_FUNCS` etc) is loaded as a module by its name (e.g., `png.c` in a package → `use('<package>/png')`)
## Project Layout
- `source/` — C source for the cell runtime and CLI
- `docs/` — master documentation (Markdown), reflected on the website
- `website/` — Hugo site; theme at `website/themes/knr/`
- `internal/` — internal ƿit scripts (engine.cm etc.)
- `packages/` — core packages
- `Makefile` — build system (`make` to rebuild, `make bootstrap` for first build)
## Documentation
The `docs/` folder is the single source of truth. The website at `website/` mounts it via Hugo. Key files:
- `docs/language.md` — language syntax reference
- `docs/functions.md` — all built-in intrinsic functions
- `docs/actors.md` — actor model and actor intrinsics
- `docs/requestors.md` — async requestor pattern
- `docs/library/*.md` — intrinsic type reference (text, number, array, object) and standard library modules

View File

@@ -20,7 +20,7 @@ type: "docs"
```javascript
// hello.ce - A simple actor
log.console("Hello, ƿit!")
print("Hello, ƿit!")
$stop()
```
@@ -30,28 +30,34 @@ pit hello
## Language
- [**ƿit Language**](/docs/language/) — syntax, types, and built-in functions
- [**ƿit Language**](/docs/language/) — syntax, types, and operators
- [**Actors and Modules**](/docs/actors/) — the execution model
- [**Requestors**](/docs/requestors/) — asynchronous composition
- [**Packages**](/docs/packages/) — code organization and sharing
- [**Command Line**](/docs/cli/) — the `pit` tool
- [**Writing C Modules**](/docs/c-modules/) — native extensions
## Reference
- [**Built-in Functions**](/docs/functions/) — intrinsics reference
- [text](/docs/library/text/) — text conversion and manipulation
- [number](/docs/library/number/) — numeric conversion and operations
- [array](/docs/library/array/) — array creation and manipulation
- [object](/docs/library/object/) — object creation, prototypes, and serialization
## Standard Library
- [text](/docs/library/text/) — string manipulation
- [number](/docs/library/number/) — numeric operations (functions are global: `floor()`, `max()`, etc.)
- [array](/docs/library/array/) — array utilities
- [object](/docs/library/object/) — object utilities
Modules loaded with `use()`:
- [blob](/docs/library/blob/) — binary data
- [time](/docs/library/time/) — time and dates
- [math](/docs/library/math/) — trigonometry and math
- [json](/docs/library/json/) — JSON encoding/decoding
- [random](/docs/library/random/) — random numbers
## Tools
- [**Command Line**](/docs/cli/) — the `pit` tool
- [**Writing C Modules**](/docs/c-modules/) — native extensions
## Architecture
ƿit programs are organized into **packages**. Each package contains:
@@ -72,3 +78,13 @@ make bootstrap
```
The ƿit shop is stored at `~/.pit/`.
## Development
After making changes, recompile with:
```bash
make
```
Run `cell --help` to see all available CLI flags.

View File

@@ -26,13 +26,13 @@ A module is a script that **returns a value**. The returned value is cached and
// math_utils.cm
var math = use('math/radians')
function distance(x1, y1, x2, y2) {
var distance = function(x1, y1, x2, y2) {
var dx = x2 - x1
var dy = y2 - y1
return math.sqrt(dx * dx + dy * dy)
}
function midpoint(x1, y1, x2, y2) {
var midpoint = function(x1, y1, x2, y2) {
return {
x: (x1 + x2) / 2,
y: (y1 + y2) / 2
@@ -65,10 +65,10 @@ An actor is a script that **does not return a value**. It runs as an independent
```javascript
// worker.ce
log.console("Worker started")
print("Worker started")
$receiver(function(msg, reply) {
log.console("Received:", msg)
print("Received:", msg)
// Process message...
})
```
@@ -88,7 +88,7 @@ Actors have access to special functions prefixed with `$`:
Reference to the current actor.
```javascript
log.console($me) // actor reference
print($me) // actor reference
```
### $stop()
@@ -105,7 +105,7 @@ Send a message to another actor.
```javascript
$send(other_actor, {type: "ping", data: 42}, function(reply) {
log.console("Got reply:", reply)
print("Got reply:", reply)
})
```
@@ -117,7 +117,7 @@ Start a new actor from a script.
```javascript
$start(function(new_actor) {
log.console("Started:", new_actor)
print("Started:", new_actor)
}, "worker")
```
@@ -127,7 +127,7 @@ Schedule a callback after a delay.
```javascript
$delay(function() {
log.console("5 seconds later")
print("5 seconds later")
}, 5)
```
@@ -174,12 +174,40 @@ $contact(function(connection) {
### $time_limit(requestor, seconds)
Wrap a requestor with a timeout.
Wrap a requestor with a timeout. See [Requestors](/docs/requestors/) for details.
```javascript
$time_limit(my_requestor, 10) // 10 second timeout
```
### $couple(actor)
Couple the current actor to another actor. When the coupled actor dies, the current actor also dies. Coupling is automatic between an actor and its overling (parent).
```javascript
$couple(other_actor)
```
### $unneeded(callback, seconds)
Schedule the actor for removal after a specified time.
```javascript
$unneeded(function() {
// cleanup before removal
}, 30)
```
### $connection(callback, actor, config)
Get information about the connection to another actor, such as latency, bandwidth, and activity.
```javascript
$connection(function(info) {
print(info.latency)
}, other_actor, {})
```
## Module Resolution
When you call `use('name')`, ƿit searches:
@@ -204,14 +232,14 @@ Files starting with underscore (`_helper.cm`) are private to the package.
// main.ce - Entry point
var config = use('config')
log.console("Starting application...")
print("Starting application...")
$start(function(worker) {
$send(worker, {task: "process", data: [1, 2, 3]})
}, "worker")
$delay(function() {
log.console("Shutting down")
print("Shutting down")
$stop()
}, 10)
```

View File

@@ -229,7 +229,7 @@ A common pattern is to have a C file provide low-level functions and a `.cm` fil
// vector.cm
var native = this // C module passed as 'this'
function Vector(x, y) {
var Vector = function(x, y) {
return {x: x, y: y}
}

View File

@@ -33,13 +33,17 @@ An approximation of circumference / diameter: 3.1415926535897932.
## Creator Functions
The creator functions make new objects. Some can take various types. All return null if their inputs are not suitable.
The creator functions are **polymorphic** — they examine the types of their arguments to decide what to do. The first argument's type selects the behavior. All return null if their inputs are not suitable.
### array
`array(number)` — Make an array. All elements are initialized to null.
The `array` function creates arrays from various inputs. Its behavior depends on the type of the first argument:
`array(number, initial_value)` — Make an array. All elements are initialized to initial_value. If initial_value is a function, it is called for each element. If the function has arity >= 1, it is passed the element number.
**From a number** — create an array of that size:
`array(number)` — All elements are initialized to null.
`array(number, initial_value)` — All elements are initialized to initial_value. If initial_value is a function, it is called for each element. If the function has arity >= 1, it is passed the element number.
```javascript
array(3) // [null, null, null]
@@ -47,6 +51,8 @@ array(3, 0) // [0, 0, 0]
array(5, i => i * 2) // [0, 2, 4, 6, 8]
```
**From an array** — copy, map, concat, or slice:
`array(array)` — Copy. Make a mutable copy of the array.
`array(array, function, reverse, exit)` — Map. Call the function with each element, collecting return values in a new array. The function is passed each element and its element number.
@@ -72,15 +78,28 @@ array([1, 2, 3, 4, 5], 1, 4) // [2, 3, 4]
array([1, 2, 3], -2) // [2, 3]
```
**From a record** — get keys:
`array(record)` — Keys. Make an array containing all text keys in the record.
`array(text)` — Split text into grapheme clusters.
```javascript
array({a: 1, b: 2}) // ["a", "b"]
```
**From text** — split into characters or substrings:
`array(text)` — Split text into an array of individual characters (grapheme clusters). This is the standard way to iterate over characters.
```javascript
array("hello") // ["h", "e", "l", "l", "o"]
array("ƿit") // ["ƿ", "i", "t"]
```
`array(text, separator)` — Split text into an array of subtexts.
`array(text, separator)` — Split text by a separator string into an array of subtexts.
```javascript
array("a,b,c", ",") // ["a", "b", "c"]
```
`array(text, length)` — Dice text into an array of subtexts of a given length.
@@ -100,6 +119,8 @@ All other values return null.
### number
The `number` function converts values to numbers. Its behavior depends on the type of the first argument:
`number(logical)` — Returns 1 or 0.
`number(number)` — Returns the number.
@@ -131,8 +152,19 @@ number("666", "h") // 1638
### text
The `text` function converts values to text. Its behavior depends on the type of the first argument:
**From an array** — join elements into text:
`text(array, separator)` — Convert array to text. Elements are concatenated with the separator (default: empty text).
```javascript
text(["h", "e", "l", "l", "o"]) // "hello"
text(["a", "b", "c"], ", ") // "a, b, c"
```
**From a number** — format as text:
`text(number, radix)` — Convert number to text. Radix is 2 thru 37 (default: 10).
`text(number, format)` — Format a number as text:
@@ -173,6 +205,8 @@ text(data, "h") // "75BCD15"
text(12, "4b8") // "0000_1100"
```
**From text** — extract a substring:
`text(text, from, to)` — Extract a substring. If from/to are negative, add length(text).
```javascript
@@ -184,12 +218,18 @@ text(my_text, -3) // "nic"
### record
The `record` function creates and manipulates records (objects). Its behavior depends on the type of the first argument:
**From a record** — copy, merge, or select:
`record(record)` — Copy. Make a mutable copy.
`record(record, another_record)` — Combine. Copy a record, then put all fields of another into the copy.
`record(record, array_of_keys)` — Select. New record with only the named fields.
**From an array of keys** — create a new record:
`record(array_of_keys)` — Set. New record using array as keys, each value is true.
`record(array_of_keys, value)` — Value Set. Each field value is value.
@@ -242,13 +282,31 @@ If text, returns the first character. If a non-negative 32-bit integer, returns
Returns the codepoint number of the first character.
### ends_with(text, suffix)
Returns `true` if the text ends with the given suffix.
```javascript
ends_with("hello.ce", ".ce") // true
ends_with("hello.cm", ".ce") // false
```
### every(array, function)
Returns `true` if every element satisfies the predicate.
```javascript
every([2, 4, 6], x => x % 2 == 0) // true
every([2, 3, 6], x => x % 2 == 0) // false
```
### extract(text, pattern, from, to)
Match text to pattern. Returns a record of saved fields, or null if no match.
### fallback(requestor_array)
Returns a requestor that tries each requestor in order until one succeeds. Returns a cancel function.
Returns a requestor that tries each requestor in order until one succeeds. Returns a cancel function. See [Requestors](/docs/requestors/) for usage.
### filter(array, function)
@@ -335,11 +393,21 @@ Returns the opposite logical. Returns null for non-logicals.
### parallel(requestor_array, throttle, need)
Returns a requestor that starts all requestors in the array. Results are collected into an array matching the input order. Optional throttle limits concurrent requestors. Optional need specifies the minimum number of successes required.
Returns a requestor that starts all requestors in the array. Results are collected into an array matching the input order. Optional throttle limits concurrent requestors. Optional need specifies the minimum number of successes required. See [Requestors](/docs/requestors/) for usage.
### print(value)
Print a value to standard output.
```javascript
print("hello")
print(42)
print(`result: ${x}`)
```
### race(requestor_array, throttle, need)
Like parallel, but returns as soon as the needed number of results are obtained. Default need is 1. Unfinished requestors are cancelled.
Like parallel, but returns as soon as the needed number of results are obtained. Default need is 1. Unfinished requestors are cancelled. See [Requestors](/docs/requestors/) for usage.
### reduce(array, function, initial, reverse)
@@ -376,12 +444,21 @@ Search text for target. Returns character position or null.
### sequence(requestor_array)
Returns a requestor that processes each requestor in order. Each result becomes the input to the next. The last result is the final result.
Returns a requestor that processes each requestor in order. Each result becomes the input to the next. The last result is the final result. See [Requestors](/docs/requestors/) for usage.
### sign(number)
Returns -1, 0, or 1.
### some(array, function)
Returns `true` if any element satisfies the predicate. Stops at the first match.
```javascript
some([1, 2, 3], x => x > 2) // true
some([1, 2, 3], x => x > 5) // false
```
### sort(array, select)
Returns a new sorted array. Sort keys must be all numbers or all texts. Sort is ascending and stable.
@@ -401,6 +478,15 @@ sort([{n: 3}, {n: 1}], "n")
// [{n: 1}, {n: 3}]
```
### starts_with(text, prefix)
Returns `true` if the text starts with the given prefix.
```javascript
starts_with("hello world", "hello") // true
starts_with("hello world", "world") // false
```
### stone(value)
Petrify the value, making it permanently immutable. The operation is deep — all nested objects and arrays are also frozen. Returns the value.

View File

@@ -11,14 +11,21 @@ type: "docs"
### Variables and Constants
Variables are declared with `var`, constants with `def`. All declarations must be initialized and must appear at the function body level — not inside `if`, `while`, `for`, or bare `{}` blocks.
```javascript
var x = 10 // mutable variable (block-scoped like let)
def PI = 3.14159 // constant (cannot be reassigned)
var x = 10
var name = "pit"
var empty = null
def PI = 3.14159 // constant, cannot be reassigned
var a = 1, b = 2, c = 3 // multiple declarations
```
### Data Types
ƿit has six fundamental types:
ƿit has eight fundamental types:
- **number** — DEC64 decimal floating point (no rounding errors)
- **text** — Unicode strings
@@ -35,12 +42,14 @@ def PI = 3.14159 // constant (cannot be reassigned)
// Numbers
42
3.14
1_000_000 // underscores for readability
-5
0
1e3 // scientific notation (1000)
// Text
"hello"
'world'
`template ${x}` // string interpolation
`template ${x}` // string interpolation
`${1 + 2}` // expression interpolation
// Logical
true
@@ -51,113 +60,196 @@ null
// Arrays
[1, 2, 3]
["a", "b", "c"]
[]
// Objects
{name: "pit", version: 1}
{x: 10, y: 20}
{a: 1, b: "two"}
{}
// Regex
/\d+/
/hello/i // with flags
```
### Operators
## Operators
### Arithmetic
```javascript
// Arithmetic
+ - * / %
** // exponentiation
// Comparison (always strict)
== // equals (like === in JS)
!= // not equals (like !== in JS)
< > <= >=
// Logical
&& || !
// Assignment
= += -= *= /=
2 + 3 // 5
5 - 3 // 2
3 * 4 // 12
12 / 4 // 3
10 % 3 // 1
2 ** 3 // 8 (exponentiation)
```
### Control Flow
### Comparison
All comparisons are strict — there is no type coercion.
```javascript
// Conditionals
if (x > 0) {
log.console("positive")
} else if (x < 0) {
log.console("negative")
} else {
log.console("zero")
}
// Ternary
var sign = x > 0 ? 1 : -1
// Loops
for (var i = 0; i < 10; i++) {
log.console(i)
}
for (var item of items) {
log.console(item)
}
for (var key in obj) {
log.console(key, obj[key])
}
while (condition) {
// body
}
// Control
break
continue
return value
disrupt
5 == 5 // true
5 != 6 // true
3 < 5 // true
5 > 3 // true
3 <= 3 // true
5 >= 5 // true
```
### Functions
### Logical
```javascript
// Named function
function add(a, b) {
return a + b
}
// Anonymous function
var multiply = function(a, b) {
return a * b
}
// Arrow function
var square = x => x * x
var sum = (a, b) => a + b
// Rest parameters
function log_all(...args) {
for (var arg of args) log.console(arg)
}
// Default parameters
function greet(name, greeting = "Hello") {
return `${greeting}, ${name}!`
}
true && true // true
true && false // false
false || true // true
false || false // false
!true // false
!false // true
```
All closures capture `this` (like arrow functions in JavaScript).
Logical operators short-circuit:
```javascript
var called = false
var fn = function() { called = true; return true }
var r = false && fn() // fn() not called
r = true || fn() // fn() not called
```
### Bitwise
```javascript
5 & 3 // 1 (AND)
5 | 3 // 7 (OR)
5 ^ 3 // 6 (XOR)
~0 // -1 (NOT)
1 << 3 // 8 (left shift)
8 >> 3 // 1 (right shift)
-1 >>> 1 // 2147483647 (unsigned right shift)
```
### Unary
```javascript
+5 // 5
-5 // -5
-(-5) // 5
```
### Increment and Decrement
```javascript
var x = 5
x++ // returns 5, x becomes 6 (postfix)
++x // returns 7, x becomes 7 (prefix)
x-- // returns 7, x becomes 6 (postfix)
--x // returns 5, x becomes 5 (prefix)
```
### Compound Assignment
```javascript
var x = 10
x += 3 // 13
x -= 3 // 10
x *= 2 // 20
x /= 4 // 5
x %= 3 // 2
```
### Ternary
```javascript
var a = true ? 1 : 2 // 1
var b = false ? 1 : 2 // 2
var c = true ? (false ? 1 : 2) : 3 // 2 (nested)
```
### Comma
The comma operator evaluates all expressions and returns the last.
```javascript
var x = (1, 2, 3) // 3
```
### In
Test whether a key exists in an object.
```javascript
var o = {a: 1}
"a" in o // true
"b" in o // false
```
### Delete
Remove a key from an object.
```javascript
var o = {a: 1, b: 2}
delete o.a
"a" in o // false
o.b // 2
```
## Property Access
### Dot and Bracket
```javascript
var o = {x: 10}
o.x // 10 (dot read)
o.x = 20 // dot write
o["x"] // 20 (bracket read)
var key = "x"
o[key] // 20 (computed bracket)
o["y"] = 30 // bracket write
```
### Object as Key
Objects can be used as keys in other objects.
```javascript
var k = {}
var o = {}
o[k] = 42
o[k] // 42
o[{}] // null (different object)
k in o // true
delete o[k]
k in o // false
```
### Chained Access
```javascript
var d = {a: {b: [1, {c: 99}]}}
d.a.b[1].c // 99
```
## Arrays
Arrays are **distinct from objects**. They are ordered, numerically-indexed sequences. You cannot add arbitrary string keys to an array.
Arrays are **distinct from objects**. They are ordered, numerically-indexed sequences.
```javascript
var arr = [1, 2, 3]
arr[0] // 1
arr[2] = 10 // [1, 2, 10]
length(arr) // 3
```
// Array spread
var more = [...arr, 4, 5] // [1, 2, 10, 4, 5]
### Push and Pop
```javascript
var a = [1, 2]
a[] = 3 // push: [1, 2, 3]
length(a) // 3
var v = a[] // pop: v is 3, a is [1, 2]
length(a) // 2
```
## Objects
@@ -168,26 +260,271 @@ Objects are key-value records with prototype-based inheritance.
var point = {x: 10, y: 20}
point.x // 10
point["y"] // 20
// Object spread
var point3d = {...point, z: 30}
// Prototype inheritance
var colored_point = {__proto__: point, color: "red"}
colored_point.x // 10 (inherited)
```
### Prototypes
```javascript
// Create object with prototype
var parent = {x: 10}
var child = meme(parent)
child.x // 10 (inherited)
proto(child) // parent
// Get prototype
var p = proto(child)
// Override does not mutate parent
child.x = 20
parent.x // 10
```
// Check prototype chain
isa(child, parent) // true
### Mixins
```javascript
var p = {a: 1}
var m1 = {b: 2}
var m2 = {c: 3}
var child = meme(p, [m1, m2])
child.a // 1 (from prototype)
child.b // 2 (from mixin)
child.c // 3 (from mixin)
```
## Control Flow
### If / Else
```javascript
var x = 0
if (true) x = 1
if (false) x = 2 else x = 3
if (false) x = 4
else if (true) x = 5
else x = 6
```
### While
```javascript
var i = 0
while (i < 5) i++
// break
i = 0
while (true) {
if (i >= 3) break
i++
}
// continue
var sum = 0
i = 0
while (i < 5) {
i++
if (i % 2 == 0) continue
sum += i
}
```
### For
Variables cannot be declared in the for initializer. Declare them at the function body level.
```javascript
var sum = 0
var i = 0
for (i = 0; i < 5; i++) sum += i
// break
sum = 0
i = 0
for (i = 0; i < 10; i++) {
if (i == 5) break
sum += i
}
// continue
sum = 0
i = 0
for (i = 0; i < 5; i++) {
if (i % 2 == 0) continue
sum += i
}
// nested
sum = 0
var j = 0
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
sum++
}
}
```
## Functions
### Function Expressions
```javascript
var add = function(a, b) { return a + b }
add(2, 3) // 5
```
### Arrow Functions
```javascript
var double = x => x * 2
double(5) // 10
var sum = (a, b) => a + b
sum(2, 3) // 5
var block = x => {
var y = x * 2
return y + 1
}
block(5) // 11
```
### Return
A function with no `return` returns `null`. An early `return` exits immediately.
```javascript
var fn = function() { var x = 1 }
fn() // null
var fn2 = function() { return 1; return 2 }
fn2() // 1
```
### Arguments
Extra arguments are ignored. Missing arguments are `null`.
```javascript
var fn = function(a, b) { return a + b }
fn(1, 2, 3) // 3 (extra arg ignored)
var fn2 = function(a, b) { return a }
fn2(1) // 1 (b is null)
```
### Immediately Invoked Function Expression
```javascript
var r = (function(x) { return x * 2 })(21) // 42
```
### Closures
Functions capture variables from their enclosing scope.
```javascript
var make = function(x) {
return function(y) { return x + y }
}
var add5 = make(5)
add5(3) // 8
```
Captured variables can be mutated:
```javascript
var counter = function() {
var n = 0
return function() { n = n + 1; return n }
}
var c = counter()
c() // 1
c() // 2
```
### Recursion
```javascript
var fact = function(n) {
if (n <= 1) return 1
return n * fact(n - 1)
}
fact(5) // 120
```
### This Binding
When a function is called as a method, `this` refers to the object.
```javascript
var obj = {
val: 10,
get: function() { return this.val }
}
obj.get() // 10
```
### Currying
```javascript
var f = function(a) {
return function(b) {
return function(c) { return a + b + c }
}
}
f(1)(2)(3) // 6
```
## Identifiers
Identifiers can contain `?` and `!` characters, both as suffixes and mid-name.
```javascript
var nil? = (x) => x == null
nil?(null) // true
nil?(42) // false
var set! = (x) => x + 1
set!(5) // 6
var is?valid = (x) => x > 0
is?valid(3) // true
var do!stuff = () => 42
do!stuff() // 42
```
The `?` in an identifier is not confused with the ternary operator:
```javascript
var nil? = (x) => x == null
var a = nil?(null) ? "yes" : "no" // "yes"
```
## Type Checking
### Type Functions
```javascript
is_number(42) // true
is_text("hi") // true
is_logical(true) // true
is_object({}) // true
is_array([]) // true
is_function(function(){}) // true
is_null(null) // true
is_object([]) // false (array is not object)
is_array({}) // false (object is not array)
```
### Truthiness
Falsy values: `false`, `0`, `""`, `null`. Everything else is truthy.
```javascript
if (0) ... // not entered
if ("") ... // not entered
if (null) ... // not entered
if (1) ... // entered
if ("hi") ... // entered
if ({}) ... // entered
if ([]) ... // entered
```
## Immutability with Stone
@@ -195,87 +532,50 @@ isa(child, parent) // true
The `stone()` function makes values permanently immutable.
```javascript
var config = stone({
debug: true,
maxRetries: 3
})
config.debug = false // Error! Stone objects cannot be modified
var o = {x: 1}
is_stone(o) // false
stone(o)
is_stone(o) // true
o.x = 2 // disrupts!
```
Stone is **deep** — all nested objects and arrays are also frozen. This cannot be reversed.
## Function Proxy
A function with two parameters (`name`, `args`) acts as a proxy when properties are accessed on it. Any method call on the function dispatches through the proxy.
```javascript
stone.p(value) // returns true if value is stone
var proxy = function(name, args) {
return `${name}:${length(args)}`
}
proxy.hello() // "hello:0"
proxy.add(1, 2) // "add:2"
proxy["method"]() // "method:0"
var m = "dynamic"
proxy[m]() // "dynamic:0"
```
## Built-in Functions
### length(value)
Returns the length of arrays (elements), text (codepoints), blobs (bits), or functions (arity).
For non-proxy functions, property access disrupts:
```javascript
length([1, 2, 3]) // 3
length("hello") // 5
length(function(a,b){}) // 2
var fn = function() { return 1 }
fn.foo // disrupts
fn.foo = 1 // disrupts
```
### use(path)
## Regex
Import a module. Returns the cached, stone value.
Regex literals are written with forward slashes, with optional flags.
```javascript
var math = use('math/radians')
var json = use('json')
```
var r = /\d+/
var result = extract("abc123", r)
result[0] // "123"
### isa(value, type)
Check type or prototype chain.
```javascript
is_number(42) // true
is_text("hi") // true
is_array([1,2]) // true
is_object({}) // true
isa(child, parent) // true if parent is in prototype chain
```
### reverse(array)
Returns a new array with elements in reverse order.
```javascript
reverse([1, 2, 3]) // [3, 2, 1]
```
### logical(value)
Convert to boolean.
```javascript
logical(0) // false
logical(1) // true
logical("true") // true
logical("false") // false
logical(null) // false
```
## Logging
```javascript
log.console("message") // standard output
log.error("problem") // error output
```
## Pattern Matching
ƿit supports regex patterns in string functions, but not standalone regex objects.
```javascript
text.search("hello world", /world/)
replace("hello", /l/g, "L")
var ri = /hello/i
var result2 = extract("Hello", ri)
result2[0] // "Hello"
```
## Error Handling
@@ -287,13 +587,27 @@ var safe_divide = function(a, b) {
if (b == 0) disrupt
return a / b
} disruption {
log.error("something went wrong")
print("something went wrong")
}
```
`disrupt` is a bare keyword — it does not carry a value. The `disruption` block knows that something went wrong, but not what.
To test whether an operation disrupts:
### Re-raising
A `disruption` block can re-raise by calling `disrupt` again:
```javascript
var outer = function() {
var inner = function() { disrupt } disruption { disrupt }
inner()
} disruption {
// caught here after re-raise
}
outer()
```
### Testing for Disruption
```javascript
var should_disrupt = function(fn) {
@@ -309,3 +623,27 @@ var should_disrupt = function(fn) {
```
If an actor has an unhandled disruption, it crashes.
## Self-Referencing Structures
Objects can reference themselves:
```javascript
var o = {name: "root"}
o.self = o
o.self.self.name // "root"
```
## Variable Shadowing
Inner functions can shadow outer variables:
```javascript
var x = 10
var fn = function() {
var x = 20
return x
}
fn() // 20
x // 10
```

View File

@@ -5,18 +5,14 @@ weight: 90
type: "docs"
---
ƿit includes a standard library of modules loaded with `use()`.
The standard library provides modules loaded with `use()`.
| Module | Description |
|--------|-------------|
| [text](/docs/library/text/) | String conversion and manipulation |
| [number](/docs/library/number/) | Numeric conversion and operations |
| [array](/docs/library/array/) | Array creation and manipulation |
| [object](/docs/library/object/) | Object creation and manipulation |
| [blob](/docs/library/blob/) | Binary data (bits, not bytes) |
| [time](/docs/library/time/) | Time constants and conversions |
| [math](/docs/library/math/) | Trigonometry, logarithms, roots |
| [json](/docs/library/json/) | JSON encoding and decoding |
| [random](/docs/library/random/) | Random number generation |
Most numeric functions (`floor`, `max`, `abs`, etc.) are global intrinsics and do not require `use`. See [Built-in Functions](/docs/functions/) for the full list.
The `text`, `number`, `array`, and `object` functions are intrinsics — they are always available without `use`. See [Built-in Functions](/docs/functions/) for the full list, and the individual reference pages for [text](/docs/library/text/), [number](/docs/library/number/), [array](/docs/library/array/), and [object](/docs/library/object/).

View File

@@ -5,13 +5,15 @@ weight: 30
type: "docs"
---
The `array` function and its methods handle array creation and manipulation.
The `array` function is an intrinsic (always available, no `use()` needed). It is **polymorphic** — its behavior depends on the type of the first argument.
## Creation
## From a Number
Create an array of a given size.
### array(number)
Create an array of specified size, filled with `null`.
All elements initialized to `null`.
```javascript
array(3) // [null, null, null]
@@ -19,24 +21,36 @@ array(3) // [null, null, null]
### array(number, initial)
Create an array with initial values.
All elements initialized to a value. If initial is a function, it is called for each element (passed the index if arity >= 1).
```javascript
array(3, 0) // [0, 0, 0]
array(3, i => i * 2) // [0, 2, 4]
```
## From an Array
Copy, map, concat, or slice.
### array(array)
Copy an array.
Copy an array (mutable).
```javascript
var copy = array(original)
```
### array(array, function)
Map — call function with each element, collect results.
```javascript
array([1, 2, 3], x => x * 2) // [2, 4, 6]
```
### array(array, from, to)
Slice an array.
Slice — extract a sub-array. Negative indices count from end.
```javascript
array([1, 2, 3, 4, 5], 1, 4) // [2, 3, 4]
@@ -45,31 +59,36 @@ array([1, 2, 3], -2) // [2, 3]
### array(array, another)
Concatenate arrays.
Concatenate two arrays.
```javascript
array([1, 2], [3, 4]) // [1, 2, 3, 4]
```
### array(object)
## From a Record
Get keys of an object.
### array(record)
Get the keys of a record as an array of text.
```javascript
array({a: 1, b: 2}) // ["a", "b"]
```
## From Text
### array(text)
Split text into grapheme clusters.
Split text into individual characters (grapheme clusters). This is the standard way to iterate over characters in a string.
```javascript
array("hello") // ["h", "e", "l", "l", "o"]
array("ƿit") // ["ƿ", "i", "t"]
```
### array(text, separator)
Split text by separator.
Split text by a separator string.
```javascript
array("a,b,c", ",") // ["a", "b", "c"]
@@ -77,7 +96,7 @@ array("a,b,c", ",") // ["a", "b", "c"]
### array(text, length)
Split text into chunks.
Dice text into chunks of a given length.
```javascript
array("abcdef", 2) // ["ab", "cd", "ef"]
@@ -91,13 +110,13 @@ Iterate over elements.
```javascript
array.for([1, 2, 3], function(el, i) {
log.console(i, el)
print(i, el)
})
// With early exit
array.for([1, 2, 3, 4], function(el) {
if (el > 2) return true
log.console(el)
print(el)
}, false, true) // prints 1, 2
```

View File

@@ -91,5 +91,5 @@ var config_text = json.encode(config, 2)
// Load configuration
var loaded = json.decode(config_text)
log.console(loaded.debug) // true
print(loaded.debug) // true
```

View File

@@ -135,21 +135,21 @@ math.e() // 2.71828...
var math = use('math/radians')
// Distance between two points
function distance(x1, y1, x2, y2) {
var distance = function(x1, y1, x2, y2) {
var dx = x2 - x1
var dy = y2 - y1
return math.sqrt(dx * dx + dy * dy)
}
// Angle between two points
function angle(x1, y1, x2, y2) {
var angle = function(x1, y1, x2, y2) {
return math.arc_tangent(y2 - y1, x2 - x1)
}
// Rotate a point
function rotate(x, y, angle) {
var c = math.cosine(angle)
var s = math.sine(angle)
var rotate = function(x, y, a) {
var c = math.cosine(a)
var s = math.sine(a)
return {
x: x * c - y * s,
y: x * s + y * c

View File

@@ -5,7 +5,7 @@ weight: 20
type: "docs"
---
The `number` function and its methods handle numeric conversion and operations.
The `number` function is an intrinsic (always available, no `use()` needed). It is **polymorphic** — its behavior depends on the type of the first argument.
## Conversion
@@ -123,20 +123,20 @@ Get the fractional part.
fraction(4.75) // 0.75
```
### min(...values)
### min(a, b)
Return the smallest value.
Return the smaller of two numbers.
```javascript
min(3, 1, 4, 1, 5) // 1
min(3, 5) // 3
```
### max(...values)
### max(a, b)
Return the largest value.
Return the larger of two numbers.
```javascript
max(3, 1, 4, 1, 5) // 5
max(3, 5) // 5
```
### remainder(dividend, divisor)

View File

@@ -5,9 +5,9 @@ weight: 40
type: "docs"
---
The `object` function and related utilities handle object creation and manipulation.
The `object` function is an intrinsic (always available, no `use()` needed). It is **polymorphic** — its behavior depends on the types of its arguments.
## Creation
## From a Record
### object(obj)
@@ -34,6 +34,8 @@ Select specific keys.
object({a: 1, b: 2, c: 3}, ["a", "c"]) // {a: 1, c: 3}
```
## From an Array of Keys
### object(keys)
Create object from keys (values are `true`).
@@ -65,9 +67,9 @@ object(["a", "b", "c"], (k, i) => i) // {a: 0, b: 1, c: 2}
Create a new object with the given prototype.
```javascript
var animal = {speak: function() { log.console("...") }}
var animal = {speak: function() { print("...") }}
var dog = meme(animal)
dog.speak = function() { log.console("woof") }
dog.speak = function() { print("woof") }
```
### proto(obj)
@@ -109,9 +111,4 @@ var obj = {a: 1, b: 2, c: 3}
// Get all keys
var keys = array(obj) // ["a", "b", "c"]
// Iterate
for (var key in obj) {
log.console(key, obj[key])
}
```

View File

@@ -48,7 +48,7 @@ var random = use('random')
var coin_flip = random.random() < 0.5
// Random element from array
function pick(arr) {
var pick = function(arr) {
return arr[random.random_whole(length(arr))]
}
@@ -56,11 +56,14 @@ var colors = ["red", "green", "blue"]
var color = pick(colors)
// Shuffle array
function shuffle(arr) {
var shuffle = function(arr) {
var result = array(arr) // copy
for (var i = length(result) - 1; i > 0; i--) {
var j = random.random_whole(i + 1)
var temp = result[i]
var i = length(result) - 1
var j = 0
var temp = null
for (i = length(result) - 1; i > 0; i--) {
j = random.random_whole(i + 1)
temp = result[i]
result[i] = result[j]
result[j] = temp
}
@@ -68,8 +71,8 @@ function shuffle(arr) {
}
// Random in range
function random_range(min, max) {
return min + random.random() * (max - min)
var random_range = function(lo, hi) {
return lo + random.random() * (hi - lo)
}
var x = random_range(-10, 10) // -10 to 10

View File

@@ -5,20 +5,24 @@ weight: 10
type: "docs"
---
The `text` function and its methods handle string conversion and manipulation.
The `text` function is an intrinsic (always available, no `use()` needed). It is **polymorphic** — its behavior depends on the type of the first argument.
## Conversion
To split text into characters, use `array(text)` — see [array](/docs/library/array/).
## From an Array
### text(array, separator)
Convert an array to text, joining elements with a separator (default: space).
Join array elements into text with a separator (default: empty string).
```javascript
text([1, 2, 3]) // "1 2 3"
text([1, 2, 3], ", ") // "1, 2, 3"
text(["a", "b"], "-") // "a-b"
text(["h", "e", "l", "l", "o"]) // "hello"
text([1, 2, 3], ", ") // "1, 2, 3"
text(["a", "b"], "-") // "a-b"
```
## From a Number
### text(number, radix)
Convert a number to text. Radix is 2-36 (default: 10).
@@ -29,13 +33,16 @@ text(255, 16) // "ff"
text(255, 2) // "11111111"
```
## From Text
### text(text, from, to)
Extract a substring from index `from` to `to`.
Extract a substring from index `from` to `to`. Negative indices count from end.
```javascript
text("hello world", 0, 5) // "hello"
text("hello world", 6) // "world"
text("hello", -3) // "llo"
```
## Methods

View File

@@ -101,7 +101,7 @@ var last_week = now - time.week
var later = now + (2 * time.hour)
// Format future time
log.console(time.text(tomorrow))
print(time.text(tomorrow))
```
## Example
@@ -113,9 +113,9 @@ var time = use('time')
var start = time.number()
// ... do work ...
var elapsed = time.number() - start
log.console(`Took ${elapsed} seconds`)
print(`Took ${elapsed} seconds`)
// Schedule for tomorrow
var tomorrow = time.number() + time.day
log.console(`Tomorrow: ${time.text(tomorrow, "yyyy-MM-dd")}`)
print(`Tomorrow: ${time.text(tomorrow, "yyyy-MM-dd")}`)
```

View File

@@ -12,7 +12,7 @@ Requestors are functions that encapsulate asynchronous work. They provide a stru
A requestor is a function with this signature:
```javascript
function my_requestor(callback, value) {
var my_requestor = function(callback, value) {
// Do async work, then call callback with result
// Return a cancel function
}
@@ -29,13 +29,13 @@ The cancel function, when called, should abort the in-progress work.
## Writing a Requestor
```javascript
function fetch_data(callback, url) {
var fetch_data = function(callback, url) {
$contact(function(connection) {
$send(connection, {get: url}, function(response) {
callback(response)
})
}, {host: url, port: 80})
return function cancel() {
return function() {
// clean up if needed
}
}
@@ -44,7 +44,7 @@ function fetch_data(callback, url) {
A requestor that always succeeds immediately:
```javascript
function constant(callback, value) {
var constant = function(callback, value) {
callback(42)
}
```
@@ -52,7 +52,7 @@ function constant(callback, value) {
A requestor that always fails:
```javascript
function broken(callback, value) {
var broken = function(callback, value) {
callback(null, "something went wrong")
}
```
@@ -74,9 +74,9 @@ var pipeline = sequence([
pipeline(function(profile, reason) {
if (reason) {
log.error(reason)
print(reason)
} else {
log.console(profile.name)
print(profile.name)
}
}, user_id)
```
@@ -133,7 +133,7 @@ var resilient = fallback([
resilient(function(data, reason) {
if (reason) {
log.error("all sources failed")
print("all sources failed")
}
}, key)
```
@@ -157,7 +157,7 @@ If the requestor does not complete within the time limit, it is cancelled and th
Requestors are particularly useful with actor messaging. Since `$send` is callback-based, it fits naturally:
```javascript
function ask_worker(callback, task) {
var ask_worker = function(callback, task) {
$send(worker, task, function(reply) {
callback(reply)
})
@@ -170,7 +170,7 @@ var pipeline = sequence([
])
pipeline(function(stored) {
log.console("done")
print("done")
$stop()
}, {type: "compute", data: [1, 2, 3]})
```

View File

@@ -1,118 +0,0 @@
---
title: "Bytecode VM"
description: "Stack-based virtual machine"
---
## Overview
The bytecode VM is a stack-based virtual machine. Instructions operate on an implicit operand stack, pushing and popping values. This is the original execution backend for ƿit.
## Compilation Pipeline
```
Source → Tokenize → Parse (AST) → Bytecode → Link → Execute
```
The compiler emits `JSFunctionBytecode` objects containing opcode sequences, constant pools, and debug information.
## Instruction Categories
### Value Loading
| Opcode | Description |
|--------|-------------|
| `push_i32` | Push a 32-bit immediate integer |
| `push_const` | Push a value from the constant pool |
| `null` | Push null |
| `push_false` | Push false |
| `push_true` | Push true |
### Stack Manipulation
| Opcode | Description |
|--------|-------------|
| `drop` | Remove top of stack |
| `dup` | Duplicate top of stack |
| `dup1` / `dup2` / `dup3` | Duplicate item at depth |
| `swap` | Swap top two items |
| `rot3l` / `rot3r` | Rotate top three items |
| `insert2` / `insert3` | Insert top item deeper |
| `nip` | Remove second item |
### Variable Access
| Opcode | Description |
|--------|-------------|
| `get_var` | Load variable by name (pre-link) |
| `put_var` | Store variable by name (pre-link) |
| `get_loc` / `put_loc` | Access local variable by index |
| `get_arg` / `put_arg` | Access function argument by index |
| `get_env_slot` / `set_env_slot` | Access closure variable (post-link) |
| `get_global_slot` / `set_global_slot` | Access global variable (post-link) |
Variable access opcodes are patched during linking. `get_var` instructions are rewritten to `get_loc`, `get_env_slot`, or `get_global_slot` depending on where the variable is resolved.
### Arithmetic
| Opcode | Description |
|--------|-------------|
| `add` / `sub` / `mul` / `div` | Basic arithmetic |
| `mod` / `pow` | Modulo and power |
| `neg` / `inc` / `dec` | Unary operations |
| `add_loc` / `inc_loc` / `dec_loc` | Optimized local variable update |
### Comparison and Logic
| Opcode | Description |
|--------|-------------|
| `strict_eq` / `strict_neq` | Equality (ƿit uses strict only) |
| `lt` / `lte` / `gt` / `gte` | Ordered comparison |
| `not` / `lnot` | Logical / bitwise not |
| `and` / `or` / `xor` | Bitwise operations |
### Control Flow
| Opcode | Description |
|--------|-------------|
| `goto` | Unconditional jump |
| `if_true` / `if_false` | Conditional jump |
| `goto8` / `goto16` | Short jumps (size-optimized) |
| `if_true8` / `if_false8` | Short conditional jumps |
| `catch` | Set exception handler |
### Function Calls
| Opcode | Description |
|--------|-------------|
| `call` | Call function with N arguments |
| `tail_call` | Tail-call optimization |
| `call_method` | Call method on object |
| `return` | Return value from function |
| `return_undef` | Return null from function |
| `throw` | Throw exception (disrupt) |
### Property Access
| Opcode | Description |
|--------|-------------|
| `get_field` | Get named property |
| `put_field` | Set named property |
| `get_array_el` | Get computed property |
| `put_array_el` | Set computed property |
| `define_field` | Define property during object literal |
### Object Creation
| Opcode | Description |
|--------|-------------|
| `object` | Create new empty object |
| `array_from` | Create array from stack values |
## Bytecode Patching
During the link/integrate phase, symbolic variable references are resolved to concrete access instructions. This is a critical optimization — the interpreter does not perform name lookups at runtime.
A `get_var "x"` instruction becomes:
- `get_loc 3` — if x is local variable at index 3
- `get_env_slot 1, 5` — if x is captured from outer scope (depth 1, slot 5)
- `get_global_slot 7` — if x is a global

View File

@@ -50,7 +50,7 @@ The collector traces from these root sources:
- **Class prototypes** — built-in type prototypes
- **Exception** — the current exception value
- **Value stack** — all values on the operand stack
- **Frame stack** — all stack frames (bytecode and register VM)
- **Frame stack** — all stack frames (register VM and mcode)
- **GC reference stack** — manually registered roots (via `JS_PUSH_VALUE` / `JS_POP_VALUE`)
- **Parser constant pool** — during compilation, constants being built

View File

@@ -19,8 +19,8 @@ Every heap-allocated object begins with a 64-bit header word (`objhdr_t`):
| 1 | `OBJ_BLOB` | Binary data (bits) |
| 2 | `OBJ_TEXT` | Unicode text string |
| 3 | `OBJ_RECORD` | Key-value object with prototype chain |
| 4 | `OBJ_FUNCTION` | Function (C, bytecode, register, or mcode) |
| 5 | `OBJ_CODE` | Compiled bytecode |
| 4 | `OBJ_FUNCTION` | Function (C, register, or mcode) |
| 5 | `OBJ_CODE` | Compiled code |
| 6 | `OBJ_FRAME` | Stack frame for closures |
| 7 | `OBJ_FORWARD` | Forwarding pointer (GC) |
@@ -93,17 +93,16 @@ struct JSFunction {
objhdr_t header; // type=4
JSValue name; // function name
int16_t length; // arity (-1 for variadic)
uint8_t kind; // C, bytecode, register, or mcode
uint8_t kind; // C, register, or mcode
union {
struct { ... } cfunc; // C function pointer
struct { ... } bytecode; // bytecode + frame
struct { ... } regvm; // register VM code
struct { ... } mcode; // mcode IR
} u;
};
```
The kind field selects which union variant is active. Functions can be implemented in C (native), bytecode (stack VM), register code (mach VM), or mcode (JSON interpreter).
The kind field selects which union variant is active. Functions can be implemented in C (native), register code (mach VM), or mcode (JSON interpreter).
## Frame

View File

@@ -387,8 +387,34 @@ static int run_eval(const char *script_or_file, int print_bytecode, int use_boot
return result;
}
static void print_usage(const char *prog)
{
printf("Usage: %s [options] <script> [args...]\n\n", prog);
printf("Run a cell script (.ce actor or .cm module).\n\n");
printf("Options:\n");
printf(" -e, --eval <code|file> Evaluate code or run a file directly\n");
printf(" -p, --print-bytecode <code|file> Compile and print bytecode\n");
printf(" -s, --serializers <code|file> Run with json/nota/wota in env\n");
printf(" --ast <code|file> Output AST as JSON\n");
printf(" --tokenize <code|file> Output token array as JSON\n");
printf(" --mcode <code|file> Output MCODE IR as JSON\n");
printf(" --run-mcode <code|file> Compile and run through MCODE interpreter\n");
printf(" --mach <code|file> Output MACH bytecode\n");
printf(" --mach-run <code|file> Compile and run through MACH VM\n");
printf(" --test [heap_size] Run C test suite\n");
printf(" -h, --help Show this help message\n");
printf("\nRecompile after changes: make\n");
printf("Bootstrap from scratch: make bootstrap\n");
}
int cell_init(int argc, char **argv)
{
/* Check for --help flag */
if (argc >= 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
print_usage(argv[0]);
return 0;
}
/* Check for --test flag to run C test suite */
if (argc >= 2 && strcmp(argv[1], "--test") == 0) {
size_t heap_size = 64 * 1024; /* 64KB default */

View File

@@ -4,7 +4,7 @@ title: "ƿit"
```javascript
// hello.ce — a simple actor
log.console("Hello, ƿit!")
print("Hello, ƿit!")
$stop()
```

View File

@@ -34,7 +34,7 @@ Create a file called `hello.ce`:
```javascript
// hello.ce
log.console("Hello, ƿit!")
print("Hello, ƿit!")
$stop()
```
@@ -58,7 +58,7 @@ var count = 0
$clock(function(dt) {
count = count + 1
log.console(`tick ${count}`)
print(`tick ${count}`)
if (count >= 5) {
$stop()
}
@@ -86,7 +86,7 @@ $receiver(function(msg, reply) {
// main.ce
$start(function(greeter) {
$send(greeter, {name: "world"}, function(response) {
log.console(response.greeting)
print(response.greeting)
$stop()
})
}, "greeter")
@@ -104,11 +104,11 @@ Modules (`.cm` files) return a value that is cached and frozen. Create a module:
```javascript
// math_helpers.cm
function square(x) {
var square = function(x) {
return x * x
}
function distance(x1, y1, x2, y2) {
var distance = function(x1, y1, x2, y2) {
var math = use('math/radians')
var dx = x2 - x1
var dy = y2 - y1
@@ -127,8 +127,8 @@ Use it from an actor:
// calc.ce
var helpers = use('math_helpers')
log.console(helpers.square(5)) // 25
log.console(helpers.distance(0, 0, 3, 4)) // 5
print(helpers.square(5)) // 25
print(helpers.distance(0, 0, 3, 4)) // 5
$stop()
```

View File

@@ -5,22 +5,14 @@ sections:
url: "/docs/language/"
- title: "Actors and Modules"
url: "/docs/actors/"
- title: "Requestors"
url: "/docs/requestors/"
- title: "Packages"
url: "/docs/packages/"
- title: "Tools"
pages:
- title: "CLI"
url: "/docs/cli/"
- title: "C Modules"
url: "/docs/c-modules/"
- title: "Reference"
pages:
- title: "Built-in Functions"
url: "/docs/functions/"
- title: "Standard Library"
pages:
- title: "Overview"
url: "/docs/library/"
- title: "text"
url: "/docs/library/text/"
- title: "number"
@@ -29,6 +21,10 @@ sections:
url: "/docs/library/array/"
- title: "object"
url: "/docs/library/object/"
- title: "Standard Library"
pages:
- title: "Overview"
url: "/docs/library/"
- title: "blob"
url: "/docs/library/blob/"
- title: "time"
@@ -39,3 +35,9 @@ sections:
url: "/docs/library/json/"
- title: "random"
url: "/docs/library/random/"
- title: "Tools"
pages:
- title: "CLI"
url: "/docs/cli/"
- title: "C Modules"
url: "/docs/c-modules/"

View File

@@ -2,57 +2,64 @@ sections:
- title: "Language Syntax"
page: "/docs/language/"
id: "language"
group: "Language"
- title: "Actors and Modules"
page: "/docs/actors/"
id: "actors"
group: "Language"
- title: "Requestors"
page: "/docs/requestors/"
id: "requestors"
group: "Language"
- title: "Packages"
page: "/docs/packages/"
id: "packages"
group: "Language"
- title: "Built-in Functions"
page: "/docs/functions/"
id: "functions"
group: "Reference"
- title: "text"
page: "/docs/library/text/"
id: "intrinsic-text"
group: "Reference"
- title: "number"
page: "/docs/library/number/"
id: "intrinsic-number"
group: "Reference"
- title: "array"
page: "/docs/library/array/"
id: "intrinsic-array"
group: "Reference"
- title: "object"
page: "/docs/library/object/"
id: "intrinsic-object"
group: "Reference"
- title: "Standard Library"
page: "/docs/library/"
id: "library"
- title: "text"
page: "/docs/library/text/"
id: "library-text"
- title: "number"
page: "/docs/library/number/"
id: "library-number"
- title: "array"
page: "/docs/library/array/"
id: "library-array"
- title: "object"
page: "/docs/library/object/"
id: "library-object"
group: "Standard Library"
- title: "blob"
page: "/docs/library/blob/"
id: "library-blob"
group: "Standard Library"
- title: "time"
page: "/docs/library/time/"
id: "library-time"
group: "Standard Library"
- title: "math"
page: "/docs/library/math/"
id: "library-math"
group: "Standard Library"
- title: "json"
page: "/docs/library/json/"
id: "library-json"
group: "Standard Library"
- title: "random"
page: "/docs/library/random/"
id: "library-random"
group: "Standard Library"
- title: "Writing C Modules"
page: "/docs/c-modules/"
id: "c-modules"
- title: "Kim Encoding"
page: "/docs/kim/"
id: "kim"
- title: "Nota Format"
page: "/docs/nota/"
id: "nota"
- title: "Wota Format"
page: "/docs/wota/"
id: "wota"
group: "Tools"

View File

@@ -14,12 +14,18 @@ sections:
- title: "Garbage Collection"
page: "/docs/spec/gc/"
id: "gc"
- title: "Bytecode VM"
page: "/docs/spec/bytecode/"
id: "bytecode"
- title: "Register VM"
page: "/docs/spec/mach/"
id: "mach"
- title: "Mcode IR"
page: "/docs/spec/mcode/"
id: "mcode"
- title: "Kim Encoding"
page: "/docs/kim/"
id: "kim"
- title: "Nota Format"
page: "/docs/nota/"
id: "nota"
- title: "Wota Format"
page: "/docs/wota/"
id: "wota"

View File

@@ -7,7 +7,7 @@
<article class="longform-content" id="longform-content">
<h1>{{ .Title }}</h1>
{{ range .Site.Data.manual_sections.sections }}
<section id="{{ .id }}" data-toc-title="{{ .title }}">
<section id="{{ .id }}" data-toc-title="{{ .title }}" data-toc-group="{{ .group }}">
{{ with $.Site.GetPage .page }}
{{ .Content }}
{{ end }}

View File

@@ -50,6 +50,7 @@ body, h1, h2, h3, h4, p, ul, ol, figure, blockquote {
--font-wynn: 'Junicode', 'Charter', Georgia, serif;
--content-width: 720px;
--sidebar-width: 180px;
--header-height: 3rem;
}
html {
@@ -199,6 +200,15 @@ th {
.site-header {
border-bottom: 1px solid var(--border);
background: var(--bg);
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
body {
padding-top: var(--header-height);
}
.site-nav {
@@ -332,8 +342,8 @@ th {
flex-shrink: 0;
padding-top: 2rem;
position: sticky;
top: 0;
max-height: 100vh;
top: var(--header-height);
max-height: calc(100vh - var(--header-height));
overflow-y: auto;
}
@@ -473,8 +483,8 @@ th {
flex-shrink: 0;
padding-top: 2rem;
position: sticky;
top: 0;
max-height: 100vh;
top: var(--header-height);
max-height: calc(100vh - var(--header-height));
overflow-y: auto;
}
@@ -492,6 +502,20 @@ th {
margin: 0;
}
.toc-group-header {
font-size: 0.65rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-secondary);
margin-top: 0.8rem;
margin-bottom: 0.15rem;
list-style: none;
}
.toc-group-header:first-child {
margin-top: 0;
}
.toc-nav li.toc-section {
margin: 0;
}

View File

@@ -8,7 +8,18 @@
if (sections.length > 0) {
// composite page (manual, spec): section-level ToC with disclosure
var lastGroup = null;
sections.forEach(function(sec) {
// Insert group header when group changes
var group = sec.dataset.tocGroup;
if (group && group !== lastGroup) {
var gh = document.createElement('li');
gh.className = 'toc-group-header';
gh.textContent = group;
tocList.appendChild(gh);
lastGroup = group;
}
var li = document.createElement('li');
li.className = 'toc-section';
var a = document.createElement('a');