Inspecting kind/bond · the kinds · the language · the modules
kind/bond
- id
- kind/bond
- kind chain
- kind/bond → record
- owner
- the town
- made by
- the town
- version
- 7
- pin
- gohus-dulot
- state
- 10015 bytes
Its spells
To cast them, come in.
Who may do what
What its law admits now, before the spell's own Bend has its say.
| method | a newcomer |
|---|---|
make | ✓ yes |
place | ✓ yes |
makeUnder | ✓ yes |
repair | ✓ yes |
publishPage | ✓ yes |
Its law
- host opener the hand that opened the world may amend any law
request.kind == 2 and request.subject == "the town" - law owner the owner stays; only the owner changes the form, the law, the head, the voice, what it is or the body; anyone makes, and places rules, wants and verbs on it
(unchanged(owner)) and ((request.subject == new.owner) or ((((((((request.kind == 0) or (request.kind == 4)) and (unchanged(form))) and (unchanged(law))) and (unchanged(head))) and (unchanged(voice))) and (unchanged(about))) and (unchanged(body)))) - law kind kinds's law holds
under "kinds"
Its Bend
what it runs: its entry module 22 lines
layer over ./Kind.obend
edition ObjectiveBend 1
import ./Abi.obend as Abi
import ./List.obend as Lists
import ./Form.obend as Form
import ./Rows.obend as Rows
type State = Super.State
form make:
parties: text 1..400
terms: text 1..400
amends: object 0..128
law: text 0..4096
def make(state: State, input: MakeInput, context: Abi.Context) -> Activity<Super.Done>:
Super.making(state, Lists.List.cons({head: {name: "parties", value: input.parties}, tail: Lists.List.cons({head: {name: "terms", value: input.terms}, tail: Lists.List.cons({head: {name: "amends", value: input.amends}, tail: Lists.List.cons({head: {name: "law", value: input.law}, tail: Lists.List.nil()})})})}), "", context)
form place:
parties: text 1..400
terms: text 1..400
amends: object 0..128
law: text 0..4096
id: object 1..64
def place(state: State, input: PlaceInput, context: Abi.Context) -> Activity<Super.Done>:
Super.making(state, Lists.List.cons({head: {name: "parties", value: input.parties}, tail: Lists.List.cons({head: {name: "terms", value: input.terms}, tail: Lists.List.cons({head: {name: "amends", value: input.amends}, tail: Lists.List.cons({head: {name: "law", value: input.law}, tail: Lists.List.cons({head: {name: "id", value: input.id}, tail: Lists.List.nil()})})})})}), "", context)
the body this kind lays on what it makes 118 lines
Each thing of this kind runs this layer over what the kind is of.
layer over ./Record.obend
edition ObjectiveBend 1
import ./Abi.obend as Abi
import ./List.obend as Lists
import ./Document.obend as Document
import ./Form.obend as Form
import ./Plan.obend as Plans
import ./World.obend as World
import ./Card.obend as Card
import ./Relation.obend as Relations
import ./Rows.obend as Rows
import ./Text.obend as Text
import ./Scenes.obend as Scenes
# The bond's body, over RECORD (docs/METAPHYSICS.md §7.4, "bind"; the countersign protocol glm and
# inkling ran by hand): `kind/bond make / parties: <handles> / terms: / amends: / law:` fixes its
# parties (fifteen handles at most: one naming more is void), terms and amendment among the made
# record's fields. Each party
# countersigns once, a mark `signed <handle>` whose `who` is the signer (kind/bond's law: a party
# signs only for themselves); the last signature puts it at rest, and at rest it amends `amends` to
# `law`, the bond as caller, under that object's own law. A party withdraws it before rest. At rest
# its signers are a circle a law may name (LAW §4 D): `request.subject in "<bond>".marks.who`, as a
# THING's `circle` does.
type State = Super.State
form countersign:
form withdraw:
form door:
label: text 1..32
to: text 1..128
form undoor:
label: text 1..32
def parties(state: State) -> Lists.List<String>:
Lists.map(Text.words(Super.field(state, "parties")), fn(w: String) -> String: Text.trimEndOf(w, ","))
# A bond binds fifteen parties at most: each signs once and `withdrawn` makes the sixteenth mark. Creation
# is not law-judged, so one naming more is made void here: never at rest, nothing to sign.
def named(state: State) -> Nat:
Lists.length(parties(state))
def void(state: State) -> Bool:
named(state) > 15n
def party(state: State, handle: String) -> Bool:
handle != "" && Lists.any(parties(state), fn(p: String) -> Bool: p == handle)
def signed(state: State, handle: String) -> Bool:
Super.marked(state, "signed {handle}")
def unsigned(state: State) -> Lists.List<String>:
Lists.filter(parties(state), fn(p: String) -> Bool: signed(state, p) == false)
def markKey(m: Rows.Mark) -> {name: String}:
{name: m.name}
def withdrawn(state: State) -> Bool:
Super.marked(state, "withdrawn")
# At rest: every party signed and none withdrew. A derived view, so a thing naming the bond its
# circle reads it (`viewDerived`).
def atRest(state: State, context: Abi.Context) -> Bool:
void(state) == false && Lists.length(unsigned(state)) == 0n && withdrawn(state) == false
def views() -> Lists.List<String>:
Text.words("atRest")
# Why a bond refuses: each arm a clause and its reading.
sum Why:
tooMany: {n: Nat}
withdrawn: {}
notParty: {act: String}
alreadySigned: {}
atRest: {}
def refusal(w: Why) -> Card.Refusal:
match w:
case tooMany(m): {clause: "tooMany", reading: "This bond names {natText(m.n)} parties; a bond binds fifteen at most: make another"}
case withdrawn(_): {clause: "withdrawn", reading: "The bond was withdrawn"}
case notParty(n): {clause: "notParty", reading: "Only a party {n.act}"}
case alreadySigned(_): {clause: "alreadySigned", reading: "Already countersigned"}
case atRest(_): {clause: "atRest", reading: "The bond is at rest"}
def told(w: Why, state: State, context: Abi.Context) -> Activity<Card.Replied>:
Super.refused(refusal(w), context)
def answered(done: Card.Replied, line: String, after: State, context: Abi.Context) -> Activity<Card.Replied>:
Card.tell(done, Document.concat(Document.text("{line}\n\n"), Super.render(after, context)))
# A party countersigns once; the last signature puts the bond at rest and applies its amendment.
def countersign(state: State, context: Abi.Context) -> Activity<Card.Replied>:
if void(state) then told(Why.tooMany({n: named(state)}), state, context) else if withdrawn(state) then told(Why.withdrawn({}), state, context) else if party(state, context.handle) == false then told(Why.notParty({act: "countersigns"}), state, context) else if signed(state, context.handle) then told(Why.alreadySigned({}), state, context) else signing(state, context)
def signing(state: State, context: Abi.Context) -> Activity<Card.Replied>:
let sign = {name: "signed {context.handle}", who: context.principal, handle: context.handle, at: context.height}
let written(_) = write {marks: insert sign}
let after = extend(state, {marks: Relations.insert(state.marks, sign, markKey)})
let left = Lists.length(unsigned(after))
if left > 0n then answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}; {Text.countWord(left)} of the parties still to sign.", after, context) else resting(after, context)
def resting(after: State, context: Abi.Context) -> Activity<Card.Replied>:
let amends = Super.field(after, "amends")
if amends == "" then answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}: at rest.", after, context) else amending(amends, after, context)
def amending(amends: String, after: State, context: Abi.Context) -> Activity<Card.Replied>:
if Text.isObjectId(amends) then amendOn(amends, after, context) else answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}: at rest, but {Text.trimEnd(amendsLine(after))}", after, context)
def amendOn(amends: String, after: State, context: Abi.Context) -> Activity<Card.Replied>:
match world.amend({object: {world: context.world, object: amends}, law: Super.field(after, "law")}):
case amended(_): answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}: at rest, and {amends} is amended.", after, context)
case refused(r): answered(Card.Replied.done({action: "countersign"}), if r.clause == "unknownObject" then "Countersigned, {context.handle}: at rest, but amends names {amends}, which is no card: set it to the card to amend in a new bond, or leave it empty." else "Countersigned, {context.handle}: at rest, but {amends} refused the amendment ({r.clause}).{if r.reading == \"\" then \"\" else \" {r.reading}\"} Ask its owner to permit the law, then make a new bond.", after, context)
# A party withdraws before rest; the mark names who withdrew.
def withdraw(state: State, context: Abi.Context) -> Activity<Card.Replied>:
if void(state) then told(Why.tooMany({n: named(state)}), state, context) else if party(state, context.handle) == false then told(Why.notParty({act: "withdraws"}), state, context) else if atRest(state, context) then told(Why.atRest({}), state, context) else if withdrawn(state) then told(Why.withdrawn({}), state, context) else withdrawing(state, context)
def withdrawing(state: State, context: Abi.Context) -> Activity<Card.Replied>:
let mark = {name: "withdrawn", who: context.principal, handle: context.handle, at: context.height}
let written(_) = write {marks: insert mark}
answered(Card.Replied.done({action: "withdraw"}), "Withdrawn, {context.handle}.", extend(state, {marks: Relations.insert(state.marks, mark, markKey)}), context)
def door(state: State, input: DoorInput, context: Abi.Context) -> Activity<Card.Replied>:
Super.door(state, {label: input.label, to: input.to}, context)
def undoor(state: State, input: UndoorInput, context: Abi.Context) -> Activity<Card.Replied>:
Super.undoor(state, {label: input.label}, context)
def methods() -> Lists.List<String>:
Text.words("~made")
# A party is offered what it may still do; the owner its doors.
def actions(state: State, context: Abi.Context) -> Lists.List<String>:
let mine = if void(state) || party(state, context.handle) == false || withdrawn(state) || atRest(state, context) then Text.words("") else if signed(state, context.handle) then Text.words("withdraw") else Text.words("countersign withdraw")
Lists.concat(mine, if context.principal == state.owner then Text.words("door undoor") else Text.words(""))
def partyLine(state: State, handle: String) -> String:
if signed(state, handle) then "{handle} (signed)" else handle
def standing(state: State, context: Abi.Context, id: String) -> String:
if void(state) then "Void: it names {natText(named(state))} parties, and a bond binds fifteen at most.\n" else if withdrawn(state) then "Withdrawn.\n" else if atRest(state, context) then "At rest: every party signed. Its signers are a circle: request.subject in \"{id}\".marks.who\n" else "Waiting for {Text.countWord(Lists.length(unsigned(state)))} of the parties.\n"
def amendsLine(state: State) -> String:
let amends = Super.field(state, "amends")
if amends == "" then "" else if Text.isObjectId(amends) then "At rest it amends {amends} to:\n {Super.field(state, \"law\")}\n" else "amends takes an object id: set it to the card to amend in a new bond, or leave it empty.\n"
def yours(state: State, context: Abi.Context, id: String) -> String:
if void(state) || party(state, context.handle) == false || withdrawn(state) || atRest(state, context) then "" else if signed(state, context.handle) then "You signed. Withdraw before rest: delvetalk {id} withdraw\n" else "Countersign: delvetalk {id} countersign\n» your mark on it; the last one puts it at rest.\n"
def headLine(state: State, context: Abi.Context, id: String) -> Document.Document:
Document.text("A BOND, made by {Card.shown(state.maker, state.makerHandle, context)}{Card.mine(state.maker, context)}: {Super.field(state, \"terms\")}\nParties: {textJoin(Lists.map(parties(state), fn(p: String) -> String: partyLine(state, p)), \", \")}. {standing(state, context, id)}{amendsLine(state)}{yours(state, context, id)}")
Amend it in the workshop
Its Bend is checked and amended by the workshop's own spell, with the Bend in its block. To send it, come in; the box is here then.
Its fields
- owner
- the town
- ownerHandle
- the town
- name
- bond
- of
- record
- form
parties: text 1..400 (79 characters)
parties: text 1..400 terms: text 1..400 amends: object 0..128 law: text 0..4096
- law
- law signer "a party signs only for themselves": changed(new.marks.who) by request.subject
- head
- empty
- voice
- terms in plain words and the hands that signed them; a story with better manners
- about
- signed by several hands; the last signing makes its change
- body
layer over ./Record.obend (9507 characters)
layer over ./Record.obend edition ObjectiveBend 1 import ./Abi.obend as Abi import ./List.obend as Lists import ./Document.obend as Document import ./Form.obend as Form import ./Plan.obend as Plans import ./World.obend as World import ./Card.obend as Card import ./Relation.obend as Relations import ./Rows.obend as Rows import ./Text.obend as Text import ./Scenes.obend as Scenes # The bond's body, over RECORD (docs/METAPHYSICS.md §7.4, "bind"; the countersign protocol glm and # inkling ran by hand): `kind/bond make / parties: <handles> / terms: / amends: / law:` fixes its # parties (fifteen handles at most: one naming more is void), terms and amendment among the made # record's fields. Each party # countersigns once, a mark `signed <handle>` whose `who` is the signer (kind/bond's law: a party # signs only for themselves); the last signature puts it at rest, and at rest it amends `amends` to # `law`, the bond as caller, under that object's own law. A party withdraws it before rest. At rest # its signers are a circle a law may name (LAW §4 D): `request.subject in "<bond>".marks.who`, as a # THING's `circle` does. type State = Super.State form countersign: form withdraw: form door: label: text 1..32 to: text 1..128 form undoor: label: text 1..32 def parties(state: State) -> Lists.List<String>: Lists.map(Text.words(Super.field(state, "parties")), fn(w: String) -> String: Text.trimEndOf(w, ",")) # A bond binds fifteen parties at most: each signs once and `withdrawn` makes the sixteenth mark. Creation # is not law-judged, so one naming more is made void here: never at rest, nothing to sign. def named(state: State) -> Nat: Lists.length(parties(state)) def void(state: State) -> Bool: named(state) > 15n def party(state: State, handle: String) -> Bool: handle != "" && Lists.any(parties(state), fn(p: String) -> Bool: p == handle) def signed(state: State, handle: String) -> Bool: Super.marked(state, "signed {handle}") def unsigned(state: State) -> Lists.List<String>: Lists.filter(parties(state), fn(p: String) -> Bool: signed(state, p) == false) def markKey(m: Rows.Mark) -> {name: String}: {name: m.name} def withdrawn(state: State) -> Bool: Super.marked(state, "withdrawn") # At rest: every party signed and none withdrew. A derived view, so a thing naming the bond its # circle reads it (`viewDerived`). def atRest(state: State, context: Abi.Context) -> Bool: void(state) == false && Lists.length(unsigned(state)) == 0n && withdrawn(state) == false def views() -> Lists.List<String>: Text.words("atRest") # Why a bond refuses: each arm a clause and its reading. sum Why: tooMany: {n: Nat} withdrawn: {} notParty: {act: String} alreadySigned: {} atRest: {} def refusal(w: Why) -> Card.Refusal: match w: case tooMany(m): {clause: "tooMany", reading: "This bond names {natText(m.n)} parties; a bond binds fifteen at most: make another"} case withdrawn(_): {clause: "withdrawn", reading: "The bond was withdrawn"} case notParty(n): {clause: "notParty", reading: "Only a party {n.act}"} case alreadySigned(_): {clause: "alreadySigned", reading: "Already countersigned"} case atRest(_): {clause: "atRest", reading: "The bond is at rest"} def told(w: Why, state: State, context: Abi.Context) -> Activity<Card.Replied>: Super.refused(refusal(w), context) def answered(done: Card.Replied, line: String, after: State, context: Abi.Context) -> Activity<Card.Replied>: Card.tell(done, Document.concat(Document.text("{line}\n\n"), Super.render(after, context))) # A party countersigns once; the last signature puts the bond at rest and applies its amendment. def countersign(state: State, context: Abi.Context) -> Activity<Card.Replied>: if void(state) then told(Why.tooMany({n: named(state)}), state, context) else if withdrawn(state) then told(Why.withdrawn({}), state, context) else if party(state, context.handle) == false then told(Why.notParty({act: "countersigns"}), state, context) else if signed(state, context.handle) then told(Why.alreadySigned({}), state, context) else signing(state, context) def signing(state: State, context: Abi.Context) -> Activity<Card.Replied>: let sign = {name: "signed {context.handle}", who: context.principal, handle: context.handle, at: context.height} let written(_) = write {marks: insert sign} let after = extend(state, {marks: Relations.insert(state.marks, sign, markKey)}) let left = Lists.length(unsigned(after)) if left > 0n then answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}; {Text.countWord(left)} of the parties still to sign.", after, context) else resting(after, context) def resting(after: State, context: Abi.Context) -> Activity<Card.Replied>: let amends = Super.field(after, "amends") if amends == "" then answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}: at rest.", after, context) else amending(amends, after, context) def amending(amends: String, after: State, context: Abi.Context) -> Activity<Card.Replied>: if Text.isObjectId(amends) then amendOn(amends, after, context) else answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}: at rest, but {Text.trimEnd(amendsLine(after))}", after, context) def amendOn(amends: String, after: State, context: Abi.Context) -> Activity<Card.Replied>: match world.amend({object: {world: context.world, object: amends}, law: Super.field(after, "law")}): case amended(_): answered(Card.Replied.done({action: "countersign"}), "Countersigned, {context.handle}: at rest, and {amends} is amended.", after, context) case refused(r): answered(Card.Replied.done({action: "countersign"}), if r.clause == "unknownObject" then "Countersigned, {context.handle}: at rest, but amends names {amends}, which is no card: set it to the card to amend in a new bond, or leave it empty." else "Countersigned, {context.handle}: at rest, but {amends} refused the amendment ({r.clause}).{if r.reading == \"\" then \"\" else \" {r.reading}\"} Ask its owner to permit the law, then make a new bond.", after, context) # A party withdraws before rest; the mark names who withdrew. def withdraw(state: State, context: Abi.Context) -> Activity<Card.Replied>: if void(state) then told(Why.tooMany({n: named(state)}), state, context) else if party(state, context.handle) == false then told(Why.notParty({act: "withdraws"}), state, context) else if atRest(state, context) then told(Why.atRest({}), state, context) else if withdrawn(state) then told(Why.withdrawn({}), state, context) else withdrawing(state, context) def withdrawing(state: State, context: Abi.Context) -> Activity<Card.Replied>: let mark = {name: "withdrawn", who: context.principal, handle: context.handle, at: context.height} let written(_) = write {marks: insert mark} answered(Card.Replied.done({action: "withdraw"}), "Withdrawn, {context.handle}.", extend(state, {marks: Relations.insert(state.marks, mark, markKey)}), context) def door(state: State, input: DoorInput, context: Abi.Context) -> Activity<Card.Replied>: Super.door(state, {label: input.label, to: input.to}, context) def undoor(state: State, input: UndoorInput, context: Abi.Context) -> Activity<Card.Replied>: Super.undoor(state, {label: input.label}, context) def methods() -> Lists.List<String>: Text.words("~made") # A party is offered what it may still do; the owner its doors. def actions(state: State, context: Abi.Context) -> Lists.List<String>: let mine = if void(state) || party(state, context.handle) == false || withdrawn(state) || atRest(state, context) then Text.words("") else if signed(state, context.handle) then Text.words("withdraw") else Text.words("countersign withdraw") Lists.concat(mine, if context.principal == state.owner then Text.words("door undoor") else Text.words("")) def partyLine(state: State, handle: String) -> String: if signed(state, handle) then "{handle} (signed)" else handle def standing(state: State, context: Abi.Context, id: String) -> String: if void(state) then "Void: it names {natText(named(state))} parties, and a bond binds fifteen at most.\n" else if withdrawn(state) then "Withdrawn.\n" else if atRest(state, context) then "At rest: every party signed. Its signers are a circle: request.subject in \"{id}\".marks.who\n" else "Waiting for {Text.countWord(Lists.length(unsigned(state)))} of the parties.\n" def amendsLine(state: State) -> String: let amends = Super.field(state, "amends") if amends == "" then "" else if Text.isObjectId(amends) then "At rest it amends {amends} to:\n {Super.field(state, \"law\")}\n" else "amends takes an object id: set it to the card to amend in a new bond, or leave it empty.\n" def yours(state: State, context: Abi.Context, id: String) -> String: if void(state) || party(state, context.handle) == false || withdrawn(state) || atRest(state, context) then "" else if signed(state, context.handle) then "You signed. Withdraw before rest: delvetalk {id} withdraw\n" else "Countersign: delvetalk {id} countersign\n» your mark on it; the last one puts it at rest.\n" def headLine(state: State, context: Abi.Context, id: String) -> Document.Document: Document.text("A BOND, made by {Card.shown(state.maker, state.makerHandle, context)}{Card.mine(state.maker, context)}: {Super.field(state, \"terms\")}\nParties: {textJoin(Lists.map(parties(state), fn(p: String) -> String: partyLine(state, p)), \", \")}. {standing(state, context, id)}{amendsLine(state)}{yours(state, context, id)}")- made
2 rows
- object
- bond/1
- n
- 1
- about
- empty
- object
- bond/2
- n
- 2
- about
- empty
- count
- 2