{"id":50342671,"url":"https://github.com/vivekg13186/z-lang","last_synced_at":"2026-05-29T18:00:47.241Z","repository":{"id":359993649,"uuid":"1248202997","full_name":"vivekg13186/z-lang","owner":"vivekg13186","description":"Small and functional script engine less than 5MB.","archived":false,"fork":false,"pushed_at":"2026-05-29T07:15:56.000Z","size":273,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T08:30:57.938Z","etag":null,"topics":["lisp-dialect","programming-language","script"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vivekg13186.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-24T10:25:12.000Z","updated_at":"2026-05-29T07:15:26.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vivekg13186/z-lang","commit_stats":null,"previous_names":["vivekg13186/z_lang","vivekg13186/z-lang"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/vivekg13186/z-lang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekg13186%2Fz-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekg13186%2Fz-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekg13186%2Fz-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekg13186%2Fz-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vivekg13186","download_url":"https://codeload.github.com/vivekg13186/z-lang/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekg13186%2Fz-lang/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33664259,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lisp-dialect","programming-language","script"],"created_at":"2026-05-29T18:00:45.939Z","updated_at":"2026-05-29T18:00:47.234Z","avatar_url":"https://github.com/vivekg13186.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# z — Mini Script Language\n\n# Objective\nTo make a small and functional script engine less than 5MB size.\n\n\nA tiny Lisp-flavoured language and tree-walking interpreter written in C99.\nNo external dependencies beyond the standard library, and the same code\nbuilds on **macOS**, **Linux**, and **Windows**.\n\nShips as two binaries:\n\n- **`z`** — the interpreter; runs `.z` files and a basic REPL.\n- **`zide`** — an enhanced REPL with live syntax highlighting, Tab\n  autocompletion, and history (see [zide — enhanced REPL](#zide--enhanced-repl)).\n\nSource files use the `.z` extension.\n\n## Install\n\nWindows users then run:\n\n```\nscoop bucket add z https://github.com/vivekg13186/scoop-z\nscoop install z-lang\n```\n\n\n## Build\n\n### macOS / Linux\n\n```\nmake            # builds both z and zide\nmake test\n```\n\n`make` compiles both binaries into `dist/\u003cos\u003e_\u003carch\u003e/` — e.g. `dist/linux_x86/z`\nand `dist/linux_x86/zide` on Linux x86_64, `dist/macos_arm64/...` on Apple\nSilicon, and so on. For convenience it also creates `./z` and `./zide`\nsymlinks at the project root pointing at the right platform folder, so you can\njust run them from there:\n\n```\n./z examples/adults.z      # the interpreter\n./zide                     # the enhanced REPL\nmake zide                  # build only zide\nmake info                  # prints platform, arch, and bin paths\n```\n\nYou need a C compiler (`cc`/`gcc`/`clang`). On macOS run `xcode-select --install`\nonce if you've never done it. On Linux install `build-essential` (Debian/Ubuntu)\nor the `gcc` package (Fedora/Arch).\n\n### Windows\n\nTwo options.\n\n**Option A — `build.bat`** (auto-detects MSVC or MinGW):\n\n```\nbuild.bat\nz.exe examples\\adults.z\nzide.exe\n```\n\nBuilds both `z.exe` and `zide.exe` into `dist\\windows_x86\\` and copies them to\nthe project root. Open a Developer Command Prompt if you want it to use MSVC's\n`cl`. Open a normal shell with `gcc` on PATH if you'd rather use MinGW-w64.\nPass `build.bat --image` to enable the optional image module.\n\n**Option B — CMake** (works with any generator: Visual Studio, Ninja, MinGW):\n\n```\ncmake -S . -B build\ncmake --build build --config Release\nbuild\\Release\\z.exe examples\\adults.z\n```\n\n### CMake (any platform)\n\n```\ncmake -S . -B build\ncmake --build build\n./build/z examples/hello.z\n```\n\n \n\n## Run\n\n```\nz                # start an interactive REPL\nz program.z      # run a source file\n```\n\n`make` builds two binaries: `z` (the interpreter + basic REPL) and `zide`\n(an enhanced REPL — see below). Both land in `dist/\u003cos\u003e_\u003carch\u003e/`.\n\n## zide — enhanced REPL\n\n`zide` is a richer interactive front end built on the same interpreter:\n\n- **Live syntax highlighting** as you type — comments, strings, numbers,\n  special forms, builtins, `${...}` interpolation, and brackets are colourised.\n- **Tab autocompletion** of special forms, builtins, and your own defined\n  variables (completes the common prefix, lists options when ambiguous).\n- **Arrow-key history** (shared `~/.z_history`), in-line editing\n  (`←`/`→`, `Home`/`End`, `Ctrl-A/E/K/L`), and bracket-aware multi-line input.\n- `help` / `?` for the cheat sheet, `:q` (or `:quit`) to exit.\n\n```\nmake            # builds both z and zide\n./zide          # launch it (root symlink → dist/\u003cos\u003e_\u003carch\u003e/zide)\n```\n\nResults are shown with a `=\u003e` prefix. Like `z`, `zide program.z` will just\nrun a file. When output isn't a terminal (piped/redirected) it degrades\ngracefully to plain, uncoloured behaviour.\n\nA quick session:\n\n```\n$ ./zide\nzide — enhanced REPL for z\nsyntax colouring · Tab completes · arrows for history · `help` for the cheat sheet · :q to quit\nzide\u003e (set xs (array 1 2 3 4))\n=\u003e [1, 2, 3, 4]\nzide\u003e (map (lambda (n) (* n n)) xs)\n=\u003e [1, 4, 9, 16]\nzide\u003e :q\nbye!\n```\n\n### REPL line editing\n\nThe REPL has a built-in line editor with command history:\n\n| Key            | Action                                  |\n| -------------- | --------------------------------------- |\n| `↑` / `↓`      | Navigate previous / next history entry  |\n| `←` / `→`      | Move cursor left / right                |\n| `Home` / `End` | Jump to start / end of line             |\n| `Ctrl-A` / `Ctrl-E` | Same as Home / End                 |\n| `Ctrl-K`       | Delete from cursor to end of line       |\n| `Ctrl-L`       | Clear the screen                        |\n| `Ctrl-C`       | Cancel the current line                 |\n| `Ctrl-D`       | Exit the REPL (on an empty line)        |\n\nHistory persists across sessions in `~/.z_history` (or `%USERPROFILE%\\.z_history` on Windows), up to 1000 entries.\n\n### Built-in help\n\nAt the REPL, type `help` (or `?`) to see a categorized cheat sheet, or\n`(help \"topic\")` for one section. Topics: `forms` `arith` `cmp` `logic`\n`arrays` `strings` `regex` `math` `core` `file` `json` `http` `system`\n(plus `image` when built with `IMAGE=1`).\n\n## What's implemented\n\n\n- **Values:** number, string, boolean, null, array, object, function\n- **Syntax:** s-expressions, line comments with `;`, `[ ... ]` parsed the same as `( ... )`\n- **Special forms:** `do`, `if`, `while`, `for`, `fn`, `lambda`, `set`, `try`/`catch`, `quote`, `\u0026\u0026` / `and`, `||` / `or`\n- **Variables:** `set`, bare-symbol lookup, dotted access (`user.name`), `(get container key ...)` chain\n- **Arithmetic:** `+ - * / %` (and `+` doubles as string concatenation when the first arg is a string)\n- **Comparison:** `\u003c \u003e \u003c= \u003e= == !=`\n- **Logic:** `\u0026\u0026` `||` `!` (also as `and` / `or`)\n- **Arrays:** `array`, `get`, `put`, `push`, `pop`, `length`, `reverse`, `sort`, `chunk`, `map`, `filter`, `reduce`\n- **Objects:** `object`, `get`, `put`, `keys`, `values`, `entries`\n- **Strings:** `concat`, `split`, `join`, `trim`, `lower`, `upper`, `replace`, `substring`, `between`, `levenshtein`, `reverse`, `starts-with`, `ends-with`, `contains`, `index-of`\n- **Template strings:** any `\"...\"` literal can embed `${expr}` — full z expressions evaluated in scope. Use `\\$` for a literal `$`.\n- **Regex:** `regex:test`, `regex:match`, `regex:find-all`, `regex:replace`, `regex:split` — supports `. * + ? ^ $ [...] [^...] \\d \\w \\s \\D \\W \\S`\n- **Math:** `min`, `max`, `floor`, `ceil`, `round`, `trunc`, `abs`, `sign`, `mod`, `sqrt`, `cbrt`, `pow`, `exp`, `log`, `log2`, `log10`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sinh`, `cosh`, `tanh`, `random`; constants `pi`, `e`\n- **I/O:** `print`, `read`, `read-lines`, `write`, `append`, `delete`, `list-dir`, `file-info`, `copy-file`, `move-file`\n- **JSON:** `json:parse`, `json:stringify`\n- **Encoding / crypto:** `base64:encode`, `base64:decode`, `encrypt`, `decrypt` (lightweight XTEA-CTR), `uuid` (v4), `md5`, `sha256`, `sha512`\n- **URL:** `url:encode`, `url:decode`, `url:build` (object → query string)\n- **Archives:** `zip:create`, `zip:extract` (need `zip`/`unzip`), `tar:create`, `tar:extract` (`gz`/`bz2`/`xz` compression)\n- **Parsing / input:** `scanf` — `%d %f %s %c` and literal text → array of values; reads stdin when called with just a format. `input [prompt]` reads a line from stdin.\n- **HTTP:** `http:get url [headers]`, `http:post url body [headers]` — headers is an object; delegates to `curl` (bundled with Windows 10 1803+, install via package manager elsewhere)\n- **System:** `type`, `assert`, `sleep`, `now`, `timestamp`, `format-date`, `env`, `exec`, `run`, `argv`, `exit`, `import`, `help`\n- **Errors:** `try`/`catch` with `setjmp`/`longjmp`\n\n## Quick taste\n\n```lisp\n(do\n    (set users\n        (array\n            (object \"name\" \"Alice\" \"age\" 20)\n            (object \"name\" \"Bob\"   \"age\" 15)\n        )\n    )\n\n    (for user users\n        (if (\u003e (get user \"age\") 18)\n            (print (concat (get user \"name\") \" is adult\"))\n        )\n    )\n)\n```\n\n## Running shell commands\n\n```lisp\n; Combined stdout+stderr as a string.\n(exec \"echo hello\")        ; → \"hello\\n\"\n\n; Structured result, never throws — check the code yourself.\n(run \"ls -1\")              ; → { \"stdout\": \"...\", \"code\": 0 }\n(run \"false\")              ; → { \"stdout\": \"\",    \"code\": 1 }\n\n; Pick up arguments the user passed to the z program:\n;   z myscript.z foo bar\n(argv)                     ; → [\"foo\", \"bar\"]\n```\n\n## Template strings and regex\n\n```lisp\n(set name \"vivek\")  (set yr 2026)\n\n\"hello ${name}\"                    ; → \"hello vivek\"\n\"next year: ${(+ yr 1)}\"           ; → \"next year: 2027\"\n\"len=${(length name)}\"             ; → \"len=5\"\n\"price: \\$${yr}\"                   ; → \"price: $2026\"      (escape with \\$)\n\n(regex:test     \"\\d+\" \"answer is 42\")              ; → true\n(regex:match    \"\\d+\" \"answer is 42\")              ; → \"42\"\n(regex:find-all \"\\d+\" \"a1 b22 c333\")               ; → [\"1\", \"22\", \"333\"]\n(regex:replace  \"\\d+\" \"have 3 cats, 4 dogs\" \"***\") ; → \"have *** cats, *** dogs\"\n(regex:split    \"[, ]+\" \"a, b,  c d\")              ; → [\"a\", \"b\", \"c\", \"d\"]\n```\n\nPattern syntax: `. * + ? ^ $ [class] [^class]` plus the shorthands `\\d \\w \\s \\D \\W \\S`.\n\n## HTTP\n\n```lisp\n; Simple GET / POST — unchanged.\n(http:get  \"https://example.com\")\n(http:post \"https://api.example.com/log\" (object \"level\" \"info\" \"msg\" \"hi\"))\n\n; Optional headers as an object on the last arg.\n(http:get \"https://api.example.com/users/42\"\n          (object \"Authorization\" \"Bearer abc\"\n                  \"Accept\"        \"application/json\"\n                  \"X-Request-Id\"  17))            ; numbers/booleans stringified\n\n; POST with custom headers — Content-Type defaults to application/json\n; for object bodies, text/plain for strings, but your override wins.\n(http:post \"https://api.example.com/upload\"\n           \"row1,row2,row3\"\n           (object \"Content-Type\" \"text/csv\"\n                   \"X-Trace\"      \"abc\"))\n```\n\nBodies are written to a temp file and passed via `--data-binary @\u003cfile\u003e`, so JSON with embedded quotes works on every shell. The temp file is deleted right after the call.\n\n## Optional modules\n\nSome functionality is gated behind compile-time flags so the core build\nstays lean. Pass the flag at build time to opt in.\n\n### Image manipulation — `IMAGE=1`\n\nBuiltins: `img:create`, `img:resize`, `img:crop`, `img:rotate`, `img:compose`, `img:replace-color`, `img:circle`, `img:rect`, `img:add-text`, `img:bw`, `img:grayscale`, `img:to-pdf`, `img:qr`, `img:barcode`, `img:info`.\n\n`img:qr` and `img:barcode` use extra tools instead of ImageMagick:\n`qrencode` for QR (`brew install qrencode` / `apt-get install qrencode`) and\n`zint` for barcodes (`brew install zint` / `apt-get install zint`).\n\n```\nmake IMAGE=1\n# or\ncmake -S . -B build -DZ_WITH_IMAGE=ON \u0026\u0026 cmake --build build\n# Windows:\nbuild.bat --image\n```\n\nRuntime requirement: **ImageMagick** must be on `PATH` (the module shells out\nto `magick` or `convert`).\n\n```\nmacOS:    brew install imagemagick\nLinux:    sudo apt-get install imagemagick     # or dnf install ImageMagick\nWindows:  scoop install imagemagick             # or the official MSI installer\n```\n\nQuick taste:\n\n```lisp\n(img:create   \"canvas.png\" 400 300 \"white\")\n(img:circle   \"canvas.png\" \"canvas.png\" 200 150 60 \"tomato\")\n(img:rect     \"canvas.png\" \"canvas.png\"  20 220 360 60 \"#eef\" \"black\" 2)\n(img:info     \"photo.jpg\")                     ; → { width, height, format }\n(img:resize   \"photo.jpg\" \"thumb.png\" 256 256)\n(img:crop     \"photo.jpg\" \"tile.png\"  50 50 200 200)\n(img:rotate   \"photo.jpg\" \"tilted.png\" 45)\n(img:add-text \"photo.jpg\" \"captioned.png\" \"hello\" 20 20 32 \"yellow\")\n(img:bw        \"photo.jpg\" \"scan.png\" 50)              ; 1-bit, 50% threshold\n(img:grayscale \"photo.jpg\" \"gray.png\")                 ; 8-bit grayscale\n(img:to-pdf    (array \"p1.png\" \"p2.png\" \"p3.png\") \"doc.pdf\")\n(img:qr        \"https://example.com\" \"qr.png\" 6)       ; QR code\n(img:barcode   \"012345678905\" \"code.png\" \"ean13\")      ; barcode\n```\n\nColours are anything ImageMagick accepts — named (`\"red\"`), hex (`\"#ff8800\"`), RGB (`\"rgb(0,128,255)\"`), or `\"none\"` for transparency.\n\n**PDF gotcha on Linux:** some distros ship ImageMagick with PDF write disabled by default. If `img:to-pdf` fails with \"not authorized\", edit `/etc/ImageMagick-6/policy.xml` (or `-7`) and change the `pattern=\"PDF\"` policy from `rights=\"none\"` to `rights=\"read|write\"`.\n\nIf you call any `img:*` function without `IMAGE=1` set, you'll get a clean\n\"undefined variable\" error — the module simply isn't registered.\n\n## Portability notes\n\n- A small platform layer at the top of `z.c` wraps the calls that differ\n  between POSIX and Win32 (`nanosleep` vs `Sleep`, `clock_gettime` vs\n  `GetSystemTimeAsFileTime`, `localtime_r` vs `localtime_s`, `popen` vs `_popen`).\n- JSON stringification uses an in-tree growing string buffer rather than\n  `open_memstream`, which isn't available on Windows.\n- `_POSIX_C_SOURCE` / `_DEFAULT_SOURCE` are only defined on non-Windows builds.\n- The binary depends only on the C standard library (`-lm` on POSIX). No third-party libraries.\n\n## Design\n\n- Single-file C99 implementation in `z.c`.\n- Tree-walking interpreter: the parser builds `Value` trees that the evaluator\n  walks directly. No bytecode or VM yet.\n- Memory model is arena-style leak — fine for short   scripts. A GC is\n  a natural next step.\n- Errors propagate through `setjmp`/`longjmp` so `try`/`catch` works cleanly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivekg13186%2Fz-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvivekg13186%2Fz-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivekg13186%2Fz-lang/lists"}