From 809785711c7113ff4e8f7a75ad75260f878a9494 Mon Sep 17 00:00:00 2001 From: dimgigov Date: Fri, 5 Jun 2026 22:19:46 +0300 Subject: [PATCH] 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 --- docs/BuildAndTest.md | 6 +- docs/LanguageRef.md | 64 ++++++++- docs/Stdlib.md | 329 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 395 insertions(+), 4 deletions(-) diff --git a/docs/BuildAndTest.md b/docs/BuildAndTest.md index 4cfe005..3982225 100644 --- a/docs/BuildAndTest.md +++ b/docs/BuildAndTest.md @@ -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 diff --git a/docs/LanguageRef.md b/docs/LanguageRef.md index 04ac579..05e1c57 100644 --- a/docs/LanguageRef.md +++ b/docs/LanguageRef.md @@ -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) { + Channel_SendInt(ch, 42); + Channel_Close(ch); +} + +func Consumer(ch: *Channel) -> int { + let val: int = Channel_RecvInt(ch); + return val; +} + +func Main() -> int { + let ch: Channel = Channel_New(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` 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. diff --git a/docs/Stdlib.md b/docs/Stdlib.md index 95466ec..28287d8 100644 --- a/docs/Stdlib.md +++ b/docs/Stdlib.md @@ -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 { + handle: *void; +} +``` + +### Functions + +| Function | Signature | Description | +|----------|-----------|-------------| +| `Channel_New` | `func Channel_New(capacity: int64) -> Channel` | Create buffered channel | +| `Channel_Send` | `func Channel_Send(ch: *Channel, value: T)` | Send value (blocks if full) | +| `Channel_Recv` | `func Channel_Recv(ch: *Channel) -> T` | Receive value (blocks if empty) | +| `Channel_Close` | `func Channel_Close(ch: *Channel)` | Close channel | +| `Channel_Free` | `func Channel_Free(ch: *Channel)` | Free channel memory | + +### Non-generic wrappers + +| Function | Signature | Description | +|----------|-----------|-------------| +| `Channel_SendInt` | `func Channel_SendInt(ch: *Channel, value: int)` | Send int (no monomorphization issues) | +| `Channel_RecvInt` | `func Channel_RecvInt(ch: *Channel) -> int` | Recv int (returns 0 if closed+empty) | +| `Channel_SendFloat64` | `func Channel_SendFloat64(ch: *Channel, value: float64)` | Send float64 | +| `Channel_RecvFloat64` | `func Channel_RecvFloat64(ch: *Channel) -> 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) { + var i: int = 1; + while i <= 5 { + Channel_SendInt(chPtr, i * 10); + i = i + 1; + } + Channel_Close(chPtr); +} + +func Consumer(chPtr: *Channel) { + 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 = Channel_New(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