{"id":13739674,"url":"https://github.com/bennn/zordoz","last_synced_at":"2026-02-25T11:03:46.572Z","repository":{"id":24403946,"uuid":"27804424","full_name":"bennn/zordoz","owner":"bennn","description":"Manipulating racket bytecode","archived":false,"fork":false,"pushed_at":"2021-10-24T23:56:48.000Z","size":4648,"stargazers_count":25,"open_issues_count":10,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-06-03T21:42:11.440Z","etag":null,"topics":["racket"],"latest_commit_sha":null,"homepage":null,"language":"Racket","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bennn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-10T05:46:16.000Z","updated_at":"2023-04-18T17:19:35.000Z","dependencies_parsed_at":"2022-08-22T17:31:26.241Z","dependency_job_id":null,"html_url":"https://github.com/bennn/zordoz","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/bennn/zordoz","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennn%2Fzordoz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennn%2Fzordoz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennn%2Fzordoz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennn%2Fzordoz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bennn","download_url":"https://codeload.github.com/bennn/zordoz/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bennn%2Fzordoz/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270065443,"owners_count":24520946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"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":["racket"],"created_at":"2024-08-03T04:00:36.423Z","updated_at":"2025-10-27T22:10:21.851Z","avatar_url":"https://github.com/bennn.png","language":"Racket","funding_links":[],"categories":["Racket","Compilers"],"sub_categories":["Platform"],"readme":"Zordoz\n======\n[![Build Status](https://travis-ci.org/bennn/zordoz.svg)](https://travis-ci.org/bennn/zordoz)\n[![Coverage Status](https://coveralls.io/repos/bennn/zordoz/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/bennn/zordoz?branch=master)\n[![Scribble](https://img.shields.io/badge/Docs-Scribble-blue.svg)](http://docs.racket-lang.org/zordoz/index.html)\n\n[ZORDOZ](https://www.youtube.com/watch?v=kbGVIdA3dx0) speaks to you! His chosen ones.\n\n\nThis is an explorer for Racket .zo files.\n\nTested to work on Racket `v6.5`\nFor compatibility with older versions, see the\n  [v6.1](https://github.com/bennn/zordoz/tree/v6.1)\n  and\n  [v6.2](https://github.com/bennn/zordoz/tree/v6.2)\n  and\n  [v6.3](https://github.com/bennn/zordoz/tree/v6.3)\n  branches of this repo.\n(Note that installing through `raco` will choose the available version, if any, matching your Racket install.)\n\nTyped Racket users can `(require zordoz/typed)` for type-annotated bindings from `zordoz`.\nAlso, `zordoz/typed/zo-structs` is a safe wrapper around Racket's [compiler/zo-structs](http://docs.racket-lang.org/raco/decompile.html#%28mod-path._compiler%2Fzo-structs%29) library.\n\n\nInstall\n-------\n\nYou have two options.\n\n1. Install from `raco` by running `raco pkg install zordoz`\n2. Build from source by cloning this repo and using `raco`:\n   `git clone https://github.com/bennn/zordoz; raco pkg install zordoz/`\n\nTo run tests, do `raco test zordoz`.\nTests are located in the `test` submodule of each source file.\n\n\nUsage\n-----\n\nZordoz provides a `raco zordoz` command.\n\n### REPL\n\nActivate the REPL by giving a path to a compiled file.\n\n```\nraco zordoz FILE.zo\n```\n\nPassing the `-t` option uses typed racket code.\nBeware, the typed racket version is up to 5x slower than untyped because of contracts with the `compiler/zo-lib` structs.\n\nThe REPL accepts the following commands:\n\n- `alst` prints all command aliases; for example, the repl treats the words 'alst' and 'aliases' the same way\n- `back` goes back to the previous context\n- `dive ARG` changes context to a new zo struct or list (other dives are not permitted)\n- `find ARG` searches for matches to `ARG` and, if successful, changes context to the list of results\n- `help` prints information about these commands\n- `info` prints data about the current context\n- `jump` reverts to a previously saved context\n- `save` marks the current context as a target for `jump`\n- `quit` exits the interpreter\n\nThe functions implementing the `dive`, `find`, and `info` commands are available outside the REPL.\nCheck the [guide](http://bennn.github.io/zordoz) for a summary.\n\n### Quick Search\n\nRunning:\n\n```\n./zordoz -f branch -f lam -f closure FILE.zo\n```\n\nWill count and print the number of times the zo structs [branch](http://docs.racket-lang.org/raco/decompile.html#%28def._%28%28lib._compiler%2Fzo-structs..rkt%29._branch%29%29) [lam](http://docs.racket-lang.org/raco/decompile.html#%28def._%28%28lib._compiler%2Fzo-structs..rkt%29._lam%29%29) and [closure](http://docs.racket-lang.org/raco/decompile.html#%28def._%28%28lib._compiler%2Fzo-structs..rkt%29._closure%29%29) appear.\nThis may take a while, depending on the size of the bytecode file.\nYou can limit the search depth by passing a natural number with the `-l` flag.\n\nSee the [decompilation guide](http://docs.racket-lang.org/raco/decompile.html#%28mod-path._compiler%2Fzo-structs%29) for a list of all zo struct names.\n\n\nBackground\n----------\n\nRacket bytecode is stored in files with a `.zo` [extension](http://docs.racket-lang.org/raco/make.html).\nThis tool makes it easier to explore the bytecode representation of a file, whether or not you have access to the file's source code.\n\nGiven a `.zo` file, we decompile the bytecode into a struct (aka, a \"zo-struct\") using Racket's built-in [decompilation API](http://docs.racket-lang.org/raco/decompile.html).\nThe REPL loads this struct as its initial _context_ and begins accepting commands, making it easy to visualize and explore Racket bytecode.\n\nExample\n-------\n\nSuppose we create and compile a small racket file:\n```\n\u003e echo -e \"#lang racket/base\\n(if #t (+ 1 1) 0)\" \u003e test.rkt\n\u003e raco make test.rkt\n```\n\nThe actual bytecode is not human readable.\nNeither is the struct representation output by `zo-parse`:\n```\n\u003e echo -e '#lang racket/base\\n(require compiler/zo-parse)\\n(call-with-input-file \"compiled/test_rkt.zo\"\\n  (lambda (fd) (displayln (zo-parse fd))))' \u003e print-test.rkt\n\u003e racket print-test.rkt\n#s((compilation-top zo 0) 0 #s((prefix zo 0) 0 (#f) ()) #s((mod form 0 zo 0) test test #\u003cmodule-path-index\u003e #s((prefix zo 0) 0 (#s((module-variable zo 0) #\u003cmodule-path-index\u003e print-values 0 0 #s((function-shape zo 0) #(struct:arity-at-least 0) #f))) ()) ((0 () ()) (1 () ()) (#f () ())) ((0 #\u003cmodule-path-index\u003e) (1) (-1) (#f)) (#s((apply-values expr 0 form 0 zo 0) #s((toplevel expr 0 form 0 zo 0) 0 0 #t #t) 2)) () ((0 () ())) 0 #s((toplevel expr 0 form 0 zo 0) 0 0 #f #f) #f #t () (#s((mod form 0 zo 0) (test configure-runtime) configure-runtime #\u003cmodule-path-index\u003e #s((prefix zo 0) 0 (#s((module-variable zo 0) #\u003cmodule-path-index\u003e configure 0 0 #s((function-shape zo 0) 1 #f))) ()) ((0 () ()) (1 () ()) (#f () ())) ((0 #\u003cmodule-path-index\u003e #\u003cmodule-path-index\u003e) (1) (-1) (#f)) (#s((application expr 0 form 0 zo 0) #s((primval expr 0 form 0 zo 0) 1000) (#t))) () ((0 () ())) 1 #s((toplevel expr 0 form 0 zo 0) 0 0 #f #f) #f #t () () ())) ()))\n```\n\nZORDOZ offers a more readable presentation.\nBelow is a sample interactive session with the same small file (interspersed with commentary):\n\n```\n\u003e racket zordoz.rkt compiled/test_rkt.zo \nINFO: Loading bytecode file 'compiled/test_rkt.zo'...\nINFO: Parsing bytecode...\nINFO: Parsing complete!\n--- Welcome to the .zo shell, version 0.1 'outlands' ---\nzo\u003e info\n\u003cstruct:compilation-top\u003e\n  max-let-depth : 0\n  prefix        : \u003cstruct:prefix\u003e\n  code          : \u003cstruct:mod\u003e\n```\n\nThe `compilation-top` struct is at the top of most every `.zo` file.\nThings get more interesting as we explore the structs nested inside it.\n\n```\nzo\u003e dive code\nzo\u003e info\n\u003cstruct:mod\u003e\n  name             : test\n  srcname          : test\n  self-modidx      : #\u003cmodule-path-index\u003e\n  prefix           : \u003cstruct:prefix\u003e\n  provides         : 0 [] [] 1 [] [] #f [] []\n  requires         : 0 #\u003cmodule-path-index\u003e 1  -1  #f \n  body             : \u003cstruct:apply-values\u003e\n  syntax-bodies    :\n  unexported       : 0\n  max-let-depth    : 0\n  dummy            : \u003cstruct:toplevel\u003e\n  lang-info        : #f\n  internal-context : #t\n  flags            :\n  pre-submodules   : \u003cstruct:mod\u003e[1]\n  post-submodules  : []\n```\n\nThe `mod` struct represents a Racket module.\nThis module has the name `test`; inferred from our filename `test.rkt`.\n\nWe could continue `dive`-ing into structs, or we can use the shell's `find` command to look for structs matching a name like `mod` or `compilation-top`.\nLet's search for `branch` structs.\nMaybe we can find the `if`-statement in our original code.\n\n```\nzo\u003e find branch\nFIND returned 0 results\n```\n\nNothing.\nThe `if`-statement has been optimized away.\nLet's try to find what it turned into by searching the body of the module.\n\n```\nzo\u003e dive body\nzo\u003e info\n(\u003cstruct:apply-values\u003e)[1]\n```\n\nThe syntax `(\u003cstruct:NAME\u003e)[LENGTH]` denotes a list of zo-structs.\n`LENGTH` is the number of elements in the list--we can `dive` into any valid index.\n\n```\nzo\u003e dive 0\nzo\u003e info\n\u003cstruct:apply-values\u003e\n  proc      : \u003cstruct:expr\u003e\n  args-expr : 2\n```\n\nLooks like our `if`-statement was optimized into a constant, `2`.\n\nHappy exploring!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbennn%2Fzordoz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbennn%2Fzordoz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbennn%2Fzordoz/lists"}