Merge branch 'test' into memorable

Conflicts:
	Makefile
	gen164/watt.c
This commit is contained in:
C. Guy Yarvin 2014-09-10 09:06:30 -07:00
commit 07cf59be1b
88 changed files with 17346 additions and 1743 deletions

View File

@ -225,7 +225,7 @@
0w0 :: 54, ~wyd, Curtis Yarvin (sator)
0w0 :: 55, ~tep, Curtis Yarvin (sator)
0w0 :: 56, ~bes, Curtis Yarvin (sator)
0w0 :: 57, ~dex, Curtis Yarvin (sator)
0w0 :: 57, ~dex, Jared Hance (aestas)
0w0 :: 58, ~sef, Curtis Yarvin (sator)
0w0 :: 59, ~wyc, Curtis Yarvin (sator)
0w0 :: 60, ~bur, Curtis Yarvin (sator)
@ -240,7 +240,7 @@
0w0 :: 69, ~pet, Curtis Yarvin (sator)
0w0 :: 70, ~rul, Curtis Yarvin (sator)
0w0 :: 71, ~syn, Curtis Yarvin (sator)
0w0 :: 72, ~reg, Curtis Yarvin (sator)
0w0 :: 72, ~reg, Henry Ault (aestas)
0w0 :: 73, ~tyd, Curtis Yarvin (sator)
0w0 :: 74, ~sup, Curtis Yarvin (sator)
0w0 :: 75, ~sem, ~boswed-nibnyd (fidelis)
@ -255,9 +255,9 @@
0w2x.~ldho.Oo7kE.QqNSx.XteFh :: 84, ~web, Ar Vicco (donum)
0w0 :: 85, ~sum, Curtis Yarvin (sator)
0w0 :: 86, ~mut, Curtis Yarvin (sator)
0w0 :: 87, ~nyx, urbit.org (civitas)
0w0 :: 87, ~nyx, Curtis Yarvin (sator)
0w30.UUr19.iBPlD.wfyJD.2CWPv :: 88, ~rex, Ben Davenport (angelus)
0w0 :: 89, ~teb, urbit.org (civitas)
0w0 :: 89, ~teb, Curtis Yarvin (sator)
0w0 :: 90, ~fus, urbit.org (civitas)
0w0 :: 91, ~hep, urbit.org (civitas)
0w0 :: 92, ~ben, urbit.org (civitas)
@ -277,7 +277,7 @@
0w0 :: 106, ~bet, urbit.org (civitas)
0w0 :: 107, ~bel, urbit.org (civitas)
0w0 :: 108, ~tux, Chen Zheng (angelus)
0w0 :: 109, ~tug, urbit.org (civitas)
0w0 :: 109, ~tug, Philip Monk (aestas)
0w0 :: 110, ~myr, urbit.org (civitas)
0w0 :: 111, ~pel, urbit.org (civitas)
0w0 :: 112, ~syp, urbit.org (civitas)
@ -316,7 +316,7 @@
0w0 :: 145, ~leb, ~nosryl-tarpem (fidelis)
0w0 :: 146, ~dux, urbit.org (civitas)
0w0 :: 147, ~ryn, urbit.org (civitas)
0w0 :: 148, ~num, urbit.org (civitas)
0w0 :: 148, ~num, Tlon (gleba)
0w0 :: 149, ~pyx, ~racbes-solmun (fidelis)
0w2g.gLmg4.MtrHQ.A5VmH.WPk6G :: 150, ~ryg, Dan Haffey (fortuna)
0w0 :: 151, ~ryx, Tlon (gleba)
@ -415,7 +415,7 @@
0w0 :: 244, ~byr, Tlon (gleba)
0w0 :: 245, ~sen, Tlon (gleba)
0w0 :: 246, ~weg, Tlon (gleba)
0w0 :: 247, ~fyr, Tlon (gleba)
0wU.VWcJa.TR1rQ.ONSCN.Mi5TW :: 247, ~fyr, Anton Dyudin (aestas)
0w0 :: 248, ~mur, Tlon (gleba)
0w0 :: 249, ~tel, Tlon (gleba)
0w0 :: 250, ~rep, Tlon (gleba)
@ -439,7 +439,7 @@
vix=(bex +((cut 0 [25 2] mag))) :: width of sender
tay=(cut 0 [27 5] mag) :: message type
==
?> =(0 vez)
?> =(7 vez)
?> =(chk (end 0 20 (mug bod)))
:+ [(end 3 wix bod) (cut 3 [wix vix] bod)]
(kins tay)
@ -459,7 +459,7 @@
=+ tay=(ksin q.kec)
%+ mix
%+ can 0
:~ [3 0]
:~ [3 7]
[20 (mug bod)]
[2 yax]
[2 qax]
@ -1047,7 +1047,7 @@
++ gnaw :: gnaw:am
|= [kay=cape ryn=lane pac=rock] :: process packet
^- [p=(list boon) q=fort]
?. =(0 (end 0 3 pac)) [~ fox]
?. =(7 (end 0 3 pac)) [~ fox]
=+ kec=(bite pac)
?: (goop p.p.kec) [~ fox]
?. (~(has by urb.ton.fox) q.p.kec)
@ -1342,7 +1342,7 @@
+>(..la (tuck p.fud q.fud r.fud))
::
%buck
=. +> ?.(=(%full aut) +> cock)
=. +> ?.(=(%full aut) +> cock) :: finish key exch
+>(..la (tock p.fud q.fud r.fud))
::
%bond
@ -1819,7 +1819,7 @@
:: ~& [%knap soq num pax]
=+ ^= fuy
=< zork =< zank
%+ ~(rack am [now fox]) soq :- pax
%^ ~(rack am [now fox]) soq pax
?-(+<.sih %mean `p.+.sih, %nice ~)
=> %_(. fox q.fuy)
=| out=(list move)

View File

@ -2,7 +2,7 @@
::
|= pit=vase
=> |%
++ cult (map duct rave) :: subscriptions
++ cult (map duct rove) :: subscriptions
++ dojo ,[p=cult q=dome] :: domestic desk state
++ gift :: out result <-$
$% [%ergo p=@p q=@tas r=@ud] :: version update
@ -20,6 +20,7 @@
[%wart p=sock q=@tas r=path s=*] :: network request
[%warp p=sock q=riff] :: file request
== ::
++ moot ,[p=case q=case r=path s=(map path lobe)] ::
++ move ,[p=duct q=(mold note gift)] :: local move
++ nako $: gar=(map ,@ud tako) :: new ids
let=@ud :: next id
@ -74,6 +75,7 @@
hez=(unit duct) :: sync duch
dos=(map desk dojo) :: native desk
== ::
++ rove (each mood moot) ::
++ rung $: rus=(map desk rede) :: neighbor desks
== ::
-- =>
@ -135,7 +137,7 @@
+>(byn [[hen ~ [p.mun q.mun syd] r.mun dat] byn])
::
++ bleb :: ship sequence
|= [hen=duct ins=@ud hip=nako]
|= [hen=duct ins=@ud hip=*]
^+ +>
(blab hen [%w [%ud ins] ~] hip)
::
@ -147,13 +149,13 @@
=+ xiq=(~(tap by qyx) ~)
^- (unit ,@da)
%+ roll xiq
|= [xaq=[p=duct q=rave] nex=(unit ,@da)]
|= [xaq=[p=duct q=rove] nex=(unit ,@da)]
%+ hunt nex
?- -.q.xaq
& ?.(?=(%da -.q.p.q.xaq) ~ [~ p.q.p.q.xaq])
::
|
=+ mot=`moat`p.q.xaq
=+ mot=`moot`p.q.xaq
%+ hunt
?. ?=(%da -.p.mot) ~
?.((lth now p.p.mot) ~ [~ p.p.mot])
@ -162,14 +164,15 @@
==
::
++ duce :: produce request
|= [hen=duct rav=rave]
|= [hen=duct rov=rove]
^+ +>
=. qyx (~(put by qyx) hen rav)
?~ ref +>
|- ^+ +>+.$
=. qyx (~(put by qyx) hen rov)
?~ ref +>.$
|- ^+ +>+.$ :: XX why?
=+ rav=(reve rov)
=+ ^= vaw ^- rave
?. ?=([%& %v *] rav) rav
[%| [%ud let.dom] `case`q.p.rav]
[%| [%ud let.dom] `case`q.p.rav r.p.rav]
=+ inx=nix.u.ref
%= +>+.$
say [[hen [(scot %ud inx) ~] for [inx syd ~ vaw]] say]
@ -211,18 +214,22 @@
=+ nab=(~(aeon ze lim dom ran) p.p.rav)
?~ nab
?> =(~ (~(aeon ze lim dom ran) q.p.rav))
(duce hen rav)
~! [%um rav]
(duce hen (rive rav))
=+ huy=(~(aeon ze lim dom ran) q.p.rav)
?: &(?=(^ huy) |((lth u.huy u.nab) &(=(0 u.huy) =(0 u.nab))))
(blub hen)
=+ top=?~(huy let.dom u.huy)
=+ fud=(~(gack ze lim dom ran) u.nab let.dom)
=. +>.$ (bleb hen u.nab fud)
=+ sar=(~(apax ze lim dom ran) u.nab r.p.rav)
=+ ear=(~(apax ze lim dom ran) top r.p.rav)
=. +>.$ ?: =(sar ear) +>.$
=+ fud=(~(gack ze lim dom ran) u.nab top)
(bleb hen u.nab fud)
?^ huy
(blub hen)
=+ ^= ptr ^- case
[%ud +(let.dom)]
(duce hen `rave`[%| ptr q.p.rav])
(duce hen `rove`[%| ptr q.p.rav r.p.rav ear])
==
::
++ echa :: announce raw
@ -336,10 +343,21 @@
haw.u.ref (~(del by haw.u.ref) nez)
==
::
++ reve
|= rov=rove
^- rave
?: ?=(%& -.rov) rov
[%| p.p.rov q.p.rov r.p.rov]
::
++ rive
|= rav=[%| p=moat]
^- rove
[%| p.p.rav q.p.rav r.p.rav ~]
::
++ wake :: update subscribers
^+ .
=+ xiq=(~(tap by qyx) ~)
=| xaq=(list ,[p=duct q=rave])
=| xaq=(list ,[p=duct q=rove])
|- ^+ ..wake
?~ xiq
..wake(qyx (~(gas by *cult) xaq))
@ -357,23 +375,28 @@
$(xiq t.xiq, ..wake (balk p.i.xiq u.nao p.q.i.xiq))
::
|
=+ mot=`moat`p.q.i.xiq
=+ mot=`moot`p.q.i.xiq
=+ nab=(~(aeon ze lim dom ran) p.mot)
?~ nab
$(xiq t.xiq, xaq [i.xiq xaq])
=+ huy=(~(aeon ze lim dom ran) q.mot)
?~ huy
=+ ptr=[%ud +(let.dom)]
=+ fud=`nako`(~(gack ze lim dom ran) u.nab let.dom)
%= $
xiq t.xiq
xaq [[p.i.xiq [%| ptr q.mot]] xaq]
..wake (bleb p.i.xiq let.dom fud)
xaq [[p.i.xiq [%| ptr q.mot r.mot s.mot]] xaq]
..wake =+ ear=(~(apax ze lim dom ran) let.dom r.p.q.i.xiq)
?: =(s.p.q.i.xiq ear) ..wake
=+ fud=(~(gack ze lim dom ran) u.nab let.dom)
(bleb p.i.xiq let.dom ear)
==
=+ fud=(~(gack ze lim dom ran) u.nab u.huy)
%= $
xiq t.xiq
..wake (blub:(bleb p.i.xiq +(u.nab) fud) p.i.xiq)
..wake =- (blub:- p.i.xiq)
=+ ear=(~(apax ze lim dom ran) u.huy r.p.q.i.xiq)
?: =(s.p.q.i.xiq ear) ..wake
=+ fud=(~(gack ze lim dom ran) u.nab u.huy)
(bleb p.i.xiq +(u.nab) ear)
==
==
--

View File

@ -139,8 +139,7 @@
hen=duct :: event trace
som=seam :: logical request
pez=pest :: request state
vaz=(list ,[p=cord q=tape]) :: variables
sip=(list manx) :: scripts in result
sip=marl :: injected scripts
== ::
++ rote :: remote server
$: cnt=@ud :: number served
@ -152,6 +151,7 @@
[%aph p=ship q=@ud r=@ud s=json] :: app heartbeat
[%apg p=term q=ship r=mark s=path] :: app get/start
[%apm p=ship q=@ud r=@ud s=hasp t=json] :: message send
[%app p=ship q=(unit ,@ud)] :: script by port
[%aps p=ship q=@ud s=hasp t=path] :: subscribe
[%apu p=ship q=@ud s=hasp t=path] :: unsubscribe
[%cog p=@ud q=@ud] :: console get
@ -226,7 +226,8 @@
=+ ten=(~(get by q.moh) 'content-type')
?~ ten ~
?~ u.ten ~
?. =('text/json' (end 3 9 i.u.ten)) ~
?. =('text/json' (end 3 9 i.u.ten))
~| %ecce-content-type ~
?~ r.moh ~
`(unit json)`(rush q.u.r.moh apex:poja)
::
@ -314,28 +315,6 @@
=+ rep=:(welp p.hop scr q.q.hop)
[%mid p.luv (tact rep)]
==
++ lofe :: variables in head
|= [vaz=(list ,[p=cord q=tape]) luv=love]
%- lofa
:_ luv
:_ ~
^- manx
:- [%script ~]
:- :/ "window.urb = \{};\0a"
(turn vaz |=([a=cord b=tape] :/("window.urb.{(trip a)}={b};\0a")))
::
++ lofi :: insert in body
|= [mog=(list manx) luv=love]
^- love
?: =(~ mog) luv
?+ -.luv luv
%mid
?. =(/text/html p.luv) luv
=+ str=(trip q.q.luv)
=+ scr=|-(^-(tape ?~(mog "</body>" (xmlt & i.mog $(mog t.mog)))))
=+ rep=(need (repg "</body>" str scr))
[%mid p.luv (tact rep)]
==
::
++ loft :: love to response
|= luv=love
@ -390,9 +369,8 @@
(slav %ud i.t.t.t.tea)
?~ ouy
+>.$
:: ?: (lth ~m2 (sub now tim.bet.siq:beat:u.ouy))
:: ~& %axon-heartbeat
:: abet:work:amok:u.ouy
?: (lth ~m2 (sub now tim.bet.siq:beat:u.ouy))
abet:work:amok:u.ouy
=* mab t.t.t.t.tea
=+ woy=(yule:u.ouy ?+(i.mab !! %mess %meg, %show %sub))
=< abet =< work =< abet
@ -608,7 +586,7 @@
=+ cyz=(need (~(get by wup.sef) ses))
~(. ya [our ses] sef cyz)
::
++ galt
++ galt ::
|= [our=ship ses=hole num=@ud mez=(each bead (list tank))]
^+ +>
=+ suf=(~(get by own) our)
@ -918,116 +896,115 @@
|= [our=ship whu=(unit ship) rul=tape ruf=tape]
^- manx
=+ ^= sic ^- manx
;script
;
; var seal = {
; who: goal,
; url: burl,
; pas: null
; }
; var hist = []
; var hind = 0
; $(
; function() {
; $input = $('#input .line')
; $prompt = $('#input .prompt')
; $prompt.addClass('prefix')
; $output = $('#output')
; $input.focus()
; $('body').click(function() { $input.focus() })
; ctrl = false;
;
; start = function(ship) {
; $prompt.text('vessel: ~')
; $input.attr('placeholder', 'ship-name')
; if(ship) {
; $input.val(ship)
; }
; }
;
; ident = function() {
; seal.who = $input.val()
;
; if( (seal.who.length != 13) &&
; (seal.who.length != 6) &&
; (seal.who.length != 3) )
; {
; $output.text('not a ship name - try again.');
; return false;
; }
;
; if(seal.who !== host) {
; var foreign = {oth: host, ses: session};
; var all = $.extend({}, seal, foreign);
;
; console.log('redirect')
; window.location="http://"+seal.who+".urbit.org/gul"
; + $.params(all);
; return false;
; }
;
; $output.text($prompt.text() + " " + seal.who)
; $input.val('')
; $input.attr('placeholder', 'ronber-bacnub-hanmev-labnyd')
; $prompt.text('secret: ~')
;
; return true;
; }
;
; login = function() {
; seal.pas = $input.val()
;
; output = $output.html()
; console.log($output.html())
; $output.html(output.replace('sorry. please try again.<br>',''))
;
; $.post(form, seal, function(data,xhr,status) {
; console.log(data);
; if(data.ok == true) {
; document.location = data.next;
; } else {
; $output.prepend('sorry. please try again.<br>')
; }
; })
; }
;
; steps = [ident,login]
; step = 0
; start(seal.who)
; if(seal.who) {
; ident()
; step++
; }
;
; $input.on('keydown', function(e) {
; if(e.keyCode == 17) {
; ctrl = true
; return;
; }
;
; if(e.keyCode == 68 &&
; ctrl == true &&
; step == 1) {
; $output.text('')
; step = 0
; start(null)
; return;
; }
;
; if(e.keyCode == 13) {
; if(steps[step]() && step < steps.length-1)
; step++
; return;
; }
; });
;
; $input.on('keyup', function(e) {
; if(e.keyCode == 17) {
; ctrl = false
; }
; });
; })
==
;script:'''
var seal = {
who: goal,
url: burl,
pas: null
}
var hist = []
var hind = 0
$(
function() {
$input = $('#input .line')
$prompt = $('#input .prompt')
$prompt.addClass('prefix')
$output = $('#output')
$input.focus()
$('body').click(function() { $input.focus() })
ctrl = false;
start = function(ship) {
$prompt.text('vessel: ~')
$input.attr('placeholder', 'ship-name')
if(ship) {
$input.val(ship)
}
}
ident = function() {
seal.who = $input.val()
if( (seal.who.length != 13) &&
(seal.who.length != 6) &&
(seal.who.length != 3) )
{
$output.text('not a ship name - try again.');
return false;
}
if(seal.who !== host) {
var foreign = {oth: host, ses: session};
var all = $.extend({}, seal, foreign);
console.log('redirect')
window.location="http://"+seal.who+".urbit.org/gul"
+ $.params(all);
return false;
}
$output.text($prompt.text() + " " + seal.who)
$input.val('')
$input.attr('placeholder', 'ronber-bacnub-hanmev-labnyd')
$prompt.text('secret: ~')
return true;
}
login = function() {
seal.pas = $input.val()
output = $output.html()
console.log($output.html())
$output.html(output.replace('sorry. please try again.<br>',''))
$.post(form, seal, function(data,xhr,status) {
console.log(data);
if(data.ok == true) {
document.location = data.next;
} else {
$output.prepend('sorry. please try again.<br>')
}
})
}
steps = [ident,login]
step = 0
start(seal.who)
if(seal.who) {
ident()
step++
}
$input.on('keydown', function(e) {
if(e.keyCode == 17) {
ctrl = true
return;
}
if(e.keyCode == 68 &&
ctrl == true &&
step == 1) {
$output.text('')
step = 0
start(null)
return;
}
if(e.keyCode == 13) {
if(steps[step]() && step < steps.length-1)
step++
return;
}
});
$input.on('keyup', function(e) {
if(e.keyCode == 17) {
ctrl = false
}
});
})
'''
=+ ^= cof
;=
; var host = '{(trip (rsh 3 1 (scot %p our)))}';
@ -1041,32 +1018,32 @@
;head
;title: urbit login
;script(type "text/javascript", src jqu);
;style
; body {
; margin: 60px 120px;
; font: normal 12px "Menlo" monospace;
; background-color: #000;
; color: #fff;
; }
;
; #output {
;
; }
;
; #input .prompt {
; display: inline-block;
; margin-right: 12px;
; }
;
; #input .line {
; outline: none;
; width: 80%;
; border: 0;
; background-color: transparent;
; color: #fff;
; font: normal 12px "Menlo" monospace;
; }
==
;style:'''
body {
margin: 60px 120px;
font: normal 12px "Menlo" monospace;
background-color: #000;
color: #fff;
}
#output {
}
#input .prompt {
display: inline-block;
margin-right: 12px;
}
#input .line {
outline: none;
width: 80%;
border: 0;
background-color: transparent;
color: #fff;
font: normal 12px "Menlo" monospace;
}
'''
==
=+ ^= bod ^- manx
;body
@ -1148,30 +1125,24 @@
?> ?=(%way pez.u.pup)
$(yov t.yov, q.rey (~(put by q.rey) i.yov u.pup(pez noz)))
::
++ duti :: heartbeat script
;script:'''
window.urb.seqn_h = 0
window.urb.heartbeat = function() {
this.poll({
type:"heb",
ship:this.ship,
dely:30000,
incs:function() {
window.urb.seqn_h++
}
},function() {
console.log('heartbeat.')
})
}
// XX 404 bug
// window.urb.heartbeat()
++ duty |= [our=ship nap=@ud you=ship orx=oryx] :: interface script
^- cord
%^ cat 3
%- crip
=- "window.urb = {(pojo (jobe -))}\0a"
:~
[%ship (jape |1:<our>)]
[%port (jone nap)]
[%auto %b %&]
[%user (jape |1:<you>)]
[%oryx %s orx]
==
'''
::
++ duty
;script:'''
window.urb.seqn_u = 0
window.urb.seqn_h = 0
window.urb.dely = 0
window.urb.puls = 0
window.urb.cabs = {}
window.urb.perms = {
pol:"gie",
sub:"tis",
@ -1241,8 +1212,11 @@
}
window.urb.gsig = function(params) {
path = params.path
if(!path)
path = ""
return params.appl+","+
params.path.replace(/[^\x00-\x7F]/g, "")+","+
path.replace(/[^\x00-\x7F]/g, "")+","+
params.ship
}
@ -1251,16 +1225,23 @@
throw new Error("You must supply params to urb.poll.")
var method, perm, url, $this
method = "get"
perm = params.type ? this.perms[params.type] : "gie"
url = [perm,this.user,this.port,this.seqn_u]
json = false
if(perm[0] == "t") {
method = "put"
json = true
}
seqn = this.seqn_u
if(params.seqn)
seqn = params.seqn()
url = [perm,this.user,this.port,seqn]
url = "/"+url.join("/")
this.puls = 1
$this = this
this.req(method,url,params,false,function(err,data) {
this.req(method,url,params,json,function(err,data) {
if (data.data.reload) {
return document.location.reload()
} else {
@ -1297,6 +1278,23 @@
}
window.urb.poll(param)
}
window.urb.heartbeat = function() {
this.poll({
type:"heb",
ship:this.ship,
dely:30000,
seqn:function() {
return window.urb.seqn_h
},
incs:function() {
window.urb.seqn_h = window.urb.seqn_h+1
}
},function() {
console.log('heartbeat.')
})
}
window.urb.heartbeat()
'''
::
++ fape :: dispatch %ape
@ -1350,6 +1348,18 @@
(need (eccu orx.ced moh))
==
::
++ fapp
|= [fur=(unit term) you=@p paw=path]
?> ?=([~ %js] fur)
?> ?=(?([%hart ~] [@ %hart ~]) paw)
:- ~
:* %app
you
?~ t.paw
~
(some (slav %ui (cat 3 '0i' i.paw)))
==
::
++ faps :: dispatch %aps
|= [fur=(unit term) you=@p paw=path moh=moth]
^- (unit seam)
@ -1455,8 +1465,9 @@
==
::
++ foin :: version request
|= [fur=(unit term) paw=(list ,@t) quy=quay]
|= [fur=(unit term) you=@p paw=(list ,@t) quy=quay]
^- (unit seam)
=. aut.ced (~(put ju aut.ced) %$ (scot %p you)) :: XX backwards
?. ?& ?=(~ fur)
?=(~ quy)
?=([@ @ ~] paw)
@ -1470,17 +1481,18 @@
~
::
[%$ ?(%da %ud %tas) @]
[~ (case p.u.soy) (case p.u.soy)]
[~ (case p.u.soy) (case p.u.soy) /]
::
[%many [%$ ?(%da %ud %tas) @] [%$ ?(%da %ud %tas) @] ~]
[~ (case i.p.u.soy) (case i.t.p.u.soy)]
[~ (case i.p.u.soy) (case i.t.p.u.soy) /]
==
|= mot=moat
`seam`[%det i.t.paw mot]
::
++ funk :: functional request
|= [nep=@tas fur=(unit term) paw=(list ,@t) quy=quay]
|= [nep=@tas fur=(unit term) you=@p paw=(list ,@t) quy=quay]
^- (unit seam)
=. aut.ced (~(put ju aut.ced) %$ (scot %p you)) :: XX backwards
=+ won==(%n (rsh 3 2 nep))
%+ bind
^- (unit ,[mark tube])
@ -1508,11 +1520,15 @@
toe(s (weld s.toe `path`[~(rent co (flux [nep ~] quy)) %web ~]))
?. won ~
:_ ~
=- =+ pey=(cat 3 (end 3 2 nep) %v)
=- =+ pey="{(scag 2 (trip nep))}v"
=. pey %+ weld pey
?. =(%i (snag 1 pey))
""
"/{(slag 1 (scow %p you))}"
=+ ven=+((,@ (need (sky %cw p.toe q.toe r.toe ~))))
=+ ^= cal :/
"path='".
"/{(trip pey)}".
"/{pey}".
"/{(scow %ud ven)}".
"/{(trip q.toe)}';"
[-.sac [cal +.sac]]
@ -1591,6 +1607,7 @@
%r :: app response
%s :: app subscribe
%h :: app heartbeat
%p :: app script by port
%n :: now
%u :: app unsubscribe
%z :: app version
@ -1615,12 +1632,13 @@
?+ one ~
%g
?+ tri ~
?(%f %n) (funk nep p.q.pul paw r.pul)
%v (foin p.q.pul paw r.pul)
?(%f %n) (funk nep p.q.pul yun paw r.pul)
%v (foin p.q.pul yun paw r.pul)
%c (flub paw ~)
%l (fool r.pul)
%g (fapg p.q.pul yun paw)
%e (fape p.q.pul yun paw)
%p (fapp p.q.pul yun paw)
==
::
%p
@ -1706,7 +1724,6 @@
*seam
`pest`[%raw pul moh]
~
~
==
==
::
@ -1777,6 +1794,10 @@
:: ~& [%wink-apm +.som.pip]
:- [~ pip(pez %way)]
(yokm num +.som.pip)
::
%app :: script by port
:: ~& [%wink-app +.som.pip]
(yokp num +.som.pip)
::
%aps :: subscribe
:: ~& [%wink-aps +.som.pip]
@ -1892,7 +1913,7 @@
:+ 500
~[content-type/'text/html']
[~ (tact (xmlt | mad ~))]
& [%fin (lofe vaz.pip (lofi mog (lopo q.p.p.pez.pip)))]
& [%fin (lofa mog (lopo q.p.p.pez.pip))]
==
==
::
@ -1948,6 +1969,17 @@
?~ yon (bust 204 num)
abet:(post:u.yon cnt num hap jon)
::
++ yokp :: script by port
|= [num=@ud you=ship nup=(unit ,@ud)]
^- [(unit pimp) _+>]
?~ nup
$(nup [~ num], +> ~(harp yo num you *sink))
=+ yon=(yolk u.nup)
?~ yon
=+ err=(bust 204 num)
[`(need (~(get by q.rey.err) num)) err]
[- abet:+]:(hark:u.yon num)
::
++ yoks :: subscribe
|= [num=@ud you=ship nap=@ud hap=hasp pax=path]
=+ yon=(yolk nap)
@ -1991,7 +2023,7 @@
(pass(hen hen.q.i.wuh) `p.i.wuh `note`[%g %nuke hap.q.i.wuh you])
==
::
++ beat
++ beat
|= [cnt=@ud num=@ud jon=json]
^- [(unit pimp) _+>]
?. =(cnt num.bet.siq)
@ -2001,6 +2033,18 @@
=. +>.$ (hear:(yule %bet) ~ %& %json !>((joba %a-ok %b %&)))
[`(need (~(get by q.rey) num)) +>.$]
::
++ hark
|= num=@ud
^- [(unit pimp) _+>]
=. +>.$ abet:(busk:(yule %nil) num _@ ~ %& %js !>((duty our nap you orx.ced)))
[`(need (~(get by q.rey) num)) +>.$]
::
++ harp
%_ abet
tim.bet.siq now
num.sub.siq 1
==
::
++ hoop :: request path
|= can=(unit ,@ud)
^- path
@ -2096,22 +2140,17 @@
==
=+ pip=u.pup
=+ ^= sip
?. =(%apg -.som.pip) sip.pip
[duti duty sip.pip]
?. ?=(%apg -.som.pip) sip.pip
=* his q.som.pip
=+ mef=?:(=(our his) "gop" "gip/{|1:<his>}")
[;script(src "/{mef}/{(pojo (jone nap))}/hart.js"); sip.pip]
?~ huq +>.$(..yo (bust 404 num))
%= +>.$
q.rey
%+ ~(put by q.rey) num
^- pimp
=+ quo=|=(a=cord :(weld "\"" (trip a) "\""))
%= pip
pez %new
vaz :~ [%ship (quo (rsh 3 1 (scot %p our)))]
[%port (trip (rsh 3 2 (scot %ui nap)))]
[%auto "true"]
[%oryx (quo orx.ced)]
[%user (quo (rsh 3 1 (scot %p you)))]
==
sip sip
som ^- seam
:+ %sil

View File

@ -503,7 +503,7 @@
(stag %hub ;~(pfix pat day:read))
(stag %man ;~(pfix tar man:read))
(stag %nap ;~(pfix cen day:read))
(stag %now ;~(pfix fas day:read))
(stag %now ;~(pfix pam day:read))
(stag %saw ;~(pfix sem saw:read))
(stag %see ;~(pfix col see:read))
(stag %sic ;~(pfix ket sic:read))

View File

@ -332,22 +332,28 @@
++ gasp :: %x take
|= [hen=duct pax=path sih=sign]
^- [(list move) _..^$]
?: ?=(%a -.sih) [~ ..^$]
?> ?=(%f -.sih)
:_ ..^$
:_ ~
:- hen
?- -.p.+.sih
%|
[%give %crud %gasp-crud p.p.+.sih]
::
%&
=+ cay=`cage`q.p.p.+.sih
?+ -.pax !!
%d [%give (best %rush cay)]
%f [%give (best %rust cay)]
?+ -.sih !!
%a
?> ?=(%woot +<.sih)
:_ ..^$ :_ ~
?~ q.sih
[hen %give %nice ~]
[hen %give %mean u.q.sih]
%f
:_ ..^$
:_ ~
:- hen
?- -.p.+.sih
%|
[%give %crud %gasp-crud p.p.+.sih]
::
%&
=+ cay=`cage`q.p.p.+.sih
?+ -.pax !!
%d [%give (best %rush cay)]
%f [%give (best %rust cay)]
== ==
==
==
::
++ gave :: %r take
|= [hen=duct pax=path sih=sign]
@ -630,7 +636,7 @@
:- hun.mat
:^ %pass (away %w %drug (scot %p p.a) q.a ~) %c
~& [%sync-subscribe our p.a q.a]
[%warp [our p.a] q.a ~ %| [%da +(now)] [%da (add now ~d1000)]]
[%warp [our p.a] q.a ~ %| [%da +(now)] [%da (add now ~d1000)] /]
=+ ^= old ^- (list move)
%+ turn
%+ skip (~(tap in ped.sat) ~)
@ -990,7 +996,7 @@
?. (warm %pour)
+>.$(qic.sat ~)
?> ?=(^ huv.sat)
=+ sam=(slop !>(p.kon) q.kon)
=+ sam=:(slop [[%atom %ud] ost] !>(p.kon) q.kon)
%+ ford /s/pour
[%call (harm %pour (conf (core u.huv.sat))) (cove %$ sam)]
==

File diff suppressed because it is too large Load Diff

View File

@ -1,165 +1,24 @@
!::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::: :::::: Preface ::::::
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
?> ?=(@ .) :: atom subject
%. . :: fun with subject
|= cud=@ :: call it cud
=- (mul:all 2 cud) :: multiply by 2
^= all :: assemble engine
=~ :: volume stack
%164 :: version constant
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::: :::::: volume 0, version stub ::::::
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
~% %k.164 ~ ~ ::
|% ::
++ stub 164 :: version stub
-- ::
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::: :::::: volume 1, Hoon models ::::::
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
~% %mood
+
~
|% ::
++ axis ,@ :: tree address
-- ::
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::: :::::: volume 2, Hoon libraries and compiler ::::::
:::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
~% %hoon
+
==
%dec dec
==
?> ?=([@ @] .)
%. .
|= [x=@ y=@]
=- (add:all x y)
^= all
=> %164
~% %k.164 ~ ~
|%
::::::::::::::::::::::::::::::::::::::::::::::::::::: ::
:::: chapter 2a, basic unsigned math ::::
:: ::::::::::::::::::::::::::::::::::::::::::::::::::::::
++ add :: add
++ add
~/ %add
|= [a=@ b=@]
^- @
?: =(0 a)
b
?: =(0 a) b
$(a (dec a), b +(b))
::
++ cap :: tree head
~/ %cap
|= a=@
^- ?(%2 %3)
?- a
%2 %2
%3 %3
?(%0 %1) !!
* $(a (div a 2))
==
::
++ dec :: decrement
++ dec
~/ %dec
|= a=@
?< =(0 a)
=+ b=0
|- ^- @
?: =(a +(b))
b
?: =(a +(b)) b
$(b +(b))
::
++ div :: divide
~/ %div
|= [a=@ b=@]
^- @
?< =(0 b)
=+ c=0
|-
?: (lth a b)
c
$(a (sub a b), c +(c))
::
++ gte :: greater-equal
~/ %gte
|= [a=@ b=@]
^- ?
!(lth a b)
::
++ gth :: greater-than
~/ %gth
|= [a=@ b=@]
^- ?
!(lte a b)
::
++ lte :: less-equal
~/ %lte
|= [a=@ b=@]
|(=(a b) (lth a b))
::
++ lth :: less-than
~/ %lth
|= [a=@ b=@]
^- ?
&(!=(a b) |-(|(=(0 a) &(!=(0 b) $(a (dec a), b (dec b))))))
::
++ mas :: tree body
~/ %mas
|= a=@
^- @
?- a
1 !!
2 1
3 1
* (add (mod a 2) (mul $(a (div a 2)) 2))
==
::
++ max :: maximum
~/ %max
|= [a=@ b=@]
^- @
?: (gth a b)
a
b
::
++ min :: minimum
~/ %min
|= [a=@ b=@]
^- @
?: (lth a b)
a
b
::
++ mod :: remainder
~/ %mod
|= [a=@ b=@]
^- @
?< =(0 b)
(sub a (mul b (div a b)))
::
++ mul :: multiply
~/ %mul
|= [a=@ b=@]
^- @
=+ c=0
|-
?: =(0 a)
c
$(a (dec a), c (add b c))
::
++ peg :: tree connect
~/ %peg
|= [a=@ b=@]
^- @
?- b
1 a
2 (mul a 2)
3 +((mul a 2))
* (add (mod b 2) (mul $(b (div b 2)) 2))
==
::
++ sub :: subtract
~/ %sub
|= [a=@ b=@]
^- @
?: =(0 b)
a
$(a (dec a), b (dec b))
--
. ==

View File

@ -828,13 +828,13 @@
=> .(+< [a b]=+<)
(scan a (parsf b))
++ parsf :: make parser from:
|^ |* (pole ,_:/(*$&(_rule tape))) :: ;"chars{rule}chars"
=> .(+< a=+<)
|^ |* a=(pole ,_:/(*$&(_rule tape))) :: ;"chars{rule}chars"
%- cook :_ (bill (norm a))
|* (list)
?~ +< ~
?~ t i
[i $(+< t)]
::
:: .= (norm [;"{n}, {n}"]:n=dim:ag) ~[[& dim] [| ", "] [& dim]]:ag
++ norm
|* (pole ,_:/(*$&(_rule tape)))
@ -847,6 +847,7 @@
?~ +.rul [%| p=rul]
?@ &2.rul [%| p=;;(tape rul)]
[%& p=rul]
::
:: .= (bill ~[[& dim] [| ", "] [& dim]]:ag)
:: ;~(plug dim ;~(pfix com ace ;~(plug dim (easy)))):ag
++ bill
@ -1045,7 +1046,7 @@
^- ankz
^$(p ank)
::
++ ze !:
++ ze
|_ [lim=@da dome rang]
++ zoal :: make yaki
|= [p=(list tako) q=(map path lobe) t=@da]
@ -1125,6 +1126,24 @@
=+ zoq=(zaru voq)
((diff (zump (zaal u.leb))) zeq zoq)
::
++ apax :: apax:ze
|= [oan=@ud pax=path] :: data at path
^- (map path lobe)
?: =(0 oan) ~
%- mo
%+ skim
%. ~
%~ tap by
=< q
%- ~(got by hut)
%- ~(got by hit)
oan
|= [p=path q=lobe]
?| ?=(~ pax)
?& !?=(~ p)
=(-.pax -.p)
$(p +.p, pax +.pax)
== ==
::
++ aeon :: aeon:ze
|= lok=case :: act count through
@ -1220,7 +1239,7 @@
|= lob=lobe
(need (~(get by lat) lob))
::
++ gack !: :: gack a through b
++ gack :: gack a through b
|= [a=@ud b=@ud]
^- [(map ,@ud tako) @ud (set yaki) (set blob)]
:_ :- b
@ -1250,7 +1269,7 @@
^+ +>
?: =(let oan) +>
?: (gth oan let) !! :: don't have this version
+>(ank (azel q:(need (~(get by hut) (need (~(get by hit) oan))))), let oan)
+>(ank (azel q:(~(got by hut) (~(got by hit) oan))), let oan)
::
::::
++ aqel :: aqel:ze
@ -1309,8 +1328,9 @@
|= [[pat=path bar=lobe] ank=ankh]
^- ankh
%- cosh
=+ zar=(zaul bar)
?~ pat [_cash [~ [(sham zar) zar]] `(map ,@ta ankh)`~]
?~ pat
=+ zar=(zaul bar)
ank(q [~ (sham zar) zar])
=+ nak=(~(get by r.ank) i.pat)
%= ank
r %+ ~(put by r.ank) i.pat
@ -1355,7 +1375,7 @@
$(gud (~(put in gud) tek), unk bun)
$(unk bun)
::
++ zeas !: :: merge points fast
++ zeas :: merge points fast
|= [p=yaki q=yaki] :: (future zeal)
^- (set yaki) :: zear still uses zule
%- zear :: this is test-only
@ -1373,13 +1393,13 @@
(~(uni in u) (zeaz v))
$(u (~(uni in u) (zeaz v)), s (zeat s.qez), t (zeat t.qez))
::
++ zeaz !:
++ zeaz
|= qez=(set tako)
^- (set yaki)
%- sa %+ turn (~(tap in qez) ~)
|= tak=tako
(~(got by hut) tak)
++ zeat !: :: expand set
++ zeat :: expand set
|= qez=(set tako)
^- (set tako)
%+ roll (~(tap in qez) ~)
@ -1839,7 +1859,7 @@
+>(ank ank:(durn:(zu ank) nyp))
--
::
++ zu !: :: filesystem
++ zu :: filesystem
|= ank=ankh :: filesystem state
=| myz=(list ,[p=path q=miso]) :: changes in reverse
=| ram=path :: reverse path into
@ -3047,7 +3067,7 @@
== ::
++ mizu ,[p=@u q=(map ,@ud tako) r=rang] :: new state
++ moar ,[p=@ud q=@ud] :: normal change range
++ moat ,[p=case q=case] :: change range
++ moat ,[p=case q=case r=path] :: change range
++ mood ,[p=care q=case r=path] :: request in desk
++ moth ,[p=meth q=math r=(unit octs)] :: http operation
++ name ,[p=@t q=(unit ,@t) r=(unit ,@t) s=@t] :: first mid/nick last

View File

@ -87,7 +87,7 @@
==
==
++ pour
|= [way=path sih=sign]
|= [ost=bone way=path sih=sign]
^- [(list move) _+>]
:_ +>.$
%+ turn (~(tap in (~(get ju pus.hid) ~)))

View File

@ -130,7 +130,7 @@
==
::
++ pour
|= [pax=path sih=*]
|= [ost=bone pax=path sih=*]
^- [(list move) _+>]
=+ sih=((hard sign) sih)
:: ~& [%chat-pour sih]

73
main/app/test/app.js Normal file
View File

@ -0,0 +1,73 @@
$(function() {
$tests = $("#tests")
runtest = function(name) {
test = $(name)
test.attr('disabled', true)
test.addClass('disabled')
window.urb.send({
appl:"test",
data:{test:name}
}, function(err,res) {
test.attr('disabled', false)
test.removeClass('disabled')
_test = {
name: name,
result: res.data
}
console.log('set it')
console.log(_test)
$tests.prepend(renderTest(_test))
})
}
renderTest = function(test) {
css = "test"
if(test.pending == true)
css += " pending"
$_test = $("<div class='"+css+"' id="+test.name+" onclick='runtest(\""+test.name+"\")'></div>")
$_test.append("<div class='name'>"+test.name+"</div>")
$_test.append("<div class='result'>"+JSON.stringify(test.result)+"</div>")
return $_test
}
renderTests = function(testlist) {
console.log("renderTests: "+testlist)
$tests.html("")
for(i in testlist) {
$tests.append(renderTest(testlist[i]))
}
}
renderError = function(error) {
$tests.html("<div class='error'>Sorry! There was an error fetching from Test: "+error+"</div>")
}
window.urb.subscribe({
appl:"test",
path:"/tests"
}, function(err,res) {
console.log('subscr')
console.log(arguments)
if (res.data.ok)
return
if(err)
renderTests(err)
else
{
if(res.data) {
if(res.data) {
renderTests(res.data)
}
else
{
renderTests("unknown error")
}
}
}
})
})

237
main/app/test/core.hook Normal file
View File

@ -0,0 +1,237 @@
:: Test suite
::
:: runnable from unix with command:
:: curl http://localhost:8080/gog/test/all-tests
::
:::: /hook/core/test/app
::
/? 314 :: need urbit 314
/= front /:/%%/front:/hymn/ :: load front page
::
:::: structures
::
|% :: structures
++ axle ,[%0 tests=(map term test)] :: application state
++ gilt :: subscription frame
$% [%json p=json] :: json data
[%html p=@t] :: html text
[%hymn p=manx] :: html tree
[%mime p=mite q=octs] :: mime data
== ::
++ gift :: output action
$% [%rust gilt] :: total update
[%mean p=ares] :: message failure
[%nice ~] :: succeed
== ::
++ hasp ,[p=ship q=term] :: see %gall
++ move ,[p=bone q=(mold note gift)] :: output operation
++ result :: test result
$% [%mean p=ares] :: failure
[%nice ~] :: success
== ::
++ note :: system request
$% $: %g :: to %ames
$% [%mess p=hasp q=ship r=cage] ::
== == == ::
++ test :: test template
$_ ^? |% ::
++ poke |+([bone ship] [_(list move) +>]) :: start test
++ pour |+([bone path *] [_(list move) +>]) :: system response
-- ::
-- ::
!:
:::: program
::
|_ $: hid=hide :: system state
axle :: custom state
==
++ et :: tests
|%
++ tests-json
%- jobe
%+ turn (~(tap by tests))
|= [nam=@t tes=test]
:- nam
%- jobe
^- (list ,[@t json])
~[[%name %s nam] [%result %s %untested]]
++ succeed
^- test
|%
++ poke
|+ [ost=bone you=ship]
^- [(list move) _+>]
[[ost %give %nice ~]~ +>.$]
++ pour
|+ [ost=bone pax=path sih=*]
^- [(list move) _+>]
!!
--
++ poke-local
^- test
=> |%
++ sign ,[%g result]
--
|%
++ poke
|+ [ost=bone you=ship]
^- [(list move) _+>]
:_ +>.$ :_ ~
:* ost %pass /poke-local %g
%mess [our.hid %test] you %json
!> (joba %test %s %bad-test-name)
==
++ pour
|+ [ost=bone pax=path sih=*]
^- [(list move) _+>]
:_ +>.$
=+ sih=((soft sign) sih)
:_ ~ :+ ost %give
?~ sih [%mean ~ %poke-local-pour-bad-sign ~]
?- +<.u.sih
%nice [%mean ~ %poke-local-pour-unexpected-nice ~]
%mean
?: ?=([~ %bad-test ~] p.u.sih)
[%nice ~]
[%mean ~ %poke-local-pour-unexpected-mean ~]
==
--
++ ze
^- test
|%
++ poke
|+ [ost=bone you=ship]
^- [(list move) _+>]
:_ +>.$ :_ ~
=+ ^= zez
%+ ~(axel ^ze lat.hid *dome *rang)
lat.hid
[%& [0v0 0v0] [/hello %ins 'hello, world']~]
=+ `[l=@da d=dome r=rang]`+<.zez
?: .= lat.r
:_ [~ ~]
[p=1.292.805.149 q=[%direct p=1.292.805.149 q='hello, world' r=%c]]
[ost %give %nice ~]
[ost %give %mean ~ %bad-rang ~[leaf/<d> leaf/<r>]]
++ pour
|+ [ost=bone pax=path sih=*]
^- [(list move) _+>]
!!
--
++ all-tests
^- test
=> |%
++ sign ,[%g result]
++ sult
$? result
[%pending ~]
==
--
=| results=(map ,@t sult)
|%
++ poke
|+ [ost=bone you=ship]
^- [(list move) _+>]
=. results
%- mo
%+ turn (~(tap by tests))
|= [nam=@t tes=test]
[nam %pending ~]
:_ +>.$
%+ turn (~(tap by tests))
|= [nam=@t tes=test]
:* ost %pass /all-tests/[nam] %g
%mess [our.hid %test] you %json
!> (joba %test %s nam)
==
++ pour
|+ [ost=bone pax=path sih=*]
^- [(list move) _+>]
=+ sih=((hard sign) sih)
?. ?=([@ ~] pax) ~& [%all-tests-strange-path pax] [~ +>.$]
=. results (~(put by results) -.pax +.sih)
:_ +>.$
?: (~(any by results) |=([res=sult] ?=(%pending -.res)))
~
:_ ~
?: (~(all by results) |=([res=sult] ?=(%nice -.res)))
[ost %give %nice ~]
:^ ost %give %mean
:+ ~ %failed-tests
%- zing
%+ turn
(skim (~(tap by results)) |=([nam=@t res=sult] ?=(%mean -.res)))
|= [nam=@t res=sult]
?> ?=(%mean -.res)
^- (list tank)
:_ ?~ p.res ~ q.u.p.res
:- %leaf
%+ weld "test %{(trip nam)} failed with "
?~ p.res "no error message"
%+ weld "error code %{(trip p.u.p.res)} and "
?~ q.u.p.res "no error info"
"the following error info:"
--
--
++ spec-pour
|= [ost=bone pax=path sih=*]
^- [(list move) _+>]
=+ sih=((hard ,[%g result]) sih)
:_ +>.$ :_ ~
[ost %give %rust %mime /text/plain (taco (cat 3 (crip <sih>) 10))]
++ prep
|= old=(unit (unit axle))
^- [(list move) _+>]
:- ~
%= +>.$
tests
?~ old
~& %prep-sig tests
?^ u.old
~& %prep-no-sig tests.u.u.old
=. tests
%- mo
^- (list ,[@t test])
=> et
:~ [%succeed succeed]
[%ze ze]
[%poke-local poke-local]
==
(~(put by tests) %all-tests all-tests:et)
==
++ peer :: accept subscriber
|= [ost=bone you=ship pax=path]
^- [(list move) _+>]
?~ pax [[ost %give %rust %hymn front]~ +>.$]
?: ?=(%tests -.pax)
[[ost %give %rust %json tests-json:et]~ +>.$]
:_ +>.$ :_ ~
:* ost %pass /automagic %g
%mess [our.hid %test] you %json
!> (joba %test %s -.pax)
==
++ poke-json :: browser message
|= [ost=bone you=ship jon=json]
^- [(list move) _+>]
=+ tes=((of [%test so] ~):jo jon)
?~ tes [[ost %give %mean ~ %strange-json ~]~ +>.$]
=+ tst=(~(get by tests) +.u.tes)
?~ tst
[[ost %give %mean ~ %bad-test ~]~ +>.$]
~& [%running-test +.u.tes]
=+ res=(poke:u.tst ost you)
:- -.res
+>.$(tests (~(put by tests) +.u.tes +.res))
++ pour :: response
|= [ost=bone pax=path sih=*]
^- [(list move) _+>]
?~ pax ~& %test-strange-path [~ +>.$]
=+ tst=(~(get by tests) -.pax)
?: ?=(%automagic -.pax)
(spec-pour ost pax sih)
?~ tst
~& %test-bad-path [~ +>.$]
=+ res=(pour:u.tst ost +.pax sih)
:- -.res
+>.$(tests (~(put by tests) -.pax +.res))
--

View File

@ -0,0 +1,30 @@
:: Front page of the twitter app.
::
:::: /hook/hymn/front/twit/app
::
/? 314 :: need urbit 314
/= urbit /:/===/lib/urb:/hymn/ :: urbit library (js)
/= style /:/%%%/style:/hymn/ :: stylesheet (css)
/= application /:/%%%/app:/hymn/ :: application (js)
!:
:::: content
::
^- manx
;html
;head
;title: Tests
;+ style
;script
=type "text/javascript"
=src "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"
;
==
==
;body
;div#tests
;p: Fetching tests...
==
;+ urbit
;+ application
==
==

82
main/app/test/style.css Normal file
View File

@ -0,0 +1,82 @@
body,
textarea,
input {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 400;
}
body {
margin-top: 4rem;
font-size: 18px;
}
.test,
.name,
.result {
width: 32rem;
}
textarea {
border: 0;
height: 8rem;
line-height: 1.5rem;
margin-bottom: .3rem;
resize: none;
padding: 1rem 1px;
background-color: #f7f7f7;
}
.name {
border: 0;
color: #333;
letter-spacing: 0.01rem;
}
.name {
background-color: transparent;
border: 2px solid #5DE668;
color: #5DE668;
padding: .3rem 1rem;
font-weight: 500;
cursor: pointer;
}
.name {
background-color: #5DE668;
color: #fff;
}
.disabled {
opacity: .6;
}
.text {
word-wrap:break-word;
margin-bottom: .3rem;
line-height: 1.6rem;
}
#twet {
margin-bottom: 3rem;
border-bottom: 2px solid #464646;
padding-bottom: 2rem;
}
#twet,
.tweet {
border-bottom: 1px solid #eee;
}
.tweet {
margin-bottom: 2rem;
padding-bottom: 1rem;
}
.pending {
opacity: .3;
}
.error {
color: #FF5F5F;
letter-spacing: .06rem;
}

View File

@ -100,7 +100,7 @@
==
::
++ pour :: HTTP response
|= [pax=path sih=sign]
|= [ost=bone pax=path sih=sign]
^- [(list move) _+>]
:_ +>.$
?+ -.pax !!

View File

@ -12,11 +12,14 @@
?~ q.ark
?- r.ark
~
~[(crip "No file {(spud pax)}")]
~[(crip "~ {(spud pax)}")]
[[@t ~] ~ ~]
$(pax (welp pax /[p.n.r.ark]))
*
~[(crip "Multiple in {(spud pax)}")]
:- (crip "* {(spud pax)}")
%- sort :_ aor
%- turn :_ |=([a=@t ~] a)
(~(tap by `(map ,@t ,~)`r.ark))
==
:- (crip (spud pax))
(lore ;;(,@t .^(%cx pax)))

View File

@ -15,7 +15,7 @@
[%tower p=@p]
[%s p=path]
==
=+ flags=*(list flag)
=+ [flags=*(list flag) lat=&3:%]
=> |%
++ chat :: user action
$% [%all p=mess] :: say
@ -63,22 +63,19 @@
==
::
++ dat
%+ cook
%+ sear
|= p=coin
?. ?=(~ -.p) [%ud 5]
?+ p.p.p [%ud 5]
%da [%da q.p.p]
%dr [%dr q.p.p]
%ud [%ud q.p.p]
==
;~(pfix (jest '\\\\ ') nuck:so)
?. ?=([%$ ?(%da %dr %ud) @] p) ~
(some +.p)
;~(pfix bas bas (star ace) nuck:so)
::
++ expn
%- sear
:_ text
|= a=@t
^- (unit ,[p=@t q=tank])
=+ hun=(rush a wide:vast)
~! %
=+ hun=(rush a wide:(vang | &1:% &2:% lat |3:%))
?~ hun ~
?~(a ~ [~ a (sell (slap !>(sed) u.hun))])
::
@ -273,7 +270,7 @@
|= [now=@da txt=@t]
^+ +>
?: =(0 txt) +>
=+ rey=(rush txt chat)
=+ rey=(rush txt chat(lat (scot da/est)))
?~ rey
(show %leaf "invalid input")
|-

View File

@ -10,5 +10,7 @@
=- ?~ q.ark -
[(crip (rend pax)) -]
%- zing
%+ turn (~(tap by r.ark))
|=([a=@t ~] ^$(pax (weld pax `path`/[a])))
%- turn :_ |=(a=@t ^$(pax (weld pax `path`/[a])))
%- sort :_ aor
%- turn :_ |=([a=@t ~] a)
(~(tap by r.ark))

View File

@ -1,13 +1,13 @@
window.urb.seqn_s = 0
window.urb.cabs = {}
window.urb.send = function(params,cb) {
if(!params)
throw new Error("You must supply params to urb.send.")
if(!params.appl)
if(!params.appl) {
if(!urb.appl)
throw new Error("You must specify an appl for urb.send.")
params.appl = urb.appl
}
if(!params.data) { params.data = {}; }
var method, perm, url, $this
@ -35,10 +35,11 @@ window.urb.subscribe = function(params,cb) {
throw new Error("You must supply a callback to urb.subscribe.")
if(!params)
throw new Error("You must supply params to urb.subscribe.")
if(!params.appl)
if(!params.appl) {
if(!urb.appl)
throw new Error("You must specify an appl for urb.subscribe.")
params.appl = urb.appl
}
if(!params.path)
throw new Error("You must specify a path for urb.subscribe.")
params.ship = params.ship ? params.ship : this.ship
@ -66,10 +67,11 @@ window.urb.subscribe = function(params,cb) {
window.urb.unsubscribe = function(params,cb) {
if(!params)
throw new Error("You must supply params to urb.unsubscribe.")
if(!params.appl)
if(!urb.appl )
if(!params.appl) {
if(!urb.appl)
throw new Error("You must specify an appl for urb.unsubscribe.")
params.appl = urb.appl
}
if(!params.path)
throw new Error("You must specify a path for urb.unsubscribe.")
params.ship = params.ship ? params.ship : this.ship

View File

@ -10,8 +10,7 @@
++ grab :: convert from
|%
++ md :: convert from %md
|= src=@t
=< (mark (trip src))
=< |=(src=@t (mark (trip src)))
|%
++ mark
|= p=tape
@ -23,7 +22,7 @@
=+ sep=(sepa tub)
?~ q.sep [p.sep ~]
:- p.sep
%- some :_ [p.sep ~]
%- some :_ [p.sep ~]
(turn p.u.q.sep |=(a=tape (scan a blos)))
::
++ base %+ stag %par
@ -39,7 +38,7 @@
code codf html para base
==
::
++ brek (stag %cut (cold ~ ;~(plug fas fas))) :: line break
++ brek (stag %cut (cold ~ ;~(plug fas fas))) :: line break
++ chrd ;~(pose escp prn (cold ' ' eol)) :: shin character data
++ code :: code block
%+ stag %pre
@ -61,7 +60,7 @@
%- plus
;~ pose
%+ cook welp
;~(plug (plus prn) (cold "\0a" eol))
;~(plug (star prn) (cold "\0a" eol))
(full (plus ;~(less ;~(plug tec tec tec) prn)))
==
::
@ -83,7 +82,7 @@
==
++ spas :: all shin elements
|* res=_rule
%- plus
%- plus
;~ pose emph stri link
brek cods (text res)
==
@ -106,19 +105,7 @@
(ifix [cab cab] (stag %bent inn))
==
::
++ escp :: escapable chars
;~ pose
(cold '`' (jest '\\`'))
(cold '*' (jest '\\*'))
(cold '#' (jest '\\#'))
(cold '-' (jest '\\-'))
(cold '.' (jest '\\.'))
(cold '{' (jest '\\{'))
(cold '}' (jest '\\}'))
(cold '[' (jest '\\['))
(cold ']' (jest '\\]'))
(cold '\\' (jest '\\\\'))
==
++ escp ;~(pfix bas (mask (trip '`*#-.{}[]\\'))) :: escapable chars
::
++ head :: header
%+ stag %had
@ -160,7 +147,7 @@
;~(plug (stun [0 3] ace) cab wits cab wits cab (star ;~(pose cab ace)))
==
::
++ html (stag %hem apex:xmlp) :: html barb
++ html (stag %hem apex:xmlp) :: html barb
++ lasd :: top level list
%+ stag %lit
%- full
@ -212,7 +199,7 @@
==
==
::
++ para (stag %par (full (spas fail))) :: paragraph
++ para (stag %par (full (spas fail))) :: paragraph
++ quot :: blockquotes
%+ stag %quo
%- full
@ -234,16 +221,28 @@
++ sepa :: separate barbs
%+ knee *wall |. ~+
=+ lin=;~(plug eol wits eol)
%- full
%+ ifix [(star whit) (star whit)]
%+ more ;~(plug eol wits (more wits eol))
;~ pose
sepc
(sepl (cold "-" hep))
(sepl (cold "*" tar))
(sepl (cold "+" lus))
(sepl (cook welp ;~(plug (star nud) (cold "." dot))))
(plus ;~(less lin ;~(pose prn ;~(simu ;~(plug eol prn) eol))))
(plus ;~(pose prn ;~(less lin eol)))
==
::
++ sepc :: separate code block
=+ tecs=(cold "```" (jest '```'))
%+ cook |=(wall `tape`(zing +<))
;~ plug
tecs
(cook zing (star ;~(plug eol ;~(less tecs (star prn)))))
(cold "\0a" eol)
tecs
(easy ~)
==
++ sepl :: separate list
|* bus=_rule
%+ cook zing
@ -285,14 +284,14 @@
::
++ grow :: convert into
=< |%
++ hymn :: convert to %hymn
++ hymn :: convert to %hymn
;html
;head:title:"Untitled"
;body
;* (apex don)
==
==
++ psal :: convert to %psal
++ psal :: convert to %psal
;div
;* (apex don)
==

View File

@ -6,7 +6,8 @@
::
++ grow :: convert to
|%
++ html (crip (xmlt | own ~)) :: convert to %html
++ hymn ;html(head:title:"Untitled" body:"+{own}") :: convert to %hymn
++ html (crip (xmlt | hymn ~)) :: convert to %html
++ mime [/text/html (taco html)] :: convert to %mime
--
--

View File

@ -0,0 +1,41 @@
:: %clay browser
::
:::: /hook/hymn/dirs/fab/pub
::
/= gas /$ fuel
/= rut /$ |= [a=beam path] ^- [p=path q=path]
[(tope a(s ~)) (flop (slag 1 s.a))]
!:
:::: ~pittyp-pittyp
::
=+ pax=`path`(flop but.gas)
=+ cot=(trip ;;(,@ (fall (file (welp p.rut pax)) '')))
=+ js="""
window.location = "/gen/main{<q.rut>}/" + pax.value
"""
;html
;head:title:"{<pax>}"
;body
;input#pax(onchange js, value (slag 1 <pax>));
;+ =+ ups="%"
|-
?: =(~ pax) ;div:a/"/gen/main{<q.rut>}":"/==="
=: ups "%{ups}"
pax (scag (dec (lent pax)) pax)
==
=+ sul=;;(arch .^(%cy (welp p.rut pax)))
?: (gte 2 ~(wyt by r.sul)) $
;div:a/"/gen/main{<q.rut>}{<pax>}":"{ups}"
::
;* =+ sub=;;(arch .^(%cy (welp p.rut pax)))
=| don=tape
%+ turn (~(tap by r.sub)) |= [a=span ~]
=: don "{don}/{(trip a)}"
pax (welp pax /[a])
==
=+ sus=;;(arch .^(%cy (welp p.rut pax)))
?: =(2 ~(wyt by r.sus)) $(a p.n.-.r.sus)
;div:a/"/gen/main{<q.rut>}{<pax>}":"{(slag 1 don)}"
;pre:"{cot}"
==
==

View File

@ -0,0 +1,114 @@
:: Documentation website generator.
::
:::: /hook/hymn/next-site/fab/fub
::
/= bod /^ manx /: /===/pub/src/doc/say/intro /psal/
/= sty /^ @t /: /===/pub/fab/site/styles /css/
/= say /^ (map ,@ (list ,[@u manx]))
/: /===/pub/src/doc/say
/% /@ /hymn/
/= ref /: /===/pub/src/doc/ref
/. /= vol /; |= vol=(map ,@ manx)
%+ sort (~(tap by vol)) |= [[a=term *] [b=term *]]
=+ [pax=(trip a) paf=(trip b)]
|-
?~ pax & ?~ paf |
?: =(i.pax i.paf) $(pax t.pax, paf t.paf)
(lth i.pax i.paf)
/, vol /% /psal/
:: /= hon /, hoon /% /psal/
==
/= gas /$ fuel
::
:::: ~tomsyt-balsen, ~pittyp-pittyp
::
|%
++ tuts
|= tut=(list ,[term tape]) ^- manx
:- /ol
%+ turn tut |= [a=term b=tape]
;li:p:a/"/gen/main/pub/fab/next-site/tut/{(trip a)}":"{b}"
++ refs
|= ref=(list ,[term tape tape]) ^- marl
%+ turn ref |= [a=term b=tape c=tape]
;p:a/"/gen/main/pub/fab/next-site/ref/{(trip a)}":";{strong "{b}"}: {c}"
--
!:
::::
::
;html
;head
;title: Urbit: Personal Cloud Computing
;link/"/gen/main/pub/fab/site/styles.css"(rel "stylesheet");
==
;body
;div(class "content container")
;+
=. but.gas (flop but.gas)
=+ ^= pag ^- marl
?. ?=([@ @ *] but.gas) ~
=+ ^- paf=(unit ,[nom=@t num=@u])
%+ rush i.t.but.gas :: XX numbers in path
;~(plug (cook crip (star alf)) dem)
?~ paf ~
?+ i.but.gas ~
%tut
=+ dir=(fall (~(get by say) nom.u.paf) ~)
=+ mir=(~(get by (mo dir)) num.u.paf)
?^ mir [u.mir]~
(turn dir |=([@ a=manx] a))
%ref
?+ nom.u.paf ~ :: XX foreword, preface
%vol
%+ murn vol.ref |= [a=term b=manx]
?. =((end 3 1 a) (scot ud/num.u.paf)) ~
(some b)
==
==
?^ pag
;div.subpage
;* pag
==
;div(class "page documentation")
;+ bod
;h1(class "page-title"): Documentation
;p ; This documentation is a work in progress. Feedback and corrections
; are welcome. Pull requests are encouraged. The repo for this site
; lives ;{a(href "https://github.com/urbit/urbit.github.io") "here"}.
==
;ul
;li
;p:(h2:"Tutorial")
;p:(a/"/gen/main/pub/fab/site/tut/setup":"Setup")
;strong: Nock
;+ %- tuts :~
nock1/"Intro to Nock" nock2/"Nock is Easy" nock3/"Using Nock"
==
;strong: Hoon
;+ %- tuts :~
hoon1/"Intro to Hoon" hoon2/"Types" hoon3/"Hoon Computes"
hoon4/"Gates" hoon5/"Tiles" hoon6/"Type Inference"
hoon7/"Odds, Ends, Quirks"
==
;strong: Arvo
;+ %- tuts :~
arvo1/"Basic Arvo" arvo2/"More Basic Arvo" arvo3/"Apps"
arvo4/"Functional Publishing I" arvo5/"Functional Publishing II"
==
==
;li
;p:(h2:"Reference")
;* %- refs :~
foreword/["Foreword" "Nock"] preface/["Preface" "Hoon Abstract"]
vol0/["Volume 0" "Version Stub"]
vol1/["Volume 1" "Hoon Structures"]
vol2/["Volume 2" "Hoon Compiler"]
vol3/["Volume 3" "Arvo Core"]
vol4/["Volume 4" "Arvo Vanes"]
==
==
==
==
==
==
==

View File

@ -139,7 +139,7 @@ pre, .codeblock {
margin-top: 0;
margin-bottom: 1rem;
padding: 1rem;
font-size: .9rem;
font-size: .8rem;
line-height: 1.4;
white-space: pre;
white-space: pre-wrap;

View File

@ -13,7 +13,7 @@ other:
= show ships in current station
\\ 5 show recent backlog (last n messages)
\\ ~m5 show recent backlog (using @dr syntax)
\\ ~2014.07.04 show recent backlog (using @da syntax)
\\ ~2014.7.4 show recent backlog (using @da syntax)
command-line parameters:
[%tower ~hoclur-bicrel] select haus server (default: ticketing ship)

View File

@ -0,0 +1,3 @@
Lexicon:
Links between common runes and their inverts.

View File

@ -0,0 +1,553 @@
Lexicon: Nouns
=======
Atom Syntax
----------
###Canonical Atom Odors
An odor is an atom format that specifies an atomic subtype.
```
@c UTF-32 codepoint
@d date
@da absolute date
@dr relative date (ie, timespan)
@f yes or no (inverse boolean)
@n nil
@p phonemic base
@r IEEE floating-point
@rd double precision (64 bits)
@rh half precision (16 bits)
@rq quad precision (128 bits)
@rs single precision (32 bits)
@s signed integer, sign bit low
@sb signed binary
@sd signed decimal
@sv signed base32
@sw signed base64
@sx signed hexadecimal
@t UTF-8 text (cord)
@ta ASCII text (span)
@tas ASCII symbol (term)
@u unsigned integer
@ub unsigned binary
@ud unsigned decimal
@uv unsigned base32
@uw unsigned base64
@ux unsigned hexadecimal
```
###Unsigned decimal, @ud
Hoon's unsigned decimal format is the normal Continental syntax. It differs
from the Anglo-American only in the use of periods, rather than commas, between
groups of 3:
~zod/try=> 19
19
~zod/try=> 1.024
1.024
An unsigned decimal not broken into groups is a syntax error. Also, whitespace
or even linebreaks can appear between the dot and the next group.
~zod/try=> 65. 536
65.536
###Unsigned hexadecimal, @ux
@ux has the same syntax as @ud, except that it's prefixed by 0x and uses groups
of four. Hex digits are lowercase only.
~zod/try=> 0x0
0x0
~zod/try=> `@ud`0x17
23
###Unsigned base64 and base32, @uv, @uw
The prefix is 0w for base64 and 0v for base32. The digits for @uw are, in
order: 0-9, a-z, A-Z, -, ~:
~zod/try=> `@ud`0w-
62
For @uv, the digits are 0-9, a-v.
Signed integers, @sd, @sx, @sw, @sv, @sb
Obviously, without finite-sized integers, the sign extension trick does not
work. A signed integer in Hoon is a different way to use atoms than an unsigned
integer; even for positive numbers, the signed integer cannot equal the
unsigned.
The prefix for a negative signed integer is a single - before the unsigned
syntax. The prefix for a positive signed integer is --. The sign bit is the low
bit:
~zod/try=> -1
-1
~zod/try=> --1
--1
~zod/try=> `@ud`-1
1
~zod/try=> `@ud`--1
2
~zod/try=> `@ud`-2
3
~zod/try=> `@ud`--2
4
~zod/try=> `@ux`-0x10
0x1f
~zod/try=> `@ux`--0x10
0x20
~zod/try=> `@ud`--0w-
124
~zod/try=> `@sw`124
--0w-
###Absolute date, @da
Urbit dates represent 128-bit chronological time, with 2^64 seconds from the
start of the universe to the end. 2^127 is 3:30:08 PM on December 5, AD 226,
for reasons not clear or relevant:
~zod/try=> `@da`(bex 127)
~226.12.5..15.30.08
~zod/try=> `@da`(dec (bex 127))
~226.12.5..15.30.07..ffff.ffff.ffff.ffff
The time of day and/or second fragment is optional:
~zod/try=> `@ux`~2013.12.7
0x8000.000d.2140.7280.0000.0000.0000.0000
~zod/try=> `@ux`~2013.12.7..15.30.07
0x8000.000d.2141.4c7f.0000.0000.0000.0000
~zod/try=> `@ux`~2013.12.7..15.30.07..1234
0x8000.000d.2141.4c7f.1234.0000.0000.0000
We also do BC:
~zod/try=> `@ux`~226-.12.5
0x7fff.fffc.afb1.b800.0000.0000.0000.0000
The semantics of the time system are that UGT (Urbit Galactic Time) is GMT/UTC
as of leap second 25. UGT is chronological and will never add leap seconds,
even if UTC continues this mistake. If a gap appears, it must be resolved in
the presentation layer, with timezones and other human curiosities.
See section 2cH of the source for more details.
###Relative date, @dr
It's also nice to have a syntax for basic time intervals:
~zod/try=> `@ux`~s1
0x1.0000.0000.0000.0000
~zod/try=> `@ux`~m1
0x3c.0000.0000.0000.0000
~zod/try=> (div ~m1 ~s1)
60
~zod/try=> (div ~h1 ~m1)
60
~zod/try=> (div ~h1 ~s1)
3.600
~zod/try=> (div ~d1 ~h1)
24
~zod/try=> `@da`(add ~2013.11.30 ~d1)
~2013.12.1
There are no @dr intervals under a second or over a day. Since the resolution
is so high, though, (div ~s1 1.000.000) produces a pretty accurate microsecond.
###Loobean, @f
A loobean, or just bean, is 0 or 1. 0 is yes, 1 is no:
~zod/try=> `@ud`.y
0
~zod/try=> `@ud`.n
1
###Nil, @n
Nil indicates an absence of information, as in a list terminator. The only
value is ~, 0.
~zod/try=> `@ud`~
0
###Unicode text, @t
@t is a sequence of UTF-8 bytes, LSB first - sometimes called a cord. For
lowercase numbers and letters, the canonical syntax is ~~text:
~zod/try=> ~~foo
'foo'
Note that the prettyprinter makes an unprincipled exception and prints the text
in a noncanonical format:
~zod/try=> `@ux`~~foo
0x6f.6f66
We want to be able to encode an arbitrary Unicode string as a single URL-safe
token, using no punctuation but .~-, in @t. Space is ., . is ~., ~ is ~~, - is
-:
~zod/try=> ~~foo.bar
'foo bar'
~zod/try=> ~~foo.bar~.baz~~moo-hoo
'foo bar.baz~moo-hoo'
For all other ASCII/Unicode characters, insert the Unicode codepoint in
lower-case hexadecimal, followed by .. For example, for U+2605 "BLACK STAR",
write:
~zod/try=> ~~foo~2605.bar
'foo★bar'
This UTF-32 codepoint is of course converted to UTF-8:
~zod/try=> `@ux`~~foo~2605.bar
0x72.6162.8598.e26f.6f66
###URL-safe ASCII text, @ta
@ta encodes the ASCII subset that all canonical atom syntaxes restrict
themselves to. The prefix is ~.. There are no escape sequences except ~~, which
means ~, and ~-, which means \_. - and . encode themselves. No other characters
besides numbers and lowercase letters need apply.
~zod/try=> `@t`~.foo
'foo'
~zod/try=> `@t`~.foo.bar
'foo.bar'
~zod/try=> `@t`~.foo~~bar
'foo~bar'
~zod/try=> `@t`~.foo~-bar
'foo_bar'
~zod/try=> `@t`~.foo-bar
'foo-bar'
A @ta atom is called a span.
###Codepoint, @c
Normally when we build atoms of Unicode text, we use a UTF-8 bytestream, LSB
first. But sometimes it's useful to build atoms of one or more UTF-32 words.
The codepoint syntax is the same as @t, except with a ~- prefix. Let's repeat
our examples, with hex display:
~zod/try=> `@ux`~-foo
0x6f.0000.006f.0000.0066
~zod/try=> `@ux`~-foo.bar
0x72.0000.0061.0000.0062.0000.0020.0000.006f.0000.006f.0000.0066
###Phonemic, @p
We've seen @p used for ships, of course. But it's not just for ships - it's for
any short number optimized for memorability, not for arithmetic. @p is great
for checksums, for instance.
That said, @p is subtly customized for the sociopolitical design of Urbit as a
digital republic. For example, one feature we don't want is the ability to see
at a glance which carrier and cruiser issued a destroyer. Consider the carrier
0x21:
~zod/try=> `@p`0x21
~mep
It issues 255 cruisers, including 0x4321:
~zod/try=> `@p`0x4321
~pasnut
Which issues 65.535 destroyers, including 0x8765.4321 and several successors:
~zod/try=> `@p`0x8765.4321
~famsyr-dirwes
~zod/try=> `@p`0x8766.4321
~lidlug-maprec
~zod/try=> `@p`0x8767.4321
~tidlus-roplen
~zod/try=> `@p`0x8768.4321
~lisnel-lonbet
Of course, anyone who can juggle bits can see that ~famsyr-dirwes is a close
cousin of ~lidlug-maprec. But she actually has to juggle bits to do it.
Obfuscation does not prevent calculated associations, just automatic ones.
But at the yacht level, we actually want to see a uniform 32-bit space of
yachts directly associated with the destroyer:
~zod/try=> `@p`0x9.8765.4321
~talfes-sibzod-famsyr-dirwes
~zod/try=> `@p`0xba9.8765.4321
~tacbep-ronreg-famsyr-dirwes
~zod/try=> `@p`0xd.cba9.8765.4321
~bicsub-ritbyt-famsyr-dirwes
~zod/try=> `@p`0xfed.cba9.8765.4321
~sivrep-hadfeb-famsyr-dirwes
###IPv4 and IPv6 addresses, @if, @is
Urbit lives atop IP and would be very foolish to not support a syntax for the
large atoms that are IPv4 and IPv6 addresses.
@if is the standard IPv4 syntax, prefixed with .:
~zod/try=> `@ux`.127.0.0.1
0x7f00.0001
@is is the same as @if, but with 8 groups of 4 hex digits:
~zod/try=> `@ux`.dead.beef.0.cafe.42.babe.dead.beef
0xdead.beef.0000.cafe.0042.babe.dead.beef
###Floating Point, @rs, @rd, @rq, @rh
The syntax for a single-precision float is the normal English syntax, with a . prefix:
.6.2832 :: τ as @rs
.-6.2832 :: -τ as @rs
.~6.2832 :: τ as @rd
.~-6.2832 :: -τ as @rd
.~~6.2832 :: τ as @rh
.~~~6.2832 :: τ as @rq
(Hoon is a Tauist language and promotes International Tau Day.)
###Transparent cell syntax
By adding _, we can encode arbitrary nouns in our safe subset. The prefix to a
canonical cell is ._; the separator is _; the terminator is __. Thus:
~zod/try=> ._3_4__
[3 4]
~zod/try=> :type; ._.127.0.0.1_._0x12_19___~tasfyn-partyv__
[.127.0.0.1 [0x12 19] ~tasfyn-partyv]
[@if [@ux @ud] @p]
Those who don't see utility in this strange feature have perhaps never needed
to jam a data structure into a URL.
###Opaque noun syntax
Speaking of jam, sometimes we really don't care what's inside our noun. Then,
the syntax to use is a variant of @uw prefixed by ~, which incorporates the
built-in jam and cue marshallers:
~zod/try=> (jam [3 4])
78.241
~zod/try=> `@uw`(jam [3 4])
0wj6x
~zod/try=> (cue 0wj6x)
[3 4]
~zod/try=> ~0wj6x
[3 4]
Noncanonical Syntax
--------------------
These are syntaxes for constants which don't fit the canonical character-set
constraints.
###Cubes, @tas
@tas, a term, is our most exclusive odor. The only characters permitted are
lowercase ASCII, - except as the first or last character, and 0-9 except as the
first character.
The syntax for @tas is the text itself, always preceded by %. This means a term
is always cubical. You can cast it to @tas if you like, but we just about
always want the cube:
~zod/try=> %dead-fish9
%dead-fish9
~zod/try=> -:!>(%dead-fish9)
[%cube p=271.101.667.197.767.630.546.276 q=[%atom p=%tas]]
The empty @tas has a special syntax, $:
~zod/try=> %$
%$
A term without % is not a constant, but a name:
~zod/try=> dead-fish9
! -find-limb.dead-fish9
! find-none
! exit
A common structure in Hoon is a noun with a cubical head and an arbitrary tail:
~zod/try=> [%foo 'bar']
[%foo 'bar']
This structure may be generated with the following irregular syntax:
~zod/try=> a/'bar'
[%a 'bar']
###Loobeans, @f
.y is a little cumbersome, so we can say & and |. The % prefix cubes as usual.
~zod/try=> `@ud`&
0
~zod/try=> `@ud`|
1
###Cords, @t
The canonical ~~ syntax for @t, while it has its place, is intolerable in a
number of ways - especially when it comes to escaping capitals. So @t is both
printed and parsed in a conventional-looking single-quote syntax:
~zod/try=> 'foo bar'
'foo bar'
~zod/try=> `@ux`'foo bar'
0x72.6162.206f.6f66
Escape ' with \:
~zod/try=> 'Foo \'bar'
'Foo \'bar'
~zod/try=> `@ux`'\''
0x27
###Strings
Text in Hoon is generally manipulated in two ways, depending on what you're
doing: as an atomic cord/span/term, or as a tape which is a list of bytes (not
codepoints).
To generate a tape, use double quotes:
~zod/try=> "foo"
"foo"
~zod/try=> `*`"foo"
[102 111 111 0]
We're getting off the constant reservation, but strings also interpolate with curly-braces:
~zod/try=> "hello {(weld "wor" "ld")} is a fun thing to say"
"hello world is a fun thing to say"
And they can be joined across space or lines with a .:
~zod/try=> "hello"."world"
"helloworld"
~zod/try=> "hello". "world"
"helloworld"
Lists
-----
A list in Hoon is a null-terminated tuple. See section 2bB for Hoon's List library.
~zod/try=> :type; `(list)`[3 4 ~]
~[3 4]
it(*)
The list type can be further specified by a subtype:
~zod/try=> :type; `(list ,@ud)`[3 4 ~]
~[3 4]
it(@ud)
The above example is a list of @ud, meaning the all values in the list must be of type @ud.
Polymorphic lists can be specified by constructing a more complex type:
~zod/try=> :type; `(list ?(@ud @ux))`[3 0xf ~]
~[3 15]
it({@ud @ux})
Not specifing a more complex type defaults to a list of raw nouns:
~zod/try=> :type; `(list)`[3 0xf ~]
~[3 15]
it(*)
Null-terminated tuples may be generated with the following syntax:
~zod/try=> ~[3 0xf]
[3 0xf ~]
~zod/try=> :type; ~[3 0xf]
[3 0xf ~]
[@ud @ux %~]
Note that this syntax is not automatically typed as a list, but may be cast as such:
~zod/try=> :type; `(list ?(@ux @ud))`~[3 0xf]
~[0x3 0xf]
it({@ux @ud})
Furthermore, a different syntax may be used to group the entire noun in the
head of a null terminated tuple:
~zod/try=> [3 0xf]~
[[3 0xf] ~]
This is often used to easily generate a list from a single noun.
~zod/try=> :type; `(list ,[@ud @ux])`[3 0xf]~
~[[3 0xf]]
it([@ud @ux])
The above is typed as a list of decimal hexadecimal pairs.
Units
-----
A Unit is Hoon's "maybe" type. As in, either some value or null. See section 2bA for Hoon's Unit library. Units are represented by a cell whose head is null and whose tail is some noun:
~zod/try=> `(unit ,@ud)`[~ 3]
[~ 3]
The unit type can be further specified by a subtype. The above example is a unit of @ud, meaning the optional value must be of type @ud.
~zod/try=> `(unit ,@ud)`[~ [3 3]]
! type-fail
! exit
~zod/try=> `(unit ,^)`[~ [3 3]]
[~ [3 3]]
For convenience, a null-headed noun may be specified with the following irregular syntax:
~zod/try=> `3
[~ 3]
~zod/try=> :type; `3
[~ 3]
[%~ @ud]
Note that this syntax is not automatically typed as a Unit, but may be cast as such:
~zod/try=> :type; `(unit)``3
[~ 3]
u(*)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,228 @@
Morphology
==========
Hoon is a statically typed language that compiles to Nock.
Types
-----
Types are nouns the compiler keeps around as it turns your Hoon into Nock.
A type serve two purposes:
1. It defines a set of nouns. Any finite noun is either in this set, or not in
it.
2. it ascribes semantics to all nouns in this set. For example, a Hoon type
exports a semantic namespace.
These are defined in Hoon as one of the ten kinds of type found in `++type`.
At its most general, the `noun` type contains all Hoon nouns. Everything in
Hoon is a noun. The `%void` type contains no values at all. The `%atom` type
contains only atoms. The `%cube` type is parameterized by a value, and it
contains only that single value. The other types are defined in the lexicon.
Type inference in Hoon works well enough that there is no direct
syntax for defining or declaring a type. There is only a syntax for
constructing twigs. Types are always produced by inference.
When resolving a face, for example, the axis that
ends up in the nock formula depends on the where the face is in the subject.
We only know this because faces are in the subject type. Thus, in `=> [p=42
q=1.337] p`, the `p` twig compiles to nock `[0 2]` while in `=> [q=42 p=1.337]
p`, the `p` twig compiles to nock `[0 3]`. This is true even though the actual
nock produced by `[p=42 q=1.337]` is the same as that produced by `[q=42
p=1.337]`. Thus, the nock formula may depend on the subject type. It is for
this reason that we say that a type defines not only a set of values, but also
the semantics for operating on those values.
Tiles
-----
What are the usual things we want to do with types?
- Test if a noun is of a particular type.
- Create a blank default example of a type
- Coerce a noun into a type
It is possible to generate twigs for each of the above use cases from two
pieces of information: (1) a tile describing a type and (2) a reference to
which case we want to generate.
Tiles are not types.
Every tile has a unique associated type, or "icon".
A tile is not a type, but every tile corresponds to some type.
Formalizing the operations on a tile, there are exactly four.
Bunting a tile is simply creating a blank default example of the tile's icon.
This may seem to have limited usefulness, but this is actually the most common
use of tiles. This is due to the the way in which we create, for example,
gates. The sample of a gate is usually defined in terms of a tile, as in `|=
[p=@ q=@] (add p q)`. The `|=` rune takes a tile (in this case `[p=@ q=@]`
and bunts it to create a default sample of `[0 0]` with the type of a cell of
two atoms. Note that this is different from `|= [p=%0 q=%0] (add p q)`,
which still bunts to create a default sample of `[0 0]`, but whose type is a
cell of two constant `0`s. In the first case, when we call our gate, the type
checker will make sure that we are only ever replacing the sample with a cell
of two atoms, while in the second case the type checker will enforce that we
are only ever replacing the sample with a cell of two `0`s.
Clamming a tile is creating a gate whose sample is a noun and whose product is
a member of the icon. This allows us to coerce any noun into any type. If the
noun is not a member of that type, then we produce some member of the type that
is either in some sense "similar" to the given noun or else we simply give a
default value, usually the bunt of this tile.
Fishing a tile is testing whether a particular value is of that type. This
returns a loobean. This obviously has many uses.
Whipping a tile is something you'll never have to do directly. Whipping is
never directly used in any Hoon source code. Whipping is used internally by
clamming.
In summary, a tile is simply a convenient syntax for creating well-typed nouns.
A tile is not a twig, but tiles always are reduced statically in one
of four ways to a twig.
Type Inference
--------------
Hoon is a higher-order typed functional language. Most languages in this class,
Haskell and ML being prominent examples, use something called the
Hindley-Milner unification algorithm. Hoon uses its own special sauce instead.
Hoon's philosophy is that a language is a UI for programmers, and the basic
test of a UI is its predictability. It is impossible (for most programmers)
to learn a language properly unless they know what the compiler is doing, which
in practice means mentally stepping through the algorithms it uses (with the
exception of semantically neutral optimizations). Haskell is a hard language to
learn (for most programmers) because it's hard (for most programmers) to follow
what the Haskell compiler is thinking.
Broadly speaking, type inference in Hoon has three general limitations as
compared to Hindley-Milner inference.
1. Hoon does not think backwards. For instance, it cannot infer a function's
argument type (or rather, a gate's sample type) from its body.
2. Hoon can infer through tail recursion, but not head recursion. It can check
head recursion, however, given an annotation.
3. The compiler catches most but not all divergent inference problems - i.e.
you can put the compiler into an infinite loop or exponential equivalent.
An interrupt will still show you your error location.
Although an inference algorithm that reasons only forward must and does require
a few more annotations from the programmer, the small extra burden on her
fingers is more than offset by the lighter load on her hippocampus.
Furthermore, programs also exist to be read. Some of these annotations (which a
smarter algorithm might infer by steam) may annoy the actual author of the code
but be a lifesaver for her replacement.
Our experience is that these limitations are minor annoyances at worst and
prudent restrictions at best. Your mileage may vary.
Type inference is a frightening problem, especially if you've been exposed to
a wall of math. Your only real problem in learning Hoon is to learn not to
fear it. Once you work past this reasonable but entirely unfounded fear of
inference, your Hoon experience will be simple, refreshing and delightful. So
first, let's talk through a few reassuring facts:
1. Type inference in Hoon never sees a tile. It operates exclusively on twigs.
All tiles and synthetic twigs are reduced to natural twigs for the inference
engine's benefit.
2. The semantics of Hoon are in ++ut in hoon.hoon, and nowhere else.
3. Within ++ut, all the semantics of Hoon are in the call graph of one arm: ++mint.
++mint has a case for every natural hoon. So do ++play and ++mull,
but their semantics are redundant with ++mint.
4. One leg in the sample of ++mint - gol - which looks for all the world like a
mechanism for backward inference, is not. It is semantically irrelevant and
only exists to get better localization on error reports.
5. ++mint is the gate that maps [type twig] to [type nock]:
[subject-type twig] => [product-type nock-formula]
When we have a type that describes the subject for the formula we're trying to
generate, as we generate that formula we want to also generate a type for the
product of that formula on that subject. As long as subject-type is a
correct description of some subject, you can take any twig and compile it
against subject-type, producing a formula such that *(subject formula) is a
product correctly described by product-type.
Compilation
------------
`++make` is a top-level function that turns text into nock.
~hoclur-bicrel/try=> `*`(make '|= [@ @ud] +<')
[8 [1 0 0] [1 0 6] 0 1]
Another way to do this is with `!=`.
~hoclur-bicrel/try=> !=(|=([@ @ud] +<))
[8 [1 0 0] [1 0 6] 0 1]
`++make` is more general, in that it can be called on programmatically
generated text, but `!=` is convenient for learning and debugging.
The compilation process is as follows:
First, a runic expression is parsed into an abstact syntax tree, called a
`twig`:
text => twig
Parsing code into a `twig` can be done with `++ream`:
~hoclur-bicrel/try=> (ream '|= [@ @ud] +<')
[ %brts
p=[p=[%axil p=[%atom p=~.]] q=[%axil p=[%atom p=~.ud]]]
q=[%cnts p=~[[%.y p=6]] q=~]
]
Refer to the Syntax section for more detail on parsing.
The compiler proper, is `++mint` in `++ut`.
++mint takes a twig and a subject type and produces a product type and a nock formula.
[subject-type twig] => [product-type nock-formula]
For example, we can call `++mint` on the twig we produced earlier with a
subject type of any noun:
~hoclur-bicrel/try=>
(~(mint ut %noun) %noun [%brts [[%axil [%atom ~.]] [%axil [%atom ~.ud]]] [%cnts ~[[%.y 6]] ~]])
[ p
[ %core
p=[%cell p=[%cell p=[%atom p=%$] q=[%atom p=%ud]] q=%noun]
q
[ p=%gold
q=[%cell p=[%cell p=[%atom p=%$] q=[%atom p=%ud]] q=%noun]
r=[p=[0 6] q={[p=%$ q=[%ash p=[%cnts p=~[[%.y p=6]] q=~]]]}]
]
]
q=[%8 p=[%1 p=[0 0]] q=[p=[%1 p=[0 6]] q=[%0 p=1]]]
]
Note that the head of the above is a type, which in this case is a gold core
with an ash gate. The second part, though, is (with a few labels, or faces added) the nock that was
produced by `++make`.

View File

@ -0,0 +1,176 @@
Orthography: Consensus Aesthetic
==========
The Hoon compiler enforces the syntactical correctness of the language, it does
not, with some exceptions, enforce aesthetic standards. Many different styles
of Hoon are possible. However, given Hoon's runic syntax, it is remarkably easy
for the novice programmer to generate idiosyncratic illegible code. Many other
languages that make heavy use of ASCII have a similar problem. Furthermore,
collaborative programming is made vastly easier by using a standard style
convention.
The Urbit source is written in a style of Hoon called the Consensus Aesthetic.
No patches to the Urbit source will be accepted unless they follow the ConsensusAesthetic.
The general rules of the Consensus Aesthetic are the following:
Character Restriction
---------------------
The horizontal tab character, \ht, ASCII 0x9, must never occur. This is
enforced by the compiler.
Line and Comments
-----------------
Lines must not exceed 80 columns in width and should not exceed 55 columns.
Blank lines (lines consisting entirely of whitespace) should not occur. For
visual separation of code, use empty comments.
Comments may appear on column 0, column 57 or inline at the same level of
indentation as the code.
Indentation
-----------
Aesthetically, the act of programming is the act of formatting a big wall of
text. This canvas has a curious but essential property - it is indefinitely
tall, but finitely wide. The programmer's task as a visual designer is to
persuade code to flow down, not across.
The first law of Hoon indentation style is that all tall form indentation is in
two-space increments. Single spaces are for wide form only.
The second law of Hoon indentation is that everything in the kernel is good
indentation style. Or at least if it's not, it needs to be changed.
The third and most important law of Hoon indentation is that large twigs should
flow down and not across. The Aesthetic prescribes a backstep pattern, which
preserves indentation level in the common case:
```
?: |
47
?: |
52
?: |
7
20
```
Notice that the first child is placed the furthest horizontal distance away
from its parent rune. Each of the subsequent children is outdented, such
that the last child (a similarly formatted twig) is vertically aligned with its parent.
However, this convention does not always prevent horizontal drift. For example,
there are many cases when the last twig is not the heaviest:
```
?: &
?: |
52
?: |
7
20
47
```
To handle cases like this, there exist several (synthetic runes)[lexicon/#rune_types]
that invert the argument order of common runes to ensure the last twig is the
heaviest. For example, where `?:` is _if-then_, `?.` is _unless_:
```
?. &
47
?: |
52
?: |
7
20
```
###N-ary runes###
For runes that take an arbitrary number of children, the children are indented,
with the closing `==` aligned with the rune:
```
;~ plug
ace
ace
==
```
For runes operating on associative lists, there exist two indentation conventions:
Kingside, where the key-value pairs are (or at least start) on the same line:
```
%= res
key1 val
key2 val2
==
```
And Queenside, where the keys lie indented on the line above their respective
values:
```
%= res
key
twig-producing-val
key2
=+ a=2
[a 3]
==
```
While both of these techniques are used to preserve the right margin, the
latter is used when the keys and/or values are especially heavy.
Naming Convention
-----------------
Names must follow one of the following naming conventions: Austere, Lapidary,
or Freehand.
In Austere Hoon, variables and arguments are named alphabetically with one
letter, a, b, c etc, in strict order of appearance in the text. This scheme is
only useful in the case of extremely regular and straightforward namespaces:
very short functions, for instance.
Austere arms must be gates or trays. Gate arms are three letters and try to
carry some mnemonic significance - for instance, ++dec. Tray arms are two
letters and try to resemble pronouns - for instance, ++by.
Austere structures must be short tuples, no wider than 5. The legs are named p,
q, r, s and/or t.
Conventional recursive structures use other standard names. The head of a list
is always i, the tail is always t. In a binary tree of nodes, the node is n,
the children l and r.
When in doubt, do not use Austere Hoon. In an ordinary context - not least
because Austere gates are easily mistaken for Lapidary variables - there should
be as few Austere arms as possible. And always remind yourself that Austere
Hoon makes it as hard as possible to refactor your code.
Lapidary Hoon is the ordinary style of most of Hoon and Arvo. In lapidary mode,
variables, arguments, attributes, etc, are three-letter strings, usually
consonant-vowel-consonant, generally meaningless. If the same string is used
more than once in the same file, it should be used for the same concept in some
sense, as often happens spontaneously in cutting and pasting. It would be nice
to have an editor with a macro that generated random unique TLV strings
automatically.
Lapidary arms are always four letters. They may or may not be English words,
which may or may not mean anything relevant.
In Freehand Hoon, do whatever you want. Note that while uppercase is not
permitted in a symbol, - is, suggesting a generally Lisp-like state of gross
hyphenated disorder. F-mode is best used for top-layer software which nothing
else is based on; prototyping and casual coding; etc. Freehand Hoon is not an acceptable style for any code in the Urbit source proper, and is discouraged for production applications.

View File

@ -0,0 +1,85 @@
Philosophy
==========
Hoon is a higher-order typed functional language that it compiles itself to
Nock in 3400 lines of Hoon. If this number is accurate (it is), Hoon is very
expressive, or very simple, or both. (It's both.) The bad news is that it
really has nothing at all in common, either syntactically or semantically, with
anything you've used before.
By understanding Nock tutorial, you've actually come closer than you realize to
knowing Hoon. Hoon is actually not much more than a fancy wrapper around Nock.
People who know C can think of Hoon as the C to Urbit's Nock - just a
sprinkling of syntax, wrapped around machine code and memory.
For instance, it's easy to imagine how instead of calculating tree axes by
hand, we could actually assign names to different parts of the tree - and those
names would stay the same as we pushed more data on the subject.
The way we're going to do this is by associating something called a type with
the subject. You may have heard of types before. Technically, Hoon is a
statically typed language, which just means that the type isn't a part of your
program: it's just a piece of data the compiler keeps around as it turns your
Hoon into Nock.
A lot of other languages use dynamic types, in which the type of a value is
carried along with the data as you use it. Even languages like Lisp, which are
nominally typeless, look rather typed from the Hoon perspective. For example, a
Lisp atom knows dynamically whether it's a symbol or an integer. A Hoon atom is
just a Nock atom, which is just a number. So without a static type, Hoon
doesn't even know how to print an atom properly.
Most higher-order typed languages, Haskell and ML being prominent examples, use
something called the Hindley-Milner unification algorithm. Hoon uses its own
special sauce instead.
Why? There are two obvious problems with Hindley-Milner as a functional type
system, the main one being the wall of heavy mathematics that greets you
instantly when you google it. We have heard some claims that Hindley-Milner is
actually quite simple. We urge all such claimants to hie themselves to its
Wikipedia page, which they'll surely be able to relieve of its present alarming
resemblance to some string-theory paper in Physics Review D.
Nor is this in any way an an anti-academic stance. Quite the contrary.
Frankly, OS guys really quite seldom find themselves in the math-department
lounge, cadging stray grants by shamelessly misrepresenting the CAP theorem as
a result in mathematics. It doesn't seem too much to expect the mathematicians
to reciprocate this basic academic courtesy.
Furthermore, besides the drawback that Hindley-Milner reeks of math and
programmers who love math are about as common as cats who love a bath - a
problem, but really only a marketing problem - Hindley-Milner has a genuine
product problem as well. It's too powerful.
Specifically, Hindley-Milner reasons both forward with evaluation, and backward
from constraints. Pretty unavoidable in any sort of unification algorithm,
obviously. But since the compiler has to think both forward and backward, and
the programmer has to predict what the compiler will do, the programmer has to
think backward as well.
Hoon's philosophy is that a language is a UI for programmers, and the basic
test of a UI is to be easy to use. It is impossible (for most programmers) to
learn a language properly unless they know what the compiler is doing, which in
practice means mentally stepping through the algorithms it uses (with the
exception of semantically neutral optimizations). Haskell is a hard language to
learn (for most programmers) because it's hard (for most programmers) to follow
what the Haskell compiler is thinking.
It's true that some programmers have an effective mathematical intuition that
let them "see" algorithms without working through them step by step. But this
is a rare talent, we feel. And even those who have a talent don't always enjoy
exercising it.
If a thorough understanding of any language demands high-grade mathematical
intuition in its programmers, the language as a UI is like a doorway that makes
you duck if you're over 6 feet tall. The only reason to build such a doorway in
your castle is if you and all your friends are short, and only your enemies are
tall. Is this really the case here?
Although an inference algorithm that reasons only forward must and does require
a few more annotations from the programmer, the small extra burden on her
fingers is more than offset by the lighter load on her hippocampus.
Furthermore, programs also exist to be read. The modern code monkey is above
all things a replaceable part, and some of these annotations (which a smarter
algorithm might infer by steam) may annoy the actual author of the code but be
a lifesaver for her replacement.

View File

@ -0,0 +1,226 @@
Phonology
=========
Glyphs
------
Hoon is a keyword-free language - any alphanumeric text in the program is part
of the program. Where other languages have reserved words, Hoon syntax uses
ASCII symbols, or glyphs. In normal English, many of these glyphs have
cumbersome multisyllabic names. As Hoon uses these glyphs heavily, it has its
own, more concise, naming scheme for them:
ace space gal < per )
bar | gar > sel [
bas \ hax # sem ;
buc $ hep - ser ]
cab _ kel { sig ~
cen % ker } soq '
col : ket ^ tar *
com , lus + tec `
doq " pam & tis =
dot . pat @ wut ?
fas / pel ( zap !
A language is meant to be spoken. Even a programming language. Studies have
shown that even when we read silently, we activate the motor cortex that
controls our vocal cords. Even if we never speak these symbols, they're easier
to think if bound to simple sounds.
Mnemonic aids for memorizing the above glyphs can be found in the comments of section 2eF of the Urbit Source, which is reprinted here:
```
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: section 2eF, parsing (ascii) ::
::
++ ace (just ' ') :: spACE
++ bar (just '|') :: vertical BAR
++ bas (just '\\') :: Back Slash (escaped)
++ buc (just '$') :: dollars BUCks
++ cab (just '_') :: CABoose
++ cen (just '%') :: perCENt
++ col (just ':') :: COLon
++ com (just ',') :: COMma
++ doq (just '"') :: Double Quote
++ dot (just '.') :: dot dot dot ...
++ fas (just '/') :: Forward Slash
++ gal (just '<') :: Greater Left
++ gar (just '>') :: Greater Right
++ hax (just '#') :: Hash
++ kel (just '{') :: Curly Left
++ ker (just '}') :: Curly Right
++ ket (just '^') :: CareT
++ lus (just '+') :: pLUS
++ hep (just '-') :: HyPhen
++ pel (just '(') :: Paren Left
++ pam (just '&') :: AMPersand pampersand
++ per (just ')') :: Paren Right
++ pat (just '@') :: AT pat
++ sel (just '[') :: Square Left
++ sem (just ';') :: SEMicolon
++ ser (just ']') :: Square Right
++ sig (just '~') :: SIGnature squiggle
++ soq (just '\'') :: Single Quote
++ tar (just '*') :: sTAR
++ tec (just '`') :: backTiCk
++ tis (just '=') :: 'tis tis, it is
++ wut (just '?') :: wut, what?
++ zap (just '!') :: zap! bang! crash!!
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
```
Digraph Glyphs: Runes
--------------------
The fundamental building block of Hoon is the digraph glyph or rune. TThe choice of glyph is not random. The first defines a semantic category. That is, all runes whose first glyph is `|` or `bar` are conceptually related. See Morphology for details.
To pronounce a rune, concatenate the glyph names, stressing the first syllable
and softening the second vowel into a "schwa." Hence, to say `~&`, say
"sigpam." To say `|=`, say "bartis."
Punctuation Runes
----------------
The following runes are used as punctuation in Tall Form Hoon (See Syntax for details) and have mandatory special pronunciation:
-- hephep phep
+- lushep slep
++ luslus slus
== tistis stet
Wing Runes
---------
The following runes are used to access specific axes or wings in a noun. See Morphology. They have optional alternate phonology.
+< lusgal glus
+> lusgar gras
-< hepgal gelp
-> hepgar garp
Tile Runes
---------
The following runes comprise the set of "Tile Runes" and are used to generate
complex types (See Morphology for details). They have an optional alternate
phonology, which describes the tile they generate:
$% buccen kelp
$^ bucket herb
$: buccol tile
$= buctis bark
$& bucpam bush
$? bucwut fern
$| bucbar reed
The following glyphs are not runes, but are commonly used with tile runes to specify basic types. (See Morphology for details). In context, they have an optional alternate phonology:
@ "atom"
^ "cell"
* "noun"
? "bean"
~ "null"
Irregular Runes
--------------
The following glyphs have optional special pronunciation when they appear as
the irregular form as certain digraph runes. It is perfectly acceptable to
pronounce the characters, but some may find the alternate phonology useful,
especially in cases where multiple irregular forms occur in sequence.
Irregular Regular Pronunciation
,p $,(p) "clam p"
_p $_(p) "bunt p"
p@q $@(p q) "whip p into q"
!p ?!(p) "NOT p"
&(p q) ?&(p q) "AND p q
|(p q) ?|(p q) "OR p q"
?(p q) $?(p q) "fern p q"
`p`q ^-(p q) "cast p q"
p=q ^=(p q) "p is q"
~[p q] :~(a b) "list p q"
`[p] [~ p] "unit p"
p^q [p q] "cell p q"
[p q] :*(p) "cell p q"
+(p) .+(p) "bump p"
=(p q) .=(p q) "equals p q"
p:q =<(p q) "p of q"
p(q r) %=(p q r) "toss p q r"
(p q) %-(p q) "slam p q"
~(p q r) %~(p q r) "slug p q r"
Nouns
-----
Some nouns also have an alternate phonology:
& "yes"
%& "yes"
%.y "yes"
| "no"
%| "no"
%.n "no"
42 "forty-two"
0i42 "dec four two"
0x2e "hex two e"
0b10 "bin one zero"
0v3t "base thirty two three t"
0wA4 "base sixty-four big a four"
'foo' "cord foo"
"foo" "tape foo"
Example
-------
Take the following snippet of Hoon:
++ dec :: decrement
~/ %dec
|= a=@
~| %decrement-underflow
?< =(0 a)
=+ b=0
|- ^- @
?: =(a +(b))
b
$(b +(b))
Omitting the spaces and comments (which only a real purist would include), the
above is pronounced:
slus dec
sigfas cen-dec
bartis A tis pat
sigbar cen-decrement-underflow
wutgal tis zero A
tislus B tis zero
barhep kethep pat
wutcol tis A lus B
B
buc B lus B
Or using the alternate phonology:
slus dec
sigfas cen-dec
bartis A is atom
sigbar cen-decrement-underflow
wutgal equals zero A
tislus B is zero
barhep kethep atom
wutcol equals A lus B
B
buc B lus B
Which is very similar. The alternate phonology exists as a result of common
speech patterns observed amongst Hoon programmers in the wild. In any language
actually spoken by actual humans, laziness soon rounds off any rough edges.

View File

@ -0,0 +1,483 @@
Syntax
======
Runes
-----
Everything in hoon is parsed into an abstract syntax tree (AST), called a `twig`.
A `twig` is a (frond)[lexicon/#fronds] composed of a (cubic)[lexicon/#cubes]
rune and one or more children:
```
~zod/try=> :-(1 2)
[1 2]
~zod/try=> (ream ':-(1 2)')
[%clhp p=[%dtzy p=%ud q=1] q=[%dtzy p=%ud q=2]]
```
As the expression above begins with `:-`, it is parsed into the twig
`[%clhp p=twig q=twig]`, which accepts two twigs with which it produces a
tuple. In this case, both elements are atom literals and are parsed into the twig
`[%dtzy p=term q=@]`, which produces atomic constants.
There are several valid twig syntaxes in hoon, which are covered below.
###Tall Form
For all multiline expressions, Tall form is used. To avoid the visual problems
that deep expression trees cause in other functional languages (namely excessive
parentheses and the tendencey for code to drift horizontally off the right side
of the screen), hoon employs neither multiline braces nor significant
indentation. Instead, when a twig, such as the `[%clhp p=twig q=twig]` from
above is parsed, the parser then knows that exactly two twigs are to follow. In
Tall Form, twigs are separated by at least two spaces (a newline is equivalent
to two spaces).
These rules do not prevent the aforementioned problem horizontal drift:
```
?: |
47
?: |
52
?: |
7
20
```
**Note:** `?:` initiaties an _if-then_else_ twig. `|` is the loobean false.
To avoid this problem, the official convention prescribes a backstep pattern, which
preserves indentation level in the common case:
```
?: |
47
?: |
52
?: |
7
20
```
Notice that the first child is placed the furthest horizontal distance away
from its parent rune. Each of the subsequent children is outdented, such
that the last child (a similarly formatted twig) is vertically aligned with its parent.
However, this convention does not always prevent horizontal drift. For example,
there are many cases when the last twig is not the heaviest:
```
?: &
?: |
52
?: |
7
20
47
```
To handle cases like this, there exist several (synthetic runes)[lexicon/#rune_types]
that invert the argument order of common runes. For example, where `?:` is _if-then_, `?.` is _unless_:
```
?. &
47
?: |
52
?: |
7
20
```
####Closing Unbounded Twigs####
Some runes accept a list of an arbitrary number of children,
which is closed by a `==` (pronounced "stet"). By convention, the children
appear in an indented block, and for most runes, the `==` is aligned vertically with
its parent.
```
:*
1
2
3
==
:: [1 2 3]
```
Some runes, such as `;~`, [%smsg p=twig q=tusk]`, have both `twig` and `tusk`
(list of twigs) children:
```
;~ plug
ace
ace
==
```
####Kingside and Queenside####
Runes such as %= accept associative lists. There exist two conventions:
Kingside, where the key-value pairs are (or at least start) on the same line:
```
%= res
key1 val
key2 val2
==
```
And queenside, where the keys lie indented on the line above their respective
values:
```
%= res
key
twig-producing-val
key2
=+ a=2
[a 3]
==
```
The latter is useful when the keys and/or values are heavy.
####Reference[#tall-reference]
For specific rune syntaxes, see the [lexicon]().
The regular form parser, `++norm:vast`, can also be helpful: for example, %dtls
(increment) is parsed by
```
++ norm :: rune regular form
|= tol=?
=< %- stew
^. stet ^. limo
:~ :- '|'
:: ......code skipped.......
```
```
:- '.'
;~ pfix dot
%- stew
^. stet ^. limo
:~ ['+' (rune lus %dtls expa)]
```
```
++ expa |.(loaf) :: one twig
```
```
++ loaf ?:(tol tall wide) :: hoon, current width
```
###Wide
Wide form is a more compact and visually structured twig syntax, where an
expression can be no longer than one line. Notably, children are enclosed by
parentheses, and twigs are separated by single spaces:
```
?:((gth 1 2) %abort-abort %correct)
```
While Tall Form expressions can contain wide form expressions, the converse is
invalid hoon:
```
?: .=(a b)
0
1
:: succeeds
?:(.= a
b 0 1)
:: fails
```
There are two other notable differences from Tall Form: `==` is no longer used,
having been made redundant by closing parentheses; and, the syntax for
associative lists gains a `','` between pairs:
```
?-(a 0 %even, 1 %odd)
:: vs.
?- a
0 %even
1 %odd
==
```
####Reference
For specific rune syntaxes, see the [lexicon]().
The regular form parser, `++norm:vast`, can also be [helpful.](#tall-reference).
###Irregular
For many common runes, there exist special wide forms. For example,
the rune `:*`, which was used as an example in the tall section[linkToExample](),
is more frequently employed in its irregular form, a list of twigs surrounded
by brackets:
```
~zod/try=> [1 2]
[1 2]
~zod/try=> (ream '[1 2]')
[%cltr p=~[[%dtzy p=%ud q=1] [%dtzy p=%ud q=2]]]
```
A comprehensive list of all of these irregular forms can be found in the
[lexicon](lexicon/irregular-section)i, and the irregular form parser
`++scat:vast`.
###Tile
Some runes accept [tiles](lexicon) instead of/in addition to twigs as children.
These runes switch us into tile syntax:
Tiles have a similar syntax to twigs when:
Examples
And different
1.The irregular forms for `^=` and `:*`, infix `=` and surrounding `[]`
repsectively, now denote `$=` and `$:`
2.Primitive types `'@'`, `'^'`, and `'*'` represent their tiles.
3.Number literals represent their cubes, and are along with actual cubes
interpreted as their associated clams.
Tile syntax defaults to parsing a twig, and using the result as a
[clam](lexicon).
```
~zod/try=> *a=@ud
a=0
```
`a=@ud` is a `tile`, representing a face _a_ wrapped around an atom of [odor]()
_unsigned-decimal_.
Tile syntax is similar to that of twigs, except that `'@'`, `'^'`, and `'*'`
represent the [clams](lexicon) for the `atom`, `cell`, and `noun` primitive types,
and numeric literals become cubed. When a twig is encountered, its product is
used as a clam directly:
```
|= a=(list char)
[' ' a]
```
See [lexicon tiles[, parser `++noil:vast`
Wings
-----
Items in the subject are accesed with wings
```
> =<(a.b.+.c c=[4 [b=[a=1 2] b=[a=6 7]])
6
```
Limbs and axes, separated by dots, inner to outer.
Limbs are terms, axes (have a few syntaces)[lexicon axis syntax]
See:**
Nouns
-----
Most common rune is the virtual %dtzy, atomic nock 1
```
>(ream '42')
[%dtzy p=%ud q=42]
```
Its counterpart %dtzz does cubes
```
>(ream '%42')
[%dtzz p=%ud q=42]
```
See [lexicon atoms]
Tapes
###Interpolation
```
"This is an {(weld "inter" (trip %polate))}d string"
Dependencies (%ford)
--------------------
While !^ provides rudimentary %clay includes...
See: ford.hoon
Templating (++sail)
-------------------
Start with `;term`
```
;html
;head:title:"Hello"
;body
;p
; Text with some ;{b "bolded"}
; and some -{(weld "inter" "polate"}d
==
==
==
```
See:
Generates `manx`, xml nouns.
[lexicon template lang], parser `++sail:vast`.
.= ~[1 2 3 4 5 6]
:~ 1
2
3
4
5
6
==
:* 1 3 4 ==
:- 1 :- 3 4
1^3^4
[1 3 4]
':-' is constructing a tuple of two elements, constants...
```
~zod/try=>(mul 4 (add 2 3))
20
~zod/try=> (ream '(mul 4 (add 2 3))')
[ %cnhp
p=[%cnzz p=~[%mul]]
q
~[
[%dtzy p=%ud q=4]
[%cnhp p=[%cnzz p=~[%add]] q=~[[%dtzy p=%ud q=2] [%dtzy p=%ud q=3]]]
]
]
```
A twig is a (frond)[lexicon frond] composed of a rune and one or
more children; here, we see `%cnhp %cnzz %dtzy`, which are defined
in `++twig` as:
```
++ twig $& [p=twig q=twig] ::
$%
[%cnhp p=twig q=tusk] :: slam p w/ sample q
[%cnzz p=wing] :: pulls p
==
++ tusk (list twig) ::
```
Skipping the particulars, '%-' (slams gates)[lexicon gates], %cnzz is a virtual
rune that (pulls arms)[lexicon cores], and %dtzy is a virtual rune that
<makes constants>; the resulting twig representing fetching `add` and `mul`,
and applying them to 2, 3, and 4.
```
++ twig $% ::
[%$ p=axis] :: simple leg
:: ::
[%bccb p=tile] :: bunt a tile
:: etc.
==
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18,8 +18,6 @@
- chapter 2c, simple noun surgery
### Chapters 2a through 2eZ refactoring and second-pass.
### Dulin and Henry.
- section 2cA, bit surgery
- section 2cB, bit logic
@ -40,8 +38,6 @@
- chapter 2e, miscellaneous libs
### Anton - virtualization
- section 2eA, packing
- section 2eB, parsing (tracing)
- section 2eC, parsing (custom rules)
@ -63,7 +59,6 @@
- section 2eY, SHA-2564 (move me)
- section 2eZ, OLD rendering (kill me)
### Chapter 2f is Philip.
- chapter 2f, Hoon proper
@ -78,20 +73,18 @@
- chapter 3b, Arvo libraries, zuse
### Anton - All of Chapter 3b except 3bE and 3bG.
- section 3bA, lite number theory
- section 3bB, cryptosuites
- section 3bC, UTC
- section 3bD, JSON and XML
- section 3bE, tree sync
- section 3bF, names etc
- section 3bG, Arvo models
- section 3bF!, filesystem interface
- section 3bG!, URL handling
- section 3bH!, names etc
- section 3bI!, Arvo models
- Volume 4, Arvo vanes
### Chapter 4a, %ames, is Philip. Possibly %ford nad %gall as well.
- chapter 4a, ames, networking
- section 4aA, structures
@ -114,8 +107,6 @@
- section 4cB, filesystem logic
- section 4cC, filesystem vane
### Anton Chapter 4d
- chapter 4d, dill: terminal handling
- chapter 4e, eyre: http servant

View File

@ -1,481 +0,0 @@
Ames
====
Ames is our networking protocol.
data models
-----------
###`++fort`, formal state
```
++ fort :: formal state
$: %0 :: version
gad=duct :: client interface
hop=@da :: network boot date
ton=town :: security
zac=(map ship corn) :: flows by server
== ::
```
This is the state of our vane. Anything that must be remembered between
calls to ames must be stored in this state.
`%0` is the version of the ames state model itself. If the data model `++fort`
changes, then this number needs to be incremented, and an adapter must be
written to upgrade the old state into the new state. Note that this is the
version number of the model itself, not the contents. When the data changes,
there is of course no need to change this.
`gad` is a `duct` over which we send `%send` cards to unix. This card is
initialized when unix sends a `%barn` card as vere starts up. Vere treats this
duct specially -- don't send anything weird over it.
`hop` is the network boot date. This is set when the `%kick` card is sent by
vere on start up.
`ton` is a `++town`, where we store all of our security/encryption state. Note
that this is shared across all ships on a pier.
`zac` is a map of ships to `++corn`. This stores all the per-ship state. The
keys to this map are the ships on the current pier.
###`++town`, all security state
```
++ town :: all security state
$: lit=@ud :: imperial modulus
any=@ :: entropy
urb=(map ship sufi) :: all keys and routes
fak=? ::
== ::
```
This is the security state of our pier.
`lit` is unused.
`any` is 256 bits of entropy. This entropy is used and updated in exactly two
places: when we send a `%junk` card, and when we generate a new symmetric key
in `++griz:lax:as:go`. When it is updated, it is updated by a SHA-256 hash of
the current time and the old value of the entropy.
`urb` is a map of ships to `++sufi`. This is where we store all the per-ship
state for the pier. The keys to this map are the ships on the current pier.
`fak` is true if we are on a fake network. This disables certain security
checks so that anyone may run a fake `~zod`. This is used only for development.
To use, run vere with the `-F` option (and the `-I ~zod` option for a fake
`~zod`).
###`++sufi`, domestic host
```
++ sufi :: domestic host
$: hoy=(list ship) :: hierarchy
val=wund :: private keys
law=will :: server will
seh=(map hand ,[p=ship q=@da]) :: key cache
hoc=(map ship dore) :: neighborhood
== ::
```
This is the security state of a domestic server.
`hoy` is a list of the ships directly above us in the hierarchy of ships. For
example, for `~hoclur-bicrel`, this would be `~tasruc` and `~tug`. See
`++sein`.
`val` is a list of our private keys.
`law` is our certificate, which is a list of the XXX
`seh`
`hoc` is a map of ships to `++dore`. The stores all the security informatoin
about foreign ships. The keys to this map are the neighbors (ships we have
been in contact with) of this domestic server.
###`++wund`, private keys
```
++ wund (list ,[p=life q=ring r=acru]) :: mace in action
```
This is a list of our own private keys, indexed by life. The key itself is
the `++ring`, and the `++acru` is the encryption engine. We generate the
`++acru` from the private key by calling `++weur`. Thus, we can at any time
regenerate our `++wund` from a `++mace`. The current crypto is at the head of
the list and can be accessed with
`++sen:as:go`.
###`++ring`, private key
```
++ ring ,@ :: private key
```
This is a private key. The first byte is reserved to identify the type of
cryptography. Lower-case means public key, upper-case means public key, and
the letter identifies which `++acru` to use.
###`++pass`, public key
```
++ pass ,@ :: public key
```
This is a public key. The first byte is reserved to identify the type of
cryptography. Lower-case means public key, upper-case means public key, and
the letter identifies which `++acru` to use.
###`++mace`, private secrets
```
++ mace (list ,[p=life q=ring]) :: private secrets
```
This is a list of the our private keys, indexed by life. From this we can
generate a `++wund` for actual use.
###`++skin`, encoding stem
```
++ skin ?(%none %open %fast %full) :: encoding stem
```
This defines the type of encryption used for each message. `%none` refers
to messages sent in the clear, `%open` refers to signed messages, `%full`
refers to sealed messages, and `%fast` refers to symmetrically encrypted
messages. See `++acru` for details.
###`++acru`, asymmetric cryptosuite
```
++ acru :: asym cryptosuite
$_ ^? |% :: opaque object
++ as ^? :: asym ops
|% ++ seal |=([a=pass b=@ c=@] _@) :: encrypt to a
++ sign |=([a=@ b=@] _@) :: certify as us
++ sure |=([a=@ b=@] *(unit ,@)) :: authenticate from us
++ tear |= [a=pass b=@] :: accept from a
*(unit ,[p=@ q=@]) ::
-- ::
++ de |+([a=@ b=@] *(unit ,@)) :: symmetric de, soft
++ dy |+([a=@ b=@] _@) :: symmetric de, hard
++ en |+([a=@ b=@] _@) :: symmetric en
++ ex ^? :: export
|% ++ fig _@uvH :: fingerprint
++ pac _@uvG :: default passcode
++ pub *pass :: public key
++ sec *ring :: private key
--
++ nu ^? :: reconstructors
|% ++ pit |=([a=@ b=@] ^?(..nu)) :: from [width seed]
++ nol |=(a=@ ^?(..nu)) :: from naked ring
++ com |=(a=@ ^?(..nu)) :: from naked pass
--
--
```
This is an opaque interface for a general asymmetric cryptosuite. Any form
of asymmetric cryptography can be dropped in to be used instead of the default.
Right now, there are two cryptosuites, `++crua`, which is your standard RSA,
and `++crub`, which is elliptic curve crypto but is mostly stubbed out at the
moment.
####`++as:acru`, asymmetric operations
```
++ as ^? :: asym ops
|% ++ seal |=([a=pass b=@ c=@] _@) :: encrypt to a
++ sign |=([a=@ b=@] _@) :: certify as us
++ sure |=([a=@ b=@] *(unit ,@)) :: authenticate from us
++ tear |= [a=pass b=@] :: accept from a
*(unit ,[p=@ q=@]) ::
-- ::
```
This is the core that defines the standard asymmetric cryptography
operations.
`++seal:as:acru` allows us to send a message encrypted with someone's public
key so that only they may read it. If Alice seals a message with Bob's public
key, then she can be sure that Bob is the only one who can read it. This is
associated with the `++skin` `%full`.
`++sign:as:acru` allows us to sign a message with our private key so that
others can verify that we sent the message. If Alice signs a message with her
private key, then Bob can verify with her public key that it was indeed Alice
who sent it. This is associated with the `++skin` `%open`.
`++sure:as:acru` is the dual to `++sign:as:acru`. It allows us to verify that
a message we have received is indeed from the claimed sender. If Alice sends a
message with her private key, then Bob can use this arm to verify that it was
indeed Alice who sent it. This is associated with the `++skin` `%open`.
`++tear:as:acru` is the dual to `++seal:as:acru`. It allows us to read a
message that we can be sure is only read by us. If Alice seals a message with
Bob's public key, then Bob can use this arm to read it. This is associated
with the `++skin` `%full`.
####`++de:acru`, `++dy:acru`, and `++en:acru`, symmetric encryption/decryption
```
++ de |+([a=@ b=@] *(unit ,@)) :: symmetric de, soft
++ dy |+([a=@ b=@] _@) :: symmetric de, hard
++ en |+([a=@ b=@] _@) :: symmetric en
```
Symmetric encryption is associated with the `++skin` `%fast`.
`++de:acru` decrypts a message with a symmetric key, returning `~` on failure
and `[~ u=data]` on success.
`++dy:acru` decrypts a message with a symmetric key, crashing on failure. This
should almost always be defined as, and should always be semantically
equivalent to, `(need (de a b))`.
`++en:acru` encrypts a message with a symmetric key.
####`++ex:acru`, exporting data
```
++ ex ^? :: export
|% ++ fig _@uvH :: fingerprint
++ pac _@uvG :: default passcode
++ pub *pass :: public key
++ sec *ring :: private key
--
```
`++fig:ex:acru` is our fingerprint, usually a hash of our public key. This is
used, for example, in `++zeno`, where every carrier owner's fingerprint is
stored so that we can ensure that carriers are indeed owned by their owners
`++pac:ex:acru` is our default passcode, which is unused at present.
`++pub:ex:acru` is the `++pass` form of our public key.
`++sec:ex:acru` is the `++ring` form of our private key.
####`++nu:acru`, reconstructors
```
++ nu ^? :: reconstructors
|% ++ pit |=([a=@ b=@] ^?(..nu)) :: from [width seed]
++ nol |=(a=@ ^?(..nu)) :: from naked ring
++ com |=(a=@ ^?(..nu)) :: from naked pass
--
```
These arms allow us to reconstruct a `++acru` from basic data.
`++pit:nu:acru` constructs a `++acru` from the width of our intended key and
seed entropy. This is usually used in the initial construction of the
`++acru`.
`++nol:nu:acru` constructs a `++acru` from a "naked ring", meaning a `++ring`
without the initial byte identifying the type of crypto. There is often a
helper arm that that wraps this; see `++weur` for `++crua` and `++wear` for
`++crub`.
`++com:nu:acru` constructs a `++acru` from a "naked pass", meaning a `++ring`
without the initial byte identifying the type of crypto. There is often a
helper arm that that wraps this; see `++haul` for `++crua` and `++hail` for
`++crub`.
###`++will`, certificate
```
++ will (list deed) :: certificate
```
This is a list of deeds associated with the current ship. There should be
an item in this list for every ship from this point up in the hierarchy times
the number of lives that each ship has had. For example, ~hoclur-bicrel may
have a will with three items: one for itself, one for ~tasruc (who issued
~hoclur-bicrel's deed) and one for ~tug (who issued ~tasruc's deed).
###`++deed`, identity
```
++ deed ,[p=@ q=step r=?] :: sig, stage, fake?
```
`p` is the signature of a particular deed, which is a signed copy of `q`.
`q` is the stage in the identity.
`r` is true if we're working on a fake network, where we don't check that the
carrier fingerprints are correct. This allows us to create fake networks for
development without interfering with the real network.
###`++step`, identity stage
```
++ step ,[p=bray q=gens r=pass] :: identity stage
```
This is a single stage in our identity. Thus, this is specific to a single
life in a single ship. Everything in here may change between lives.
`p`
`q`
`r` is the public key for this stage in the identity.
###`++bray`
```
++ bray ,[p=life q=(unit life) r=ship s=@da] :: our parent us now
```
XXX
###`++gens`, general identity
```
++ gens ,[p=lang q=gcos] :: general identity
```
`p` is the IETF language code for the preferred language of this identity.
This is unused at the moment, but in the future text should be localized based
on this.
`q` is the description of the ship.
###`++gcos`, identity description
```
++ gcos :: id description
$% [%czar ~] :: 8-bit ship
[%duke p=what] :: 32-bit ship
[%earl p=@t] :: 64-bit ship
[%king p=@t] :: 16-bit ship
[%pawn p=(unit ,@t)] :: 128-bit ship
== ::
```
This is the description of the identity of a ship. Most types of identity have
a `@t` field, which is their human-readable name. The identity of a `%duke` is
more involved.
A `%czar`, a carrier, is a ship with an 8-bit address. Thus, there are only
256 carriers. These are at the top of the namespace hierarchy, and the
fingerprint of each carrier is stored in `++zeno`. These are the "senators" of
Urbit.
A `%king`, a cruiser, is a ship with a 16-bit address. Thus, there are 65,536
cruisers. Each carrier may issue 256 cruisers. These are the infrastructure
of Urbit.
A `%duke`, a destroyer, is a ship with a 32-bit address. Thus, there are
4,294,967,296 destroyers. Each cruiser may issue 65,536 cruisers. These are
the individuals of Urbit.
A `%earl`, a yacht, is a ship with a 64-bit address. Thus, there are
18,446,744,073,709,551,616 yachts. Each destroyer may issue 4,294,967,296
yachts. These are the devices of Urbit.
A `%pawn`, a submarine, is a ship with a 128-bit address. Thus, there are a
lot of submarines. The chance of random name collision is negligible, so
submarines are not issued by any ship. They must simply assert their presence,
and they are all considered children of ~zod. This is the underworld of Urbit,
where anonymity reigns supreme.
###`++what`, logical destroyer identity
```
++ what :: logical identity
$% [%anon ~] :: anonymous
[%lady p=whom] :: female person ()
[%lord p=whom] :: male person []
[%punk p=sect q=@t] :: opaque handle ""
== ::
```
This is the logical identity of a destroyer.
A `%anon` is a completely anonymous destroyer. The difference between this and
a submarine is that a submarine is ephemeral while a `%anon` destroyer is not.
Thus, we may not know who ~hoclur-bicrel is, but we do know that it's always
the same person.
A `%lady` is a female person. The name used here should be a real name.
A `%lord` is a male person. The name used here should be a real name.
A `%punk` is a person who is identified only by a handle.
###`++whom`, real person
```
++ whom ,[p=@ud q=govt r=sect s=name] :: year/govt/id
```
Ths is the information associated with a real person. It is mostly information
that could be observed with the briefest of interactions.
`p` is the birth year.
`q` is the location of a user, usually of the form "country/zip".
`r` is the sect of the user.
`s` is the real name of the person.
###`++govt`
```
++ govt path :: country/postcode
```
This is the location of the user, usually of the form "country/zip".
###`++sect`
```
++ sect ?(%black %blue %red %orange %white) :: banner
```
XXX
###`++name`
```
++ name ,[p=@t q=(unit ,@t) r=(unit ,@t) s=@t] :: first mid/nick last
```
This is the given name, possible middle name/initial, possible nickname, and
surname of a user.
packet format
-------------
`++go`, PKI engine
------------------
###`++as`, per server
####`++born`, register user
#####`++lax`, per client
`++pu`, packet pump
-------------------
`++am`, protocol engine
-----------------------
###`++um`, per server
####`++ho`, per friend
#####`++la`, per packet
protocol vane
-------------

View File

@ -1,484 +0,0 @@
Clay
====
Clay is our filesystem.
data models
-----------
###`++raft`, formal state
```
++ raft :: filesystem
$: fat=(map ship room) :: domestic
hoy=(map ship rung) :: foreign
ran=rang :: hashes
== ::
```
This is the state of our vane. Anything that must be remembered between calls
to clay must be stored in this state.
`fat` is the set of domestic servers. This stores all the information that is
specfic to a particular ship on this pier. The keys to this map are the ships
on the current pier.
`hoy` is the set of foreign servers that we know anything about. This stores
all the information that is specific to a particular foreign ship. The keys to
this map are all the ships whose filesystems we have attempted to access
through clay.
`ran` is the store of all commits and deltas, keyed by hash. The is where all
the "real" data we know is stored; the rest is "just bookkeeping".
###`++room`, filesystem per domestic ship
```
++ room :: fs per ship
$: hun=duct :: terminal duct
hez=(unit duct) :: sync duch
dos=(map desk dojo) :: native desk
== ::
```
This is the representation of the filesystem of a ship on our pier.
`hun` is the duct that we use to send messages to dill to display notifications
of filesystem changes. Only `%note` gifts should be produced along this duct.
This is set by the `%init` kiss.
`hez`, if present, is the duct we use to send sync messages to unix so that
they end up in the pier unix directory. Only `%ergo` gifts should be producd
along this duct. This is set by `%into` and `%invo` gifts.
`dos` is a well-known operating system released in 1981. It is also the set of
desks on this ship, mapped to their data.
###`++desk`, filesystem branch
```
++ desk ,@tas :: ship desk case spur
```
This is the name of a branch of the filesystem. The default desks are "arvo",
"main", and "try". More may be created by simply referencing them. Desks have
independent histories and states, and they may be merged into each other.
###`++dojo`, domestic desk state
```
++ dojo ,[p=cult q=dome] :: domestic desk state
```
This is the all the data that is specific to a particular desk on a domestic
ship. `p` is the set of subscribers to this desk and `q` is the data in the
desk.
###`++cult`, subscriptions
```
++ cult (map duct rave) :: subscriptions
```
This is the set of subscriptions to a particular desk. The keys are the ducts
from where the subscriptions requests came. The results will be produced along
these ducts. The values are a description of the requested information.
###`++rave`, general subscription request
```
++ rave :: general request
$% [& p=mood] :: single request
[| p=moat] :: change range
== ::
```
This represents a subscription request for a desk. The request can be for
either a single item in the desk or else for a range of changes on the desk.
###`++mood`, single subscription request
```
++ mood ,[p=care q=case r=path] :: request in desk
```
This represents a request for the state of the desk at a particular commit,
specfied by `q`. `p` specifies what kind of information is desired, and `r`
specifies the path we are requesting.
###`++moat`, range subscription request
```
++ moat ,[p=case q=case] :: change range
```
This represents a request for all changes between `p` and `q`. Note that there
is currently no way to request to be notified only on changes to particular
paths in the filesystem. You must subscribe to the entire desk.
###`++care`, clay submode
```
++ care ?(%u %v %w %x %y %z) :: clay submode
```
This specifies what type of information is requested in a subscription or a
scry.
`%u` requests the `++rang` at the current moment. Because this information is
not stored for any moment other than the present, we crash if the `++case` is
not a `%da` for now.
`%v` requests the `++dome` at the specified commit.
`%w` requests the current revsion number of the desk.
`%x` requests the file at a specified path at the specified commit. If there
is no node at that path or if the node has no contents (that is, if `q:ankh` is
null), then this produces null.
`%y` requests a `++arch` of the specfied commit at the specified path.
`%z` requests the `++ankh` of the specified commit at the specfied path.
###`++arch`, shallow filesystem node
```
++ arch ,[p=@uvI q=(unit ,@uvI) r=(map ,@ta ,~)] :: fundamental node
```
This is analogous to `++ankh` except that the we have neither our contents nor
the ankhs of our children. The other fields are exactly the same, so `p` is a
hash of the associated ankh, `u.q`, if it exists, is a hash of the contents of
this node, and the keys of `r` are the names of our children. `r` is a map to
null rather than a set so that the ordering of the map will be equivalent to
that of `r:ankh`, allowing efficient conversion.
###`++case`, specifying a commit
```
++ case :: ship desk case spur
$% [%da p=@da] :: date
[%tas p=@tas] :: label
[%ud p=@ud] :: number
== ::
```
A commit can be referred to in three ways: `%da` refers to the commit that was
at the head on date `p`, `%tas` refers to the commit labeled `p`, and `%ud`
refers to the commit numbered `p`. Note that since these all can be reduced
down to a `%ud`, only numbered commits may be referenced with a `++case`.
###`++dome`, desk data
```
++ dome :: project state
$: ang=agon :: pedigree
ank=ankh :: state
let=@ud :: top id
hit=(map ,@ud tako) :: changes by id
lab=(map ,@tas ,@ud) :: labels
== ::
```
This is the data that is actually stored in a desk.
`ang` is unused and should be removed.
`ank` is the current state of the desk. Thus, it is the state of the
filesystem at revison `let`. The head of a desk is always a numbered commit.
`let` is the number of the most recently numbered commit. This is also the
total number of numbered commits.
`hit` is a map of numerical ids to hashes of commits. These hashes are mapped
into their associated commits in `hut:rang`. In general, the keys of this map
are exactly the numbers from 1 to `let`, with no gaps. Of course, when there
are no numbered commits, `let` is 0, so `hit` is null. Additionally, each of
the commits is an ancestor of every commit numbered greater than this one.
Thus, each is a descendant of every commit numbered less than this one. Since
it is true that the date in each commit (`t:yaki`) is no earlier than that of
each of its parents, the numbered commits are totally ordered in the same way
by both pedigree and date. Of course, not every commit is numbered. If that
sounds too complicated to you, don't worry about it. It basically behaves
exactly as you would expect.
`lab` is a map of textual labels to numbered commits. Note that labels can
only be applied to numbered commits. Labels must be unique across a desk.
###`++ankh`, filesystem node
```
++ ankh :: fs node (new)
$: p=cash :: recursive hash
q=(unit ,[p=cash q=*]) :: file
r=(map ,@ta ankh) :: folders
== ::
```
This is a single node in the filesystem. This may be file or a directory or
both. In earth filesystems, a node is a file xor a directory. On mars, we're
inclusive, so a node is a file ior a directory.
`p` is a recursive hash that depends on the contents of the this file or
directory and on any children.
`q` is the contents of this file, if any. `p.q` is a hash of the contents
while `q.q` is the data itself.
`r` is the set of children of this node. In the case of a pure file, this is
empty. The keys are the names of the children and the values are, recursively,
the nodes themselves.
###`++cash`, ankh hash
```
++ cash ,@uvH :: ankh hash
```
This is a 128-bit hash of an ankh. These are mostly stored within ankhs
themselves, and they are used to check for changes in possibly-deep
hierarchies.
###`++rung`, filesystem per neighbor ship
```
++ rung $: rus=(map desk rede) :: neighbor desks
== ::
```
This is the filesystem of a neighbor ship. The keys to this map are all the
desks we know about on their ship.
###`++rede`, desk state
```
++ rede :: universal project
$: lim=@da :: complete to
qyx=cult :: subscribers
ref=(unit rind) :: outgoing requests
dom=dome :: revision state
== ::
```
This is our knowledge of the state of a desk, either foreign or domestic.
`lim` is the date of the last full update. We only respond to requests for
stuff before this time.
`qyx` is the list of subscribers to this desk. For domestic desks, this is
simply `p:dojo`, all subscribers to the desk, while in foreign desks this is
all the subscribers from our ship to the foreign desk.
`ref` is the request manager for the desk.
`dom` is the actual data in the desk.
###`++rind`, request manager
```
++ rind :: request manager
$: nix=@ud :: request index
bom=(map ,@ud ,[p=duct q=rave]) :: outstanding
fod=(map duct ,@ud) :: current requests
haw=(map mood (unit)) :: simple cache
== ::
```
This is the request manager for a desk.
`nix` is one more than the index of the most recent request. Thus, it is the
next available request number.
`bom` is the set of outstanding requests. The keys of this map are some subset
of the numbers between 0 and one less than `nix`. The members of the map are
exactly those requests that have not yet been fully satisfied.
`fod` is the same set as `bom`, but from a different perspective. In
particular, the values of `fod` are the same as the values of `bom`, and the
`p` out of the values of `bom` are the same as the keys of `fod`. Thus, we can
map ducts to their associated request number and `++rave`, and we can map
numbers to their associated duct and `++rave`.
`haw` is a map from simple requests to their values. This acts as a cache for
requests that have already been made. Thus, the second request for a
particular `++mood` is nearly instantaneous.
###`++rang`, data store
```
++ rang $: hut=(map tako yaki) ::
lat=(map lobe blob) ::
== ::
```
This is a set of data keyed by hash. Thus, this is where the "real" data is
stored, but it is only meaningful if we know the hash of what we're looking
for.
`hut` is a map from hashes to commits. We often get the hashes from
`hit:dome`, which keys them by logical id. Not every commit has an id.
`lat` is a map from hashes to the actual data. We often get the hashes from a
`++yaki`, a commit, which references this map to get the data. There is no
`++blob` in any `++yaki`. They are only accessible through this map.
###`++tako`, commit reference
```
++ tako ,@ :: yaki ref
```
This is a hash of a `++yaki`, a commit. These are most notably used as the
keys in `hut:rang`, where they are associated with the actual `++yaki`, and as
the values in `hit:dome`, where sequential ids are associated with these.
###`++yaki`, commit
```
++ yaki ,[p=(list tako) q=(map path lobe) r=tako t=@da] :: commit
```
This is a single commit.
`p` is a list of the hashes of the parents of this commit. In most cases, this
will be a single commit, but in a merge there may be more parents. In theory,
there may be an arbitrary number of parents, but in practice merges have
exactly two parents. This may change in the future. For commit 1, there is no
parent.
`q` is a map of the paths on a desk to the data at that location. If you
understand what a `++lobe` and a `++blob` is, then the type signature here
tells the whole story.
`r` is the hash associated with this commit.
`t` is the date at which this commit was made.
###`++lobe`, data reference
```
++ lobe ,@ :: blob ref
```
This is a hash of a `++blob`. These are most notably used in `lat:rang`, where
they are associated with the actual `++blob`, and as the values in `q:yaki`,
where paths are associated with their data in a commit.
###`++blob`, data
```
++ blob $% [%delta p=lobe q=lobe r=udon] :: delta on q
[%direct p=lobe q=* r=umph] ::
[%indirect p=lobe q=* r=udon s=lobe] ::
== ::
```
This is a node of data. In every case, `p` is the hash of the blob.
`%delta` is the case where we define the data by a delta on other data. In
practice, the other data is always the previous commit, but nothing depends on
this. `q` is the hash of the parent blob, and `r` is the delta.
`%direct` is the case where we simply have the data directly. `q` is the data
itself, and `r` is any preprocessing instructions. These almost always come
from the creation of a file.
`%indirect` is both of the preceding cases at once. `q` is the direct data,
`r` is the delta, and `s` is the parent blob. It should always be the case
that applying `r` to `s` gives the same data as `q` directly (with the
prepreprocessor instructions in `p.r`). This exists purely for performance
reasons. This is unused, at the moment, but in general these should be created
when there are a long line of changes so that we do not have to traverse the
delta chain back to the creation of the file.
###`++udon`, abstract delta
```
++ udon :: abstract delta
$: p=umph :: preprocessor
$= q :: patch
$% [%a p=* q=*] :: trivial replace
[%b p=udal] :: atomic indel
[%c p=(urge)] :: list indel
[%d p=upas q=upas] :: tree edit
== ::
== ::
```
This is an abstract change to a file. This is a superset of what would
normally be called diffs. Diffs usually refer to changes in lines of text
while we have the ability to do more interesting deltas on arbitrary data
structures.
`p` is any preprocessor instructions.
`%a` refers to the trival delta of a complete replace of old data with new
data.
`%b` refers to changes in an opaque atom on the block level. This has very
limited usefulness, and is not used at the moment.
`%c` refers to changes in a list of data. This is often lines of text, which
is your classic diff. We, however, will work on any list of data.
`%d` refers to changes in a tree of data. This is general enough to describe
changes to any hoon noun, but often more special-purpose delta should be
created for different content types. This is not used at the moment, and may
in fact be unimplemented.
###`++urge`, list change
```
++ urge |*(a=_,* (list (unce a))) :: list change
```
This is a parametrized type for list changes. For example, `(urge ,@t)` is a
list change for lines of text.
###`++unce`, change part of a list.
```
++ unce |* a=_,* :: change part
$% [%& p=@ud] :: skip[copy]
[%| p=(list a) q=(list a)] :: p -> q[chunk]
== ::
```
This is a single change in a list of elements of type `a`. For example, `(unce ,@t)` is
a single change in a lines of text.
`%&` means the next `p` lines are unchanged.
`%|` means the lines `p` have changed to `q`.
###`++umph`, preprocessing information
```
++ umph :: change filter
$| $? %a :: no filter
%b :: jamfile
%c :: LF text
== ::
$% [%d p=@ud] :: blocklist
== ::
```
This space intentionally left undocumented. This stuff will change once we get
a well-typed clay.
###`++upas`, tree change
```
++ upas :: tree change (%d)
$& [p=upas q=upas] :: cell
$% [%0 p=axis] :: copy old
[%1 p=*] :: insert new
[%2 p=axis q=udon] :: mutate!
== ::
```
This space intentionally left undocumented. This stuff is not known to work,
and will likely change when we get a well-typed clay. Also, this is not a
complicated type; it is not difficult to work out the meaning.

View File

@ -0,0 +1,472 @@
Structures
==========
The fundamental hoon structure used to generate XML is a manx. A manx is
composed of a `marx` and a `marl`, representing an XML node:
```
++ manx ,[g=marx c=marl] :: XML node
++ marx ,[n=mane a=mart] :: XML tag
++ mane $|(@tas [@tas @tas]) :: XML name/space
```
Names, manes
------------
The most basic `manx` consists of an XML node name, called a `mane`, an empty
`marl`, and an empty `mart`:
```
~zod/try=> ;div
[[%div ~] ~]
~zod/try=> ;namespaced_div;
[[[%namespaced %div] ~] ~]
```
This represents an XML node, an opening and a closing tag with no attributes
nor children:
```
~zod/try=> (xmlt | ;div; "")
"<div></div>"
~zod/try=> (xmlt | ;namespaced_div; ~)
"<namespaced:div></namespaced:div>"
```
**Note**: `++xmlt` takes three arguments: a loobean determening whether text should be
xml-escaped, the `manx` to be rendered, and a tape onto which to append the
results. `<script>` and `<style>` tags are unescaped by default. For more
information, see the XML documentation in Volume 3, section 3bD.
However, `%gall` applications operate on nouns of the type `[%hymn manx]`,
making direct calls to `++xmlt` rare.
Attributes and child nodes
--------------------------
To represent XML nodes with children and/or attributes, `marl` and `mart` are
used respectively:
```
++ marl (list manx) :: XML node list
++ mart (list ,[n=mane v=tape]) :: XML attributes
```
Each child node is simply another manx, and attributes are pairs of key `mane`
to value `tape`. `marl` and `mart` are lists of these respective values.
Wide Form
=========
Children
--------
The XML templating syntax begins with a `';'` followed by a `term`.
In wide form, a child node is appended with a `':'`:
```
~zod/try=> ;div:p;
[[%div ~] [[%p ~] ~] ~]
~zod/try=> :poxo ;div:p;
<div><p></p></div>
```
**Note:**`/~zod/try/1/bin/poxo/hoon` is a shell script that applies `(curr (cury xmlt |) ~)`
to a `manx`, rendering it as a `tape`.
Multiple nodes can be represented inside of parentheses, separated by single spaces:
```
~zod/try=> ;div:(p ul:(li li))
[[%div ~] [[%p ~] ~] [[%ul ~] [[%li ~] ~] [[%li ~] ~] ~] ~]
~zod/try=> :poxo ;div:(p ul:(li li))
<div><p></p><ul><li></li><li></li></ul></div>
```
Tags must always be closed. In wide form, this is done either with a `';'` if the
node contains no children, or with a `':'`, followed by one or more children.
In wide form, terminating `';'`s are implied: `;div:(p p p)` is equivalent to
`;div:(p; p; p;)`.
However, in instances where there are a chain of nodes where each node
contains only one child, as with `;div:p;`, it is good practice to include the
final `';'` to avoid confusion with an unclosed single tag.
Attributes
----------
Attributes are included as `','`-separated pairs of `mane` and and a `tape` producing twig. These
pairs are contained within parentheses, which immediately follow a `mane`:
```
~zod/try=> ;div(id "me", class "elem");
[[%div [%id "me"] [%class "elem"] ~] ~]
~zod/try=> :poxo ;div(class "elem", id "me"); ~))
<div class="elem" id="me"></div>
```
The characters `'.'`, `'#'`, and `'/'` are short forms of the attributes `class`,
`id`, and `href` respectively:
```
~zod/try=> ;div.elem#me;
[[%div [%id "me"] [%class "elem"] ~] ~]
~zod/try=> ;a/"//google.com";
[[%a [%href "//google.com"] ~] ~]
```
As demonstrated above, the short forms of both `class` and `id` accept unquoted
terms instead of tapes.
The resulting XML is, of course, identical:
```
~zod/try=> :poxo ;div.elem#me;
<div id="me" class="elem"></div>
```
Character data
--------------
Nodes can also contain text:
```
~zod/try=> ;p:"contents of paragraph"
[[%p ~] [[%~. [%~. "contents of paragraph"] ~] ~] ~]
~zod/try=> :poxo ;p:"contents of paragraph"
<p>contents of paragraph</p>
```
Text is stored as a `mars` (a cdata node):
```
++ mars ,[t=[n=%$ a=[i=[n=%$ v=tape] t=~]] c=~] :: XML cdata
```
Techincally, a `mars` is a `manx` with an empty `mane`, one empty-named attribute
containing the text, and no children. Equivalently, it is a `_:/(*tape)`.
To insert text with newlines, it is surrounded in triple quotes:
```
;code:"""
block
with newlines
"""
```
This is rendered as:
```
<code>block
with newlines</code>
```
Interpolation
-------------
Similar to the syntax for `tape` interpolation,
```
~zod/try=> "Tape with {(weld "inter" (trip %polate))}d text"
"Tape with interpolated text"
```
there exists a `manx` syntax to insert XML produced by twigs. The simplest form
is that of embedded nodes:
```
~zod/try=> ;p:"Text text ;{b "bolded text"} more text"
[ [%p ~]
[[%~. [%~. "Text text "] ~] ~]
[[%b ~] [[%~. [%~. "bolded text"] ~] ~] ~]
[[%~. [%~. " more text"] ~] ~]
~
]
~zod/try=> :poxo ;p:"Text text ;{b "bolded text"} more text"
<p>Text text <b>bolded text</b> more text</p>
```
Notice that the syntax calls for a `marx`, followed by zero or more wide-form children
`manx`, placed within `';{}'`.
Dynamic data can also be interpolated. This is done by prefixing the `{}` wrapped twig with one of the following glyphs: `-, +, *, or %`.
A `{}` prefixed by a `'-'` accepts a `tape`:
```
~zod/try=> ;p:"Paragraph with -{(weld "inter" (trip %polate))}d text"
[ [%p ~]
[[%~. [%~. "Paragraph with "] ~] ~]
[[%~. [%~. ~[~~i ~~n ~~t ~~e ~~r ~~p ~~o ~~l ~~a ~~t ~~e]] ~] ~]
[[%~. [%~. "d text"] ~] ~]
~
]
```
If no glyph prefix is present, a`'-'` is assumed:
```
~zod/try=> ;p:"Paragraph with {(weld "inter" (trip %polate))}d text"
[ [%p ~]
[[%~. [%~. "Paragraph with "] ~] ~]
[[%~. [%~. ~[~~i ~~n ~~t ~~e ~~r ~~p ~~o ~~l ~~a ~~t ~~e]] ~] ~]
[[%~. [%~. "d text"] ~] ~]
~
]
~zod/try=> :poxo ;p:"Paragraph with {(weld "inter" (trip %polate))}d text"
<p>Paragraph with interpolated text</p>
```
A prefix of `'+'` accepts a `manx`:
```
~zod/try=> ;p:"This text +{?:((gth 2 1) ;b:"be bold" ;i:"be scared")}"
[[%p ~] [[%~. [%~. "This text "] ~] ~] [[%b ~] [[%~. [%~. "be bold"] ~] ~] ~] ~]
~zod/try=> :poxo ;p:"This text +{?:((gth 2 1) ;b:"be bold" ;i:"be scared")}"
<p>This text <b>be bold</b></p>
```
A prefix of `'*'` accepts a `marl`:
```
~zod/try=> ;p:"Today *{(turn `wain`~[%live %love] |=(a=@tas ;span:"we {(trip a)}, "))}"
[ [%p ~]
[[%~. [%~. "Today "] ~] ~]
[ i=[[%span ~] [[%~. [%~. "we "] ~] ~] [[%~. [%~. "live"] ~] ~] [[%~. [%~. ", "] ~] ~] ~]
t
[ i=[[%span ~] [[%~. [%~. "we "] ~] ~] [[%~. [%~. "love"] ~] ~] [[%~. [%~. ", "] ~] ~] ~]
t=~
]
]
]
~zod/try=> :poxo ;p:"Today *{(turn `wain`~[%live %love] |=(a=@tas ;span:"we {(trip a)}, "))}"
<p>Today <span>we live, </span><span>we love, </span></p>
```
A prefix of `'%'` accepts `$+(marl marl)`, a gate with both a sample and product of `marl`. The gate is then slammed by the nodes that follow it:
```
~zod/try=> ;p:"%{|=(a=marl (weld a a))}dup"
[ [%p ~]
~[[g=[n=%$ a=~[[n=%$ v="dup"]]] c=~] [g=[n=%$ a=~[[n=%$ v="dup"]]] c=~]]
]
~zod/try=> :poxo ;p:"%{|=(a=marl (weld a a))}dup"
<p>dupdup</p>
```
Interpolation can be disabled by replacing double quotes with single quotes.
For example, `;unescaped:'Kel {}'` becomes `<unescaped>Kel {}</unescaped>`,
and:
```
;script:'''
function(){
console.log(42)
}
'''
```
when rendered, is:
```
<script>function(){
console.log(42)
}</script>
```
Tall form
==========
Most development is done in tall form:
```
;html
;head
;title
; Hi
==
==
;body
;p
; Hello world
==
==
==
```
This produces the `manx`:
```
g=[n=%html a=~]
c
~[
[ g=[n=%head a=~]
c=~[[g=[n=%title a=~] c=~[[g=[n=%$ a=~[[n=%$ v="Hi
"]]] c=~]]]]
]
[ g=[n=%body a=~]
c=~[[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="Hello world
"]]] c=~]]]]
]
]
]
```
When the `manx` is rendered, it produces:
```
<html><head><title>Hi
</title></head><body><p>Hello world
</p></body></html>
```
As previously mentioned, a tag must always be closed. In tall form, this is accomplished by a `'=='`, which should align directly beneath it; any node in between the two is a subnnode.
As demonstrated in the example above, the tall form for character data
is opened by `'; '` (note the space). Unlike wide form, the text that follows
the `'; '` is not wrapped in quotes, but is instead terminated with a new
line. The syntax for interpolation remains the same.
The final way in which a tag may be closed is with `': '`, which is equivalent
to a `manx` with a single child declared by `'; '`. As with `'; '`, the text
declared by the `': '` is terminated by a new line:
```
;p: par contents
:: <p>par contents</p>
```
Another syntax that is unique to tall form is`';='`, which describes a `marl`
with no tag:
```
!:
=- [- (xmll | - ~)]
;=
;p: node
;node(with "attribute");
==
```
This produces the `marl`:
```
[[[%p ~] [[%~. [%~. "node"] ~] ~] ~] [[%node [%with "attribute"] ~] ~] ~]
```
Notice how this renders two XML nodes without an outer tag:
```
"<p>node</p><node with="attribute"></node>"
```
Tall interpolation
------------------
A ';' followed by an interpolation glyph(`-, +, *, or %`) and two or more spaces,
accepts a twig and interpolates it into the surrounding structure:
```
;div#demo
;- "foo"
;+ ;p:"bar"
;* :- ;p:"baz"
?: &
~
~[;hi;]
;% |= a=marl
(weld a a)
; dup
==
```
This produces the `manx`:
```
[ g=[n=%div a=~[[n=%id v="demo"]]]
c
~[
[g=[n=%$ a=~[[n=%$ v="foo"]]] c=~]
[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="bar"]]] c=~]]]
[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="baz"]]] c=~]]]
[g=[n=%$ a=~[[n=%$ v="dup
"]]] c=~]
[g=[n=%$ a=~[[n=%$ v="dup
"]]] c=~]
]
]
```
When the `manx` is rendered, it produces:
```
<div id="demo">foo<p>bar</p><p>baz</p>dup
dup
</div>
```
Attributes
----------
The tall form syntax for attributes is `'='` followed by a `mane` (the key), two
or more spaces, and a tall twig that produces a tape:
```
;div
=id "foo"
=class "bar"
;p: baz`
==
```
This produces the `manx`:
```
[ g=[n=%div a=~[[n=%id v="foo"] [n=%class v="bar"]]]
c=~[[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="baz"]]] c=~]]]]
]
```
When rendered, this `manx` produces:
```
<div id="foo" class="bar"><p>baz</p></div>
```
The tall-form syntax can be combined with the wide-form attribute syntax (and all of its short forms):
```
;html
;div#foo(tag "bar")
=attr "exceedingly value in here"
; tall form
;p: contents
==
==
```
This produces the `manx`:
```
[ [%html ~]
[ [%div [%id "foo"] [%tag "bar"] [%attr "hella long value in here"] ~]
[[%~. [%~. "tall form
"] ~] ~]
[[%p ~] [[%~. [%~. "contents"] ~] ~] ~]
~
]
~
]
```
When rendered, this `manx` produces:
```
"<html><div id="foo" tag="bar" attr="hella long value in here">tall form
<p>contents</p></div></html>"
```

View File

@ -238,7 +238,7 @@ we put:
:::: /hoon/three/mad/fab/pub
::
/= hello /: /===/pub/fab/mad/res/hello /hymn/
:
::
:::: ~tasfyn-partyv
::
::

View File

@ -319,7 +319,7 @@ example, it'll be obvious what it is.
<<33r:: *[a 7 b c] *[*[a b] c]>>
*[*[a c] 2 [0 1] 0 b]]
<<27 :: *[a 2 b c] *[*[a b] *[a c]]>>
*[*[*[a c] [0 1]] *[*[a c] 0 b]]

View File

@ -1,4 +1,4 @@
|= ^
|= [a=manx ~]
=- ~[$/!>(-)]~
(xmlt | a "")
=- ~[te/[-]~]~
(crip (xmlt | a ""))