···6464 | expr - expr
6565 | expr * expr
6666 | expr expr
6767+ | [expr, ...]
6868+ | { key = expr, ... }
6969+ | null
6770 | (expr)
6871 | true | false | 123 | "text" | name
6972···7275type ::= Int | Bool | String | Data | List | Result | Error | type -> type | (type)
7376```
74777878+Inside the REPL, there is also a top-level binding form:
7979+8080+```text
8181+repl ::= let name = expr
8282+```
8383+8484+Bare REPL bindings persist across later entries, so you can write:
8585+8686+```mlang
8787+let x = 42
8888+x + 1
8989+```
9090+7591Expressions are checked as `Type ! Effects`. Pure expressions get `{}`; division carries `{Error}` implicitly. `readFile` is a builtin with type `String -> String ! {IO, Error}`. `readFileNickel` is a builtin with type `String -> Data ! {IO, Error}`. `parseNickel` is a builtin with type `String -> Data ! {Error}` and is backed by the real Nickel Rust crate. Nickel source is evaluated on the host side and converted back into `mlang` `Data`. Parsed data inspection is available through:
76927793- `httpGet : String -> String ! {IO, Error}`
9494+- `parseJson : String -> Data ! {Error}`
78957996- `get : Data -> String -> Data ! {Error}`
8097- `at : Data -> Int -> Data ! {Error}`
8198- `asInt : Data -> Int ! {Error}`
8299- `asString : Data -> String ! {Error}`
83100- `asBool : Data -> Bool ! {Error}`
101101+- `toJson : Data -> String`
102102+- `toNickel : Data -> String`
8410385104`httpGet` is implemented through a thin Rust host library plus a small C shim for Lean FFI. The Rust layer uses a real HTTP client crate rather than spawning an external tool.
86105`try ... with name => ...` handles `Error`, binds the caught error as an `Error` value, and removes `Error` from the resulting effect set when recovered locally.
···9511496115Non-integer numeric Nickel values are not supported yet by `mlang`'s `Data` model.
97116117117+Native `Data` literals are also supported directly in `mlang`:
118118+119119+```mlang
120120+{ answer = 42, flags = [true, false], note = "ok", empty = null }
121121+```
122122+123123+Fields and array elements may be `Int`, `Bool`, `String`, or existing `Data` expressions.
124124+98125`pmap name in expr => body` expects `expr` to evaluate to a native `Data` array. It evaluates `body` concurrently for each element bound to `name`, preserves input order, and returns a native `List` of native `Result` values instead of failing the whole traversal.
99126100127There is also a thread-first form that desugars statically to nested application:
···110137 => get x "answer"
111138```
112139113113-Files and REPL entries may contain multiple expressions separated by `;`. Each expression is parsed, typechecked, evaluated, and printed in order. `devenv shell -- run` now launches a Rust `rustyline` frontend for the REPL, while the Lean binary still handles evaluation. Use `:quit` to exit the REPL.
140140+Files and REPL entries may contain multiple expressions separated by `;`. Each expression is parsed, typechecked, evaluated, and printed in order. REPL-specific bare `let` bindings persist across later entries. `devenv shell -- run` now launches a Rust `rustyline` frontend for the REPL, while the Lean binary still handles evaluation. Use `:quit` to exit the REPL.
114141115142The checked-in sample program is [examples/samples.mlg](/home/nandi/code/mlang/examples/samples.mlg:1), which now contains the old demo coverage as semicolon-separated expressions, including file IO, Nickel parsing, threading, `pmap`, local error handling, and an HTTP fetch. It reads from [examples/sample.ncl](/home/nandi/code/mlang/examples/sample.ncl:1).
116143···118145119146## Next steps
120147121121-- persist top-level bindings across REPL entries
122148- add recursive functions
123149- add algebraic data types and pattern matching
124150- compile to a bytecode VM or another backend