docs: make doc work on top level and document macros (#1265)

This commit is contained in:
Veit Heller 2021-07-01 09:42:37 +02:00 committed by GitHub
parent 09c91c7f90
commit 97c0b5a61b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 3 deletions

View File

@ -1,3 +1,4 @@
(hidden thread-first-internal)
(defndynamic thread-first-internal [xs]
(if (= (length xs) 2)
(if (list? (last xs))
@ -13,6 +14,7 @@
(cdr (last xs)))
(list (last xs) (thread-first-internal (all-but-last xs))))))
(hidden thread-last-internal)
(defndynamic thread-last-internal [xs]
(if (= (length xs) 2)
(if (list? (last xs))
@ -30,12 +32,35 @@
(defmacro ==> [:rest forms]
(thread-last-internal forms))
(doc -> "threads the first form through the following ones, making it the first
argument.
Example:
```
(-> 1
(- 10)
(* 5)
) ; => -45
```")
(defmacro -> [:rest forms]
(thread-first-internal forms))
(doc --> "threads the first form through the following ones, making it the last
argument.
Example:
```
(--> 1
(- 10)
(/ 45)
) ; => 5
```")
(defmacro --> [:rest forms]
(thread-last-internal forms))
(hidden comp-internal)
(defndynamic comp-internal [sym fns]
(if (= (length fns) 0)
sym
@ -90,26 +115,33 @@
(list 'while (list 'not cnd)
body))
(doc let-do "is a `let` with an implicit `do` body.")
(defmacro let-do [bindings :rest forms]
(list 'let bindings
(cons 'do forms)))
(doc while-do "is a `while` with an implicit `do` body.")
(defmacro while-do [condition :rest forms]
(list 'while condition
(cons 'do forms)))
(doc defn-do "is a `defn` with an implicit `do` body.")
(defmacro defn-do [name arguments :rest body]
(eval (list 'defn name arguments (cons 'do body))))
(doc forever-do "is a `forever` with an implicit `do` body.")
(defmacro forever-do [:rest forms]
(list 'while true (cons 'do forms)))
(doc when "is an `if` without an else branch.")
(defmacro when [condition form]
(list 'if condition form (list)))
(doc unless "is an `if` without a then branch.")
(defmacro unless [condition form]
(list 'if condition (list) form))
(hidden case-internal)
(defndynamic case-internal [name xs]
(if (= (length xs) 0)
(list)
@ -122,8 +154,20 @@
(cadr xs)
(case-internal name (cddr xs)))))))
(defmacro case [name :rest forms]
(case-internal name forms))
(doc case "takes a form and a list of branches which are value and operation
pairs. If a value matches, the operation is executed. It takes a catch-all else
branch that is executed if nothing matches.
Example:
```
(case (+ 10 1)
10 (println* \"nope\")
11 (println* \"yup\")
(println* \"else branch\")
)
```")
(defmacro case [form :rest branches]
(case-internal form branches))
(defmodule Dynamic
(doc flip

View File

@ -1,10 +1,12 @@
;; Defining the meta data macros early so that they can be used by all the other code.
;; Defined early so that `doc` can accept a rest arg
(meta-set! map-internal "hidden" true)
(defndynamic map-internal [f xs acc]
(if (= 0 (length xs))
acc
(map-internal f (cdr xs) (cons-last (f (car xs)) acc))))
(meta-set! list-to-array-internal "hidden" true)
(defndynamic list-to-array-internal [xs acc]
(if (= 0 (length xs))
acc
@ -80,7 +82,7 @@
(Dynamic.String.concat [x newline])))
strings
())]
(list 'meta-set! name "doc" (Dynamic.String.concat (list-to-array-internal separated [])))))
(eval (list 'meta-set! name "doc" (Dynamic.String.concat (list-to-array-internal separated []))))))
(doc print-doc "Print the documentation for a binding.")
(defmacro print-doc [name]
@ -113,6 +115,10 @@
(if (= 1 (length xs))
(car xs)
(list 'if (car xs) (and- (cdr xs)) false) )))
(doc and "evaluates the forms `xs` one at a time, from left to right. If a form
evaluates to `false`, `and` returns that value and doesn't evaluate any of the
other expressions, otherwise it returns the value of the last form in `xs`.
`(and)` returns `true`.")
(defmacro and [:rest xs]
(and- xs))
@ -126,6 +132,10 @@
(if (= 1 (length xs))
(car xs)
(list 'if (car xs) true (or- (cdr xs))) )))
(doc or "evaluates the forms `xs` one at a time, from left to right. If a form
evaluates to `true`, `or` returns that value and doesn't evaluate any of the
other expressions, otherwise it returns the value of the last form in `xs`.
`(or)` returns `false`.")
(defmacro or [:rest xs]
(or- xs))
@ -142,6 +152,7 @@
(defmacro hidden? [name]
(eval (list 'not (list 'list? (list 'meta name "hidden")))))
(hidden annotate-helper)
(defndynamic annotate-helper [name annotation]
(list 'cons annotation (list 'meta name "annotations")))
@ -168,6 +179,7 @@
(eval (list 'hidden name))
(list 'def name value)))
(hidden cond-internal)
(defndynamic cond-internal [xs]
(if (= (length xs) 0)
(list)
@ -194,16 +206,22 @@
(defmacro cond [:rest xs]
(cond-internal xs))
(doc refstr "stringifies `x` and takes the reference of that string.")
(defmacro refstr [x]
(list 'ref
(list 'str x)))
(doc swap! "swaps its arguments `x` and `y` in place.
*Note*: Unhygienic!")
(defmacro swap! [x y]
(list 'let (array 'tmp y) (list 'do (list 'set! y x) (list 'set! x 'tmp))))
(doc update! "updates `x` in place using the function `f`.")
(defmacro update! [x f]
(list 'set! x (list f x)))
(hidden use-all-fn)
(defndynamic use-all-fn [names]
(if (= (length names) 0)
(macro-error "Trying to call use-all without arguments")
@ -213,17 +231,22 @@
()
(use-all-fn (cdr names))))))
(doc use-all "is a variadic version of `use`.")
(defmacro use-all [:rest names]
(use-all-fn names))
(doc load-and-use "loads a file and uses the module with in it. Assumes that
the filename and module name are the same.")
(defmacro load-and-use [name]
(do
(eval (list 'load (str name ".carp")))
(eval (list 'use name))))
(doc comment "ignores `forms`.")
(defmacro comment [:rest forms]
())
(hidden build-vararg)
(defndynamic build-vararg [func forms]
(if (= (length forms) 0)
(macro-error "vararg macro needs at least one argument")
@ -231,6 +254,7 @@
(car forms)
(list func (car forms) (build-vararg func (cdr forms))))))
(doc ignore "ignores the return value of the expression `form`.")
(defmacro ignore [form]
(list 'let (array '_ form) (list)))
@ -253,6 +277,7 @@
(defmacro inline-c [name defcode :rest declcode]
(eval (list 'deftemplate name (list) defcode (if (empty? declcode) "" (car declcode)))))
(doc bottom "aborts the program if reached.")
(deftemplate bottom (Fn [] a) "$a $NAME()" "$DECL { abort(); }")
(doc unreachable
@ -270,6 +295,7 @@
(list 'System.abort)
(list 'bottom)))
(hidden implement-declaration)
(defndynamic implement-declaration [mod interface]
(list 'implements interface (Symbol.prefix mod interface)))