kernel.hoon 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /+ *wrapper
  2. =>
  3. |%
  4. +$ state-0 [%0 cached-hoon=(unit (trap vase)) ~]
  5. +$ state-1 [%1 cached-hoon=(unit (trap vase)) bc=build-cache pc=parse-cache]
  6. +$ versioned-state
  7. $% state-0
  8. state-1
  9. ==
  10. +$ choo-state state-1
  11. ::
  12. ++ moat (keep choo-state)
  13. +$ cause
  14. $% $: %build
  15. pat=cord
  16. tex=cord
  17. directory=(list [cord cord])
  18. arbitrary=?
  19. out=cord
  20. ==
  21. [%file %write path=@t contents=@ success=?]
  22. [%boot hoon-txt=cord]
  23. ==
  24. +$ effect
  25. $% [%file %write path=@t contents=@]
  26. [%exit id=@]
  27. ==
  28. ::
  29. :: $entry: path of a file along with unit of its contents.
  30. ::
  31. :: If unit is null, the path must exist inside of the dir map.
  32. ::
  33. +$ entry [pat=path tex=(unit cord)]
  34. ::
  35. +$ hash @
  36. +$ build-cache (map hash (trap vase))
  37. ::
  38. :: $build-result: result of a build
  39. ::
  40. :: either a (trap vase) or an error trace.
  41. ::
  42. +$ build-result (each (trap vase) tang)
  43. ::
  44. :: $taut: file import from /lib or /sur
  45. ::
  46. +$ taut [face=(unit term) pax=term]
  47. ::
  48. :: $pile: preprocessed hoon file
  49. ::
  50. +$ pile
  51. $: sur=(list taut) :: /-
  52. lib=(list taut) :: /+
  53. raw=(list [face=(unit term) pax=path]) :: /=
  54. bar=(list [face=term mark=@tas =path])
  55. =hoon
  56. ==
  57. ::
  58. :: $parse-cache: content addressed cache of preprocessed hoon files.
  59. ::
  60. +$ parse-cache (map hash pile)
  61. --
  62. ::
  63. =<
  64. ~& >> %choo-choo
  65. %- (moat &)
  66. ^- fort:moat
  67. |_ k=choo-state
  68. +* builder +>
  69. ::
  70. :: +load: upgrade from previous state
  71. ::
  72. ::
  73. ++ load
  74. |= old=versioned-state
  75. ^- choo-state
  76. ::
  77. :: We do not use the result of the soft because
  78. :: clamming (trap vase) overwrites the contents
  79. :: with the bunt resulting in the honc and the build
  80. :: artifacts being replaced with *(trap vase).
  81. ::
  82. ?~ ((soft versioned-state) old)
  83. ~& "choo: +load old state does not nest under versioned-state"
  84. !!
  85. ?- -.old
  86. %0
  87. ~& >> %upgrade-0-to-1
  88. :* %1
  89. cached-hoon.old
  90. *build-cache
  91. *parse-cache
  92. ==
  93. ::
  94. %1
  95. ~& >> %no-upgrade
  96. old
  97. ==
  98. ::
  99. :: +peek: external inspect
  100. ::
  101. ++ peek
  102. |= =path
  103. ^- (unit (unit *))
  104. ``?=(^ cached-hoon.k)
  105. ::
  106. :: +poke: external apply
  107. ::
  108. ++ poke
  109. |= [=wire eny=@ our=@ux now=@da dat=*]
  110. ^- [(list effect) choo-state]
  111. =/ cause=(unit cause) ((soft cause) dat)
  112. ?~ cause
  113. ~& >>> "input is not a proper cause"
  114. !!
  115. =/ cause u.cause
  116. ?- -.cause
  117. %file
  118. ?: success.cause
  119. ~& > "choo: output written successfully to {<path.cause>}"
  120. [[%exit 0]~ k]
  121. ~& > "choo: failed to write output to {<path.cause>}"
  122. [[%exit 1]~ k]
  123. ::
  124. %boot
  125. ~& >> hoon-version+hoon-version
  126. ?: ?=(^ cached-hoon.k)
  127. [~ k]
  128. [~ k(cached-hoon `(build-honc hoon-txt.cause))]
  129. ::
  130. %build
  131. ~& >> "building path: {<pat.cause>}"
  132. =/ =entry
  133. ~| "path did not parse: {<pat.cause>}"
  134. [(parse-file-path pat.cause) `tex.cause]
  135. =/ dir
  136. %- ~(gas by *(map path cord))
  137. (turn directory.cause |=((pair @t @t) [(stab p) q]))
  138. ?> ?=(^ cached-hoon.k)
  139. =/ [compiled=* new-bc=build-cache new-pc=parse-cache]
  140. ?: arbitrary.cause
  141. %- ~(create-arbitrary builder u.cached-hoon.k bc.k pc.k)
  142. [entry dir]
  143. %- ~(create builder u.cached-hoon.k bc.k pc.k)
  144. [entry dir]
  145. :_ k(bc new-bc, pc new-pc)
  146. =/ write-effect
  147. :* %file
  148. %write
  149. path=out.cause
  150. contents=(jam compiled)
  151. ==
  152. =/ success !=(compiled *(trap vase))
  153. ?: success
  154. ~& >>> "choo: build succeeded, sending out write effect"
  155. [write-effect]~
  156. ~& >>> "choo: build failed, skipping write and exiting"
  157. [%exit 1]~
  158. ==
  159. --
  160. ::
  161. :: build system
  162. ::
  163. =>
  164. ::
  165. :: dependency system
  166. ::
  167. |%
  168. +$ raut
  169. :: resolved taut - pax contains real path to file after running taut through +get-fit
  170. [face=(unit @tas) pax=path]
  171. ++ rile
  172. :: resolved pile
  173. $: sur=(list raut)
  174. lib=(list raut)
  175. raw=(list raut)
  176. bar=(list raut)
  177. =hoon
  178. ==
  179. ::
  180. :: +parse-file-path: parse cord of earth file path to path
  181. ++ parse-file-path
  182. |= pat=cord
  183. (rash pat gawp)
  184. ::
  185. :: +gawp: parse an absolute earth file path
  186. ++ gawp
  187. %+ sear
  188. |= p=path
  189. ^- (unit path)
  190. ?: ?=([~ ~] p) `~
  191. ?. =(~ (rear p)) `p
  192. ~
  193. ;~(pfix fas (most fas bic))
  194. ::
  195. :: +bic: parse file/dir name in earth file path
  196. ++ bic
  197. %+ cook
  198. |=(a=tape (rap 3 ^-((list @) a)))
  199. (star ;~(pose nud low hig hep dot sig cab))
  200. ::
  201. ++ to-wain :: cord to line list
  202. |= txt=cord
  203. ^- wain
  204. ?~ txt ~
  205. =/ len=@ (met 3 txt)
  206. =/ cut =+(cut -(a 3, c 1, d txt))
  207. =/ sub sub
  208. =| [i=@ out=wain]
  209. |- ^+ out
  210. =+ |- ^- j=@
  211. ?: ?| =(i len)
  212. =(10 (cut(b i)))
  213. ==
  214. i
  215. $(i +(i))
  216. =. out :_ out
  217. (cut(b i, c (sub j i)))
  218. ?: =(j len)
  219. (flop out)
  220. $(i +(j))
  221. ::
  222. ++ parse-pile
  223. |= [pax=path tex=tape]
  224. ^- pile
  225. =/ [=hair res=(unit [=pile =nail])]
  226. %- road |.
  227. ((pile-rule pax) [1 1] tex)
  228. ?^ res pile.u.res
  229. %- mean
  230. =/ lyn p.hair
  231. =/ col q.hair
  232. ^- (list tank)
  233. :~ leaf+"syntax error at [{<lyn>} {<col>}] in {<pax>}"
  234. ::
  235. =/ =wain (to-wain (crip tex))
  236. ?: (gth lyn (lent wain))
  237. '<<end of file>>'
  238. (snag (dec lyn) wain)
  239. ::
  240. leaf+(runt [(dec col) '-'] "^")
  241. ==
  242. ::
  243. ++ pile-rule
  244. |= pax=path
  245. %- full
  246. %+ ifix
  247. :_ gay
  248. :: parse optional /? and ignore
  249. ::
  250. ;~(plug gay (punt ;~(plug fas wut gap dem gap)))
  251. |^
  252. ;~ plug
  253. %+ cook (bake zing (list (list taut)))
  254. %+ rune hep
  255. (most ;~(plug com gaw) taut-rule)
  256. ::
  257. %+ cook (bake zing (list (list taut)))
  258. %+ rune lus
  259. (most ;~(plug com gaw) taut-rule)
  260. ::
  261. %+ rune tis
  262. ;~(plug ;~(pose (cold ~ tar) (stag ~ sym)) ;~(pfix gap stap))
  263. ::
  264. %+ rune tar
  265. ;~ (glue gap)
  266. sym
  267. ;~(pfix cen sym)
  268. ;~(pfix stap)
  269. ==
  270. ::
  271. %+ stag %tssg
  272. (most gap tall:(vang & pax))
  273. ==
  274. ::
  275. ++ pant
  276. |* fel=rule
  277. ;~(pose fel (easy ~))
  278. ::
  279. ++ mast
  280. |* [bus=rule fel=rule]
  281. ;~(sfix (more bus fel) bus)
  282. ::
  283. ++ rune
  284. |* [bus=rule fel=rule]
  285. %- pant
  286. %+ mast gap
  287. ;~(pfix fas bus gap fel)
  288. --
  289. ::
  290. ++ taut-rule
  291. %+ cook |=(taut +<)
  292. ;~ pose
  293. (stag ~ ;~(pfix tar sym)) :: *foo -> [~ %foo]
  294. ;~(plug (stag ~ sym) ;~(pfix tis sym)) :: bar=foo -> [[~ %bar] %foo]
  295. (cook |=(a=term [`a a]) sym) :: foo -> [[~ %foo] %foo]
  296. ==
  297. ::
  298. ++ segments
  299. |= suffix=@tas
  300. ^- (list path)
  301. =/ parser
  302. (most hep (cook crip ;~(plug ;~(pose low nud) (star ;~(pose low nud)))))
  303. =/ torn=(list @tas) (fall (rush suffix parser) ~[suffix])
  304. %- flop
  305. |- ^- (list (list @tas))
  306. ?< ?=(~ torn)
  307. ?: ?=([@ ~] torn)
  308. ~[torn]
  309. %- zing
  310. %+ turn $(torn t.torn)
  311. |= s=(list @tas)
  312. ^- (list (list @tas))
  313. ?> ?=(^ s)
  314. ~[[i.torn s] [(crip "{(trip i.torn)}-{(trip i.s)}") t.s]]
  315. ::
  316. ++ get-fit
  317. |= [pre=@ta pax=@tas dir=(map path cord)]
  318. ^- (unit path)
  319. =/ paz=(list path) (segments pax)
  320. |-
  321. ?~ paz
  322. ~& >> "{<pax>}-not-found" ~
  323. =/ last=term (rear i.paz)
  324. =. i.paz `path`(snip i.paz)
  325. =/ puz
  326. ^- path
  327. %+ snoc
  328. `path`[pre i.paz]
  329. `@ta`(rap 3 ~[last %'.' %hoon])
  330. ?^ (~(get by dir) puz)
  331. `puz
  332. $(paz t.paz)
  333. ::
  334. ++ resolve-pile
  335. :: turn fits into resolved path suffixes
  336. |= [=pile dir=(map path cord)]
  337. ^- (list raut)
  338. ;: weld
  339. (turn sur.pile |=(taut ^-(raut [face (need (get-fit %sur pax dir))])))
  340. (turn lib.pile |=(taut ^-(raut [face (need (get-fit %lib pax dir))])))
  341. ::
  342. %+ turn raw.pile
  343. |= [face=(unit term) pax=path]
  344. =/ pax-snip (snip pax)
  345. =/ pax-rear (rear pax)
  346. ^- raut
  347. [face `path`(snoc pax-snip `@ta`(rap 3 ~[pax-rear %'.' %hoon]))]
  348. ::
  349. %+ turn bar.pile
  350. |= [face=term mark=@tas pax=path]
  351. =/ pax-snip (snip pax)
  352. =/ pax-hind (rear pax-snip)
  353. =/ pax-rear (rear pax)
  354. ^- raut
  355. [`face `path`(snoc (snip pax-snip) `@ta`(rap 3 ~[pax-hind %'.' pax-rear]))]
  356. ==
  357. --
  358. ::
  359. :: builder core
  360. ::
  361. |_ [honc=(trap vase) bc=build-cache pc=parse-cache]
  362. ::
  363. ++ build-honc
  364. |= hoon-txt=cord
  365. ^- (trap vase)
  366. (swet *(trap vase) (ream hoon-txt))
  367. ::
  368. +$ octs [p=@ud q=@]
  369. ::
  370. :: $node: entry of adjacency matrix with metadata
  371. ::
  372. +$ node
  373. $: =path
  374. hash=@
  375. :: holds only outgoing edges
  376. deps=(list raut)
  377. leaf=graph-leaf
  378. ==
  379. ::
  380. +$ graph-leaf
  381. $% [%hoon =hoon]
  382. [%octs =octs]
  383. ==
  384. ::
  385. :: $create: build a trap from a hoon/jock file with dependencies
  386. ::
  387. :: .entry: the entry to build
  388. :: .dir: the directory to get dependencies from
  389. ::
  390. :: this is meant to build a kernel gate that takes a hash of a the
  391. :: dependency directory.
  392. ::
  393. :: returns a trap, a build-cache, and a parse-cache
  394. ++ create
  395. |= [=entry dir=(map path cord)]
  396. ^- [(trap) build-cache parse-cache]
  397. =/ dir-hash `@uvI`(mug dir)
  398. ~& >> dir-hash+dir-hash
  399. =/ compile
  400. (create-target entry dir)
  401. =/ ker-gen (head compile)
  402. =/ [=build-cache =parse-cache] (tail compile)
  403. :: +shot calls the kernel gate to tell it the hash of the dependency directory
  404. :_ [build-cache parse-cache]
  405. :: build failure, just return the bunted trap
  406. ?: =(ker-gen *(trap vase)) ker-gen
  407. => %+ shot ker-gen
  408. => d=!>(dir-hash)
  409. |.(d)
  410. |.(+:^$)
  411. ::
  412. :: $create-arbitrary: builds a hoon/jock file with dependencies without file hash injection
  413. ::
  414. :: .entry: the entry to build
  415. :: .dir: the directory to get dependencies from
  416. ::
  417. :: returns a trap, a build-cache, and a parse-cache
  418. ++ create-arbitrary
  419. |= [=entry dir=(map path cord)]
  420. ^- [(trap) build-cache parse-cache]
  421. =/ [tase=(trap) =build-cache =parse-cache]
  422. (create-target entry dir)
  423. :_ [build-cache parse-cache]
  424. ?: =(tase *(trap vase))
  425. tase
  426. => tase
  427. |.(+:^$)
  428. ::
  429. :: $create-target: builds a hoon/jock file with dependencies
  430. ::
  431. :: .entry: the entry to build
  432. :: .dir: the directory to get dependencies from
  433. ::
  434. :: returns a trap with the compiled hoon/jock file and the updated caches
  435. ++ create-target
  436. |= [=entry dir=(map path cord)]
  437. ^- [(trap vase) build-cache parse-cache]
  438. =/ [parsed-dir=(map path node) pc=parse-cache] (parse-dir entry dir)
  439. =/ all-nodes=(map path node) parsed-dir
  440. =/ [dep-dag=merk-dag =path-dag] (build-merk-dag all-nodes)
  441. ::
  442. :: delete invalid cache entries in bc
  443. =. bc
  444. %+ roll
  445. ~(tap by bc)
  446. |= [[hash=@ *] bc=_bc]
  447. ?: (~(has by dep-dag) hash)
  448. bc
  449. (~(del by bc) hash)
  450. ::
  451. =/ compile
  452. %: compile-target
  453. pat.entry
  454. path-dag
  455. all-nodes
  456. bc
  457. ==
  458. ::
  459. [(head compile) (tail compile) pc]
  460. ::
  461. :: $parse-dir: parse $entry and get dependencies from $dir
  462. ::
  463. :: .entry: entry to parse
  464. :: .dir: directory to get dependencies from
  465. ::
  466. :: returns a map of nodes and a parse cache
  467. ++ parse-dir
  468. |= [suf=entry dir=(map path cord)]
  469. ^- [(map path node) parse-cache]
  470. ~& > parsing+pat.suf
  471. |^
  472. =/ file=cord (get-file suf dir) :: get target file
  473. =/ hash=@ (shax file) :: hash target file
  474. =/ target=node
  475. ?. (is-hoon pat.suf)
  476. :* pat.suf :: path
  477. hash :: hash
  478. ~ :: deps
  479. [%octs [(met 3 file) file]] :: octs
  480. ==
  481. =/ =pile (parse-pile pat.suf (trip file)) :: parse target file
  482. =/ deps=(list raut) (resolve-pile pile dir) :: resolve deps
  483. :* pat.suf :: path
  484. hash :: hash
  485. deps :: deps
  486. [%hoon hoon.pile] :: hoon
  487. ==
  488. =| nodes=(map path node) :: init empty node map
  489. =. nodes (~(put by nodes) pat.suf target) :: add target node
  490. =/ seen=(set path) (~(put in *(set path)) pat.suf)
  491. (resolve-all nodes seen deps.target)
  492. ::
  493. ++ resolve-all
  494. |= [nodes=(map path node) seen=(set path) deps=(list raut)]
  495. ^- [(map path node) parse-cache]
  496. ?~ deps [nodes pc] :: done if no deps
  497. ?. (~(has in seen) pax.i.deps) :: skip if seen
  498. ~& >> parsing+pax.i.deps
  499. =/ dep-file (get-file [pax.i.deps ~] dir) :: get dep file
  500. =/ dep-hash (shax dep-file) :: hash dep file
  501. =^ dep-node=node pc
  502. ?. (is-hoon pax.i.deps)
  503. :_ pc
  504. :* pax.i.deps :: path
  505. dep-hash :: hash
  506. ~ :: deps
  507. [%octs [(met 3 dep-file) dep-file]] :: octs
  508. ==
  509. =/ dep-pile
  510. ?: (~(has by pc) dep-hash) :: check cache
  511. (~(got by pc) dep-hash)
  512. (parse-pile pax.i.deps (trip dep-file)) :: parse dep file
  513. ~& >> parsed+pax.i.deps
  514. =/ dep-deps (resolve-pile dep-pile dir) :: resolve dep deps
  515. ~& >> resolved+pax.i.deps
  516. :_ (~(put by pc) dep-hash dep-pile) :: cache parse
  517. :* pax.i.deps
  518. dep-hash
  519. dep-deps
  520. [%hoon hoon.dep-pile]
  521. ==
  522. =. nodes (~(put by nodes) pax.i.deps dep-node) :: add dep node
  523. =. seen (~(put in seen) pax.i.deps) :: mark as seen
  524. %= $
  525. nodes nodes
  526. seen seen
  527. deps (weld t.deps deps.dep-node) :: add new deps
  528. ==
  529. $(deps t.deps) :: next dep
  530. ::
  531. --
  532. ::
  533. :: $merk-dag: content-addressed map of nodes
  534. ::
  535. :: maps content hashes to nodes. each hash is computed from the node's
  536. :: content and the hashes of its dependencies, forming a merkle tree.
  537. :: used to detect changes in the dependency graph and enable caching.
  538. ::
  539. +$ merk-dag (map @ node)
  540. ::
  541. :: $path-dag: path-addressed map of nodes with their content hashes
  542. ::
  543. :: maps file paths to [hash node] pairs. provides a way to look up nodes
  544. :: by path while maintaining the connection to their content hash in the
  545. :: merk-dag. used during traversal to find dependencies by path.
  546. ::
  547. +$ path-dag (map path [@ node])
  548. ::
  549. :: $graph-view: adjacency matrix with easier access to neighbors
  550. ::
  551. :: used to keep track of traversal when building the merkle DAG
  552. ::
  553. +$ graph-view (map path (set path))
  554. ::
  555. :: $build-merk-dag: builds a merkle DAG out of the dependency folder
  556. ::
  557. :: .nodes: the nodes of the dependency graph
  558. ::
  559. :: returns a merkle DAG and a path-dag
  560. ++ build-merk-dag
  561. |^
  562. ::
  563. :: node set of entire dir + target
  564. |= nodes=(map path node)
  565. ^- [merk-dag path-dag]
  566. ~& >> building-merk-dag-for+~(key by nodes)
  567. ::
  568. :: need a way to uniquely identify dep directories
  569. =| dep-dag=merk-dag
  570. =| =path-dag
  571. =/ graph (build-graph-view nodes)
  572. =/ next=(map path node) (update-next nodes graph)
  573. ::
  574. :: traverse via a topological sorting of the DAG using Kahn's algorithm
  575. |-
  576. ?: .=(~ next)
  577. ?. .=(~ graph)
  578. ~|(cycle-detected+~(key by graph) !!)
  579. [dep-dag path-dag]
  580. =-
  581. %= $
  582. next (update-next nodes graph)
  583. graph graph
  584. dep-dag dd
  585. path-dag pd
  586. ==
  587. ^- [graph=(map path (set path)) dd=(map @ node) pd=^path-dag]
  588. ::
  589. :: every node in next is put into path-dag and dep-dag along with
  590. :: its hash
  591. %+ roll
  592. ~(tap by next)
  593. |= [[p=path n=node] graph=_graph dep-dag=_dep-dag path-dag=_path-dag]
  594. =/ hash (calculate-hash n dep-dag path-dag)
  595. :+ (update-graph-view graph p)
  596. (~(put by dep-dag) hash n)
  597. (~(put by path-dag) p [hash n])
  598. ::
  599. :: $calculate-hash: calculate the hash of a node
  600. ::
  601. :: .n: the node to calculate the hash of
  602. :: .dep-dag: the merkle DAG of the dependency graph
  603. :: .path-dag: the path-dag of the dependency graph
  604. ::
  605. :: returns the hash of the node
  606. ++ calculate-hash
  607. |= [n=node dep-dag=merk-dag =path-dag]
  608. ^- @
  609. %+ roll
  610. deps.n
  611. |= [raut hash=_hash.n]
  612. ?. (~(has by path-dag) pax)
  613. ~& >>> "calculate-hash: Missing {<pax>}" !!
  614. =/ [dep-hash=@ *]
  615. (~(got by path-dag) pax)
  616. (shax (rep 8 ~[hash dep-hash]))
  617. --
  618. ::
  619. :: $compile-target: compile a target hoon file
  620. ::
  621. :: .pat: path to the target hoon file
  622. :: .path-dag: the path-dag of the dependency graph
  623. :: .nodes: the nodes of the dependency graph
  624. :: .bc: the build cache
  625. ::
  626. :: returns a trap vase with the compiled hoon file and the updated build
  627. :: cache. if a build failure is detected, a bunted (trap vase) is returned
  628. :: instead.
  629. ++ compile-target
  630. |^
  631. |= [pat=path =path-dag nodes=(map path node) bc=build-cache]
  632. ^- [(trap vase) build-cache]
  633. ~& >> compiling-target+pat
  634. =/ n=node
  635. ~| """
  636. couldn't find node {<pat>} in path-dag.
  637. nodes: {<~(key by nodes)>}
  638. path-dag: {<~(key by path-dag)>}
  639. """
  640. +:(~(got by path-dag) pat)
  641. =/ graph (build-graph-view nodes)
  642. =/ next=(map path node) (update-next nodes graph)
  643. =| failed=_|
  644. |- ^- [(trap vase) build-cache]
  645. ?: failed [*(trap vase) bc]
  646. ?: .=(~ next)
  647. =/ [=build-result new-bc=build-cache]
  648. (compile-node n path-dag bc)
  649. ?- -.build-result
  650. ::
  651. %| ~& >>> "compile-target: failed: {<pat>}"
  652. [*(trap vase) new-bc]
  653. ::
  654. %& [p.build-result new-bc]
  655. ==
  656. =/ [err=? bc=build-cache]
  657. %+ roll ~(tap by next)
  658. |= [[p=path n=node] [err=_| bc=_bc]]
  659. =/ [=build-result new-bc=build-cache]
  660. (compile-node n path-dag bc)
  661. ?- -.build-result
  662. ::
  663. %| ~& >>> "compile-target: failed: {<p>}"
  664. [& new-bc]
  665. ::
  666. %& [err new-bc]
  667. ==
  668. =. graph
  669. (roll ~(tap by next) |=([[p=path *] g=_graph] (update-graph-view g p)))
  670. %= $
  671. next (update-next nodes graph)
  672. graph graph
  673. bc bc
  674. failed err
  675. ==
  676. ::
  677. :: $compile-node: compile a single node
  678. ::
  679. :: .n: the node to compile
  680. :: .path-dag: the path-dag of the dependency graph
  681. :: .bc: the build cache
  682. ::
  683. :: looks up the node in the build cache and compiles it if it's not already
  684. :: cached.
  685. ::
  686. :: returns a $build-result and the updated build cache
  687. ++ compile-node
  688. |= [n=node =path-dag bc=build-cache]
  689. ^- [build-result build-cache]
  690. =/ [dep-hash=@ *] (~(got by path-dag) path.n)
  691. ?: (~(has by bc) dep-hash)
  692. ~& > build-cache-hit+path.n
  693. :_ bc
  694. [%.y (~(got by bc) dep-hash)]
  695. ~& > build-cache-miss+path.n
  696. =/ =build-result (mule |.((build-node n path-dag bc)))
  697. =? bc ?=(%& -.build-result)
  698. (~(put by bc) dep-hash p.build-result)
  699. =- ?. ?=(%| -.build-result) -
  700. ((slog p.build-result) -)
  701. [build-result bc]
  702. ::
  703. :: $build-node: build a single node and its dependencies
  704. ::
  705. :: .n: the node to compile
  706. :: .path-dag: the path-dag of the dependency graph
  707. :: .bc: the build cache
  708. ::
  709. :: returns a trap vase with the compiled hoon
  710. ++ build-node
  711. |= [n=node =path-dag bc=build-cache]
  712. ^- (trap vase)
  713. ~> %bout
  714. =; dep-vaz=(trap vase)
  715. ?: ?=(%hoon -.leaf.n)
  716. ::
  717. :: Faces are resolved via depth-first search into the subject.
  718. :: We append the honc (hoon.hoon) to the end of the vase
  719. :: because imports have higher precedence when resolving faces.
  720. :: To avoid shadowing issues with hoon.hoon, attach faces to your
  721. :: imports or avoid shadowed names altogether.
  722. (swet (slat dep-vaz honc) hoon.leaf.n)
  723. => octs=!>(octs.leaf.n)
  724. |.(octs)
  725. %+ roll deps.n
  726. |= [r=raut vaz=(trap vase)]
  727. ~& > grabbing-dep+pax.r
  728. =/ [dep-hash=@ dep-node=node]
  729. ~| "couldn't find dep hash for {<pax.r>}"
  730. (~(got by path-dag) pax.r)
  731. =/ dep-vaz=(trap vase)
  732. ~| "couldn't find artifact for {<pax.r>} in build cache"
  733. (~(got by bc) dep-hash)
  734. ~& > attaching-face+face.r
  735. ::
  736. :: Ford imports are included in the order that they appear in the deps.
  737. (slat vaz (label-vase dep-vaz face.r))
  738. ::
  739. :: $label-vase: label a (trap vase) with a face
  740. ::
  741. :: .vaz: the (trap vase) to label
  742. :: .face: the face to label the (trap vase) with
  743. ::
  744. :: returns a (trap vase) labeled with the given face
  745. ++ label-vase
  746. |= [vaz=(trap vase) face=(unit @tas)]
  747. ^- (trap vase)
  748. ?~ face vaz
  749. => [vaz=vaz face=u.face]
  750. |.
  751. =/ vas $:vaz
  752. [[%face face p.vas] q.vas]
  753. --
  754. ::
  755. :: $update-next: returns nodes from a $graph-view that have no outgoing edges
  756. ::
  757. :: .nodes: the nodes of the dependency graph
  758. :: .gv: the graph-view of the dependency graph
  759. ::
  760. :: assumes that entries in $nodes that are not in the $graph-view have
  761. :: already been visited.
  762. ::
  763. ++ update-next
  764. |= [nodes=(map path node) gv=graph-view]
  765. ^- (map path node)
  766. ::
  767. :: if we don't have the entry in gv, already visited
  768. %+ roll
  769. ~(tap by gv)
  770. |= [[pax=path edges=(set path)] next=(map path node)]
  771. ::
  772. :: if a node has no out edges, add it to next
  773. ?. =(*(set path) edges)
  774. next
  775. %+ ~(put by next)
  776. pax
  777. (~(got by nodes) pax)
  778. ::
  779. :: $update-graph-view: updates a $graph-view by removing a $path
  780. ::
  781. :: .gv: the graph-view to update
  782. :: .p: the path to remove from the graph-view
  783. ::
  784. :: deletes the $path from the $graph-view and removes it from all edge sets
  785. ::
  786. ++ update-graph-view
  787. |= [gv=graph-view p=path]
  788. ^- graph-view
  789. =. gv (~(del by gv) p)
  790. %- ~(urn by gv)
  791. |= [pax=path edges=(set path)]
  792. (~(del in edges) p)
  793. ::
  794. :: $build-graph-view: build a graph-view from a node map
  795. ::
  796. :: .nodes: the nodes of the dependency graph
  797. ::
  798. :: returns a graph-view of the dependency graph
  799. ::
  800. ++ build-graph-view
  801. |= nodes=(map path node)
  802. ^- graph-view
  803. %- ~(urn by nodes)
  804. |= [* n=node]
  805. %- silt
  806. (turn deps.n |=(raut pax))
  807. ::
  808. :: $slat: merge two (trap vase)s
  809. ::
  810. :: .hed: the first (trap vase)
  811. :: .tal: the second (trap vase)
  812. ::
  813. :: returns a merged (trap vase)
  814. ++ slat
  815. |= [hed=(trap vase) tal=(trap vase)]
  816. ^- (trap vase)
  817. => +<
  818. |.
  819. =+ [bed bal]=[$:hed $:tal]
  820. [[%cell p:bed p:bal] [q:bed q:bal]]
  821. :: +shot: deferred slam
  822. ::
  823. :: .gat: the gate to slam with the sample as a (trap vase)
  824. :: .sam: the sample to slam with the gate
  825. ::
  826. :: NOTE: this should never run inside of a trap. if it does, the builder
  827. :: dependencies will leak into the result.
  828. ::
  829. ++ shot
  830. |= [gat=(trap vase) sam=(trap vase)]
  831. ^- (trap vase)
  832. =/ [typ=type gen=hoon]
  833. :- [%cell p:$:gat p:$:sam]
  834. [%cnsg [%$ ~] [%$ 2] [%$ 3] ~]
  835. =+ gun=(~(mint ut typ) %noun gen)
  836. => [typ=p.gun +<.$]
  837. |.
  838. [typ .*([q:$:gat q:$:sam] [%9 2 %10 [6 %0 3] %0 2])]
  839. ::
  840. :: +swet: deferred +slap
  841. ::
  842. :: NOTE: this is +swat but with a bug fixed that caused a space leak in
  843. :: the resulting trap vases.
  844. ::
  845. ++ swet
  846. |= [tap=(trap vase) gen=hoon]
  847. ^- (trap vase)
  848. =/ gun (~(mint ut p:$:tap) %noun gen)
  849. => [gun=gun tap=tap]
  850. |. ~+
  851. [p.gun .*(q:$:tap q.gun)]
  852. ::
  853. ++ get-file :: get file contents
  854. |= [suf=entry dir=(map path cord)]
  855. ^- cord
  856. ?~ tex.suf
  857. ~| "file not found: {<pat.suf>}"
  858. (~(got by dir) pat.suf)
  859. u.tex.suf
  860. ::
  861. ++ is-hoon
  862. |= pax=path
  863. ^- ?
  864. =/ end (rear pax)
  865. !=(~ (find ".hoon" (trip end)))
  866. ::
  867. --