docs: add missing stdlib modules and update language reference
Stdlib.md: - Add Std::Task (thread spawn/join/sleep) - Add Std::Channel (generic channels + wrappers) - Add Std::Net (TCP sockets) - Add Std::Json (parser/serializer) - Add Std::Crypto (SHA-256, HMAC, Base64, random) - Add Std::Fmt (formatting wrappers) - Add Std::Math (Sqrt, Pow, Abs, Min, Max) - Add String_FromFloat to String docs - Update Future Modules list LanguageRef.md: - Add Concurrency section (threads + channels) - Update Ownership with move semantics and own T BuildAndTest.md: - Add libssl-dev/openssl prerequisite note - Mention -lcrypto auto-linking
This commit is contained in:
@@ -12,14 +12,16 @@ This guide covers building the Bux bootstrap compiler, creating projects, and ru
|
||||
|
||||
On Debian/Ubuntu:
|
||||
```bash
|
||||
sudo apt-get install nim gcc make
|
||||
sudo apt-get install nim gcc make libssl-dev
|
||||
```
|
||||
|
||||
On macOS:
|
||||
```bash
|
||||
brew install nim gcc make
|
||||
brew install nim gcc make openssl
|
||||
```
|
||||
|
||||
> **Note:** The `Std::Crypto` module requires OpenSSL (`-lcrypto`). The build system links it automatically.
|
||||
|
||||
---
|
||||
|
||||
## Building the Compiler
|
||||
|
||||
+63
-1
@@ -402,7 +402,33 @@ func BadWrite(val: &int) {
|
||||
| Raw pointer | `*T` | C-style pointer, no checks |
|
||||
| Shared ref | `&T` | Borrowed reference (read-only in checked functions) |
|
||||
| Mutable ref | `&mut T` | Exclusive mutable borrow (allows mutation) |
|
||||
| Owned | `own T` | Ownership transfer (syntax parsed, not yet enforced) |
|
||||
| Owned | `own T` | Ownership type — values can be moved |
|
||||
|
||||
### Move Semantics
|
||||
|
||||
`own T` values can be **moved**. After a move, the original variable is uninitialized and cannot be used until reassigned.
|
||||
|
||||
```bux
|
||||
@[Checked]
|
||||
func Process(data: own String) {
|
||||
PrintLine(data);
|
||||
// data is consumed here
|
||||
}
|
||||
|
||||
@[Checked]
|
||||
func Main() {
|
||||
let msg: own String = "hello";
|
||||
Process(msg); // move: msg is now uninitialized
|
||||
// PrintLine(msg); // ERROR: use after move
|
||||
msg = "reassigned"; // OK: reinitialization
|
||||
PrintLine(msg);
|
||||
}
|
||||
```
|
||||
|
||||
Moves happen in three contexts:
|
||||
- **Function call argument**: `Process(msg)` moves `msg` into the parameter
|
||||
- **Assignment**: `b = a` moves `a` into `b`
|
||||
- **Return**: `return x` moves `x` out of the function
|
||||
|
||||
### Rules in @[Checked] functions
|
||||
|
||||
@@ -510,6 +536,42 @@ func PrivateFunc() -> int {
|
||||
|
||||
---
|
||||
|
||||
## Concurrency
|
||||
|
||||
Bux supports both **async/await** (stackful coroutines) and **pthread-based threads** with channels.
|
||||
|
||||
### Threads and Channels
|
||||
|
||||
```bux
|
||||
import Std::Task::{Task_Spawn, Task_Join, TaskHandle};
|
||||
import Std::Channel::{Channel, Channel_New, Channel_SendInt, Channel_RecvInt, Channel_Close};
|
||||
|
||||
func Producer(ch: *Channel<int>) {
|
||||
Channel_SendInt(ch, 42);
|
||||
Channel_Close<int>(ch);
|
||||
}
|
||||
|
||||
func Consumer(ch: *Channel<int>) -> int {
|
||||
let val: int = Channel_RecvInt(ch);
|
||||
return val;
|
||||
}
|
||||
|
||||
func Main() -> int {
|
||||
let ch: Channel<int> = Channel_New<int>(1);
|
||||
let p: *void = spawn Producer(&ch);
|
||||
let c: *void = spawn Consumer(&ch);
|
||||
Task_Join(TaskHandle { handle: p });
|
||||
Task_Join(TaskHandle { handle: c });
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
- `spawn Func()` creates a new pthread running `Func`
|
||||
- `Channel<T>` is a buffered channel with mutex/condvar
|
||||
- `Channel_RecvInt` returns `0` when the channel is closed and empty
|
||||
|
||||
---
|
||||
|
||||
## Async/Await
|
||||
|
||||
Bux supports stackful coroutines via `async`/`await` with a round-robin scheduler.
|
||||
|
||||
+328
-1
@@ -139,6 +139,7 @@ String manipulation utilities.
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `String_FromInt` | `func String_FromInt(n: int64) -> String` | Int to string |
|
||||
| `String_FromFloat` | `func String_FromFloat(f: float64) -> String` | Float to string |
|
||||
| `String_ToInt` | `func String_ToInt(s: String) -> int64` | String to int |
|
||||
|
||||
### Find, Replace & Format
|
||||
@@ -408,6 +409,328 @@ These C functions are provided by `runtime.c` and are available via `extern` dec
|
||||
|
||||
---
|
||||
|
||||
## Std::Task
|
||||
|
||||
Pthread-based threading primitives.
|
||||
|
||||
### Types
|
||||
```bux
|
||||
struct TaskHandle {
|
||||
handle: *void;
|
||||
}
|
||||
```
|
||||
|
||||
### Functions
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Task_Spawn` | `func Task_Spawn(fn: *void, arg: *void) -> TaskHandle` | Spawn a new thread running `fn(arg)` |
|
||||
| `Task_Join` | `func Task_Join(t: TaskHandle)` | Block until thread completes |
|
||||
| `Task_Sleep` | `func Task_Sleep(ms: int64)` | Sleep current thread for N milliseconds |
|
||||
|
||||
### Example
|
||||
```bux
|
||||
import Std::Task::{Task_Spawn, Task_Join, TaskHandle};
|
||||
|
||||
func Worker(arg: *void) -> *void {
|
||||
PrintLine("Hello from thread!");
|
||||
return null;
|
||||
}
|
||||
|
||||
func Main() -> int {
|
||||
let handle: TaskHandle = Task_Spawn(Worker as *void, null);
|
||||
Task_Join(handle);
|
||||
PrintLine("Thread finished");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Channel
|
||||
|
||||
Generic channel for thread communication over pthread mutex/cond.
|
||||
|
||||
### Types
|
||||
```bux
|
||||
struct Channel<T> {
|
||||
handle: *void;
|
||||
}
|
||||
```
|
||||
|
||||
### Functions
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Channel_New<T>` | `func Channel_New<T>(capacity: int64) -> Channel<T>` | Create buffered channel |
|
||||
| `Channel_Send<T>` | `func Channel_Send<T>(ch: *Channel<T>, value: T)` | Send value (blocks if full) |
|
||||
| `Channel_Recv<T>` | `func Channel_Recv<T>(ch: *Channel<T>) -> T` | Receive value (blocks if empty) |
|
||||
| `Channel_Close<T>` | `func Channel_Close<T>(ch: *Channel<T>)` | Close channel |
|
||||
| `Channel_Free<T>` | `func Channel_Free<T>(ch: *Channel<T>)` | Free channel memory |
|
||||
|
||||
### Non-generic wrappers
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Channel_SendInt` | `func Channel_SendInt(ch: *Channel<int>, value: int)` | Send int (no monomorphization issues) |
|
||||
| `Channel_RecvInt` | `func Channel_RecvInt(ch: *Channel<int>) -> int` | Recv int (returns 0 if closed+empty) |
|
||||
| `Channel_SendFloat64` | `func Channel_SendFloat64(ch: *Channel<float64>, value: float64)` | Send float64 |
|
||||
| `Channel_RecvFloat64` | `func Channel_RecvFloat64(ch: *Channel<float64>) -> float64` | Recv float64 |
|
||||
|
||||
### Example
|
||||
```bux
|
||||
import Std::Io::{PrintLine, PrintInt};
|
||||
import Std::Task::{Task_Join, TaskHandle};
|
||||
import Std::Channel::{Channel, Channel_New, Channel_SendInt, Channel_RecvInt, Channel_Close};
|
||||
|
||||
func Producer(chPtr: *Channel<int>) {
|
||||
var i: int = 1;
|
||||
while i <= 5 {
|
||||
Channel_SendInt(chPtr, i * 10);
|
||||
i = i + 1;
|
||||
}
|
||||
Channel_Close<int>(chPtr);
|
||||
}
|
||||
|
||||
func Consumer(chPtr: *Channel<int>) {
|
||||
var total: int = 0;
|
||||
while true {
|
||||
let val: int = Channel_RecvInt(chPtr);
|
||||
if val == 0 { break; }
|
||||
total = total + val;
|
||||
}
|
||||
PrintLine("Total:");
|
||||
PrintInt(total);
|
||||
}
|
||||
|
||||
func Main() -> int {
|
||||
let ch: Channel<int> = Channel_New<int>(3);
|
||||
let p: *void = spawn Producer(&ch);
|
||||
let c: *void = spawn Consumer(&ch);
|
||||
Task_Join(TaskHandle { handle: p });
|
||||
Task_Join(TaskHandle { handle: c });
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Net
|
||||
|
||||
TCP socket operations.
|
||||
|
||||
### Functions
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Net_Create` | `func Net_Create() -> int` | Create TCP socket (-1 on error) |
|
||||
| `Net_SetReuse` | `func Net_SetReuse(fd: int) -> bool` | Enable SO_REUSEADDR |
|
||||
| `Net_Bind` | `func Net_Bind(fd: int, addr: String, port: int) -> bool` | Bind socket |
|
||||
| `Net_Listen` | `func Net_Listen(fd: int, backlog: int) -> bool` | Start listening |
|
||||
| `Net_Accept` | `func Net_Accept(fd: int) -> int` | Accept connection (-1 on error) |
|
||||
| `Net_Connect` | `func Net_Connect(fd: int, addr: String, port: int) -> bool` | Connect to remote |
|
||||
| `Net_Send` | `func Net_Send(fd: int, data: String) -> int` | Send data (bytes sent or -1) |
|
||||
| `Net_Recv` | `func Net_Recv(fd: int, maxLen: int) -> String` | Receive up to maxLen bytes |
|
||||
| `Net_Close` | `func Net_Close(fd: int) -> bool` | Close socket |
|
||||
| `Net_LastError` | `func Net_LastError() -> String` | Get last socket error |
|
||||
|
||||
### Example — Echo Server
|
||||
```bux
|
||||
import Std::Net::*;
|
||||
import Std::Io::PrintLine;
|
||||
|
||||
func Main() -> int {
|
||||
let fd: int = Net_Create();
|
||||
Net_SetReuse(fd);
|
||||
Net_Bind(fd, "127.0.0.1", 8080);
|
||||
Net_Listen(fd, 10);
|
||||
PrintLine("Listening on :8080");
|
||||
let client: int = Net_Accept(fd);
|
||||
let msg: String = Net_Recv(client, 1024);
|
||||
Net_Send(client, msg);
|
||||
Net_Close(client);
|
||||
Net_Close(fd);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Json
|
||||
|
||||
JSON parser and serializer using a flat struct with int tag.
|
||||
|
||||
### Types
|
||||
```bux
|
||||
struct JsonValue {
|
||||
tag: int,
|
||||
boolVal: bool,
|
||||
numVal: float64,
|
||||
strVal: String,
|
||||
arrData: *JsonValue,
|
||||
arrLen: uint,
|
||||
objKeys: *String,
|
||||
objValues: *JsonValue,
|
||||
objLen: uint
|
||||
}
|
||||
```
|
||||
|
||||
### Constructors
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Json_Null` | `func Json_Null() -> JsonValue` | Null value |
|
||||
| `Json_Bool` | `func Json_Bool(b: bool) -> JsonValue` | Boolean value |
|
||||
| `Json_Number` | `func Json_Number(n: float64) -> JsonValue` | Number value |
|
||||
| `Json_String` | `func Json_String(s: String) -> JsonValue` | String value |
|
||||
| `Json_Array` | `func Json_Array() -> JsonValue` | Empty array |
|
||||
| `Json_Object` | `func Json_Object() -> JsonValue` | Empty object |
|
||||
|
||||
### Accessors
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Json_IsNull` | `func Json_IsNull(v: JsonValue) -> bool` | Check if null |
|
||||
| `Json_AsBool` | `func Json_AsBool(v: JsonValue) -> bool` | Get bool (false if wrong type) |
|
||||
| `Json_AsNumber` | `func Json_AsNumber(v: JsonValue) -> float64` | Get number (0.0 if wrong type) |
|
||||
| `Json_AsString` | `func Json_AsString(v: JsonValue) -> String` | Get string ("" if wrong type) |
|
||||
| `Json_ArrayLen` | `func Json_ArrayLen(v: JsonValue) -> uint` | Array length |
|
||||
| `Json_ArrayGet` | `func Json_ArrayGet(v: JsonValue, index: uint) -> JsonValue` | Get array element |
|
||||
| `Json_ObjectLen` | `func Json_ObjectLen(v: JsonValue) -> uint` | Object key count |
|
||||
| `Json_ObjectGet` | `func Json_ObjectGet(v: JsonValue, key: String) -> JsonValue` | Get object value by key |
|
||||
| `Json_ObjectHas` | `func Json_ObjectHas(v: JsonValue, key: String) -> bool` | Check if key exists |
|
||||
|
||||
### Mutators
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Json_ArrayPush` | `func Json_ArrayPush(self: *JsonValue, val: JsonValue)` | Append to array |
|
||||
| `Json_ObjectSet` | `func Json_ObjectSet(self: *JsonValue, key: String, val: JsonValue)` | Set object key |
|
||||
|
||||
### Parser / Serializer
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Json_Parse` | `func Json_Parse(s: String) -> JsonValue` | Parse JSON string |
|
||||
| `Json_Stringify` | `func Json_Stringify(v: JsonValue) -> String` | Serialize to JSON string |
|
||||
|
||||
### Example
|
||||
```bux
|
||||
import Std::Json::*;
|
||||
import Std::Io::PrintLine;
|
||||
|
||||
func Main() -> int {
|
||||
let json: JsonValue = Json_Parse(`{"name": "Bux", "version": 1}`);
|
||||
let name: String = Json_AsString(Json_ObjectGet(json, "name"));
|
||||
PrintLine(name); // "Bux"
|
||||
|
||||
var arr: JsonValue = Json_Array();
|
||||
Json_ArrayPush(&arr, Json_Number(10));
|
||||
Json_ArrayPush(&arr, Json_Number(20));
|
||||
PrintLine(Json_Stringify(arr)); // [10,20]
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Crypto
|
||||
|
||||
Cryptographic primitives via OpenSSL (`-lcrypto`).
|
||||
|
||||
### Functions
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Crypto_Sha256` | `func Crypto_Sha256(data: String) -> String` | SHA-256 hex string |
|
||||
| `Crypto_HmacSha256` | `func Crypto_HmacSha256(key: String, message: String) -> String` | HMAC-SHA256 hex string |
|
||||
| `Crypto_HmacSha256Raw` | `func Crypto_HmacSha256Raw(key: String, message: String) -> String` | HMAC-SHA256 base64 string |
|
||||
| `Crypto_RandomBytes` | `func Crypto_RandomBytes(n: int) -> String` | `n` random bytes as base64 |
|
||||
| `Crypto_Base64Encode` | `func Crypto_Base64Encode(s: String) -> String` | Base64 encode |
|
||||
| `Crypto_Base64Decode` | `func Crypto_Base64Decode(s: String) -> String` | Base64 decode |
|
||||
|
||||
### Example
|
||||
```bux
|
||||
import Std::Crypto::*;
|
||||
import Std::Io::PrintLine;
|
||||
|
||||
func Main() -> int {
|
||||
let hash: String = Crypto_Sha256("hello");
|
||||
PrintLine(hash);
|
||||
|
||||
let hmac: String = Crypto_HmacSha256("key", "message");
|
||||
PrintLine(hmac);
|
||||
|
||||
let rand: String = Crypto_RandomBytes(16);
|
||||
PrintLine(rand);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Fmt
|
||||
|
||||
Convenience wrappers for string formatting.
|
||||
|
||||
### Functions
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Fmt_Fmt1` | `func Fmt_Fmt1(pattern: String, a: String) -> String` | Format with 1 arg |
|
||||
| `Fmt_Fmt2` | `func Fmt_Fmt2(pattern: String, a: String, b: String) -> String` | Format with 2 args |
|
||||
| `Fmt_Fmt3` | `func Fmt_Fmt3(pattern: String, a: String, b: String, c: String) -> String` | Format with 3 args |
|
||||
| `Fmt_FmtInt` | `func Fmt_FmtInt(pattern: String, n: int64) -> String` | Format with int arg |
|
||||
| `Fmt_FmtInt2` | `func Fmt_FmtInt2(pattern: String, n1: int64, n2: int64) -> String` | Format with 2 int args |
|
||||
| `Fmt_FmtFloat` | `func Fmt_FmtFloat(pattern: String, f: float64) -> String` | Format with float arg |
|
||||
| `Fmt_FmtBool` | `func Fmt_FmtBool(pattern: String, b: bool) -> String` | Format with bool arg |
|
||||
|
||||
### Example
|
||||
```bux
|
||||
import Std::Fmt::*;
|
||||
import Std::Io::PrintLine;
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine(Fmt_Fmt1("Hello, {0}!", "World"));
|
||||
PrintLine(Fmt_FmtInt("Count: {0}", 42));
|
||||
PrintLine(Fmt_FmtFloat("Pi: {0}", 3.14159));
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Math
|
||||
|
||||
Mathematical functions.
|
||||
|
||||
### Functions
|
||||
|
||||
| Function | Signature | Description |
|
||||
|----------|-----------|-------------|
|
||||
| `Sqrt` | `func Sqrt(x: float64) -> float64` | Square root |
|
||||
| `Pow` | `func Pow(x: float64, y: float64) -> float64` | Power |
|
||||
| `Abs` | `func Abs(n: int64) -> int64` | Absolute value (int) |
|
||||
| `AbsF` | `func AbsF(f: float64) -> float64` | Absolute value (float) |
|
||||
| `Min` | `func Min(a: int64, b: int64) -> int64` | Minimum (int) |
|
||||
| `Max` | `func Max(a: int64, b: int64) -> int64` | Maximum (int) |
|
||||
| `MinF` | `func MinF(a: float64, b: float64) -> float64` | Minimum (float) |
|
||||
| `MaxF` | `func MaxF(a: float64, b: float64) -> float64` | Maximum (float) |
|
||||
|
||||
### Example
|
||||
```bux
|
||||
import Std::Math::*;
|
||||
import Std::Io::PrintInt;
|
||||
|
||||
func Main() -> int {
|
||||
PrintInt(Max(10, 20) as int); // 20
|
||||
PrintInt(Min(10, 20) as int); // 10
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Std::Async
|
||||
|
||||
Low-level async runtime for stackful coroutines. These functions are used by the `async`/`await` language features.
|
||||
@@ -457,9 +780,13 @@ func Main() -> int {
|
||||
- `Std::Os` — `Args`, `Env`, `Cwd`, `Chdir` ✅
|
||||
- `Std::Time` — `NowMs`, `NowUs`, `SleepMs` ✅
|
||||
- `Std::Process` — `Run`, `Output` ✅
|
||||
- `Std::Fmt` — String formatting with interpolation ⏳
|
||||
- `Std::Fmt` — String formatting with interpolation ✅
|
||||
- `Std::Iter` — Iterator trait and combinators ⏳
|
||||
- `Std::Task` / `Std::Channel` — Lightweight concurrency (pthread-based threads) ✅
|
||||
- `Std::Net` — TCP sockets ✅
|
||||
- `Std::Json` — JSON parser/serializer ✅
|
||||
- `Std::Crypto` — SHA-256, HMAC, Base64, random bytes ✅
|
||||
- `Std::Math` — Sqrt, Pow, Abs, Min, Max ✅
|
||||
---
|
||||
|
||||
## Std::Os
|
||||
|
||||
Reference in New Issue
Block a user