@@ -8,19 +8,19 @@
9A guide for new Urbit developers.
9A guide for new Urbit developers.
11−Problem statement: coder A has written some hoon, and you - coder B - need to jet it.
11+Problem statement: coder A has written some Hoon and you, coder B, need to jet it.
13Preconditions:
13Preconditions:
15- You have a pill `jetted.pill`, located in ~/tlon.
15- You have a pill `jetted.pill`, located in ~/tlon.
16−- You have an example of hoon code that, executed in dojo, does the right thing.
16+- You have an example of Hoon code that, executed in dojo, does the right thing.
18## Get all the source code you need.
18## Get all the source code you need.
20The source code you will need to modify lives in two different repos:
20The source code you will need to modify lives in two different repos:
21urbit and arvo. The urbit repo has the source code for the
21urbit and arvo. The urbit repo has the source code for the
22interpreter / personal server, written in C. The arvo repo has the
22interpreter / personal server, written in C. The arvo repo has the
23−operating system, written in hoon. Since you're jetting the hoon, you
23+operating system, written in Hoon. Since you're jetting the Hoon, you
24need to modify both.
24need to modify both.
26For simplicity, I'm going to assume that you are doing all of your
26For simplicity, I'm going to assume that you are doing all of your
@@ -45,25 +45,24 @@ your development elsewhere, if you like, and make a symbolic link.
46## Add new subprojects / libraries to urbit, if necessary
46## Add new subprojects / libraries to urbit, if necessary
48−If we have a complicated hoon function that, say, computes square
48+If we have a complicated Hoon function that, say, computes square
49roots, we need to speed it up, and there is an open source library
49roots, we need to speed it up, and there is an open source library
50libsquareroots, adding libsquareroots to our build might solve 90% of
50libsquareroots, adding libsquareroots to our build might solve 90% of
51our problems.
51our problems.
53−If this describes your task, read this section. If not, skip to the next section - none of this is necessary.
53+If this describes your task, read this section. If not, skip to the next section -- none of this is necessary.
55+ have someone with github.com/urbit repo privileges fork libsquareroots into github.com/urbit
55+ have someone with github.com/urbit repo privileges fork libsquareroots into github.com/urbit
56+ fork this new repo github.com/urbit/libsquareroots
56+ fork this new repo github.com/urbit/libsquareroots
57+ cd ~tlon/urbit/subprojects
57+ cd ~tlon/urbit/subprojects
58+ git submodule add <url>
58+ git submodule add <url>
59+ edit ~tlon/urbit/subprojects/meson.build
59+ edit ~tlon/urbit/subprojects/meson.build
60− - add a line `<foo>_dep = dependency('<foo>', version: '>=0.1.0', fallback: ['<foo>', '<foo>_dep'])`
60+ + add a line `<foo>_dep = dependency('<foo>', version: '>=0.1.0', fallback: ['<foo>', '<foo>_dep'])`
61− - add `<foo>_dep` to the list of dependencies at the bottom of the file. Remember to use a comma.
61+ + add `<foo>_dep` to the list of dependencies at the bottom of the file. Remember to use a comma.
63+ generate a meson.build for the new subproject: cd subprojects/<new directory>; meson wrap promote subprojects/secp256k1
62+ generate a meson.build for the new subproject: cd subprojects/<new directory>; meson wrap promote subprojects/secp256k1
64+ edit the meson.build until it works ("works" is defined as "in the top level ~/tlon/urbit invoking scripts/build builds the library and links it into the urbit executable")
63+ edit the meson.build until it works ("works" is defined as "in the top level ~/tlon/urbit invoking scripts/build builds the library and links it into the urbit executable")
65−+ git add meson.build ; git commit -m"now builds with meson for Tlon" .
64++ git add meson.build ; git commit -m "now builds with meson for Tlon" .
66−+ cd .. ; git add .gitmodules ; git commit -m"added submodule" .
65++ cd .. ; git add .gitmodules ; git commit -m "added submodule" .
67+ test the whole thing by
66+ test the whole thing by
69 + rm -rf urbit
68 + rm -rf urbit
@@ -76,35 +75,42 @@ If this describes your task, read this section. If not, skip to the next sectio
76+ submit a pull request from your copy of <libsquareroots> to the urbit copy
75+ submit a pull request from your copy of <libsquareroots> to the urbit copy
77+ submit a pull request from your copy of urbit to the urbit copy
76+ submit a pull request from your copy of urbit to the urbit copy
80### If the submodule is modified
78### If the submodule is modified
82The steps above add a submodule to the urbit repo. Or, more specifically, they add a specific version of the submodule to the repo.
80The steps above add a submodule to the urbit repo. Or, more specifically, they add a specific version of the submodule to the repo.
84−If the submodule has commits made to it (perhaps, the urbit repo will not track those new commits. XXXX)
82+If the submodule has commits made to it after that point in time, the urbit repo will not automatically track those new commits.
84+To make urbit use an updated version of the submodule:
86++ change to the submodule directory: `cd submodule_dir`
87++ checkout desired branch: `git checkout master`
89++ get back to your project root : `cd ..`
90++ now the submodules are in the state you want, so: `git commit -am "Pulled down update to submodule_dir"`
86## Edit the source code
92## Edit the source code
88There are several things you're going to do:
94There are several things you're going to do:
90−+ hint the hoon code, so that the urbit interpreter will know to look for C code
96++ hint the Hoon code, so that the urbit interpreter will know to look for C code
91+ for each jet you want you're going to declare two functions in two .h files (one takes the arguments as separate arguments, one takes them as one big tree)
97+ for each jet you want you're going to declare two functions in two .h files (one takes the arguments as separate arguments, one takes them as one big tree)
92+ then implement the two C functions in a single .c file
98+ then implement the two C functions in a single .c file
93−+ register the new C jet functions so the urbit interpretter knows the names / function pointers of the C funcs
99++ register the new C jet functions so the urbit interpreter knows the names / function pointers of the C funcs
95### Edit the Hoon Source code
101### Edit the Hoon Source code
97−Let's edit the hoon source code first.
103+Let's edit the Hoon source code first.
99There are multiple runes to do hinting, but we're going to concentrate
105There are multiple runes to do hinting, but we're going to concentrate
100on three. All hinting runes start with a tilda ("sig"). A mnemonic
106on three. All hinting runes start with a tilda ("sig"). A mnemonic
101−is "we're signalling some information to the interpretter".
107+is "we're signaling some information to the interpreter".
103−+ ~/ sigfas: simple jet registration, using defaults for some arguments
109++ `~/` "signet": simple jet registration, using defaults for some arguments
104−+ ~% sigcen: more complicated jet registration, specifying all arguments
110++ `~%` "sigcen": more complicated jet registration, specifying all arguments
105−+ ~& sigpam: debugging printf
111++ `~&` "sigpad": debugging printf
107−Feel free to use ~& liberally! (Just remove them when you're done).
113+Feel free to use `~&` liberally! (Just remove them when you're done).
109Let's use the three to jet some code. Starting with this example:
115Let's use the three to jet some code. Starting with this example:
@@ -135,30 +141,30 @@ What we're doing here is hinting `ccc`, and then adding a string of
135hints up the enclosing tree of arms. Each of these hints is
141hints up the enclosing tree of arms. Each of these hints is
136implemented w the simple / minimalist `~/` rune, which takes one
142implemented w the simple / minimalist `~/` rune, which takes one
137argument: the symbol that should be used to label the hint (these
143argument: the symbol that should be used to label the hint (these
138−symbols will be used later in the C code to match up C code with hoon code).
144+symbols will be used later in the C code to match up C code with Hoon code).
140The top hint (for `aaa`) uses the more verbose `~%` hint syntax, which
146The top hint (for `aaa`) uses the more verbose `~%` hint syntax, which
141−specifies two additional fields: `...is` means "parent jet can not be
147+specifies two additional fields: `..is` means "parent jet can not be
142determined by context, so use 'is' as the parent" ("is" is the name of a system-supplied jet).
148determined by context, so use 'is' as the parent" ("is" is the name of a system-supplied jet).
144−[ N.B. saying " `is` is the parent " is a quick-and-dirty lie. The
150+[N.B. saying " `is` is the parent " is a quick-and-dirty lie. The
145fuller version is: `+is` is an arm of the Arvo core, so `..is` is a
151fuller version is: `+is` is an arm of the Arvo core, so `..is` is a
146reference to the entire Arvo core. The whole Arvo core is hinted with
152reference to the entire Arvo core. The whole Arvo core is hinted with
147the jet label `%hex`, which is used as the parent for all the
153the jet label `%hex`, which is used as the parent for all the
148−top-level jet hints in %zuse. ]
154+top-level jet hints in %zuse.]
150When hinting your own code, make sure to hint each nesting arm.
156When hinting your own code, make sure to hint each nesting arm.
151Skipping any one will result in the jet code not being run.
157Skipping any one will result in the jet code not being run.
153Note that you do not need to provide C implementations for everything
159Note that you do not need to provide C implementations for everything
154−you hint. In this above example we hint aaa, bbb, and ccc - even if
160+you hint. In this above example we hint aaa, bbb, and ccc -- even if
155our intent is only to jet ccc.
161our intent is only to jet ccc.
157### Edit the C Source code (overview)
163### Edit the C Source code (overview)
159−Having hinted our hoon, we now need to write the matching C code. If
165+Having hinted our Hoon, we now need to write the matching C code. If
160−we don't, there isn't a problem - hinting code merely tells the
166+we don't, there isn't a problem -- hinting code merely tells the
161−interpretter to look for a jet, but if a jet is not found, the hoon
167+interpreter to look for a jet, but if a jet is not found, the Hoon
162still runs just fine.
168still runs just fine.
164There are two distinct tasks to be done in C:
170There are two distinct tasks to be done in C:
@@ -166,33 +172,28 @@ There are two distinct tasks to be done in C:
166+ write the jet
172+ write the jet
167+ register the jet
173+ register the jet
169−For each jet you will write one u3we() function and one u3qe() function.
175+For each jet you will write one `u3we()` function and one `u3qe()` function.
171### Edit the C Source code to add registration
177### Edit the C Source code to add registration
173−* edit the header file `include/jets/w.h` to have a declaration for each of your u3we() functions. Every u3we() function looks the same, e.g.
179+- edit the header file `include/jets/w.h` to have a declaration for each of your `u3we()` functions. Every `u3we()` function looks the same, e.g.
176−u3_noun u3we_xxx(u3_noun);
179−* edit the header file `~/tlon/urbit/include/jets/q.h` to have a declaration for your u3qe() function. u3qe() functions can differ from each other, taking distinct numbers of u3_nouns and/or u3_atoms, e.g
182− u3_noun u3qe_yyy(u3_atom, u3_atom);
183− u3_noun u3qe_zzz(u3_noun, u3_noun, u3_atom, u3_atom);
186−* create a new .c file to hold your jets (both the u3we_() and u3qe_() functions go in the same file). For example, ~/tlon/urbit/jets/e/secp.c
181+ ```
187−(The choice of subdirectory under 'jets' (a through g) is XXX )
182+ u3_noun u3we_xxx(u3_noun);
188−The new file should have three things:
183+ ```
189−+ \#include "all.h"
184+- edit the header file `~/tlon/urbit/include/jets/q.h` to have a declaration for your `u3qe()` function. `u3qe()` functions can differ from each other, taking distinct numbers of `u3_nouns` and/or `u3_atoms`, e.g.
190−+ the new u3we() function
191−+ the new u3qe() function
187+ u3_noun u3qe_yyy(u3_atom, u3_atom);
188+ u3_noun u3qe_zzz(u3_noun, u3_noun, u3_atom, u3_atom);
190+- create a new .c file to hold your jets (both the `u3we_()` and `u3qe_()` functions go in the same file). For example, `~/tlon/urbit/jets/e/secp.c`. The new file should have three things:
192+ + the new `u3we()` function
193+ + the new `u3qe()` function
193−* edit ~/tlon/urbit/jets/tree.c to register jet
194+- edit ~/tlon/urbit/jets/tree.c to register jet
195−In the hoon code we hinted some leaf node functions (`ccc` in our example) and then hinted each parent node up to the root `aaa`).
196+In the Hoon code we hinted some leaf node functions (`ccc` in our example) and then hinted each parent node up to the root `aaa`).
197We need to replicate this structure in C. Here's example C code to jet our above example Hoon:
198We need to replicate this structure in C. Here's example C code to jet our above example Hoon:
@@ -204,21 +205,21 @@ We need to replicate this structure in C. Here's example C code to jet our abov
207− // 2: that implements a jet for hoon arm 'ccc'
208+ // 2: that implements a jet for Hoon arm 'ccc'
208 static u3j_core _143_hex_hobo_bbb_d[] =
209 static u3j_core _143_hex_hobo_bbb_d[] =
210 { "ccc", _143_hex_hobo_ccc_d },
211 { "ccc", _143_hex_hobo_ccc_d },
214− // 3: ... that is inside a hoon arm 'bbb'
215+ // 3: ... that is inside a Hoon arm 'bbb'
215 static u3j_core _143_hex_hobo_hobo_d[] =
216 static u3j_core _143_hex_hobo_hobo_d[] =
217 { "bbb", 0, _143_hex_hobo_bbb_d },
218 { "bbb", 0, _143_hex_hobo_bbb_d },
221− // 4: ... that is inside a hoon arm 'aaa'
222+ // 4: ... that is inside a Hoon arm 'aaa'
222 static u3j_core _143_hex_d[] =
223 static u3j_core _143_hex_d[] =
223 { { "down", 0, _143_hex_down_d },
224 { { "down", 0, _143_hex_down_d },
224 { "lore", _143_hex_lore_a },
225 { "lore", _143_hex_lore_a },
@@ -233,37 +234,36 @@ We need to replicate this structure in C. Here's example C code to jet our abov
236−There are 4 things steps here. Let's look at each in turn.
237+There are 4 steps here. Let's look at each in turn.
238−Section 1 names the C function that we want to invoke: 'u3we_ccc()'.
239+Section 1 names the C function that we want to invoke: `u3we_ccc()`.
239The precise manner in which it does this is by putting entries in an
240The precise manner in which it does this is by putting entries in an
240−array of 'u3j_harm's. The first one specifies the jet; the second one
241+array of `u3j_harm`s. The first one specifies the jet; the second one
241is empty and serves as a termination to the array, similar to how a C
242is empty and serves as a termination to the array, similar to how a C
242string is null terminated with a zero. The jet registration supplies
243string is null terminated with a zero. The jet registration supplies
243−two fields {".2", u3we_secp}, but this does not initialize all of the
244+two fields `{".2", u3we_secp}`, but this does not initialize all of the
244−fields of u3j_harm. Other fields can be specified.
245+fields of `u3j_harm`. Other fields can be specified.
246The first field, with value ".2" in this example, is "arm 2".
247The first field, with value ".2" in this example, is "arm 2".
248[ N.B. ".2" labels the axis of the arm in the core. With a %fast hint
249[ N.B. ".2" labels the axis of the arm in the core. With a %fast hint
249−(~/), we're hinting a gate, so the relevant arm formula is always just
250+(`~/`), we're hinting a gate, so the relevant arm formula is always just
250the entire battery at +2. I assume the jet dashboard is flexible
251the entire battery at +2. I assume the jet dashboard is flexible
251enough to hint arms at different axes, but I've never seen it done. ]
252enough to hint arms at different axes, but I've never seen it done. ]
253−The second field, with value u3we_secp in this example, is a function
254+The second field, with value `u3we_secp` in this example, is a function
254pointer (to the C implementation of the jet).
255pointer (to the C implementation of the jet).
256The third field (absent here) is a flag to turn on verification of C
257The third field (absent here) is a flag to turn on verification of C
257−jet vs hoon at run time. It can take value c3n (which means verify at run time) or c3y
258+jet vs Hoon at run time. It can take value `c3n` (which means verify at run time) or `c3y`
258(which means don't verify). If not present, it is set to don't verify.
259(which means don't verify). If not present, it is set to don't verify.
260−[N.B. The use of the flags seems inverted. Why is c3y ("yes") used to
261+[N.B. The use of the flags seems inverted. Why is `c3y` ("yes") used to
261turn OFF verification? A: because the flag is actually "is the jet
262turn OFF verification? A: because the flag is actually "is the jet
262already known to be perfect?" ]
263already known to be perfect?" ]
264There are additional flags; see ~/tlon/urbit/include/noun/jets.h
265There are additional flags; see ~/tlon/urbit/include/noun/jets.h
267Section 2 associated the previous jet registration with the name
267Section 2 associated the previous jet registration with the name
268"ccc". Note that this is the symbol used in the Hoon hint! Note also
268"ccc". Note that this is the symbol used in the Hoon hint! Note also
269that we again have a "null terminated" (metaphorically) list, ending with `{}`.
269that we again have a "null terminated" (metaphorically) list, ending with `{}`.
@@ -273,22 +273,24 @@ Section 3 references structure built in step 2 and slots it under
273hinting in Hoon).
273hinting in Hoon).
275The line in section 2
275The line in section 2
277 { "ccc", _143_hex_hobo_ccc_a },
278 { "ccc", _143_hex_hobo_ccc_a },
280looks very similar to the line in section 3
281looks very similar to the line in section 3
282 { "bbb", 0, _143_hex_hobo_bbb_d },
284 { "bbb", 0, _143_hex_hobo_bbb_d },
285But note that the line in section 2 fill in the first 2 fields in the
287But note that the line in section 2 fill in the first 2 fields in the
286struct, and the line in section 3 fills in the first three fields.
288struct, and the line in section 3 fills in the first three fields.
287−Section 2 is registering an array of u3j_harm, i.e. is registering an actual C
289+Section 2 is registering an array of `u3j_harm`, i.e. is registering an actual C
290−Section 3 is specifying 0 for the array of u3j_harm and is instead
292+Section 3 is specifying 0 for the array of `u3j_harm` and is instead
291−specifying an array of u3j_core, i.e. it is registering nesting of
293+specifying an array of `u3j_core`, i.e. it is registering nesting of
292another core which is not a leaf node.
294another core which is not a leaf node.
294Section 4 is much like section 3, but it's the root of this particular
296Section 4 is much like section 3, but it's the root of this particular
@@ -298,23 +300,23 @@ jet-registration tree may have multiple children.
298Using this example you should be able to register jets whether your
300Using this example you should be able to register jets whether your
299nesting is 2 layers deep, 3 (like this example), or more. You should
301nesting is 2 layers deep, 3 (like this example), or more. You should
300also be able to register multiple jets at the same nesting level (e.g.
302also be able to register multiple jets at the same nesting level (e.g.
301−a function u3we_ddd() which is a sibling of u3we_ccc() inside data structure _143_hex_hobo_reco_d[] ).
303+a function `u3we_ddd()` which is a sibling of `u3we_ccc()` inside data structure `_143_hex_hobo_reco_d[]` ).
303−### Edit the C source code to add the u3we_() function
305+### Edit the C source code to add the `u3we_()` function
305There are two C functions per jet, because separation of concerns is a good thing.
307There are two C functions per jet, because separation of concerns is a good thing.
307−The first C function - named u3we_something() - unpacks arguments from
309+The first C function -- named `u3we_something()` -- unpacks arguments from
308the Hoon code and gets them ready.
310the Hoon code and gets them ready.
310−The second C function - named u3qe_something() - takes those arguments
312+The second C function -- named `u3qe_something()` -- takes those arguments
311−and actually performs the operations that parallel the hoon code being
313+and actually performs the operations that parallel the Hoon code being
314−Let's write the u3we_() function.
316+Let's write the `u3we_()` function.
316−Your function is going to accept one argument, of type u3_noun. This
318+Your function is going to accept one argument, of type `u3_noun`. This
317−is the same type as a hoon noun ('*').
319+is the same type as a Hoon noun (`*`).
319This one argument is the payload.
321This one argument is the payload.
@@ -325,12 +327,12 @@ of "global variables and available methods", if analogies to other
325programming languages were allowed!) and on the left branch the
327programming languages were allowed!) and on the left branch the
326sample (the arguments to this particular function call).
328sample (the arguments to this particular function call).
328−Your u3we_() function does one thing: unpack the sample from 'cor',
330+Your `u3we_()` function does one thing: unpack the sample from 'cor',
329−sanity check them, and pass them in to the u3qe_() function.
331+sanity check them, and pass them in to the `u3qe_()` function.
331To unpack the sample
333To unpack the sample
333−We use the function u3r_mean() to do this, thusly:
335+We use the function `u3r_mean()` to do this, thusly:
336 u3_noun arg_a, arg_b, arg_c ... ;
338 u3_noun arg_a, arg_b, arg_c ... ;
@@ -343,12 +345,12 @@ We use the function u3r_mean() to do this, thusly:
346−If we want to to assign the data located at axis 3 of cor to arg_a, we'd set axis_a = 3.
348+If we want to to assign the data located at axis 3 of cor to `arg_a`, we'd set `axis_a = 3`.
348−u3r_mean() takes varargs, so we can pass in as many axis /
350+`u3r_mean()` takes varargs, so we can pass in as many axis /
349return-argument pairs as we wish, terminated with a 0.
351return-argument pairs as we wish, terminated with a 0.
351−When pulling arguments out of a hoon remember that Nock and Hoon store
353+When pulling arguments out of a Hoon remember that Nock and Hoon store
352lists as skinny right-descending trees (because a linked list is a
354lists as skinny right-descending trees (because a linked list is a
353degenerate case of a tree).
355degenerate case of a tree).
@@ -372,13 +374,13 @@ Note that there are #defines to help you specify the axises you want.
372They are in include/noun/xtract.h
374They are in include/noun/xtract.h
374If the sample has one item, that one item it is located at the axis
376If the sample has one item, that one item it is located at the axis
375−specified by the #define u3x_sam_1.
377+specified by the #define `u3x_sam_1`.
377If the sample has 2 items, they are located at the axis specified by
379If the sample has 2 items, they are located at the axis specified by
378−the #defines u3x_sam_2 and u3x_sam_3.
380+the #defines `u3x_sam_2` and `u3x_sam_3`.
380If the sample has 3 items, they are located at the axis specified by
382If the sample has 3 items, they are located at the axis specified by
381−the #defines u3x_sam_2, u3x_sam_6, and u3x_sam_7.
383+the #defines `u3x_sam_2`, `u3x_sam_6`, and `u3x_sam_7`.
@@ -388,6 +390,7 @@ N.B. in our fprintf()s we're using both \n and \r to achieve line feed
388(move cursor down one line) and carriage return (move it to the left),
390(move cursor down one line) and carriage return (move it to the left),
389because Urbit uses ncurses to control the screen and it changes the
391because Urbit uses ncurses to control the screen and it changes the
390default behavior you may be used to (where \n accomplishes both).
392default behavior you may be used to (where \n accomplishes both).
392 c3_o ret;
395 c3_o ret;
393 u3_noun sample;
396 u3_noun sample;
@@ -412,14 +415,17 @@ default behavior you may be used to (where \n accomplishes both).
412 u3m_p("15: ", sample);
415 u3m_p("15: ", sample);
415−If the hoon that you're jetting looks like this
418+If the Hoon that you're jetting looks like this
417 ++ make-k
421 ++ make-k
418 ~/ %make-k
422 ~/ %make-k
419 =, mimes:html
423 =, mimes:html
420 |= [aaa=@ bbb=@ ccc=@]
424 |= [aaa=@ bbb=@ ccc=@]
422In the C code you'd fetch them out of the payload with
427In the C code you'd fetch them out of the payload with
424 u3r_mean(cor,
430 u3r_mean(cor,
425 u3x_sam_2, & arg_aaa,
431 u3x_sam_2, & arg_aaa,
@@ -428,18 +434,22 @@ In the C code you'd fetch them out of the payload with
431If you're confident, go ahead and write code. If you want to inspect
438If you're confident, go ahead and write code. If you want to inspect
432your arguments to see what's going on, you can pretty print the
439your arguments to see what's going on, you can pretty print the
435You could - IN THEORY - inspect / pretty-print the noun by calling
442You could - IN THEORY - inspect / pretty-print the noun by calling
437 u3m_p("description", cor); :: DO NOT DO THIS !!!
445 u3m_p("description", cor); :: DO NOT DO THIS !!!
439...but you don't want to do this, because, recall, cor contains the
448...but you don't want to do this, because, recall, cor contains the
440entire context - the whole enchilada.
449entire context - the whole enchilada.
442Do instead, perhaps,
451Do instead, perhaps,
444 c3_o ret;
454 c3_o ret;
445 u3_noun sample;
455 u3_noun sample;
@@ -447,19 +457,25 @@ Do instead, perhaps,
447 ret = u3r_mean(sample, u3x_sam_1, &sample, 0);
457 ret = u3r_mean(sample, u3x_sam_1, &sample, 0);
448 fprintf(stderr, "ret = %i\n\r", ret); // we want ret = 0 = yes
458 fprintf(stderr, "ret = %i\n\r", ret); // we want ret = 0 = yes
449 u3m_p("sample", sample); // pretty print the entire sample
459 u3m_p("sample", sample); // pretty print the entire sample
452After our C function pulls out the arguments it needs to type check them.
463After our C function pulls out the arguments it needs to type check them.
454−If arg_a is supposed to be a atom, trust but verify:
465+If `arg_a` is supposed to be a atom, trust but verify:
456 u3ud(arg_a); // checks for atomicity; alias for u3a_is_atom()
468 u3ud(arg_a); // checks for atomicity; alias for u3a_is_atom()
458If it's supposed to be a cell:
471If it's supposed to be a cell:
460 u3du(arg_a); // checks for cell-ness
474 u3du(arg_a); // checks for cell-ness
462There are other tests you might need to use
477There are other tests you might need to use
464 u3a_is_cat()
480 u3a_is_cat()
465 u3a_is_dog()
481 u3a_is_dog()
@@ -467,59 +483,71 @@ There are other tests you might need to use
467 u3a_is_pug()
483 u3a_is_pug()
468 u3a_is_pom()
484 u3a_is_pom()
470All of these rests return Hoon loobeans (yes/no vs true / false), so
487All of these rests return Hoon loobeans (yes/no vs true / false), so
471−check return values vs c3n / c3y. If any of these u3_mean(), u3ud()
488+check return values vs `c3n` / `c3y`. If any of these `u3_mean()`, `u3ud()`
472etc return u3n you have an error and should return
489etc return u3n you have an error and should return
474 return u3m_bail(c3__exit);
492 return u3m_bail(c3__exit);
476otherwise pass the arguments into your "inner" jet function and return the results of that.
495otherwise pass the arguments into your "inner" jet function and return the results of that.
478−### Edit the C source code to add the u3qe_() function
497+### Edit the C source code to add the `u3qe_()` function
480−The u3qe_() function is the "real" jet - the C code that replaces the hoon.
499+The `u3qe_()` function is the "real" jet -- the C code that replaces the Hoon.
482First, you may need to massage your inputs a bit to get them into types that you can use.
501First, you may need to massage your inputs a bit to get them into types that you can use.
484−You have received a bunch of u3_nouns or u3_atoms, but you presumably want to do
503+You have received a bunch of `u3_nouns` or `u3_atoms`, but you presumably want to do things in a native C / non-Hoon manner: computing w raw integers, etc.
485−things in a native C / non-Hoon manner: computing w raw integers, etc.
487−A u3_noun will want to be further diassembled into atoms. XXX
505+A `u3_noun` will want to be further diassembled into atoms.
489−A u3_atom represents a simple number, but the implementation may or
507+A `u3_atom` represents a simple number, but the implementation may or
490may not be simple. If the value held in the atom is 31 bits or less,
508may not be simple. If the value held in the atom is 31 bits or less,
491it's stored directly in the atom. If the value is 32 bits the atom
509it's stored directly in the atom. If the value is 32 bits the atom
492−holds a pointer into the loom where the actual value is stored. ( see https://urbit.org/docs/vere/nouns/ )
510+holds a pointer into the loom where the actual value is stored. ( see [https://urbit.org/docs/vere/nouns/](../nouns) )
494−You don't want to get bogged down in the details of this - you just
512+You don't want to get bogged down in the details of this -- you just
495want to get data out of your atoms.
513want to get data out of your atoms.
497If you know that the data fits in 32 bits or less, you can use
515If you know that the data fits in 32 bits or less, you can use
499 u3r_word(c3_w a_w, u3_atom b);
518 u3r_word(c3_w a_w, u3_atom b);
502If it is longer than 32 bits, use
521If it is longer than 32 bits, use
504 u3r_words(c3_w a_w, c3_w b_w, c3_w* c_w, u3_atom d);
524 u3r_words(c3_w a_w, c3_w b_w, c3_w* c_w, u3_atom d);
509 u3r_bytes(c3_w a_w, c3_w b_w, c3_y* c_y, u3_atom d)
530 u3r_bytes(c3_w a_w, c3_w b_w, c3_y* c_y, u3_atom d)
512−(N.B. You may want to use u3r_bytes regardless, as
533+If you need to get the size
514The actual meat of the function is up to you. What is it supposed to do?
539The actual meat of the function is up to you. What is it supposed to do?
516Now we move on to return semantics.
541Now we move on to return semantics.
518First, you can transfer raw values into nouns using
543First, you can transfer raw values into nouns using
520 u3_noun u3i_words(c3_w a_w, const c3_w* b_w)
546 u3_noun u3i_words(c3_w a_w, const c3_w* b_w)
522and you can build cells out of nouns using
549and you can build cells out of nouns using
524 u3nc(); // pair
552 u3nc(); // pair
525 u3nt(); // triple
553 u3nt(); // triple
@@ -528,7 +556,8 @@ and you can build cells out of nouns using
529There are two facets here: (i) data format, (ii) memory allocation.
557There are two facets here: (i) data format, (ii) memory allocation.
531−Regarding data format, if the hoon is expected to return a single atom (e.g. if the hoon looks like this
559+Regarding data format, if the Hoon is expected to return a single atom (e.g. if the Hoon looks like this:)
533 ++ make-k
562 ++ make-k
534 ~/ %make-k
563 ~/ %make-k
@@ -536,11 +565,15 @@ Regarding data format, if the hoon is expected to return a single atom (e.g. if
536 ^- @ :: <---- return value is a single value of type '@' (atom)
565 ^- @ :: <---- return value is a single value of type '@' (atom)
539then your C code - at least when you're stubbing it out - can do something like
569then your C code - at least when you're stubbing it out - can do something like
541 return(123);
572 return(123);
543Or, if you want to create an atom more formally, you can build it like this
575Or, if you want to create an atom more formally, you can build it like this
545 // this variable is on the stack and will disappear
578 // this variable is on the stack and will disappear
546 unsigned char nonce32[32];
579 unsigned char nonce32[32];
@@ -552,7 +585,9 @@ Or, if you want to create an atom more formally, you can build it like this
552 // this returns the 32 bit handle to the atom
585 // this returns the 32 bit handle to the atom
553 return(nonce);
586 return(nonce);
555−If, on the other hand, your hoon looks like
589+If, on the other hand, your Hoon looks like
557 ++ ecdsa-raw-sign :: generate signature
592 ++ ecdsa-raw-sign :: generate signature
558 ~/ %ecdsa-raw-sign
593 ~/ %ecdsa-raw-sign
@@ -560,34 +595,37 @@ If, on the other hand, your hoon looks like
560 ^- [v=@ r=@ s=@]
595 ^- [v=@ r=@ s=@]
563ending your C code with
599ending your C code with
565 return(123);
602 return(123);
567is wrong and will result in a dojo error because you are returning a single atom, instead of a list of three atoms.
605is wrong and will result in a dojo error because you are returning a single atom, instead of a list of three atoms.
569Instead do one of these:
607Instead do one of these:
571 return(u3nc(a, b)); // for two atoms
610 return(u3nc(a, b)); // for two atoms
572 return(u3nt(a, b, c)); // for three atoms
611 return(u3nt(a, b, c)); // for three atoms
573 return(u3nq(a, b, c, d)); // for four atoms
612 return(u3nq(a, b, c, d)); // for four atoms
575If you need to return a longer list, you can compose your own. Look
615If you need to return a longer list, you can compose your own. Look
576at the definitions of these three functions and you will see that they
616at the definitions of these three functions and you will see that they
577−are just recursive calls to the cell constructor u3i_cell() e.g.
617+are just recursive calls to the cell constructor `u3i_cell()` e.g.
579 u3i_cell(a, u3i_cell(b, u3i_cell(c, d));
620 u3i_cell(a, u3i_cell(b, u3i_cell(c, d));
582−XXX more here about memory model, allocation, ownership
623+Understanding the memory model, allocation, freeing, and ownership ('transfer' vs 'retain' semantics) is important. Some info is available at [https://www.urbit.org/docs/vere/nouns/](../nouns).
586## Compile the C code
625## Compile the C code
588You've edited C code; now you need to compile it to build a new urbit executable!
627You've edited C code; now you need to compile it to build a new urbit executable!
591+ cd ~/tlon/urbit
629+ cd ~/tlon/urbit
592+ rm -rf build
630+ rm -rf build
593+ configure: choose one of
631+ configure: choose one of
@@ -595,73 +633,69 @@ You've edited C code; now you need to compile it to build a new urbit executable
595 + meson configure -Dbuildtype=debugoptimized build
633 + meson configure -Dbuildtype=debugoptimized build
596 + meson configure -Dbuildtype=debug build
634 + meson configure -Dbuildtype=debug build
598−Note that debugoptimized builds run slower than release builds, and debug builds run slower yet. Booting a debug builkd of urbit may take several minutes. [ N.B. compiler flags -O2 vs -O3 ]
636+ Note that debugoptimized builds run slower than release builds, and debug builds run slower yet. Booting a debug builkd of urbit may take several minutes. [ N.B. compiler flags -O2 vs -O3 ]
599+ scripts/build
637+ scripts/build
601## Compile the Hoon code into a pill
639## Compile the Hoon code into a pill
603You've compiled the Hoon code. Now you need to compile it.
641You've compiled the Hoon code. Now you need to compile it.
605−Wait, compile? Isn't Hoon that one types at the dojo prompt interpretted, or compiled on the fly?
643+Wait, compile? Isn't Hoon that one types at the dojo prompt interpreted, or compiled on the fly?
609When the urbit executable runs the first thing it does is load the
647When the urbit executable runs the first thing it does is load the
610−complete arvo operating system. That step is much faster if it can
648+complete Arvo operating system. That step is much faster if it can
611−load a "jam"-ed "pill", where all of the hoon has already been parsed
649+load a "jam"-ed "pill", where all of the Hoon has already been parsed
612from text file into Hoon abstract syntax tree, and then compiled from
650from text file into Hoon abstract syntax tree, and then compiled from
613−the hoon into the Nock equivalent.
651+the Hoon into the Nock equivalent.
615Note that this means that if you edit hoon.hoon, zuse.hoon, arvo.hoon,
653Note that this means that if you edit hoon.hoon, zuse.hoon, arvo.hoon,
616−vane/ames.hoon, etc. and then restart the urbit executable **YOU ARE
654+vane/ames.hoon, etc. and then restart the urbit executable *YOU ARE
617−NOT RUNNING YOUR NEW CODE**.
655+NOT RUNNING YOUR NEW CODE*.
619The only way to run the new code is to follow the following process:
657The only way to run the new code is to follow the following process:
621−+ start up urbit, tell it to be a fake zod (act as a galaxy and disconnect from the rest of the network) and have it know where your edited arvo files are (although not execute them, as discussed above):
659++ start up urbit, tell it to be a fake zod (act as a galaxy and disconnect from the rest of the network) and have it know where your edited Arvo files are (although not execute them, as discussed above):
622 + rm -rf ~/zod
660 + rm -rf ~/zod
623− + rm -rf ~/tlon/mypill.pill
661+ + rm -rf ~/tlon/mypill.pill
624− + ~/tlon/urbit/build/urbit -FI zod -A ~/bus/tlon/arvo/ -c zod
662+ + ~/tlon/urbit/build/urbit -FI zod -A ~/bus/tlon/arvo/ -c zod
626−This should take < 90 seconds.
663+ + This should take < 90 seconds.
628−+ If you accidentally exit urbit you can restart it XXX
664+ + If you accidentally exit urbit you can restart it
629−+ inside your urbit, from the dojo command line, load the hoon files and compile them into a pill file:
665++ inside your urbit, from the dojo command line, load the Hoon files and compile them into a pill file:
630 + .pill +solid
666 + .pill +solid
632−This should take < 90 seconds.
667+ + This should take < 90 seconds.
634−+ examine the output. Expect to see something like this
668+ + examine the output. Expect to see something like this
636− %solid-start
671+ %solid-start
637− %solid-loaded
672+ %solid-loaded
638− %solid-parsed
673+ %solid-parsed
639− %solid-compiled
674+ %solid-compiled
640− %solid-arvo
675+ %solid-arvo
641− [%solid-kernel 0x6aa7.627e]
676+ [%solid-kernel 0x6aa7.627e]
642− %arvo-assembly
677+ %arvo-assembly
643− [%solid-veer p=%$ q=/zuse]
678+ [%solid-veer p=%$ q=/zuse]
644− [%tang /~zod/home/~2018.7.25..20.47.51..0027/sys/zuse ~mondyr-rovmes]
679+ [%tang /~zod/home/~2018.7.25..20.47.51..0027/sys/zuse ~mondyr-rovmes]
646− + if, on the contrary, you see anything like this:
681+ + if, on the contrary, you see anything like this:
648− syntax error
684+ syntax error
649− {3,356 7}
685+ {3,356 7}
650− /~zod/home/~2018.7.25..20.47.51..0027/sys/zuse
686+ /~zod/home/~2018.7.25..20.47.51..0027/sys/zuse
652− you have an error. In this case the error is on line 3,356, character 7 of file ~/tlon/arvo/sys/zuse.hoon.
689+ you have an error. In this case the error is on line 3,356, character 7 of file ~/tlon/arvo/sys/zuse.hoon.
655− + the urbit executable will not reload the .hoon files as you edit them. Neither `|reset` nor `.pill +solid` will make edits visible. Instead do this:
690+ + the urbit executable will not reload the .hoon files as you edit them. Neither `|reset` nor `.pill +solid` will make edits visible. Instead do this:
656− + in dojo: `|mount /=base=`
691+ + in dojo: `|mount /=base=`
657− + in dojo: `|autoload %.y`
692+ + in dojo: `|autoload %.y`
658− + at the command line : `ln -s ~/tlon/arvo/sys/zuse.hoon ~/zod/base/sys/zuse.hoon ` (make changes to both arguments of the ln command if you're editing, say, base/sys/vane/ford.hoon)
693+ + at the command line : `ln -s ~/tlon/arvo/sys/zuse.hoon ~/zod/base/sys/zuse.hoon ` (make changes to both arguments of the ln command if you're editing, say, base/sys/vane/ford.hoon)
660−This does three things: it makes urbit's file system mount your own, it makes urbit scan its own filesystem for changes and load them automatically, and it keeps your zuse.hoon
695+ This does three things: it makes urbit's file system mount your own, it makes urbit scan its own filesystem for changes and load them automatically, and it keeps your zuse.hoon
662−Make a change to the hoon file. In dojo you should see `<<sync>>`. If you do not, one of the above steps was done incorrectly. If you do see this, it will be followed by any compile errors.
697+ Make a change to the Hoon file. In dojo you should see `<<sync>>`. If you do not, one of the above steps was done incorrectly. If you do see this, it will be followed by any compile errors.
664−+ Edit the hoon and try again. Keep iterating until the hoon compiles.
698+ + Edit the Hoon and try again. Keep iterating until the Hoon compiles.
665+ exit urbit with control-D
699+ exit urbit with control-D
666+ save the pill file
700+ save the pill file
667 + cp ~/zod/.urb/put.pill ~/tlon/mypill.pill
701 + cp ~/zod/.urb/put.pill ~/tlon/mypill.pill
@@ -670,10 +704,10 @@ Make a change to the hoon file. In dojo you should see `<<sync>>`. If you do n
671Here's some things to note about the pill (and -A):
705Here's some things to note about the pill (and -A):
673−An urbit has to boot into the Arvo kernel -- a nock core with a
707+An urbit has to boot into the Arvo kernel -- a Nock core with a
674particular interface. It'd be possible to make some ad-hoc procedure
708particular interface. It'd be possible to make some ad-hoc procedure
675to initialize Arvo, but it would be a pretty drastic layering
709to initialize Arvo, but it would be a pretty drastic layering
676−violation and couple urbit to all sorts of internal implementation
710+violation and couple Urbit to all sorts of internal implementation
677details of Arvo and Hoon. In contrast, the pill is basically a
711details of Arvo and Hoon. In contrast, the pill is basically a
678serialized, declarative set of steps to initialize Arvo.
712serialized, declarative set of steps to initialize Arvo.
@@ -682,9 +716,9 @@ basically a snapshot of a pristine Arvo kernel. In the future (see
682+metal or +brass), the pill will contain something like:
716+metal or +brass), the pill will contain something like:
684+ a boot formula
718+ a boot formula
685−+ the hoon compiler as nock
719++ the Hoon compiler as nock
686−+ the hoon compiler as source
720++ the Hoon compiler as source
687−+ arvo as source
721++ Arvo as source
688+ the vanes as source
722+ the vanes as source
689+ userspace as source (ie, an initial %clay sync)
723+ userspace as source (ie, an initial %clay sync)
@@ -698,60 +732,42 @@ Hopefully this helps to demystify these startup procedures.
702## Run the compiled C / compiled Hoon pill
735## Run the compiled C / compiled Hoon pill
704+ type `cd ~`
737+ type `cd ~`
705+ type `rm -rf zod`
738+ type `rm -rf zod`
706−+ type `~/tlon/urbit/build/urbit -FI zod -A ~/tlon/arvo/ -B ~/tlon/mypill.pill -c zod`.
739++ type `~/tlon/urbit/build/urbit -FI zod -A ~/tlon/arvo/ -B ~/tlon/mypill.pill -c zod`
708−N.B. booting should not take more than about 90 seconds. If it
741+ N.B. booting should not take more than about 90 seconds. If it goes longer than that you might have created a 'poison pill', which hangs things. Try booting without the -B flag, and/or reverting your Hoon changes, generating a new pill based on that, and launching urbit with the known-clean pill. If these steps and boot in < 90 seconds, but a boot with a pill created from your own Hoon does not, you have a Hoon bug of some sort.
709−goes longer than that you might have created a 'poison pill', which
710−hangs things. Try booting without the -B flag, and/or reverting
711−your hoon changes, generating a new pill based on that, and
712−launching urbit with the known-clean pill. If these steps and boot
713−in < 90 seconds, but a boot with a pill created from your own hoon
714−does not, you have a hoon bug of some sort.
716−Hoon bugs that disable booting can be as simple as the wrong number
717−of spaces. Many, but not all of them, will result in compile
718−errors during the `.pill +solid` step. If your booting takes > 90
719−seconds, abort it, and look at your hoon. Do a git diff, and
720−remove half the edits. Run through the entire process again. If
721−booting from the pill still hangs, remove half of what remains. Do
722−a binary search to find the precise error.
743+ Hoon bugs that disable booting can be as simple as the wrong number of spaces. Many, but not all of them, will result in compile errors during the `.pill +solid` step. If your booting takes > 90 seconds, abort it, and look at your Hoon. Do a git diff, and remove half the edits. Run through the entire process again. If booting from the pill still hangs, remove half of what remains. Do a binary search to find the precise error.
724+ inside dojo: `|reset`
744+ inside dojo: `|reset`
725+ You now have created a galaxy fakezod, on its own detached network, running your own strange variant of the OS.
745+ You now have created a galaxy fakezod, on its own detached network, running your own strange variant of the OS.
726−+ inside dojo: `(make-k:secp256k1:secp:crypto `@uvI`12 33)` # or whatever command runs the hoon you're jetting
746++ inside dojo: `` (make-k:secp256k1:secp:crypto `@uvI`12 33) `` # or whatever command runs the Hoon you're jetting
727+ do your development work
747+ do your development work
728+ If you happen to exit, you can restart with `urbit -FI zod zod`
748+ If you happen to exit, you can restart with `urbit -FI zod zod`
730To expand:
750To expand:
731−* F means "fake"
751+- F means "fake"
732−* I means "run as galaxy zod"
752+- I means "run as galaxy zod"
733−* the final argument is the unix directory holding the files for the galaxy
753+- the final argument is the unix directory holding the files for the galaxy
735## Run the jetted code and compare to the non jetted code
755## Run the jetted code and compare to the non jetted code
737You are now running your jetted code in a fake zod.
757You are now running your jetted code in a fake zod.
739−It would be convenient to fire up a second urbit in a terminal next to your fake zod, this one using non-jetted hoon.
759+It would be convenient to fire up a second urbit in a terminal next to your fake zod, this one using non-jetted Hoon.
741Then you can run identical commands in each, in parallel, and confirm that they do the same thing.
761Then you can run identical commands in each, in parallel, and confirm that they do the same thing.
743+ edit ~/tlon/urbit/jets/e/secp.c (or whatever) to include `fprintf(stderr, "*** u3we_sign 2\n");` (or similar) in your jetted functions. This will let us verify that the jets exist and are running.
763+ edit ~/tlon/urbit/jets/e/secp.c (or whatever) to include `fprintf(stderr, "*** u3we_sign 2\n");` (or similar) in your jetted functions. This will let us verify that the jets exist and are running.
744+ `cd ~/tlon/ubit ; scripts/build `
764+ `cd ~/tlon/ubit ; scripts/build `
746+ `cp ~/tlon/arvo ~/tlon/arvo_nojet`
765+ `cp ~/tlon/arvo ~/tlon/arvo_nojet`
748−+ edit ~/tlon/arvo_nojet/sys/zuse_nojetting.hoon to remove jetting
766++ edit `~/tlon/arvo_nojet/sys/zuse_nojetting.hoon` to remove jetting
750−+ Because we can not run two instances of the same fake galaxy on the same machine (their ports would conflict), we need to pick a new galaxy name. Galaxy names are not arbitrary. You may not name your galaxy "mygalaxy", "withjet", "withoutjet", or anything like that. Galaxy names are restricted to the range 0-255, converted into pronounceable syllables. 'Zod' is just the pronunciation of '0' ( to see this, in a dojo, cast ~zod to an untyped atom thusly: `@`~zod). Let's pick 1 as our new galaxy id. Use dojo to convert this into a urbit name: `@p`1 yields ~nec.
767++ Because we can not run two instances of the same fake galaxy on the same machine (their ports would conflict), we need to pick a new galaxy name. Galaxy names are not arbitrary. You may not name your galaxy "mygalaxy", "withjet", "withoutjet", or anything like that. Galaxy names are restricted to the range 0-255, converted into pronounceable syllables. `zod` is just the pronunciation of '0' ( to see this, in a dojo, cast `~zod` to an untyped atom thusly: `` `@`~zod ``). Let's pick 1 as our new galaxy id. Use dojo to convert this into a urbit name: `` `@p`1 `` yields `~nec`.
752+ Open a new terminal. In that terminal: `cd ~ ; rm -rf nec ; ~/tlon/urbit/build/urbit -FI nec -A ~/tlon/arvo_nojetting/ -c nec`
768+ Open a new terminal. In that terminal: `cd ~ ; rm -rf nec ; ~/tlon/urbit/build/urbit -FI nec -A ~/tlon/arvo_nojetting/ -c nec`
753+ This should take < 90 seconds.
769+ This should take < 90 seconds.
754−+ inside your urbit, from the dojo command line, load the hoon files and compile them into a pill file: `.pill +solid`
770++ inside your urbit, from the dojo command line, load the Hoon files and compile them into a pill file: `.pill +solid`
755+ This should take < 90 seconds.
771+ This should take < 90 seconds.
756+ exit urbit with control-D
772+ exit urbit with control-D
757+ save the pill file
773+ save the pill file