build a doc file, bring in some other documentation

This commit is contained in:
Scott Richmond 2025-07-07 00:10:37 -04:00
parent 79720ba833
commit 49bb50ada1
11 changed files with 173 additions and 154 deletions

View File

@ -1039,7 +1039,7 @@ fn self {
() -> base :process (:self) () -> base :process (:self)
} }
fn send { fn send! {
"Sends a message to the specified process and returns the message." "Sends a message to the specified process and returns the message."
(pid as :keyword, msg) -> { (pid as :keyword, msg) -> {
base :process (:send, pid, msg) base :process (:send, pid, msg)
@ -1052,7 +1052,7 @@ fn link! {
(pid as :keyword) -> base :process (:link, pid) (pid as :keyword) -> base :process (:link, pid)
} }
fn spawn! { fn spawn {
"Spawns a process. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly spawned process." "Spawns a process. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly spawned process."
(f as :fn) -> { (f as :fn) -> {
let new_pid = base :process (:spawn, f) let new_pid = base :process (:spawn, f)
@ -1061,7 +1061,7 @@ fn spawn! {
} }
} }
fn fledge! { fn fledge {
"Spawns a process and then immediately unlinks from it. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly fledged process." "Spawns a process and then immediately unlinks from it. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly fledged process."
(f as :fn) -> base :process (:spawn, f) (f as :fn) -> base :process (:spawn, f)
} }
@ -1088,7 +1088,7 @@ fn monitor! {
else nil else nil
} }
fn flush! { fn flush {
"Clears the current process's mailbox and returns all the messages." "Clears the current process's mailbox and returns all the messages."
() -> base :process (:flush) () -> base :process (:flush)
} }
@ -1098,7 +1098,7 @@ fn sleep! {
(ms as :number) -> base :process (:sleep, ms) (ms as :number) -> base :process (:sleep, ms)
} }
fn await! { fn await {
"Parks the current process until it receives an exit signal from the passed process. Returns the result of a successful execution or panics if the awaited process panics. If the other process is not alive, returns `nil`." "Parks the current process until it receives an exit signal from the passed process. Returns the result of a successful execution or panics if the awaited process panics. If the other process is not alive, returns `nil`."
(pid as :keyword) -> if monitor! (pid) (pid as :keyword) -> if monitor! (pid)
then receive { then receive {
@ -1127,7 +1127,7 @@ fn hibernate! {
() -> receive { _ -> hibernate! () } () -> receive { _ -> hibernate! () }
} }
fn heed! { fn heed {
"Parks the current process until it receives a reply, and returns whatever is replied. Causes a panic if it gets anything other than a `(:reply, result)` tuple." "Parks the current process until it receives a reply, and returns whatever is replied. Causes a panic if it gets anything other than a `(:reply, result)` tuple."
() -> receive { () -> receive {
(:reply, result) -> result (:reply, result) -> result
@ -1164,7 +1164,7 @@ fn request_fetch! {
} }
fn fetch { fn fetch {
"Requests the contents of the URL passed in. Returns a result tuple of `(:ok, {contents})` or `(:err, {status code})`." "Requests the contents of the URL passed in. Returns a result tuple of (:ok, <contents>) or (:err, <status code>)."
(url) -> { (url) -> {
let pid = self () let pid = self ()
spawn! (fn () -> request_fetch! (pid, url)) spawn! (fn () -> request_fetch! (pid, url))
@ -1402,7 +1402,7 @@ fn turtle_listener () -> {
turtle_listener () turtle_listener ()
} }
fn spawn_turtle! { fn spawn_turtle {
"Spawns a new turtle in a new process. Methods on the turtle process mirror those of turtle graphics functions in prelude. Returns the pid of the new turtle." "Spawns a new turtle in a new process. Methods on the turtle process mirror those of turtle graphics functions in prelude. Returns the pid of the new turtle."
() -> { () -> {
let pid = spawn! (fn () -> turtle_listener ()) let pid = spawn! (fn () -> turtle_listener ())
@ -1498,106 +1498,73 @@ fn llist {
} }
&&& keyboard input &&& keyboard input
fn key_pressed? { fn key_down? {
"Returns true ie the key is currently pressed. Keys are indicated by strings. For non-alphanumeric keys, consult the documentation to get key codes." "Returns true ie the key is currently pressed. Keys are indicated by strings. For non-alphanumeric keys, consult the documentation to get key codes."
(key as :string) -> do keys_down > unbox > contains? (key, _) (key as :string) -> do keys_down > unbox > contains? (key, _)
} }
#{ #{
& completed actor functions abs & math
self add & math
send alive? & processes
spawn! & <- is no longer a special form angle & math
yield! any? & types and values
sleep! append & lists
alive? assert! & errors
flush! assoc & dicts
at & tuples, strings, lists
& wip actor functions atan/2 & math
link! await & processes
monitor! back! & turtle graphics
await! background! & turtle graphics
heed! between? & math
unlink! bg! & turtle graphics
hibernate! bk! & turtle graphics
bool & bools
spawn_turtle! bool? & bools
box? & boxes
key_pressed? butlast & list, tuple, string
car & llist
& shared memory w/ rust cdr & llist
& `box`es are actually way cool ceil & math
console chars & strings
input clear! & turtle graphics
fetch_outbox coll? & dicts, tuples, lists
colors & turtle graphics
colours & turtle graphics
concat & list string
cons & llist
console & buffers
contains? & list, tuple, string
cos & math
count & list, tuple, string
dec & math
deg/rad &math
deg/turn &math
dict & dicts
dict? & dicts
dissoc & dicts
dist & math
div & math
div/0 & math
div/safe & math
doc! & io
downcase & string
each! & list
empty? & list string dict tuple
eq? & values
err & result
err? & result
even? & math
false? & bool
fd! & turtles
fetch &
fetch_inbox fetch_inbox
keys_down fetch_outbox
& a fetch fn
fetch
& await user input
read_input
abs
abs
add
angle
any?
append
assert!
assoc
& assoc?
at
atan/2
back!
background!
between?
bg!
bk!
bool
bool?
box?
butlast
car
cdr
ceil
chars
clear!
coll?
colors
colours
concat
condense
cons
console
contains?
cos
count
dec
deg/rad
deg/turn
dict
dict?
dissoc
dist
div
div/0
div/safe
doc!
downcase
each!
empty?
eq?
err
err?
even?
false?
fd!
filter filter
first first
first
first
floor floor
flush
fn? fn?
fold fold
foldr foldr
@ -1609,21 +1576,27 @@ fn key_pressed? {
has? has?
heading heading
heading/vector heading/vector
heed
hibernate!
hideturtle! hideturtle!
home! home!
inc inc
indexed?
index_of index_of
indexed?
indices_of indices_of
input
inv inv
inv/0 inv/0
inv/safe inv/safe
join join
keep keep
key_down?
keys keys
keys_down
keyword? keyword?
last last
left! left!
link!
list list
list? list?
llist llist
@ -1635,6 +1608,7 @@ fn key_pressed? {
mod mod
mod/0 mod/0
mod/safe mod/safe
monitor!
mult mult
neg neg
neg? neg?
@ -1665,6 +1639,7 @@ fn key_pressed? {
random random
random_int random_int
range range
read_input
report! report!
rest rest
right! right!
@ -1672,15 +1647,20 @@ fn key_pressed? {
round round
rt! rt!
second second
self
send!
sentence sentence
setheading! setheading!
show show
showturtle! showturtle!
sin sin
sleep!
slice slice
slice_n slice_n
some some
some? some?
spawn
spawn_turtle
split split
sqrt sqrt
sqrt/safe sqrt/safe
@ -1703,6 +1683,7 @@ fn key_pressed? {
turtle_state turtle_state
type type
unbox unbox
unlink!
unwrap! unwrap!
unwrap_or unwrap_or
upcase upcase
@ -1711,5 +1692,6 @@ fn key_pressed? {
values values
words words
ws? ws?
yield!
zero? zero?
} }

View File

@ -1,7 +1,7 @@
# A base library for Ludus # A base library for Ludus
# Only loaded in the prelude # Only loaded in the prelude
(import /src/scanner :as s) (import /janet/scanner :as s)
(defn bool [x] (if (= :^nil x) nil x)) (defn bool [x] (if (= :^nil x) nil x))

View File

@ -1,5 +1,5 @@
(import /src/base :as base) (import /janet/base :as base)
(import /src/prelude :as prelude) (import /janet/prelude :as prelude)
(defn map-values [f dict] (defn map-values [f dict]
(from-pairs (map (fn [[k v]] [k (f v)]) (pairs dict)))) (from-pairs (map (fn [[k v]] [k (f v)]) (pairs dict))))
@ -23,20 +23,21 @@
(string/join (map toc-entry sorted-names) "&nbsp;&nbsp;&nbsp; ")) (string/join (map toc-entry sorted-names) "&nbsp;&nbsp;&nbsp; "))
(def topics { (def topics {
"math" ["abs" "add" "angle" "atan/2" "between?" "ceil" "cos" "dec" "deg/rad" "deg/turn" "dist" "div" "div/0" "div/safe" "even?" "floor" "gt?" "gte?" "heading/vector" "inc" "inv" "inv/0" "inv/safe" "lt?" "lte?" "max" "min" "mod" "mod/0" "mod/safe" "mult" "neg" "neg?" "odd?" "pi" "pos?" "rad/deg" "rad/turn" "random" "random_int" "range" "round" "sin" "sqrt" "sqrt/safe" "square" "sub" "sum_of_squares" "tan" "tau" "to_number" "turn/deg" "turn/rad" "zero?"] "math" ["abs" "add" "angle" "atan/2" "between?" "ceil" "cos" "dec" "deg/rad" "deg/turn" "dist" "div" "div/0" "div/safe" "even?" "floor" "gt?" "gte?" "heading/vector" "inc" "inv" "inv/0" "inv/safe" "lt?" "lte?" "max" "min" "mod" "mod/0" "mod/safe" "mult" "neg" "neg?" "odd?" "pi" "pos?" "pow" "rad/deg" "rad/turn" "random" "random_int" "range" "round" "sin" "sqrt" "sqrt/safe" "square" "sub" "sum_of_squares" "tan" "tau" "to_number" "turn/deg" "turn/rad" "zero?"]
"boolean" ["and" "bool" "bool?" "false?" "not" "or" "true?"] "bools" ["and" "bool" "bool?" "false?" "not" "or" "true?"]
"dicts" ["any?" "assoc" "assoc?" "coll?" "count" "dict" "dict?" "diff" "dissoc" "empty?" "get" "keys" "random" "update" "values"] "dicts" ["any?" "assoc" "coll?" "count" "dict" "dict?" "diff" "dissoc" "empty?" "get" "has?" "keys" "random" "update" "values"]
"lists" ["any?" "append" "at" "butlast" "coll?" "concat" "count" "each!" "empty?" "filter" "first" "fold" "join" "keep" "last" "list" "list?" "map" "ordered?" "random" "range" "rest" "second" "sentence" "slice"] "lists" ["any?" "append" "at" "butlast" "coll?" "concat" "count" "each!" "empty?" "filter" "first" "fold" "index_of" "indexed?" "indices_of" "join" "keep" "last" "list" "list?" "map" "random" "range" "rest" "second" "sentence" "slice"]
"llists" ["car" "cdr" "cons" "llist"] "llists" ["car" "cdr" "cons" "llist"]
"sets" ["any?" "append" "coll?" "concat" "contains?" "count" "empty?" "omit" "random" "set" "set?"] # "sets" ["any?" "append" "coll?" "concat" "contains?" "count" "empty?" "omit" "random" "set" "set?"]
"tuples" ["any?" "at" "coll?" "count" "empty?" "first" "last" "ordered?" "rest" "second" "tuple?"] "tuples" ["any?" "at" "coll?" "count" "empty?" "first" "last" "ordered?" "rest" "second" "tuple?"]
"strings" ["any?" "chars" "chars/safe" "concat" "count" "downcase" "empty?" "join" "sentence" "show" "slice" "split" "string" "string?" "strip" "to_number" "trim" "upcase" "words"] "strings" ["any?" "at" "chars" "chars/safe" "concat" "count" "downcase" "empty?" "join" "sentence" "show" "slice" "slice_n" "split" "string" "string?" "strip" "to_number" "trim" "upcase" "words"]
"types and values" ["assoc?" "bool?" "box?" "coll?" "dict?" "eq?" "fn?" "keyword?" "list?" "neq?" "nil?" "number?" "ordered?" "set?" "show" "some" "some?" "string?" "tuple?" "type"] "types and values" ["bool?" "box?" "coll?" "dict?" "eq?" "fn?" "indexed?" "keyword?" "list?" "nil?" "number?" "set?" "show" "some" "some?" "string?" "tuple?" "type"]
"boxes and state" ["box?" "unbox" "store!" "update!"] "boxes" ["box?" "unbox" "store!" "update!"]
"results" ["err" "err?" "ok" "ok?" "unwrap!" "unwrap_or"] "results" ["err" "err?" "ok" "ok?" "unwrap!" "unwrap_or"]
"errors" ["assert!"] "errors" ["assert!"]
"turtle graphics" ["back!" "background!" "bk!" "clear!" "colors" "fd!" "forward!" "goto!" "heading" "heading/vector" "hideturtle!" "home!" "left!" "loadstate!" "lt!" "pc!" "pd!" "pencolor" "pencolor!" "pendown!" "pendown?" "penup!" "penwidth" "penwidth!" "position" "pu!" "pw!" "render_turtle!" "reset_turtle!" "right!" "rt!" "setheading!" "showturtle!" "turtle_state"] "turtle graphics" ["back!" "background!" "bk!" "clear!" "colors" "fd!" "forward!" "goto!" "heading" "heading/vector" "hideturtle!" "home!" "left!" "loadstate!" "lt!" "pc!" "pd!" "pencolor" "pencolour" "pencolor!" "pencolour!" "pendown!" "pendown?" "penup!" "penwidth" "penwidth!" "position" "pu!" "pw!" "render_turtle!" "reset_turtle!" "right!" "rt!" "setheading!" "showturtle!" "spawn_turtle" "turtle_state"]
"environment and i/o" ["doc!" "print!" "report!" "state"] "environment and i/o" ["console" "doc!" "fetch_inbox" "fetch_outbox" "input" "key_down?" "keys_down" "print!" "read_input" "report!"]
"processes" ["alive?" "await" "fledge" "flush" "heed" "hibernate!" "monitor" "self" "send!" "sleep!" "spawn" "unlink!" "yield!"]
}) })
(defn capitalize [str] (defn capitalize [str]

View File

@ -1,4 +1,4 @@
(import /src/base :as b) (import /janet/base :as b)
(defn- get-line [source line] (defn- get-line [source line]
((string/split "\n" source) (dec line))) ((string/split "\n" source) (dec line)))

View File

@ -1,6 +1,6 @@
# A tree walk interpreter for ludus # A tree walk interpreter for ludus
(import /src/base :as b) (import /janet/base :as b)
(var interpret nil) (var interpret nil)
(var match-pattern nil) (var match-pattern nil)

View File

@ -2,14 +2,14 @@
# devised in order to run under wasm # devised in order to run under wasm
# takes a string, returns a string with a json object # takes a string, returns a string with a json object
# (try (os/cd "janet") ([_] nil)) # for REPL # (try (os/cd "janet") ([_] nil)) # for REPL
(import /src/scanner :as s) (import /janet/scanner :as s)
(import /src/parser :as p) (import /janet/parser :as p)
(import /src/validate :as v) (import /janet/validate :as v)
(import /src/interpreter :as i) (import /janet/interpreter :as i)
(import /src/errors :as e) (import /janet/errors :as e)
(import /src/base :as b) (import /janet/base :as b)
(import /src/prelude :as prelude) (import /janet/prelude :as prelude)
(import /src/json :as j) (import /janet/json :as j)
(defn ludus [source] (defn ludus [source]
# if we can't load prelude, bail # if we can't load prelude, bail

View File

@ -1,7 +1,7 @@
### A recursive descent parser for Ludus ### A recursive descent parser for Ludus
### We still need to scan some things ### We still need to scan some things
(import /src/scanner :as s) (import /janet/scanner :as s)
# stash janet type # stash janet type
(def janet-type type) (def janet-type type)
@ -698,6 +698,25 @@
@{:type :match :data [to-match clauses] :token origin}) @{:type :match :data [to-match clauses] :token origin})
([err] err))) ([err] err)))
(defn- receive [parser]
(def origin (current parser))
(def ast {:type :receive :data @[] :token origin})
(def clauses @[])
(expect parser :receive)
(advance parser)
(try
(do
(def open-brace (current parser))
(expect parser :lbrace) (advance parser)
(accept-many parser :newline)
(while (not (check parser :rbrace))
(when (check parser :eof)
(error {:type :error :token open-brace :msg "unclosed brace"}))
(array/push clauses (match-clause parser)))
(advance parser)
@{:type :receive :data [clauses] :token origin})
([err] err)))
# {pattern} = {nonbinding} {terminators} # {pattern} = {nonbinding} {terminators}
(defn- with-clause [parser] (defn- with-clause [parser]
(try (try
@ -973,7 +992,7 @@
(def body (nonbinding parser)) (def body (nonbinding parser))
{:type :test :data [desc body] :token origin}) {:type :test :data [desc body] :token origin})
### loops and repeates ### loops and repeats
(defn- loopp [parser] (defn- loopp [parser]
(def origin (current parser)) (def origin (current parser))
(expect parser :loop) (advance parser) (expect parser :loop) (advance parser)
@ -1031,9 +1050,10 @@
:startdict (dict parser) :startdict (dict parser)
:startset (sett parser) :startset (sett parser)
:word (word-expr parser) :word (word-expr parser)
:pkg-name (pkg-name parser) # :pkg-name (pkg-name parser)
:recur (recur parser) :recur (recur parser)
:panic (panicc parser) :panic (panicc parser)
:do (doo parser)
(panic parser (string "expected simple expression, got " (type curr))) (panic parser (string "expected simple expression, got " (type curr)))
) )
) )
@ -1072,6 +1092,7 @@
:when (whenn parser) :when (whenn parser)
:match (matchh parser) :match (matchh parser)
:with (withh parser) :with (withh parser)
:receive (receive parser)
# do # do
:do (doo parser) :do (doo parser)
@ -1114,12 +1135,13 @@
:startdict (dict parser) :startdict (dict parser)
:startset (sett parser) :startset (sett parser)
:word (word-expr parser) :word (word-expr parser)
:pkg-name (pkg-name parser) # :pkg-name (pkg-name parser)
:recur (recur parser) :recur (recur parser)
:if (iff parser) :if (iff parser)
:when (whenn parser) :when (whenn parser)
:match (matchh parser) :match (matchh parser)
:with (withh parser) :receive (receive parser)
# :with (withh parser)
:do (doo parser) :do (doo parser)
:lbrace (block parser) :lbrace (block parser)
:loop (loopp parser) :loop (loopp parser)

View File

@ -1,20 +1,20 @@
(import /src/base :as b) (import /janet/base :as b)
(import /src/scanner :as s) (import /janet/scanner :as s)
(import /src/parser :as p) (import /janet/parser :as p)
(import /src/validate :as v) (import /janet/validate :as v)
(import /src/interpreter :as i) (import /janet/interpreter :as i)
(import /src/errors :as e) (import /janet/errors :as e)
(def pkg (do (def pkg (do
(def pre-ctx @{:^parent {"base" b/base}}) (def pre-ctx @{:^parent {"base" b/base}})
(def pre-src (slurp "../assets/prelude.ld")) (def pre-src (slurp "./assets/prelude.ld"))
(def pre-scanned (s/scan pre-src :prelude)) (def pre-scanned (s/scan pre-src :prelude))
(def pre-parsed (p/parse pre-scanned)) (def pre-parsed (p/parse pre-scanned))
(def parse-errors (pre-parsed :errors)) (def parse-errors (pre-parsed :errors))
(when (any? parse-errors) (each err parse-errors (e/parse-error err)) (break :error)) (when (any? parse-errors) (each err parse-errors (e/parse-error err)) (break :error))
(def pre-validated (v/valid pre-parsed pre-ctx)) # (def pre-validated (v/valid pre-parsed pre-ctx))
(def validation-errors (pre-validated :errors)) # (def validation-errors (pre-validated :errors))
(when (any? validation-errors) (each err validation-errors (e/validation-error err)) (break :error)) # (when (any? validation-errors) (each err validation-errors (e/validation-error err)) (break :error))
(try (try
(i/interpret (pre-parsed :ast) pre-ctx) (i/interpret (pre-parsed :ast) pre-ctx)
([err] (e/runtime-error err) :error)))) ([err] (e/runtime-error err) :error))))
@ -27,16 +27,16 @@
(set (ctx "^type") nil) (set (ctx "^type") nil)
ctx)) ctx))
(def post/src (slurp "postlude.ld")) # (def post/src (slurp "postlude.ld"))
(def post/ast (do # (def post/ast (do
(def post-ctx @{:^parent ctx}) # (def post-ctx @{:^parent ctx})
(def post-scanned (s/scan post/src :postlude)) # (def post-scanned (s/scan post/src :postlude))
(def post-parsed (p/parse post-scanned)) # (def post-parsed (p/parse post-scanned))
(def parse-errors (post-parsed :errors)) # (def parse-errors (post-parsed :errors))
(when (any? parse-errors) (each err parse-errors (e/parse-error err)) (break :error)) # (when (any? parse-errors) (each err parse-errors (e/parse-error err)) (break :error))
(def post-validated (v/valid post-parsed post-ctx)) # # (def post-validated (v/valid post-parsed post-ctx))
(def validation-errors (post-validated :errors)) # # (def validation-errors (post-validated :errors))
(when (any? validation-errors) (each err validation-errors (e/validation-error err)) (break :error)) # # (when (any? validation-errors) (each err validation-errors (e/validation-error err)) (break :error))
(post-parsed :ast))) # (post-parsed :ast)))

View File

@ -9,20 +9,21 @@
"false" :false ## impl -> literal word "false" :false ## impl -> literal word
"fn" :fn ## impl "fn" :fn ## impl
"if" :if ## impl "if" :if ## impl
"import" :import ## impl # "import" :import ## impl
"let" :let ## impl "let" :let ## impl
"loop" :loop ## impl "loop" :loop ## impl
"match" :match ## impl "match" :match ## impl
"nil" :nil ## impl -> literal word "nil" :nil ## impl -> literal word
"ns" :ns ## impl # "ns" :ns ## impl
"panic!" :panic ## impl (should _not_ be a function) "panic!" :panic ## impl (should _not_ be a function)
"pkg" :pkg # "pkg" :pkg
"receive" :receive
"recur" :recur ## impl "recur" :recur ## impl
"repeat" :repeat ## impl "repeat" :repeat ## impl
"test" :test # "test" :test
"then" :then ## impl "then" :then ## impl
"true" :true ## impl -> literal word "true" :true ## impl -> literal word
"use" :use ## wip # "use" :use ## wip
"when" :when ## impl, replaces cond "when" :when ## impl, replaces cond
"with" :with ## impl "with" :with ## impl
}) })

View File

@ -286,6 +286,13 @@ Deferred until a later iteration of Ludus:
(match-clauses validator clauses) (match-clauses validator clauses)
validator) validator)
(defn- receive [validator]
(def ast (validator :ast))
(def [clauses] (ast :data))
(match-clauses validator clauses)
validator)
(defn- declare [validator fnn] (defn- declare [validator fnn]
(def status (validator :status)) (def status (validator :status))
(def declared (get status :declared @{})) (def declared (get status :declared @{}))
@ -758,6 +765,7 @@ Deferred until a later iteration of Ludus:
:loop (loopp validator) :loop (loopp validator)
:recur (recur validator) :recur (recur validator)
:box (box validator) :box (box validator)
:receive (receive validator)
(error (string "unknown node type " type))))) (error (string "unknown node type " type)))))
(set validate validate*) (set validate validate*)

View File

@ -38,3 +38,8 @@ release:
serve: serve:
live-server pkg live-server pkg
# build the documentation
doc:
janet janet/doc.janet
-rm doc/prelude.md
mv prelude.md doc/