:: :::: /hoon/brass/gen :: /? 310 :: :::: !: :- %say |= $: {now/@da * bec/beak} {$~ try/_| $~} == :: :: we're creating an event series E whose lifecycle can be computed :: with the urbit lifecycle formula L, `[2 [0 3] [0 2]]`. that is: :: if E is the list of events processed by a computer in its life, :: its final state is S, where S is nock(E L). :: :: in practice, the first five nouns in E are: two boot formulas, :: a hoon compiler as a nock formula, the same compiler as source, :: and the arvo kernel as source. :: :: after the first five special events, we enter an iterative :: sequence of regular events which continues for the rest of the :: computer's life. during this sequence, each state is a function :: that, passed the next event, produces the next state. :: :: a regular event is a `[date wire type data]` tuple, where `date` is a :: 128-bit Urbit date; `wire` is an opaque path which output can :: match to track causality; `type` is a symbol describing the type :: of input; and `data` is input data specific to `type`. :: :: in real life we don't actually run the lifecycle loop, :: since real life is updated incrementally and also cares :: about things like output. we couple to the internal :: structure of the state machine and work directly with :: the underlying arvo engine. :: :: this arvo core, which is at `+7` (Lisp `cddr`) of the state :: function (see its public interface in `sys/arvo`), gives us :: extra features, like output, which are relevant to running :: a real-life urbit vm, but don't affect the formal definition. :: :: so a real-life urbit interpreter is coupled to the shape of :: the arvo core. it becomes very hard to change this shape. :: fortunately, it is not a very complex interface. :: :- %noun :: :: boot-one: lifecycle formula :: =+ ^= boot-one :: :: event 1 is the lifecycle formula which computes the final :: state from the full event sequence. :: :: the formal urbit state is always just a gate (function) :: which, passed the next event, produces the next state. :: => [boot-formula=* full-sequence=*] != :: :: first we use the boot formula (event 1) to set up :: the pair of state function and main sequence. the boot :: formula peels off the first 5 events :: to set up the lifecycle loop. :: =+ [state-gate main-sequence]=.*(full-sequence boot-formula) :: :: in this lifecycle loop, we replace the state function :: with its product, called on the next event, until :: we run out of events. :: |- ?@ main-sequence state-gate %= $ main-sequence +.main-sequence state-gate .*(state-gate(+< -.main-sequence) -.state-gate) == :: :: boot-two: startup formula :: =+ ^= boot-two :: :: event 2 is the startup formula, which verifies the compiler :: and starts the main lifecycle. :: => :* :: event 3: a formula producing the hoon compiler :: compiler-formula=** :: :: event 4: hoon compiler source, compiling to event 2 :: compiler-source=*@t :: :: event 5: arvo kernel source :: arvo-source=*@t :: :: events 6..n: main sequence with normal semantics :: main-sequence=** == != :_ main-sequence :: :: activate the compiler gate. the product of this formula :: is smaller than the formula. so you might think we should :: save the gate itself rather than the formula producing it. :: but we have to run the formula at runtime, to register jets. :: :: as always, we have to use raw nock as we have no type. :: the gate is in fact ++ride. :: ~> %slog.[0 leaf+"1-b"] =+ ^= compiler-gate .*(0 compiler-formula) :: :: compile the compiler source, producing (pair span nock). :: the compiler ignores its input so we use a trivial span. :: ~> %slog.[0 leaf+"1-c (compiling compiler, wait a few minutes)"] =+ ^= compiler-tool .*(compiler-gate(+< [%noun compiler-source]) -.compiler-gate) :: :: switch to the second-generation compiler. we want to be :: able to generate matching reflection nouns even if the :: language changes -- the first-generation formula will :: generate last-generation spans for `!>`, etc. :: ~> %slog.[0 leaf+"1-d"] =. compiler-gate .*(0 +:compiler-tool) :: :: get the span (type) of the kernel core, which is the context :: of the compiler gate. we just compiled the compiler, :: so we know the span (type) of the compiler gate. its :: context is at tree address `+>` (ie, `+7` or Lisp `cddr`). :: we use the compiler again to infer this trivial program. :: ~> %slog.[0 leaf+"1-e"] =+ ^= kernel-span -:.*(compiler-gate(+< [-.compiler-tool '+>']) -.compiler-gate) :: :: compile the arvo source against the kernel core. :: ~> %slog.[0 leaf+"1-f"] =+ ^= kernel-tool .*(compiler-gate(+< [kernel-span arvo-source]) -.compiler-gate) :: :: create the arvo kernel, whose subject is the kernel core. :: ~> %slog.[0 leaf+"1-g"] .*(+>:compiler-gate +:kernel-tool) :: :: sys: root path to boot system, `/~me/[desk]/now/sys` :: =+ sys=`path`/(scot %p p.bec)/[q.bec]/(scot %da now)/sys :: :: compiler-source: hoon source file producing compiler, `sys/hoon` :: =+ compiler-source=.^(@t %cx (welp sys /hoon/hoon)) :: :: compiler-twig: compiler as hoon expression :: ~& %metal-parsing =+ compiler-twig=(ream compiler-source) ~& %metal-parsed :: :: compiler-formula: compiler as nock formula :: ~& %metal-compiling =+ compiler-formula=q:(~(mint ut %noun) %noun compiler-twig) ~& %metal-compiled :: :: arvo-source: hoon source file producing arvo kernel, `sys/arvo` :: =+ arvo-source=.^(@t %cx (welp sys /arvo/hoon)) :: :: boot-ova: startup events :: =+ ^= boot-ova ^- (list *) :~ boot-one boot-two compiler-formula compiler-source arvo-source == :: :: module-ova: vane load operations. :: =+ ^= module-ova ^- (list ovum) |^ :~ :: :: sys/zuse: standard library :: (vent %$ /zuse) :: :: sys/vane/ames: network :: (vent %a /vane/ames) :: :: sys/vane/behn: timer :: (vent %b /vane/behn) :: :: sys/vane/clay: revision control :: (vent %c /vane/clay) :: :: sys/vane/dill: console :: (vent %d /vane/dill) :: :: sys/vane/eyre: web :: (vent %e /vane/eyre) :: :: sys/vane/ford: build :: (vent %f /vane/ford) :: :: sys/vane/gall: applications :: (vent %g /vane/gall) :: :: sys/vane/jael: security :: (vent %j /vane/jael) == :: ++ vent |= {abr/term den/path} =+ pax=(weld sys den) =+ txt=.^(@ %cx (welp pax /hoon)) `ovum`[[%vane den] [%veer abr pax txt]] -- :: :: file-ovum: userspace filesystem load :: =+ ^= file-ovum ^- ovum :: :: /app %gall applications :: /gen :dojo generators :: /lib %ford libraries :: /mar %ford marks :: /sur %ford structures :: /ren %ford renderers :: /web %eyre web content :: /sys system files :: /neo new system files :: %. [/app /gen /lib /mar /neo /ren /sec /sur /sys /web ~] |= :: sal: all spurs to load from :: sal/(list spur) ^- ovum :: :: hav: all user files :: =; hav ~& user-files+(lent hav) [[%$ %sync ~] [%into %$ & hav]] =| hav/mode:clay |- ^+ hav ?~ sal ~ =. hav $(sal t.sal) :: :: tyl: spur :: =/ tyl i.sal |- ^+ hav :: :: pax: full path at `tyl` :: lon: directory at `tyl` :: =/ pax (en-beam:format bec tyl) =/ lon .^(arch %cy pax) =? hav ?=(^ fil.lon) ?. ?=({$hoon *} tyl) :: :: install only hoon files for now :: hav :: :: cot: file as plain-text octet-stream :: =; cot [[(flop `path`tyl) `[/text/plain cot]] hav] ^- octs ?- tyl {$hoon *} =/ dat .^(@t %cx pax) [(met 3 dat) dat] == =/ all ~(tap by dir.lon) |- ^- mode:clay ?~ all hav $(all t.all, hav ^$(tyl [p.i.all tyl])) :: [boot-ova module-ova file-ovum]