Zordoz (original) (raw)
8.15
Zordoz is a tool for exploring .zo bytecode files. It offers a simple command-line interface for exploring string representations of bytecode structures.
These files describe the REPL and the API functions supporting it. Jump to the bottom of the REPL section for example usage.
1 Overview🔗ℹ
1.1 Quickstart🔗ℹ
To install, either use raco
raco pkg install zordoz
Or clone the repository and install manually, via raco.
$ git clone https://github.com/bennn/zordoz $ raco pkg install zordoz/
Zordoz provides a raco command. To see help information, run:
raco zordoz --help
1.1.1 Explorer🔗ℹ
The default mode is to interactively explore a bytecode file. Assuming FILE.zo is a compiled file on your computer,
raco zordoz FILE.zo
will start a REPL session. Type help at the REPL to see available commands. See REPL for a detailed explanation of each.
1.1.2 Automated Search🔗ℹ
To search a bytecode file for occurrences of a certain zo struct, use the -f flag. (This flag may be supplied more than once.)
raco zordoz -f STRUCT-NAME FILE.zo
The number of occurrences of each struct will be printed to the console. For example:
$ raco zordoz -f branch -f lam private/compiled/zo-string_rkt.zo INFO: Loading bytecode file 'private/compiled/zo-string_rkt.zo'... INFO: Parsing bytecode... INFO: Parsing complete! Searching... FIND 'branch': 427 results FIND 'lam': 433 results All done!
1.1.3 Just Print the Parsed Bytecode🔗ℹ
$ raco zordoz -p compiled/foo_rkt.zo
1.2 Testing🔗ℹ
Each source file contains a module+ test with unit tests. Run them all with:
raco test zordoz
or individually using:
raco test FILE.rkt
1.3 Project Goals🔗ℹ
Racket offers a de-compilation API, however the structs it produces are still dense reading. This project takes a de-compiled zo struct and offers:
- A string representation of the struct, with name and fields clearly labeled.
- Interactive exploration of the struct’s fields.
- A simple search interface for finding patterns nested within a struct.
This library should be available to as many versions of Racket as possible, and kept up-to-date.
We also hope to add more features, especially a tool for comparing two bytecode files.Feedback and suggestions appreciated!
2 REPL🔗ℹ
2.1 Summary |
---|
2.2 Commands |
2.2.1 alst |
2.2.2 back |
2.2.3 dive |
2.2.4 find |
2.2.5 help |
2.2.6 info |
2.2.7 jump |
2.2.8 save |
2.2.9 quit |
2.3 Sample Interaction |
The REPL is a simple, interactive way to explore bytecode files. This document is a users’ guide for the REPL. See the API page for alternate ways of starting a REPL (besides the command line).
2.1 Summary🔗ℹ
The REPL works by storing an internal context and reacting to commands. This context is either:
- A zo struct
- A list of zo structs
- Search results, obtained by calling find.
The commands observe or advance this context. Commands may be separated by newlines or semicolons.
For convenience, the REPL records previous states. We call this recorded past the history of the REPL; it is a stack of contexts.
Keeping this stack in mind is useful for understanding the REPL commands.
2.2 Commands🔗ℹ
2.2.1 alst🔗ℹ
List all command aliases.
For uniformity, the canonical name of each command has 4 letters. But each has a few mnemonic aliases to choose from. For example, you can type ls instead of info and cd instead of dive.
2.2.2 back🔗ℹ
Move up to the previous context.
Each successful dive or find command changes the current context to new struct or list. Before making these transitions, we save the previous context to a stack. The back command pops and switches to the most recent element from this stack.
Note that back will fail (and print a warning) at the top of the zo struct hierarchy or the top of a saved subtree.
2.2.3 dive🔗ℹ
Enter a struct’s field.
This is where exploring happens. Each struct has a few fields; you can see these by printing with info. Any field containing zo structs is a candidate for dive. For example, the struct assign has a field rhs, which can be accessed by:
If you know where you are going, you can chain paths together. Starting at a beg0 struct, this command moves to the first expr or seq in the sequence.
Extra Notes:
- Only fields that contain zo structures or lists of zo structures may be explored.
- Changing to a zo structure field changes the context to the child zo structure. Changing to a list field changes context to that list, from which you can select a natural-number position in the list to explore.
- dive takes exactly one argument. Any more or less is not permitted.
2.2.4 find🔗ℹ
Search the current struct’s children for a certain zo struct.
Find uses string matching to automate a simple search process. Give it a string, for instance find lam structs nested within the current context. The string must be the name of a zo struct—anything else will return null results.
A successful find changes context to a list of zo structs. Exploring any element of the list changes the current history to be that element’s history. You are free to explore the children and parents of any struct returned by a find query. Use jump to immediately return to the search results.
Note:
- If, after exploring a search result, you move back past the list of search results, the REPL will print a notice.
2.2.5 help🔗ℹ
Print command information.
Shows a one-line summary of each command. The tabernacle is all-knowing.
2.2.6 info🔗ℹ
Print the current context.
This info command does the real work of exploring. It shows the current context, whether struct or list. Lists give their length and the names of their elements. Zo structs show their name, their fields’ names, and their fields’ values.
Struct fields are printed as best we can.
- Fields which are zo structures print their names. These fields may be dive-ed into.
- Fields which are lists containing at least one zo structure are printed with a natural number in square braces, indicating the number of zo structs inside the list. These fields may also be dived into.
- Other fields are printed with Racket’s default printer. Be aware, lists and hashes can sometimes cause very large printouts.
2.2.7 jump🔗ℹ
Warp back to a previously-saved context.
The commands jump and save work together. After saving or making a successful query with find, the current history is saved. At this point, a step backwards will recover this history. The interesting thing is that steps forward create a new history, and you can immediately forget that new history by calling jump.
For example, if you call find and explore one of the results, you can immediately jump back to your search results.
2.2.8 save🔗ℹ
Mark the current context and history as a future target for jump. This is useful for marking a struct you want to backtrack to.
Note that, if you manually backtrack past a saved struct then its mark disappears and the REPL prints a notice.
2.2.9 quit🔗ℹ
Exit the REPL.
2.3 Sample Interaction🔗ℹ
Let’s explore the REPL’s own bytecode. Starting from the directory you cloned this repo to (or where ‘raco‘ put it on your filesystem):
$ raco zordoz private/compiled/zo-string_rkt.zo INFO: Loading bytecode file 'private/compiled/zo-string_rkt.zo'... INFO: Parsing bytecode... INFO: Parsing complete! --- Welcome to the .zo shell,version 1.0 'vortex'--- zo>
Now we can start typing commands, like info.
zo> info zo:compilation-top max-let-depth : 31 prefix : zo:prefix code : zo:mod
Next, let’s try a dive.
zo> dive max-let-depth 'dive max-let-depth'not permitted.
Didn’t work! That’s because max-let-depth is an integer. Let’s try one of the structs.
zo> dive prefix zo> info zo:prefix num-lifts : 0 toplevels : [#f] stxs : []
Great! We can’t dive any further from here, so let’s go back up.
zo> back zo> info zo:compilation-top max-let-depth : 31 prefix : zo:prefix code : zo:mod
And we’re back to where we began. From here we could dive to the code field and print it, but the printout is a little overwhelming. The module we’re exploring, zo-string, creates over 40 different functions. There’s just a lot of data to look at, and because it’s heterogenous data we do not have a nice way of truncating it.
Instead, we’ll try the find command. Be warned, the search might take a minute.
zo> find compilation-top FIND returned 0 results
Zero results is good: there should not be any other compilation-top structs besides the one we’re currently in. Now try searching for something else, like branch.
zo> find branch FIND returned 422 results FIND automatically saving context zo:branch[422]
Wow! Over 400 results. We can start exploring one of them:
zo> dive 17 zo> info zo:branch test : zo:application then : zo:seq else : zo:branch
We can also explore its children and parents.
zo> dive test zo> info zo:application rator : zo:primval rands : [zo:localref] zo> dive rator zo> info zo:primval id : 90 zo> up zo> up zo> info zo:branch test : zo:application then : zo:seq else : zo:branch zo> up zo> info zo:branch test : zo:localref then : zo:branch else : #f
And if we do a jump, we return to the search results.
zo> jump zo> info zo:branch[422]
3 API🔗ℹ
These functions support the REPL, but may be useful in more general settings. Import them with (require zordoz).
3.1 Starting a REPL🔗ℹ
Start a REPL to explore a .zo bytecode file.
Start a REPL to explore a zo struct.
Start a REPL to explore a syntax object. First compiles the syntax to a zo representation.
3.2 String Representations🔗ℹ
These tools convert a zo structure to a pretty-printed string, or a more structured representation.
Convert a zo struct into a string. When the optional argument #:deep? is set, include the struct’s fields in the string representation. Otherwise, only print the name.
Examples:
(zo->spec z) → spec/c z : zo?
Convert a zo struct into a spec/c representation. A spec/c is a list containing:
- A string, representing its name.
- Pairs, representing the struct’s fields. The first element of each pair should be a string representing the field name. The second element should be a thunk that, when forced, yields either a string or another spec.
The thunks delay pretty-printing an entire nested struct.
Examples:
> (zo->spec (primval 129)) '("primval" ("id" . #procedure:...ivate/zo-string.rkt:87:26)) > (zo->spec (branch (= 3 1) "true" 'false)) '("branch" ("test" . #procedure:...ivate/zo-string.rkt:87:26) ("then" . #procedure:...ivate/zo-string.rkt:87:26) ("else" . #procedure:...ivate/zo-string.rkt:87:26))
3.3 Traversing zo Structs🔗ℹ
Racket does not provide a reflective way of accessing struct fields at runtime. So we provide a function that does this by-force, just for zo structures.
Identify what specific zo struct z is, then access its field named str, if any. The multiple return values deal with the following cases:
- If the field str does not exist, or does not denote a zo struct, return the argument z and the boolean value #f.
- If the field str denotes a list and we can parse zo structs from the list, return a list of zo structs and the boolean #t.
- (Expected case) If the field points to a zo struct, return the new zo struct and the boolean #t.
Examples:
#f '#s((primval expr 0 form 0 zo 0) 42) #f '#s((primval expr 0 form 0 zo 0) 42) #t '#s((primval expr 0 form 0 zo 0) 42)
3.4 Searching Structs🔗ℹ
If you know the name of the zo struct you hope to find by exploring a subtree, you can automate the exploring. Literally, find is repeated application of zo->string and zo-transition.
(zo-find z str [#:limit lim]) → (listof result?) z : zo? str : string? lim : (or/c natural-number/c #f) = #f
Starting with the children of the struct z, search recursively for struct instances matching the string str. For example, if str is application then find will return all application structs nested below z.
The return value is a list of result structs rather than plain zo structs because we record the path from the argument z down to each match.
Examples:
(list (result '#s((seq expr 0 form 0 zo 0) (#s((seq expr 0 form 0 zo 0) ()) #s((seq expr 0 form 0 zo 0) ()))) '()) (result '#s((seq expr 0 form 0 zo 0) (#s((seq expr 0 form 0 zo 0) ()) #s((seq expr 0 form 0 zo 0) ()))) '())) '(#s((primval expr 0 form 0 zo 0) 0) #s((primval expr 0 form 0 zo 0) 1) #s((primval expr 0 form 0 zo 0) 2))
(result-zo result) → zo? result : zo-result?
Converts a zo-result? to the found zo? field. See zo-find.
#:transparent) z : zo? path : (listof zo?)
A result contains a zo struct and a path leading to it from the search root. In the context of find, the path is always from the struct find was called with.
(find-all fname qry* [#:limit lim]) → void? fname : path-string? qry* : (Listof String) lim : (or/c natural-number/c #f) = #f
Apply find iteratively on the bytecode file fname. Print the results for each string in the list qry* to current-output-port.
3.5 Compiling and Decompiling🔗ℹ
Tools for compiling syntax fragments rather than entire modules.
Compiles a syntax object to a zo struct.
Examples:
> (syntax->zo #'6) '#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!)) () 6) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#() '#())) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet")))))) > (syntax->zo #'(member 'a '(a b c))) '#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!) (member)) () (member 'a '(a b c))) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#(#(racket/base) #("private/base.rkt" 0) #("pre-base.rkt" 1) #("member.rkt" 2)) '#(3))) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list (module-use (unsafe-vector*-ref .mpi-vector 0) 0)))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet")))))) > (syntax->zo #'(if #t 'left 'right)) '#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!)) () 'left) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#() '#())) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet"))))))
Compiles a syntax object, then immediately decompiles the compiled code back to an S-expression. Similar to syntax->zo, except the final output is Racket code and not a zo structure.
Examples:
> (syntax->decompile #'6) 6 > (syntax->decompile #'(member 'a '(a b c))) '(member 'a '(a b c)) > (syntax->decompile #'(if #t 'left 'right)) ''left
Converts a compiled expression into a zo struct. Differs from zo-parse in that the input is expected to be acompiled-expression?. This function is the inverse of zo->compiled-expression.
Examples:
> (compiled-expression->zo (compile-syntax #'6)) '#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!)) () 6) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#() '#())) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet")))))) > (compiled-expression->zo (compile-syntax #'(member 'a '(a b c)))) '#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!) (member)) () (member 'a '(a b c))) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#(#(racket/base) #("private/base.rkt" 0) #("pre-base.rkt" 1) #("member.rkt" 2)) '#(3))) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list (module-use (unsafe-vector*-ref .mpi-vector 0) 0)))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet")))))) > (compiled-expression->zo (compile-syntax #'(if #t 'left 'right))) '#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!)) () 'left) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#() '#())) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet"))))))
Transform a zo struct to compiled code. The compiled code can be run with eval. If the struct z encodes a module (i.e., contains a mod sub-struct) then the result zo->compiled-expressions z can be written to a .rkt file and run using the Racket executable.
Example:
Variant of syntax->zo, except can handle top level syntax expressions. Uses eval-compile-time-part-of-top-level/compile to compile syntax rather than just compile. As such, this function returns a list of zo structs rather than just one.
Example:
'(#s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!)) (x) #s(faslable-correlated (define-values (x) 5) eval 21 21 0 1 #f) (if #f (begin (set! x #f)) (void)) (begin (.top-level-bind! (unsafe-vector*-ref .syntax-literals 0) (unsafe-vector*-ref .mpi-vector 0) 0 .phase .namespace 'x #f '#f))) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#(top #(racket) #(racket/base) #(racket/undefined)) '#(0 1 2 3))) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list))) (define-values (.syntax-literals) (let-values (((ns+stxss) (let-values (((data) '#(#(#:representative-scope module -2 #:representative-scope module -1 #:representative-scope module 0 #:scope) #(#hasheq() #:multi-scope top-level #:hasheqv 3 -2 #:ref 0 -1 #:ref 1 0 #:ref 2 #:seteq 1 #:shifted-multi-scope 0 #:ref 5 #:seteq 1 #:ref 3 #:seteq 2 #:ref 3 #:ref 2 #:seteq 2 #:ref 3 #:ref 1) #(#:representative-scope-fill! #:table-with-bulk-bindings #:ref 4 #:cons #:bulk-binding-at #:seteq 2 #:ref 3 #:ref 0 #:bulk-binding #f #:ref 4 #:mpi 1 2 0 #:bulk-binding-registry () #:ref 5 #:representative-scope-fill! #:table-with-bulk-bindings #:ref 4 #:list 2 #:bulk-binding-at #:ref 9 #:bulk-binding #f #:ref 4 #:mpi 1 1 0 #:bulk-binding-registry #:bulk-binding-at #:ref 9 #:bulk-binding #f #:ref 4 #:mpi 2 1 0 #:bulk-binding-registry #:ref 5 #:representative-scope-fill! #:table-with-bulk-bindings #:hasheq 1 x #:hash 1 #:ref 8 #:simple-module-binding #:mpi 0 x 0 #:mpi 0 #:list 3 #:bulk-binding-at #:ref 8 #:bulk-binding #f #:ref 4 #:mpi 1 0 0 #:bulk-binding-registry #:bulk-binding-at #:ref 8 #:bulk-binding #f #:ref 4 #:mpi 3 0 0 #:bulk-binding-registry #:bulk-binding-at #:ref 8 #:bulk-binding #f #:ref 4 #:mpi 2 0 0 #:bulk-binding-registry #:ref 5 #f) #(#:list 2 #:syntax #:vector 2 #:syntax post #:vector 3 #:ref 4 #:ref 6 () #f #:syntax other #:vector 3 #:ref 7 #:ref 4 () #f #:vector 3 #:ref 4 #:ref 4 () #f #:syntax x #:vector 3 #:ref 7 #:ref 6 () #:srcloc eval 21 0 21 1)))) (deserialize .mpi-vector .inspector .bulk-binding-registry '4 (unsafe-vector*-ref data 0) '6 (unsafe-vector*-ref data 1) (unsafe-vector*-ref data 2) (unsafe-vector*-ref data 3))))) (let-values (((ns-scope-s) (car ns+stxss))) (list->vector (map (lambda (stx) (swap-top-level-scopes (syntax-module-path-index-shift (syntax-shift-phase-level stx (- 0 .dest-phase)) (unsafe-vector*-ref .mpi-vector 0) .self) ns-scope-s .namespace)) (cdr ns+stxss))))))) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet")))))) #s((linkl-directory zo 0) #hash((() . #s((linkl-bundle zo 0) #hasheq((0 . #s(faslable-correlated-linklet (linklet ((.top-level-bind! .top-level-require!) (.mpi-vector .syntax-literals) (.namespace .phase .self .inspector .bulk-binding-registry .set-transformer!)) (x) x) module)) (link . #s(faslable-correlated-linklet (linklet ((deserialize-module-path-indexes syntax-module-path-index-shift syntax-shift-phase-level force-syntax-object module-use deserialize) (.namespace .dest-phase .self .bulk-binding-registry .inspector swap-top-level-scopes)) (.mpi-vector .deserialized-syntax-vector phase-to-link-modules .syntax-literals) (define-values (.mpi-vector) (deserialize-module-path-indexes '#() '#())) (define-values (.deserialized-syntax-vector) (make-vector 1 #f)) (define-values (phase-to-link-modules) (hasheqv 0 (list))) (define-values (.syntax-literals) #f)) #f)) (max-phase . 0) (original-phase . 0) (vm . #"linklet")))))))
3.6 Compiling C Modules🔗ℹ
Tools for compiling modules implemented in C.
Compiles a C module to a form where it can be required later.
See Inside: Racket C API for more information on how to build Racket modules in C.
WARNING:Do not replace the file produced by the functions while still inside the Racket VM. Doing so will cause undefined and potentially catastrophic behavior. As a general rule of thumb, if you modify a C file implementing a module, shut down all Racket VMs using that library. This means restarting DrRacket (not just reloading the file) whenever the C file is modified.
c-path is the path to the C file that implemented the module.
For example:
A convenience form to compile a C module and require it directly. Use outside of a require form is a syntax error.
c-path is the path to the C file that implements the module.
For example:
3.7 Typed API🔗ℹ
A typed version of this API is available with (require zordoz/typed).
A typed version of zordoz. Provided identifiers are: