mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-01 03:23:09 +03:00
577 lines
13 KiB
Plaintext
577 lines
13 KiB
Plaintext
:: An aquarium of virtual ships. Put in some fish and watch them!
|
|
::
|
|
:: usage:
|
|
:: |start %aqua
|
|
:: /- aquarium
|
|
:: :aqua &pill .^(pill:aquarium %cx %/urbit/pill)
|
|
:: OR
|
|
:: :aqua &pill +solid
|
|
::
|
|
:: Then try stuff:
|
|
:: :aqua [%init ~[~bud ~dev]]
|
|
:: :aqua [%dojo ~[~bud ~dev] "[our eny (add 3 5)]"]
|
|
:: :aqua [%dojo ~[~bud] "|hi ~dev"]
|
|
:: :aqua [%wish ~[~bud ~dev] '(add 2 3)']
|
|
:: :aqua [%peek ~[~bud] /cx/~bud/home/(scot %da now)/app/curl/hoon]
|
|
:: :aqua [%dojo ~[~bud ~dev] '|mount %']
|
|
:: :aqua [%file ~[~bud ~dev] %/sys/vane]
|
|
:: :aqua [%pause-events ~[~bud ~dev]]
|
|
::
|
|
::
|
|
:: We get ++unix-event and ++pill from /-aquarium
|
|
::
|
|
/- aquarium
|
|
/+ pill
|
|
=, pill-lib=pill
|
|
=, aquarium
|
|
=> $~ |%
|
|
+$ move (pair bone card)
|
|
+$ card
|
|
$% [%diff diff-type]
|
|
==
|
|
::
|
|
:: Outgoing subscription updates
|
|
::
|
|
+$ diff-type
|
|
$% [%aqua-effects aqua-effects]
|
|
[%aqua-events aqua-events]
|
|
[%aqua-boths aqua-boths]
|
|
==
|
|
::
|
|
+$ state
|
|
$: %0
|
|
pil=pill
|
|
assembled=*
|
|
tym=@da
|
|
fleet-snaps=(map term (map ship pier))
|
|
piers=(map ship pier)
|
|
==
|
|
::
|
|
+$ pier
|
|
$: snap=*
|
|
event-log=(list unix-timed-event)
|
|
next-events=(qeu unix-event)
|
|
processing-events=?
|
|
==
|
|
--
|
|
=, gall
|
|
::
|
|
:: unix-{effects,events,boths}: collect jar of effects and events to
|
|
:: brodcast all at once to avoid gall backpressure
|
|
:: moves: Hoist moves into state for cleaner state management
|
|
::
|
|
=| unix-effects=(jar ship unix-effect)
|
|
=| unix-events=(jar ship unix-timed-event)
|
|
=| unix-boths=(jar ship unix-both)
|
|
=| moves=(list move)
|
|
|_ $: hid=bowl
|
|
state
|
|
==
|
|
::
|
|
:: Represents a single ship's state.
|
|
::
|
|
++ pe
|
|
|= who=ship
|
|
=+ (~(gut by piers) who *pier)
|
|
=* pier-data -
|
|
|%
|
|
::
|
|
:: Done; install data
|
|
::
|
|
++ abet-pe
|
|
^+ this
|
|
=. piers (~(put by piers) who pier-data)
|
|
this
|
|
::
|
|
:: Initialize new ship
|
|
::
|
|
++ apex
|
|
=. pier-data *pier
|
|
=. snap assembled
|
|
~& pill-size=(met 3 (jam snap))
|
|
..abet-pe
|
|
::
|
|
:: Enqueue events to child arvo
|
|
::
|
|
++ push-events
|
|
|= ues=(list unix-event)
|
|
^+ ..abet-pe
|
|
=. next-events (~(gas to next-events) ues)
|
|
..abet-pe
|
|
::
|
|
:: Send moves to host arvo
|
|
::
|
|
++ emit-moves
|
|
|= ms=(list move)
|
|
=. this (^emit-moves ms)
|
|
..abet-pe
|
|
::
|
|
:: Process the events in our queue.
|
|
::
|
|
++ plow
|
|
|- ^+ ..abet-pe
|
|
?: =(~ next-events)
|
|
..abet-pe
|
|
?. processing-events
|
|
..abet-pe
|
|
=^ ue next-events ~(get to next-events)
|
|
=/ poke-arm (mox +47.snap)
|
|
?> ?=(%0 -.poke-arm)
|
|
=/ poke p.poke-arm
|
|
=. tym (max +(tym) now.hid)
|
|
=/ poke-result (mule |.((slum poke tym ue)))
|
|
?: ?=(%| -.poke-result)
|
|
%- (slog >%aqua-crash< >guest=who< p.poke-result)
|
|
$
|
|
=. snap +.p.poke-result
|
|
=. ..abet-pe (publish-event tym ue)
|
|
=. ..abet-pe (handle-effects ((list ovum) -.p.poke-result))
|
|
$
|
|
::
|
|
:: Peek
|
|
::
|
|
++ peek
|
|
|= p=*
|
|
=/ res (mox +46.snap)
|
|
?> ?=(%0 -.res)
|
|
=/ peek p.res
|
|
=/ pax (path p)
|
|
?> ?=([@ @ @ @ *] pax)
|
|
=. i.t.t.t.pax (scot %da tym)
|
|
=/ pek (slum peek [tym pax])
|
|
pek
|
|
::
|
|
:: Wish
|
|
::
|
|
++ wish
|
|
|= txt=@t
|
|
=/ res (mox +22.snap)
|
|
?> ?=(%0 -.res)
|
|
=/ wish p.res
|
|
~& [who=who %wished (slum wish txt)]
|
|
..abet-pe
|
|
::
|
|
++ mox |=(* (mock [snap +<] scry))
|
|
::
|
|
:: Start/stop processing events. When stopped, events are added to
|
|
:: our queue but not processed.
|
|
::
|
|
++ start-processing-events .(processing-events &)
|
|
++ stop-processing-events .(processing-events |)
|
|
::
|
|
:: Handle all the effects produced by a single event.
|
|
::
|
|
++ handle-effects
|
|
|= effects=(list ovum)
|
|
^+ ..abet-pe
|
|
?~ effects
|
|
..abet-pe
|
|
=. ..abet-pe
|
|
=/ sof ((soft unix-effect) i.effects)
|
|
?~ sof
|
|
~? aqua-debug=& [who=who %unknown-effect i.effects]
|
|
..abet-pe
|
|
(publish-effect u.sof)
|
|
$(effects t.effects)
|
|
::
|
|
:: Give effect to our subscribers
|
|
::
|
|
++ publish-effect
|
|
|= uf=unix-effect
|
|
^+ ..abet-pe
|
|
=. unix-effects (~(add ja unix-effects) who uf)
|
|
=. unix-boths (~(add ja unix-boths) who [%effect uf])
|
|
..abet-pe
|
|
::
|
|
:: Give event to our subscribers
|
|
::
|
|
++ publish-event
|
|
|= ute=unix-timed-event
|
|
^+ ..abet-pe
|
|
=. event-log [ute event-log]
|
|
=. unix-events (~(add ja unix-events) who ute)
|
|
=. unix-boths (~(add ja unix-boths) who [%event ute])
|
|
..abet-pe
|
|
--
|
|
::
|
|
++ this .
|
|
::
|
|
:: ++apex-aqua and ++abet-aqua must bookend calls from gall
|
|
::
|
|
++ apex-aqua
|
|
^+ this
|
|
=: moves ~
|
|
unix-effects ~
|
|
unix-events ~
|
|
unix-boths ~
|
|
==
|
|
this
|
|
::
|
|
++ abet-aqua
|
|
^- (quip move _this)
|
|
=. this
|
|
%- emit-moves
|
|
%- zing ^- (list (list move))
|
|
%+ turn ~(tap by sup.hid)
|
|
|= [b=bone her=ship pax=path]
|
|
^- (list move)
|
|
?+ pax ~
|
|
[%effects @ ~]
|
|
=/ who (slav %p i.t.pax)
|
|
=/ ufs (~(get ja unix-effects) who)
|
|
?~ ufs
|
|
~
|
|
[b %diff %aqua-effects who (flop ufs)]~
|
|
::
|
|
[%effects ~]
|
|
%+ turn
|
|
~(tap by unix-effects)
|
|
|= [who=ship ufs=(list unix-effect)]
|
|
[b %diff %aqua-effects who (flop ufs)]
|
|
::
|
|
[%events @ ~]
|
|
=/ who (slav %p i.t.pax)
|
|
=/ ve (~(get ja unix-events) who)
|
|
?~ ve
|
|
~
|
|
[b %diff %aqua-events who (flop ve)]~
|
|
::
|
|
[%boths @ ~]
|
|
=/ who (slav %p i.t.pax)
|
|
=/ bo (~(get ja unix-boths) who)
|
|
?~ bo
|
|
~
|
|
[b %diff %aqua-boths who (flop bo)]~
|
|
==
|
|
[(flop moves) this]
|
|
::
|
|
++ emit-moves
|
|
|= ms=(list move)
|
|
=. moves (weld ms moves)
|
|
this
|
|
::
|
|
::
|
|
:: Run all events on all ships until all queues are empty
|
|
::
|
|
++ plow-all
|
|
|- ^+ this
|
|
=/ who
|
|
=/ pers ~(tap by piers)
|
|
|- ^- (unit ship)
|
|
?~ pers
|
|
~
|
|
?: &(?=(^ next-events.q.i.pers) processing-events.q.i.pers)
|
|
`p.i.pers
|
|
$(pers t.pers)
|
|
~? aqua-debug=| plowing=who
|
|
?~ who
|
|
this
|
|
=. this abet-pe:plow:(pe u.who)
|
|
$
|
|
::
|
|
:: Subscribe to effects from a ship
|
|
::
|
|
++ peer-effects
|
|
|= pax=path
|
|
^- (quip move _this)
|
|
?. ?=([@ *] pax)
|
|
~& [%aqua-bad-peer-effects pax]
|
|
`this
|
|
?~ (slaw %p i.pax)
|
|
~& [%aqua-bad-peer-effects-ship pax]
|
|
!!
|
|
`this
|
|
::
|
|
:: Subscribe to events to a ship
|
|
::
|
|
++ peer-events
|
|
|= pax=path
|
|
^- (quip move _this)
|
|
?. ?=([@ ~] pax)
|
|
~& [%aqua-bad-peer-events pax]
|
|
`this
|
|
?~ (slaw %p i.pax)
|
|
~& [%aqua-bad-peer-events-ship pax]
|
|
!!
|
|
`this
|
|
::
|
|
:: Subscribe to both events and effects of a ship
|
|
::
|
|
++ peer-boths
|
|
|= pax=path
|
|
^- (quip move _this)
|
|
?. ?=([@ ~] pax)
|
|
~& [%aqua-bad-peer-boths pax]
|
|
`this
|
|
?~ (slaw %p i.pax)
|
|
~& [%aqua-bad-peer-boths-ship pax]
|
|
!!
|
|
`this
|
|
::
|
|
:: Load a pill and assemble arvo. Doesn't send any of the initial
|
|
:: events.
|
|
::
|
|
++ poke-pill
|
|
|= p=pill
|
|
^- (quip move _this)
|
|
=. this apex-aqua =< abet-aqua
|
|
=. pil p
|
|
~& lent=(met 3 (jam boot-ova.pil))
|
|
=/ res=toon :: (each * (list tank))
|
|
(mock [boot-ova.pil [2 [0 3] [0 2]]] scry)
|
|
=. fleet-snaps ~
|
|
?- -.res
|
|
%0
|
|
~& %suc
|
|
=. assembled +7.p.res
|
|
this
|
|
::
|
|
%1
|
|
~& [%vere-blocked p.res]
|
|
this
|
|
::
|
|
%2
|
|
~& %vere-fail
|
|
%- (slog p.res)
|
|
this
|
|
==
|
|
::
|
|
:: Handle commands from CLI
|
|
::
|
|
:: Should put some thought into arg structure, maybe make a mark.
|
|
::
|
|
:: Should convert some of these to just rewrite into ++poke-events.
|
|
::
|
|
++ poke-noun
|
|
|= val=*
|
|
^- (quip move _this)
|
|
=. this apex-aqua =< abet-aqua
|
|
^+ this
|
|
:: Could potentially factor out the three lines of turn-ships
|
|
:: boilerplate
|
|
::
|
|
?+ val ~|(%bad-noun-arg !!)
|
|
[%swap-vanes vs=*]
|
|
?> ?=([[%7 * %1 installed=*] ~] boot-ova.pil)
|
|
=. installed.boot-ova.pil
|
|
%+ roll (,(list term) vs.val)
|
|
|= [v=term _installed.boot-ova.pil]
|
|
%^ slum installed.boot-ova.pil now.hid
|
|
=/ vane
|
|
?+ v ~|([%unknown-vane v] !!)
|
|
%a %ames
|
|
%b %behn
|
|
%c %clay
|
|
%d %dill
|
|
%e %eyre
|
|
%f %ford
|
|
%g %gall
|
|
%j %jael
|
|
==
|
|
=/ pax
|
|
/(scot %p our.hid)/home/(scot %da now.hid)/sys/vane/[vane]
|
|
=/ txt .^(@ %cx (weld pax /hoon))
|
|
[/vane/[vane] [%veer v pax txt]]
|
|
=> .(this ^+(this this))
|
|
=^ ms this (poke-pill pil)
|
|
(emit-moves ms)
|
|
::
|
|
[%swap-files ~]
|
|
=. userspace-ova.pil
|
|
=/ slim-dirs
|
|
`(list path)`~[/app /gen /lib /mar /sur /hoon/sys /arvo/sys /zuse/sys]
|
|
:_ ~
|
|
%- unix-event
|
|
%- %*(. file-ovum:pill-lib directories slim-dirs)
|
|
/(scot %p our.hid)/home/(scot %da now.hid)
|
|
=^ ms this (poke-pill pil)
|
|
(emit-moves ms)
|
|
::
|
|
[%wish hers=* p=@t]
|
|
%+ turn-ships ((list ship) hers.val)
|
|
|= [who=ship thus=_this]
|
|
=. this thus
|
|
(wish:(pe who) p.val)
|
|
::
|
|
[%unpause-events hers=*]
|
|
%+ turn-ships ((list ship) hers.val)
|
|
|= [who=ship thus=_this]
|
|
=. this thus
|
|
start-processing-events:(pe who)
|
|
::
|
|
[%pause-events hers=*]
|
|
%+ turn-ships ((list ship) hers.val)
|
|
|= [who=ship thus=_this]
|
|
=. this thus
|
|
stop-processing-events:(pe who)
|
|
::
|
|
[%clear-snap lab=@tas]
|
|
=. fleet-snaps ~ :: (~(del by fleet-snaps) lab.val)
|
|
this
|
|
==
|
|
::
|
|
:: Apply a list of events tagged by ship
|
|
::
|
|
++ poke-aqua-events
|
|
|= events=(list aqua-event)
|
|
^- (quip move _this)
|
|
=. this apex-aqua =< abet-aqua
|
|
%+ turn-events events
|
|
|= [ae=aqua-event thus=_this]
|
|
=. this thus
|
|
?- -.ae
|
|
%init-ship
|
|
=. this abet-pe:(publish-effect:(pe who.ae) [/ %sleep ~])
|
|
=/ initted
|
|
=< plow
|
|
%- push-events:apex:(pe who.ae)
|
|
^- (list unix-event)
|
|
:~ [/ %wack 0] :: eny
|
|
[/ %whom who.ae] :: eny
|
|
[//newt/0v1n.2m9vh %barn ~]
|
|
[//behn/0v1n.2m9vh %born ~]
|
|
:^ //term/1 %boot &
|
|
?~ keys.ae
|
|
[%fake who.ae]
|
|
[%dawn u.keys.ae]
|
|
-.userspace-ova.pil
|
|
[//http-client/0v1n.2m9vh %born ~]
|
|
[//http-server/0v1n.2m9vh %born ~]
|
|
[//http-server/0v1n.2m9vh %live 8.080 `8.445]
|
|
==
|
|
=. this abet-pe:initted
|
|
(pe who.ae)
|
|
::
|
|
%pause-events
|
|
stop-processing-events:(pe who.ae)
|
|
::
|
|
%snap-ships
|
|
=. fleet-snaps
|
|
%+ ~(put by fleet-snaps) lab.ae
|
|
%- malt
|
|
%+ murn hers.ae
|
|
|= her=ship
|
|
^- (unit (pair ship pier))
|
|
=+ per=(~(get by piers) her)
|
|
?~ per
|
|
~
|
|
`[her u.per]
|
|
(pe -.hers.ae)
|
|
::
|
|
%restore-snap
|
|
=. this
|
|
%+ turn-ships (turn ~(tap by piers) head)
|
|
|= [who=ship thus=_this]
|
|
=. this thus
|
|
(publish-effect:(pe who) [/ %sleep ~])
|
|
=. piers (~(uni by piers) (~(got by fleet-snaps) lab.ae))
|
|
=. this
|
|
%+ turn-ships (turn ~(tap by piers) head)
|
|
|= [who=ship thus=_this]
|
|
=. this thus
|
|
(publish-effect:(pe who) [/ %restore ~])
|
|
(pe ~bud) :: XX why ~bud? need an example
|
|
::
|
|
%event
|
|
~? &(aqua-debug=| !?=(?(%belt %hear) -.q.ue.ae))
|
|
raw-event=[who.ae -.q.ue.ae]
|
|
~? &(debug=| ?=(%receive -.q.ue.ae))
|
|
raw-event=[who.ae ue.ae]
|
|
(push-events:(pe who.ae) [ue.ae]~)
|
|
==
|
|
::
|
|
:: Run a callback function against a list of ships, aggregating state
|
|
:: and plowing all ships at the end.
|
|
::
|
|
:: I think we should use patterns like this more often. Because we
|
|
:: don't, here's some points to be aware.
|
|
::
|
|
:: `fun` must take `this` as a parameter, since it needs to be
|
|
:: downstream of previous state changes. You could use `state` as
|
|
:: the state variable, but it muddles the code and it's not clear
|
|
:: whether it's better. You could use the `_(pe)` core if you're
|
|
:: sure you'll never need to refer to anything outside of your pier,
|
|
:: but I don't think we can guarantee that.
|
|
::
|
|
:: The callback function must start with `=. this thus`, or else
|
|
:: you don't get the new state. Would be great if you could hot-swap
|
|
:: that context in here, but we don't know where to put it unless we
|
|
:: restrict the callbacks to always have `this` at a particular axis,
|
|
:: and that doesn't feel right
|
|
::
|
|
++ turn-plow
|
|
|* arg=mold
|
|
|= [hers=(list arg) fun=$-([arg _this] _(pe))]
|
|
|- ^+ this
|
|
?~ hers
|
|
plow-all
|
|
=. this
|
|
abet-pe:plow:(fun i.hers this)
|
|
$(hers t.hers, this this)
|
|
::
|
|
++ turn-ships (turn-plow ship)
|
|
++ turn-events (turn-plow aqua-event)
|
|
::
|
|
:: Check whether we have a snapshot
|
|
::
|
|
++ peek-x-fleet-snap
|
|
|= pax=path
|
|
^- (unit (unit [%noun noun]))
|
|
?. ?=([@ ~] pax)
|
|
~
|
|
:^ ~ ~ %noun
|
|
(~(has by fleet-snaps) i.pax)
|
|
::
|
|
:: Pass scry into child ship
|
|
::
|
|
++ peek-x-i
|
|
|= pax=path
|
|
^- (unit (unit [%noun noun]))
|
|
?. ?=([@ @ @ @ @ *] pax)
|
|
~
|
|
=/ who (slav %p i.pax)
|
|
=/ pier (~(get by piers) who)
|
|
?~ pier
|
|
~
|
|
:^ ~ ~ %noun
|
|
(peek:(pe who) t.pax)
|
|
::
|
|
:: Get all created ships
|
|
::
|
|
++ peek-x-ships
|
|
|= pax=path
|
|
^- (unit (unit [%noun (list ship)]))
|
|
?. ?=(~ pax)
|
|
~
|
|
:^ ~ ~ %noun
|
|
`(list ship)`(turn ~(tap by piers) head)
|
|
::
|
|
::
|
|
::
|
|
++ peek-x-pill
|
|
|= pax=path
|
|
^- (unit (unit [%pill pill]))
|
|
=/ pill-size (met 3 (jam pil))
|
|
?: (lth pill-size 100)
|
|
~& [%no-pill size=pill-size]
|
|
[~ ~]
|
|
``pill+pil
|
|
::
|
|
:: Trivial scry for mock
|
|
::
|
|
++ scry |=([* *] ~)
|
|
::
|
|
:: Throw away old state if it doesn't soft to new state.
|
|
::
|
|
++ prep
|
|
|= old/(unit noun)
|
|
^- [(list move) _+>.$]
|
|
~& prep=%aqua
|
|
?~ old
|
|
`+>.$
|
|
=+ new=((soft state) u.old)
|
|
?~ new
|
|
`+>.$
|
|
`+>.$(+<+ u.new)
|
|
--
|