Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/goth-eval/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ fn prim_arity(prim: PrimFn) -> usize {
PrimFn::Neg | PrimFn::Abs | PrimFn::Not | PrimFn::Exp | PrimFn::Ln | PrimFn::Sqrt | PrimFn::Sin | PrimFn::Cos | PrimFn::Tan | PrimFn::Floor | PrimFn::Ceil | PrimFn::Round | PrimFn::Sum | PrimFn::Prod | PrimFn::Len | PrimFn::Shape | PrimFn::Reverse | PrimFn::Transpose | PrimFn::Norm | PrimFn::ToInt | PrimFn::ToFloat | PrimFn::ToBool | PrimFn::ToChar | PrimFn::ParseInt | PrimFn::ParseFloat | PrimFn::Iota | PrimFn::ToString | PrimFn::Chars => 1,
PrimFn::Print | PrimFn::Write | PrimFn::ReadLine | PrimFn::ReadKey | PrimFn::ReadFile | PrimFn::Sleep => 1,
PrimFn::Flush | PrimFn::RawModeEnter | PrimFn::RawModeExit => 1, // Terminal control (take unit)
PrimFn::FromChars => 1, // [n]Char → String
PrimFn::Lines | PrimFn::Words | PrimFn::Bytes => 1, // String splitting (unary)
PrimFn::Re | PrimFn::Im | PrimFn::Conj | PrimFn::Arg => 1, // Complex decomposition
PrimFn::Trace | PrimFn::Det | PrimFn::Inv | PrimFn::Diag | PrimFn::Eye | PrimFn::Eig | PrimFn::EigVecs => 1, // Matrix utilities
Expand Down
32 changes: 29 additions & 3 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,32 @@ cargo run --quiet --package goth-cli -- ../examples/crypto/hashfile.goth /tmp/te

---

## json/

JSON parsing and serialization — pure Goth implementation using recursive descent parsing and fold-based serialization. All functions are implemented entirely in Goth via the `json.goth` standard library.

| File | Description | Example |
|------|-------------|---------|
| `parse_simple.goth` | Parse JSON, extract fields, serialize | `parseJson "{\"name\":\"Goth\"}" → ⟨⊤, ..., ""⟩` |
| `roundtrip.goth` | Parse → serialize → re-parse roundtrip test | `toJson (parseJson input).1` |

```sh
# Parse and extract fields from JSON
cargo run --quiet --package goth-cli -- ../examples/json/parse_simple.goth
# Name: Goth
# Version: 1
# Features: 3
# ...

# Roundtrip: parse → serialize → parse → serialize
cargo run --quiet --package goth-cli -- ../examples/json/roundtrip.goth
# Roundtrip: PASS
```

**Demonstrates:** Recursive descent parsing, `chars`, `fromChars`, `parseFloat`, fold-based string building, tagged tuples as sum types, `strEq`, `use` imports.

---

## Language Features Covered

| Feature | Examples |
Expand All @@ -291,13 +317,13 @@ cargo run --quiet --package goth-cli -- ../examples/crypto/hashfile.goth /tmp/te
| Sum/Product (`Σ`/`Π`) | numeric, higher-order, simulation |
| Iota (`ι`) | numeric, simulation |
| Array concat (`⊕`) | higher-order |
| String concat (`⧺`) | simulation, crypto |
| String concat (`⧺`) | simulation, crypto, json |
| Conditionals (`if/then/else`) | basic, recursion, algorithms |
| Contracts (`⊢`/`⊨`) | contracts, random |
| Uncertainty (`±`) | uncertainty |
| File I/O (`▷`, `writeFile`, `readFile`) | io, simulation, crypto |
| Module imports (`use`) | simulation, random, crypto |
| Module imports (`use`) | simulation, random, crypto, json |
| Tail-call optimization | tco |
| Bitwise ops (`bitand`, `bitor`, `bitxor`, `shl`, `shr`) | crypto |
| Tuple destructuring (`⟨a, b⟩`) | random |
| Tuple destructuring (`⟨a, b⟩`) | random, json |
| PRNG / entropy | random |
19 changes: 19 additions & 0 deletions examples/json/parse_simple.goth
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# JSON Parsing Example
# Parse a JSON string and extract fields
use "../../stdlib/json.goth"

╭─ main : () → String
╰─ let input = "{\"name\":\"Goth\",\"version\":1.0,\"features\":[\"arrays\",\"tuples\",\"unicode\"],\"stable\":true}"
in let result = parseJson input
in if ¬(result.0) then "Parse error: " ⧺ result.2
else let json = result.1
in let nameOpt = jsonGet "name" json
in let nameLine = if nameOpt.0 then "Name: " ⧺ asStr nameOpt.1 else "No name"
in let verOpt = jsonGet "version" json
in let verLine = if verOpt.0 then "Version: " ⧺ toString (asNum verOpt.1) else "No version"
in let featOpt = jsonGet "features" json
in let featLine = if featOpt.0 then "Features: " ⧺ toString (jsonLen featOpt.1) else "No features"
in let stableOpt = jsonGet "stable" json
in let stableLine = if stableOpt.0 then "Stable: " ⧺ toString (asBool stableOpt.1) else "No stable"
in let serialized = toJson json
in nameLine ⧺ "\n" ⧺ verLine ⧺ "\n" ⧺ featLine ⧺ "\n" ⧺ stableLine ⧺ "\n" ⧺ "Serialized: " ⧺ serialized
18 changes: 18 additions & 0 deletions examples/json/roundtrip.goth
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# JSON Roundtrip Example
# Parse JSON, serialize back, and compare
use "../../stdlib/json.goth"

╭─ main : () → String
╰─ let input = "{\"a\":1,\"b\":[2,3],\"c\":{\"d\":true},\"e\":null,\"f\":\"hello\\nworld\"}"
in let r1 = parseJson input
in if ¬(r1.0) then "Parse error: " ⧺ r1.2
else let serialized = toJson r1.1
in let r2 = parseJson serialized
in if ¬(r2.0) then "Re-parse error: " ⧺ r2.2
else let serialized2 = toJson r2.1
in "Input: " ⧺ input ⧺ "\n"
⧺ "Serialized: " ⧺ serialized ⧺ "\n"
⧺ "Re-serial: " ⧺ serialized2 ⧺ "\n"
⧺ if strEq serialized serialized2
then "Roundtrip: PASS"
else "Roundtrip: FAIL"
12 changes: 12 additions & 0 deletions examples/nockchain/balance.goth
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Query wallet balance via nockchain-bridge
# Usage: nockchain-bridge examples/nockchain/balance.goth <address>
#
# The bridge spawns this program, pipes its stdout as commands,
# and feeds gRPC responses back via stdin.
#
# Protocol: print "BALANCE <addr>", readLine → "OK <nicks>" or "ERROR <msg>"

╭─ main : String → ()
╰─ let _ = print ("BALANCE " ⧺ ₀) in
let resp = readLine ⟨⟩ in
print (words resp)
10 changes: 10 additions & 0 deletions examples/nockchain/blocks.goth
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# List recent blocks from Nockchain
# Usage: nockchain-bridge examples/nockchain/blocks.goth
#
# Sends GET_BLOCKS, reads multi-line response (each line: OK <height> <id> <ts>),
# terminated by a blank line.

╭─ main : I64 → ()
╰─ let _ = print "GET_BLOCKS" in
let resp = readLine ⟨⟩ in
print resp
9 changes: 9 additions & 0 deletions examples/nockchain/tx_status.goth
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Check if a transaction has been accepted
# Usage: nockchain-bridge examples/nockchain/tx_status.goth <tx_id>
#
# Protocol: print "TX_ACCEPTED <txid>", readLine → "OK true|false" or "ERROR <msg>"

╭─ main : String → ()
╰─ let _ = print ("TX_ACCEPTED " ⧺ ₀) in
let resp = readLine ⟨⟩ in
print resp
Loading
Loading