Compare commits

..

3 Commits

Author SHA1 Message Date
Scott Richmond
68aca09de6 updated janet-based docs 2024-06-15 17:04:01 -04:00
Scott Richmond
d94eb5485d fix some bugs, prep for doc 2024-06-15 17:03:49 -04:00
Scott Richmond
98d6b1c865 fix some bugs 2024-06-15 17:03:37 -04:00
4 changed files with 736 additions and 305 deletions

View File

@ -18,7 +18,7 @@ fn join
fn neg?
fn atan/2
fn mod
fn assoc?
fn assoc & ?
fn dict
fn get
fn unbox
@ -370,14 +370,26 @@ fn ws? {
(_) -> false
}
fn strip {
"Removes punctuation from a string, removing all instances of ,.;:?!"
("{x},{y}") -> strip ("{x}{y}")
("{x}.{y}") -> strip ("{x}{y}")
("{x};{y}") -> strip ("{x}{y}")
("{x}:{y}") -> strip ("{x}{y}")
("{x}?{y}") -> strip ("{x}{y}")
("{x}!{y}") -> strip ("{x}{y}")
(x) -> x
}
fn words {
"Takes a string and returns a list of the words in the string. Strips all whitespace."
(str as :string) -> {
let raw_strs = split (str, " ")
fn joiner (list, str) -> if eq? (str, "")
let no_punct = strip (str)
let strs = split (no_punct, " ")
fn worder (list, str) -> if empty? (str)
then list
else append (list, str)
fold (joiner, raw_strs, [])
fold (worder, strs, [])
}
}
@ -502,6 +514,11 @@ fn inv/0 {
(x as :number) -> div/0 (1, x)
}
fn inv/safe {
"Returns the inverse of a number: 1/n or `div/safe (1, n)`. Returns a result tuple."
(x as :number) -> div/safe (1, x)
}
fn abs {
"Returns the absolute value of a number."
(0) -> 0
@ -620,16 +637,13 @@ fn max {
& additional list operations now that we have comparitors
fn at {
"Returns the element at index n of a list or tuple. Zero-indexed: the first element is at index 0."
(xs as :list, n as :number) -> when {
neg? (n) -> nil
gte? (n, count (xs)) -> nil
true -> base :nth (n, xs)
}
(xs as :tuple, n as :number) -> when {
neg? (n) -> nil
gte? (n, count (xs)) -> nil
true -> base :nth (n, xs)
"Returns the element at index n of a list or tuple, or the byte at index n of a string. Zero-indexed: the first element is at index 0. Returns nil if nothing is found in a list or tuple; returns an empty string if nothing is found in a string."
(xs as :list, n as :number) -> base :nth (xs, n)
(xs as :tuple, n as :number) -> base :nth (n, xs)
(str as :string, n as :number) -> when {
neg? (n) -> ""
gte? (n, count (str)) -> ""
true -> base :slice (str, n, inc (n))
}
(_) -> nil
}
@ -741,21 +755,17 @@ fn update {
}
fn keys {
"Takes an associative collection and returns a list of keys in that collection. Returns an empty list on anything other than a collection."
(coll) -> if not (assoc? (coll))
then []
else do coll > list > map (first, _)
"Takes a dict and returns a list of keys in that dict."
(dict as :dict) -> do dict > list > map (first, _)
}
fn values {
"Takes an associative collection and returns a list of values in that collection. Returns an empty list on anything other than a collection."
(coll) -> if not (assoc? (coll))
then []
else do coll > list > map (second, _)
"Takes a dict and returns a list of values in that dict."
(dict) -> do dict > list > map (second, _)
}
fn diff {
"Takes two associate data structures and returns a dict describing their differences. Does this shallowly, offering diffs only for keys in the original dict."
"Takes two dicts and returns a dict describing their differences. Does this shallowly, offering diffs only for keys in the original dict."
(d1 as :dict, d2 as :dict) -> {
let key1 = keys (d1)
let key2 = keys (d2)
@ -782,7 +792,7 @@ fn diff {
}
fn coll? {
"Returns true if a value is a collection: dict, struct, list, tuple, or set."
"Returns true if a value is a collection: dict, list, pkg, tuple, or set."
(coll as :dict) -> true
(coll as :list) -> true
(coll as :tuple) -> true
@ -799,7 +809,7 @@ fn ordered? {
}
fn assoc? {
"Returns true if a value is an associative collection: a dict, struct, or namespace."
"Returns true if a value is an associative collection: a dict or a pkg."
(assoc as :dict) -> true
(assoc as :pkg) -> true
(_) -> false
@ -807,10 +817,10 @@ fn assoc? {
& TODO: consider merging `get` and `at`
fn get {
"Takes a dict or struct, key, and optional default value; returns the value at key. If the value is not found, returns nil or the default value. Returns nil or default if the first argument is not a dict or struct."
"Takes a key, dict, and optional default value; returns the value at key. If the value is not found, returns nil or the default value."
(key as :keyword) -> get (key, _)
(key as :keyword, coll) -> base :get (key, coll)
(key as :keyword, coll, default) -> base :get (key, coll, default)
(key as :keyword, dict as :dict) -> get (key, dict)
(key as :keyword, dict as :dict, default) -> base :get (key, dict, default)
}
& TODO: add sets to this?
@ -1338,159 +1348,164 @@ fn penwidth {
box state = nil
pkg Prelude {
abs
add
and
angle
any?
append
assert!
assoc
assoc?
at
atan/2
back!
background!
between?
bg!
bgcolor
bk!
bool
bool?
box?
butlast
ceil
clear!
coll?
colors
concat
cos
count
dec
deg/rad
deg/turn
dict
dict?
diff
dissoc
dist
div
div/0
div/safe
doc!
downcase
each!
empty?
eq?
err
err?
even?
false?
fd!
filter
first
floor
fn?
fold
forward!
get
goto!
gt?
gte?
heading
heading/vector
home!
inc
inv
inv/0
join
keep
keys
keyword?
last
left!
list
load_turtle_state!
lt!
lt?
lte?
map
max
min
mod
mult
neg
neg?
neq?
nil?
not
odd?
ok
ok?
or
ordered?
p5_calls
pc!
pd!
pencolor
pencolor!
pendown!
pendown?
penup!
penwidth
penwidth!
pi
pos?
position
print!
prn!
pu!
pw!
rad/deg
rad/turn
random
random_int
range
render_turtle!
report!
reset_turtle!
rest
right!
round
rt!
second
set
set?
show
sin
slice
some
some?
split
square
state
store!
string
string?
sub
sum_of_squares
tan
tau
trim
tuple?
turn/deg
turn/rad
turtle_commands
turtle_state
turtle_states
type
unbox
unwrap!
unwrap_or
upcase
update
update!
values
words
zero?
abs & math
add & math
and & bool
angle & math
any? & dicts lists strings sets tuples
append & lists sets
assert! & errors
assoc & dicts
assoc? & dicts
at & lists strings
atan/2 & math
back! & turtles
background! & turtles
between? & math
bg! & turtles
bgcolor & turtles
bk! & turtles
bool & bool
bool? & bool
box? & boxes
butlast & lists strings tuples
ceil & math
clear! & turtles
coll? & dicts lists sets tuples
colors & turtles
concat & string list set
cos & math
count & string list set tuple dict
dec & math
deg/rad & math
deg/turn & math
dict & dict
dict? & dict
diff & dict
dissoc & dict
dist & math
div & math
div/0 & math
div/safe & math
doc! & env
downcase & string
each! & list
empty? & list dict set string tuple
eq? & values
err & result
err? & result
even? & math
false? & bool
fd! & turtles
filter & list
first & list tuple
floor & math
fn? & functions
fold & lists
forward! & turtles
get & dicts
goto! & turtles
gt? & math
gte? & math
heading & turtles
heading/vector & math
home! & turtles
inc & math
inv & math
inv/0 & math
inv/safe & math
join & lists strings
keep & lists
keys & dicts
keyword? & keywords
last & lists tuples
left! & turtles
list & lists
list? & lists
load_turtle_state! & turtles
lt! & turtles
lt? & math
lte? & math
map & lists
max & math
min & math
mod & math
mult & math
neg & math
neg? & math
neq? & values
nil? & nil
not & bool
odd? & math
ok & results
ok? & results
or & bool
ordered? & lists tuples strings
p5_calls & turtles
pc! & turtles
pd! & turtles
pencolor & turtles
pencolor! & turtles
pendown! & turtles
pendown? & turtles
penup! & turtles
penwidth & turtles
penwidth! & turtles
pi & math
pos? & math
position & turtles
print! & environment
& prn! & environment
pu! & turtles
pw! & turtles
rad/deg & math
rad/turn & math
random & math dicts lists tuples sets
random_int & math
range & math lists
render_turtle! & turtles
report! & environment
reset_turtle! & turtles
rest & lists tuples
right! & turtles
round & math
rt! & turtles
second & lists tuples
sentence & lists strings
set & sets
set? & sets
show & strings
sin & math
slice & lists tuples strings
some & values
some? & values
split & strings
square & math
state & environment
store! & boxes
string & strings
string? & strings
strip & strings
sub & math
sum_of_squares & math
tan & math
tau & math
trim & strings
tuple? & tuples
turn/deg & math
turn/rad & math
turtle_commands & turtles
turtle_state & turtles
turtle_states & turtles
type & values
unbox & boxes
unwrap! & results
unwrap_or & results
upcase & strings
update & dicts
update! & boxes
values & dicts
words & strings lists
ws? & strings
zero? & math
}

File diff suppressed because one or more lines are too long

View File

@ -130,8 +130,12 @@
(string/join (map (fn [x] (-> x first show-patt)) clauses) "\n"))
(defn doc [fnn]
(def {:name name :doc doc} fnn)
(string/join [name (pretty-patterns fnn) doc] "\n"))
(when (not= :fn (ludus/type fnn)) (break "No documentation available."))
(def {:name name :doc docstring} fnn)
(string/join [name
(pretty-patterns fnn)
(if docstring docstring "No docstring available.")]
"\n"))
(defn- conj!-set [sett value]
(set (sett value) true)

127
src/doc.janet Normal file
View File

@ -0,0 +1,127 @@
(import /src/base :as base)
(import /src/prelude :as prelude)
(defn map-values [f dict]
(from-pairs (map (fn [[k v]] [k (f v)]) (pairs dict))))
(def with-docs (map-values base/doc prelude/ctx))
(def sorted-names (-> with-docs keys sort))
(defn escape-underscores [str] (string/replace "_" "\\_" str))
(defn escape-punctuation [str] (->> str
(string/replace "?" "")
(string/replace "!" "")))
(defn toc-entry [name]
(def escaped (escape-underscores name))
(string "[" escaped "](#" (escape-punctuation escaped) ")"))
(def alphabetical-list
(string/join (map toc-entry sorted-names) "    "))
(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" "mult" "neg" "neg?" "odd?" "pi" "pos?" "rad/deg" "rad/turn" "random" "random_int" "range" "round" "sin" "square" "sub" "sum_of_squares" "tan" "tau" "turn/deg" "turn/rad" "zero?"]
"boolean" ["and" "bool" "bool?" "false?" "not" "or"]
"dicts" ["any?" "assoc" "assoc?" "coll?" "count" "dict" "dict?" "diff" "dissoc" "empty?" "get" "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"]
"sets" ["any?" "append" "coll?" "concat" "count" "empty?" "random" "set" "set?"]
"strings" ["any?" "concat" "count" "downcase" "empty?" "join" "sentence" "show" "slice" "split" "string" "string?" "strip" "trim" "upcase" "words"]
"types and values" ["assoc?" "bool?" "coll?" "dict?" "eq?" "fn?" "keyword?" "list?" "neq?" "nil?" "number?" "ordered?" "show" "some" "some?" "string?" "type"]
"boxes and state" ["unbox" "store!" "update!"]
"results" ["err" "err?" "ok" "ok?" "unwrap!" "unwrap_or"]
"errors" ["assert!"]
"turtle graphics" ["back!" "background!" "bk!" "clear!" "colors" "fd!" "forward!" "goto!" "heading" "heading/vector" "home!" "left!" "lt!" "pc!" "pd!" "pencolor" "pencolor!" "pendown!" "pendown?" "penup!" "penwidth" "penwidth!" "position" "pu!" "pw!" "render_turtle!" "reset_turtle!" "right!" "rt!" "turtle_state"]
"environment and i/o" ["doc!" "print!" "report!" "state"]
})
(defn capitalize [str]
(def fst (slice str 0 1))
(def rest (slice str 1))
(def init_cap (string/ascii-upper fst))
(def lower_rest (string/ascii-lower rest))
(string init_cap lower_rest))
(defn topic-entry [topic]
(string "### " (capitalize topic) "\n"
(as-> topic _ (topics _) (slice _) (sort _) (map toc-entry _)
(string/join _ "    "))
"\n"))
(def by-topic (let [the-topics (-> topics keys sort)
topics-entries (map topic-entry the-topics)]
(string/join topics-entries "\n")))
(defn compose-entry [name]
(def header (string "### " name "\n"))
(def the-doc (get with-docs name))
(when (= "No documentation available." the-doc)
(break (string header the-doc "\n")))
(def lines (string/split "\n" the-doc))
(def description (last lines))
(def patterns (string/join (slice lines 1 (-> lines length dec)) "\n"))
(string header description "\n```\n" patterns "\n```\n"))
(compose-entry "update")
(def entries (string/join (map compose-entry sorted-names) "\n\n"))
(def doc-file (string
```
# Ludus prelude documentation
These functions are available in every Ludus script.
The documentation for any function can be found within Ludus by passing the function to `doc!`,
e.g., running `doc! (add)` will send the documentation for `add` to the console.
For more information on the syntax & semantics of the Ludus language, see [language.md](./language.md).
## A few notes
**Naming conventions.** Functions whose name ends with a question mark, e.g., `eq?`, return booleans.
Functions whose name ends with an exclamation point, e.g., `make!`, change state in some way.
In other words, they _do things_ rather than _calculating values_.
Functions whose name includes a slash either convert from one value to another, e.g. `deg/rad`,
or they are variations on a function, e.g. `div/0` as a variation on `div`.
**How entries are formatted.** Each entry has a brief (sometimes too brief!) description of what it does.
It is followed by the patterns for each of its function clauses.
This should be enough to indicate order of arguments, types, and so on.
**Patterns often, but do not always, indicate types.** Typed patterns are written as `foo as :bar`,
where the type is indicated by the keyword.
Possible ludus types are: `:nil`, `:boolean`, `:number`, `:keyword` (atomic values);
`:string` (strings are their own beast); `:tuple` and `:list` (indexed collections); `:set` (sets are specific),
`:dict` and `:ns` (associative collections); and `:ref` (references).
**Conventional types.** Ludus has two types based on conventions.
* _Result tuples._ Results are a way of modeling the result of a calculation that might fail.
The two possible values are `(:ok, value)` and `(:err, msg)`.
`msg` is usually a string describing what went wrong.
To work with result tuples, see [`unwrap!`](#unwrap) and [`unwrap_or`](#unwrap_or).
That said, usually you work with these using pattern matching.
* _Vectors._ Vectors are 2-element tuples of x and y coordinates.
The origin is `(0, 0)`.
Many math functions take vectors as well as numbers, e.g., `add` and `mult`.
You will see vectors indicated in patterns by an `(x, y)` tuple.
You can see what this looks like in the last clause of `add`: `((x1, y1), (x2, y2))`.
## Functions by topic
```
by-topic
```
## All functions, alphabetically
```
alphabetical-list
```
## Function documentation
```
entries
))
(spit "prelude.md" doc-file)