From efded2f9b8c4bcbda829d4525c6cec8d2a38e716 Mon Sep 17 00:00:00 2001 From: Felix Brendel Date: Thu, 27 Jun 2019 11:11:18 +0200 Subject: [PATCH] lota things --- bin/alist.slime | 96 ++ bin/cxr.slime | 39 + bin/pre.slime | 105 +- bin/pre.slime.expanded | 57 +- bin/tests/alists.slime | 49 + manual/built-in-docs.org | 285 ++-- manual/manual.html | 2722 ++++++++++++++++++++++++++++++++++++++ manual/manual.org | 3 + src/defines.cpp | 4 +- src/docgeneration.cpp | 2 +- src/io.cpp | 46 +- src/main.cpp | 3 +- src/testing.cpp | 1 + 13 files changed, 3212 insertions(+), 200 deletions(-) create mode 100644 bin/alist.slime create mode 100644 bin/cxr.slime create mode 100644 bin/tests/alists.slime create mode 100644 manual/manual.html diff --git a/bin/alist.slime b/bin/alist.slime new file mode 100644 index 0000000..e9898f2 --- /dev/null +++ b/bin/alist.slime @@ -0,0 +1,96 @@ +(import "cxr.slime") + +;; alist: +;; [ |/] +;; | +;; V +;; [ | ]------------->[ | ]-------------> ... +;; | | +;; V V +;; [ | ]->value1 [ | ]->value2 +;; | | +;; V V +;; key1 key2 +;; +;; '(((key1 . value1) (key2 . value2))) +(define key-not-found-index -1) + +(define (make-alist) + '(())) + +(define (pprint-alist alist) + (let ((associations (first alist))) + (define (pprint-intern associations) + (when associations + (printf " " + (caar associations) "->" + (cdar associations)) + (pprint-intern (rest associations)))) + (print "(") + (when associations + (print "\n") + (pprint-intern associations)) + (print ")\n"))) + + +(define (alist-get alist key) + (let ((associations (first alist))) + (define (alist-get-intern associations key) + (cond ((null? associations) + (error "key was not found in alist")) + ((= (caar associations) key) + (cdar associations)) + (else (alist-get-intern (rest alist) key)))) + (alist-get-intern associations key))) + + +(define (alist-find alist key) + (let ((associations (first alist))) + (define (alist-find-intern associations key current-index) + (cond ((null? associations) key-not-found-index) + ((= (caar associations) key) current-index) + (else (alist-find-intern (rest associations) + key + (+ 1 current-index))))) + (alist-find-intern associations key 0))) + + +(define (alist-key-exists? alist key) + (not (= (alist-find alist key) + key-not-found-index))) + + +(define (alist-remove! alist key) + (let ((index (alist-find alist key))) + (define (alist-remove!-internal asociations index) + ;; reminder: we only get called if we are not replacing the + ;; first element in the alist + ;; reminder2: we know that the key exists + (if (= index 1) + ;; we want to remove the next one, so we set our + ;; cdr to the next next one + (mutate associations (pair (first associations) + (rest (rest associations)))) + ;; else cdr-recurse + (alist-remove!-internal (rest asociations) (- index 1)))) + + (cond ((= index key-not-found-index) (error "key to remove was not found")) + ((= index 0) (mutate alist (pair (cdar alist) ()))) + (else (alist-remove!-internal alist index))))) + + +(define (alist-set! alist key value) + (mutate alist (pair (pair (pair key value) + (car alist)) + ()))) + + +(define (alist-set-overwrite! alist key value) + (let ((associations (first alist))) + (define (alist-set-overwrite-intern associations key value) + (cond ((= (caar associations) key) + (mutate (car associations) (pair key value))) + ((null? associations) (alist-set! alist key value)) + (else (alist-set-overwrite-intern + (rest associations) key value)))) + (alist-set-overwrite-intern associations key value))) diff --git a/bin/cxr.slime b/bin/cxr.slime new file mode 100644 index 0000000..7dafcc9 --- /dev/null +++ b/bin/cxr.slime @@ -0,0 +1,39 @@ +(define cons pair) +(define car first) +(define cdr rest) + +(define (caar seq) + (car (car seq))) + +(define (cddr seq) + (cdr (cdr seq))) + +(define (cadr seq) + (car (cdr seq))) + +(define (cdar seq) + (cdr (car seq))) + +(define (caaar seq) + (car (caar seq))) + +(define (caadr seq) + (caar (cdr seq))) + +(define (cadar seq) + (car (cdr (car seq)))) + +(define (caddr seq) + (car (cddr seq))) + +(define (cdaar seq) + (cdr (caar seq))) + +(define (cdadr seq) + (cdr (car (cdr seq)))) + +(define (cddar seq) + (cddr (car seq))) + +(define (cdddr seq) + (cdr (cddr seq))) diff --git a/bin/pre.slime b/bin/pre.slime index b2ed1f1..ffe7f9e 100644 --- a/bin/pre.slime +++ b/bin/pre.slime @@ -2,12 +2,27 @@ `(printf ',expr "evaluates to" ,expr)) (define-syntax (when condition :rest body) - "Doc String for `when'" + "Special form for when multiple actions should be done if a +condition is true. + +{{{example_start}}} +(when (not ()) + (print \"Hello \") + (print \"from \") + (print \"when!\")) + +(when () + (print \"Goodbye \") + (print \"World!\")) +{{{example_end}}} +" (if (= (rest body) ()) `(if ,condition @body) `(if ,condition (begin @body)))) (define-syntax (unless condition :rest body) + "Special form for when multiple actions should be done if a +condition is false." (if (= (rest body) ()) `(if ,condition nil @body) `(if ,condition nil (begin @body)))) @@ -55,9 +70,11 @@ (define-syntax (construct-list :rest body) " +{{{example_start}}} (construct-list i <- '(1 2 3 4 5) yield (* i i)) +{{{example_end}}} (construct-list i <- '(1 2 3 4) @@ -68,7 +85,6 @@ i <- '(1 2 3 4 5 6 7 8) when (evenp i) yield i) - " (define (append-map f ll) (unless (= ll ()) @@ -113,7 +129,7 @@ ithe sequence as arguemens." :package))))) -(define (nil? x) +(define (null? x) "Checks if the argument is =nil=." (= x nil)) @@ -160,13 +176,25 @@ ithe sequence as arguemens." (built-in-function? x))) (define (end seq) - "Returns the last pair in the sqeuence." - (if (or (nil? seq) (not (pair? (rest seq)))) + "Returns the last pair in the sqeuence. + +{{{example_start}}} +(define a (list 1 2 3 4)) +(printf (end a)) +{{{example_end}}} +" + (if (or (null? seq) (not (pair? (rest seq)))) seq (end (rest seq)))) (define (last seq) - "Returns the (first) of the last (pair) of the given sequence." + "Returns the (first) of the last (pair) of the given sequence. + +{{{example_start}}} +(define a (list 1 2 3 4)) +(printf (last a)) +{{{example_end}}} +" (first (end seq))) (define (extend seq elem) @@ -197,10 +225,23 @@ with (pair elem nil)." (define (length seq) "Returns the length of the given sequence." - (if (nil? seq) + (if (null? seq) 0 (+ 1 (length (rest seq))))) +(define (sublist-starting-at-index seq index) + (cond ((< index 0) + (error "sublist-starting-at-index: index must be positive")) + ((null? seq) ()) + ((= 0 index) seq) + (else (sublist-starting-at (rest seq) (- index 1))))) + +(define (list-without-index seq index) + (cond ((or (< index 0) (null? seq)) + (error "list-remove-index!: index out of range")) + ((= 0 index) (rest seq)) + (else (pair (first seq) (list-without-index (rest seq) (- index 1)))))) + (define (increment val) "Adds one to the argument." (+ val 1)) @@ -232,7 +273,7 @@ by the key 'from' and ends with the number defined in 'to'." "Takes a function and a sequence as arguments and returns a new sequence which contains the results of using the first sequences elemens as argument to that function." - (if (nil? seq) + (if (null? seq) seq (pair (fun (first seq)) (map fun (rest seq))))) @@ -246,11 +287,11 @@ instead." (apply fun seq)) (define (reduce-binary fun seq) - "Takes a function and a sequence as arguments and applies the -function to the argument sequence. reduce-binary applies the -arguments `pair-wise' which means it works with binary functions -as compared to `reduce'." - (if (nil? (rest seq)) + "Takes a function and a sequence as arguments and applies the +function to the argument sequence. reduce-binary applies the arguments +*pair-wise* which means it works with binary functions as compared to +[[=reduce=]]." + (if (null? (rest seq)) (first seq) (fun (first seq) (reduce-binary fun (rest seq))))) @@ -268,7 +309,7 @@ added to a list, which in the end is returned." (define (zip l1 l2) - (unless (and (nil? l1) (nil? l2)) + (unless (and (null? l1) (null? l2)) (pair (list (first l1) (first l2)) (zip (rest l1) (rest l2))))) @@ -280,9 +321,9 @@ added to a list, which in the end is returned." (iter (rest lists) (pair (first elem) l1) (pair (first (rest elem)) l2)) - (list l1 l2)))) + (list l1 l2))) - (iter lists () ())) + (iter lists () ()))) (define (enumerate seq) (define (enumerate-inner seq next-num) @@ -291,20 +332,20 @@ added to a list, which in the end is returned." (enumerate-inner (rest seq) (+ 1 next-num))))) (enumerate-inner seq 0)) - (define (printf :keys sep :defaults-to " " end :defaults-to "\n" :rest args) - "A wrapper for the built-in (print) that accepts a variable number -of arguments and also provides keywords for specifying the printed -separators between the arguments and what should be printed after the -las argument." - (define printf-quoted (special-lambda (:keys sep end :rest args) - (if (nil? args) - (begin (print (eval end)) nil) - (begin - (print (first args)) - (unless (nil? (rest args)) - (print (eval sep))) - (eval (pair printf-quoted - (extend (list :sep (eval sep) :end (eval end)) (rest args)))))))) - - (eval (pair printf-quoted (extend (list :sep (eval sep) :end (eval end)) args)))) + "A wrapper for the built-in function [[=print=]] that accepts a +variable number of arguments and also provides keywords for specifying +the printed separators (=sep=) between the arguments and what should +be printed after the last argument (=end=)." + (define (printf-inner args) + (if args + (begin + (print (first args)) + (when (rest args) + (print sep)) + (printf-inner (rest args))) + ; else + (print end))) + + (printf-inner args) + ()) diff --git a/bin/pre.slime.expanded b/bin/pre.slime.expanded index bba9bd2..41813de 100644 --- a/bin/pre.slime.expanded +++ b/bin/pre.slime.expanded @@ -1,4 +1,4 @@ -(define (nil? x) "Checks if the argument is =nil=." (= x nil)) +(define (null? x) "Checks if the argument is =nil=." (= x nil)) (define (number? x) "Checks if the argument is a number." (= (type x) :number)) @@ -20,60 +20,43 @@ (define (callable? x) (or (lambda? x) (special-lambda? x) (macro? x) (built-in-function? x))) -(define (end seq) "Returns the last pair in the sqeuence." (if (or (nil? seq) (not (pair? (rest seq)))) seq (end (rest seq)))) +(define (end seq) "Returns the last pair in the sqeuence.\n\n{{{example_start}}}\n(define a (list 1 2 3 4))\n(printf (end a))\n{{{example_end}}}\n" (if (or (null? seq) (not (pair? (rest seq)))) seq (end (rest seq)))) -(define (last seq) "Returns the (first) of the last (pair) of the given sequence." (first (end seq))) +(define (last seq) "Returns the (first) of the last (pair) of the given sequence.\n\n{{{example_start}}}\n(define a (list 1 2 3 4))\n(printf (last a))\n{{{example_end}}}\n" (first (end seq))) -(define (extend seq elem) "Extends a list with the given element, by putting it in -the (rest) of the last element of the sequence." (if (pair? seq) (begin (define e (end seq)) (mutate e (pair (first e) elem)) seq) elem)) +(define (extend seq elem) "Extends a list with the given element, by putting it in\nthe (rest) of the last element of the sequence." (if (pair? seq) (begin (define e (end seq)) (mutate e (pair (first e) elem)) seq) elem)) -(define (extend2 seq elem) "Extends a list with the given element, by putting it in -the (rest) of the last element of the sequence." (printf "addr of (end seq)" (addr-of (end seq))) (if (pair? seq) (let ((e (end seq))) (printf "addr if e inner" (addr-of e)) (mutate e (pair (first e) elem)) seq)) elem) +(define (extend2 seq elem) "Extends a list with the given element, by putting it in\nthe (rest) of the last element of the sequence." (printf "addr of (end seq)" (addr-of (end seq))) (if (pair? seq) (let ((e (end seq))) (printf "addr if e inner" (addr-of e)) (mutate e (pair (first e) elem)) seq)) elem) -(define (append seq elem) "Appends an element to a sequence, by extendeing the list -with (pair elem nil)." (extend seq (pair elem ()))) +(define (append seq elem) "Appends an element to a sequence, by extendeing the list\nwith (pair elem nil)." (extend seq (pair elem ()))) -(define (length seq) "Returns the length of the given sequence." (if (nil? seq) 0 (+ 1 (length (rest seq))))) +(define (length seq) "Returns the length of the given sequence." (if (null? seq) 0 (+ 1 (length (rest seq))))) + +(define (sublist-starting-at-index seq index) (cond ((< index 0) (error "sublist-starting-at-index: index must be positive")) ((null? seq) ()) ((= 0 index) seq) (else (sublist-starting-at (rest seq) (- index 1))))) + +(define (list-without-index seq index) (cond ((or (< index 0) (null? seq)) (error "list-remove-index!: index out of range")) ((= 0 index) (rest seq)) (else (pair (first seq) (list-without-index (rest seq) (- index 1)))))) (define (increment val) "Adds one to the argument." (+ val 1)) (define (decrement val) "Subtracts one from the argument." (- val 1)) -(define (range :keys from :defaults-to 0 to) "Returns a sequence of numbers starting with the number defined by the -key =from= and ends with the number defined in =to=." (when (< from to) (pair from (range :from (+ 1 from) :to to)))) +(define (range :keys from :defaults-to 0 to) "Returns a sequence of numbers starting with the number defined by the\nkey =from= and ends with the number defined in =to=." (when (< from to) (pair from (range :from (+ 1 from) :to to)))) -(define (range-while :keys from :defaults-to 0 to) "Returns a sequence of numbers starting with the number defined -by the key 'from' and ends with the number defined in 'to'." (define result (list (copy from))) (define head result) (mutate from (increment from)) (while (< from to) (begin (mutate head (pair (first head) (pair (copy from) nil))) (define head (rest head)) (mutate from (increment from)))) result) +(define (range-while :keys from :defaults-to 0 to) "Returns a sequence of numbers starting with the number defined\nby the key 'from' and ends with the number defined in 'to'." (define result (list (copy from))) (define head result) (mutate from (increment from)) (while (< from to) (begin (mutate head (pair (first head) (pair (copy from) nil))) (define head (rest head)) (mutate from (increment from)))) result) -(define (map fun seq) "Takes a function and a sequence as arguments and returns a new -sequence which contains the results of using the first sequences -elemens as argument to that function." (if (nil? seq) seq (pair (fun (first seq)) (map fun (rest seq))))) +(define (map fun seq) "Takes a function and a sequence as arguments and returns a new\nsequence which contains the results of using the first sequences\nelemens as argument to that function." (if (null? seq) seq (pair (fun (first seq)) (map fun (rest seq))))) -(define (reduce fun seq) "Takes a function and a sequence as arguments and applies the -function to the argument sequence. This only works correctly if the -given function accepts a variable amount of parameters. If your -funciton is limited to two arguments, use [[=reduce-binary=]] -instead." (apply fun seq)) +(define (reduce fun seq) "Takes a function and a sequence as arguments and applies the\nfunction to the argument sequence. This only works correctly if the\ngiven function accepts a variable amount of parameters. If your\nfunciton is limited to two arguments, use [[=reduce-binary=]]\ninstead." (apply fun seq)) -(define (reduce-binary fun seq) "Takes a function and a sequence as arguments and applies the -function to the argument sequence. reduce-binary applies the -arguments `pair-wise' which means it works with binary functions -as compared to `reduce'." (if (nil? (rest seq)) (first seq) (fun (first seq) (reduce-binary fun (rest seq))))) +(define (reduce-binary fun seq) "Takes a function and a sequence as arguments and applies the\nfunction to the argument sequence. reduce-binary applies the arguments\n*pair-wise* which means it works with binary functions as compared to\n[[=reduce=]]." (if (null? (rest seq)) (first seq) (fun (first seq) (reduce-binary fun (rest seq))))) -(define (filter fun seq) "Takes a function and a sequence as arguments and applies the -function to every value in the sequence. If the result of that -funciton application returns a truthy value, the original value is -added to a list, which in the end is returned." (when seq (if (fun (first seq)) (pair (first seq) (filter fun (rest seq))) (filter fun (rest seq))))) +(define (filter fun seq) "Takes a function and a sequence as arguments and applies the\nfunction to every value in the sequence. If the result of that\nfunciton application returns a truthy value, the original value is\nadded to a list, which in the end is returned." (when seq (if (fun (first seq)) (pair (first seq) (filter fun (rest seq))) (filter fun (rest seq))))) -(define (zip l1 l2) (unless (and (nil? l1) (nil? l2)) (pair (list (first l1) (first l2)) (zip (rest l1) (rest l2))))) +(define (zip l1 l2) (unless (and (null? l1) (null? l2)) (pair (list (first l1) (first l2)) (zip (rest l1) (rest l2))))) -(define (unzip lists) (when lists (define (iter lists l1 l2) (define elem (first lists)) (if elem (iter (rest lists) (pair (first elem) l1) (pair (first (rest elem)) l2)) (list l1 l2)))) (iter lists () ())) +(define (unzip lists) (when lists (define (iter lists l1 l2) (define elem (first lists)) (if elem (iter (rest lists) (pair (first elem) l1) (pair (first (rest elem)) l2)) (list l1 l2))) (iter lists () ()))) (define (enumerate seq) (define (enumerate-inner seq next-num) (when seq (pair (list (first seq) next-num) (enumerate-inner (rest seq) (+ 1 next-num))))) (enumerate-inner seq 0)) -(define (printf :keys sep :defaults-to " " end :defaults-to " -" :rest args) "A wrapper for the built-in (print) that accepts a variable number -of arguments and also provides keywords for specifying the printed -separators between the arguments and what should be printed after the -las argument." (define printf-quoted (special-lambda (:keys sep end :rest args) (if (nil? args) (begin (print (eval end)) nil) (begin (print (first args)) (unless (nil? (rest args)) (print (eval sep))) (eval (pair printf-quoted (extend (list :sep (eval sep) :end (eval end)) (rest args)))))))) (eval (pair printf-quoted (extend (list :sep (eval sep) :end (eval end)) args)))) +(define (printf :keys sep :defaults-to " " end :defaults-to "\n" :rest args) "A wrapper for the built-in function [[=print=]] that accepts a\nvariable number of arguments and also provides keywords for specifying\nthe printed separators (=sep=) between the arguments and what should\nbe printed after the last argument (=end=)." (define (printf-inner args) (if args (begin (print (first args)) (when (rest args) (print sep)) (printf-inner (rest args))) (print end))) (printf-inner args) ()) diff --git a/bin/tests/alists.slime b/bin/tests/alists.slime new file mode 100644 index 0000000..3a473c9 --- /dev/null +++ b/bin/tests/alists.slime @@ -0,0 +1,49 @@ +(import "alist.slime") + +(define a (make-alist)) +;; a == () + +(assert (= (first a) ())) + +(alist-set! a 'key1 'value1) +;; a == (key1: value1) + +(assert (= (alist-get a 'key1) 'value1)) +(assert (alist-key-exists? a 'key1)) +(assert (not (alist-key-exists? a 'key2))) + +(alist-set! a 'key2 'value2) +;; a == (key2: value2, +;; key1: value1) + +(assert (= (alist-get a 'key2) 'value2)) +(assert (alist-key-exists? a 'key2)) +(assert (= (alist-find a 'key2) 0)) +(assert (= (alist-find a 'key1) 1)) +(assert (= (length (first a)) 2)) + + +(alist-set! a 'key1 'value3) +;; a == (key1: value3, +;; key2: value2, +;; key1: value1) + +(assert (= (length (first a)) 3)) +(assert (= (alist-get a 'key1) 'value3)) + +(alist-set-overwrite! a 'key1 'value4) +;; a == (key1: value4, +;; key2: value2, +;; key1: value1) + +(assert (= (length (first a)) 3)) +(pprint-alist a) +(assert (= (alist-get a 'key1) 'value4)) + +(alist-remove! a 'key1) +;; a == (key2: value2, +;; key1: value1) + +(assert (= (length (first a)) 2)) +(assert (= (alist-get a 'key1) 'value1)) +(assert (= (alist-get a 'key2) 'value2)) diff --git a/manual/built-in-docs.org b/manual/built-in-docs.org index 0fed9da..959692d 100644 --- a/manual/built-in-docs.org +++ b/manual/built-in-docs.org @@ -1,4 +1,4 @@ - +\hrule * === - defined in :: =src/./built_ins.cpp:158:0= @@ -7,7 +7,7 @@ #+BEGIN: Takes 0 or more arguments and returns =t= if all arguments are equal and =()= otherwise. #+END: - +\hrule * =>= - defined in :: =src/./built_ins.cpp:175:0= @@ -16,7 +16,7 @@ Takes 0 or more arguments and returns =t= if all arguments are equal and =()= ot #+BEGIN: TODO #+END: - +\hrule * =>== - defined in :: =src/./built_ins.cpp:193:0= @@ -25,7 +25,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =<= - defined in :: =src/./built_ins.cpp:211:0= @@ -34,7 +34,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =<== - defined in :: =src/./built_ins.cpp:231:0= @@ -43,7 +43,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =+= - defined in :: =src/./built_ins.cpp:249:0= @@ -52,7 +52,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =-= - defined in :: =src/./built_ins.cpp:262:0= @@ -61,7 +61,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =*= - defined in :: =src/./built_ins.cpp:285:0= @@ -70,7 +70,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =/= - defined in :: =src/./built_ins.cpp:306:0= @@ -79,7 +79,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =**= - defined in :: =src/./built_ins.cpp:327:0= @@ -88,7 +88,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =%= - defined in :: =src/./built_ins.cpp:343:0= @@ -97,7 +97,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =assert= - defined in :: =src/./built_ins.cpp:359:0= @@ -106,7 +106,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =define= - defined in :: =src/./built_ins.cpp:371:0= @@ -115,7 +115,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =mutate= - defined in :: =src/./built_ins.cpp:433:0= @@ -124,7 +124,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =if= - defined in :: =src/./built_ins.cpp:458:0= @@ -133,7 +133,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =quote= - defined in :: =src/./built_ins.cpp:480:0= @@ -142,7 +142,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =quasiquote= - defined in :: =src/./built_ins.cpp:485:0= @@ -151,7 +151,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =and= - defined in :: =src/./built_ins.cpp:583:0= @@ -160,7 +160,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =or= - defined in :: =src/./built_ins.cpp:594:0= @@ -169,7 +169,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =not= - defined in :: =src/./built_ins.cpp:605:0= @@ -178,7 +178,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =while= - defined in :: =src/./built_ins.cpp:615:0= @@ -187,7 +187,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =lambda= - defined in :: =src/./built_ins.cpp:693:0= @@ -196,7 +196,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =special-lambda= - defined in :: =src/./built_ins.cpp:705:0= @@ -205,7 +205,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =eval= - defined in :: =src/./built_ins.cpp:713:0= @@ -214,7 +214,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =begin= - defined in :: =src/./built_ins.cpp:725:0= @@ -223,7 +223,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =list= - defined in :: =src/./built_ins.cpp:741:0= @@ -232,7 +232,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =pair= - defined in :: =src/./built_ins.cpp:745:0= @@ -241,7 +241,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =first= - defined in :: =src/./built_ins.cpp:755:0= @@ -250,7 +250,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =rest= - defined in :: =src/./built_ins.cpp:766:0= @@ -259,7 +259,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =set-type= - defined in :: =src/./built_ins.cpp:777:0= @@ -268,7 +268,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =delete-type= - defined in :: =src/./built_ins.cpp:789:0= @@ -277,7 +277,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =type= - defined in :: =src/./built_ins.cpp:796:0= @@ -286,7 +286,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =info= - defined in :: =src/./built_ins.cpp:828:0= @@ -295,7 +295,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =show= - defined in :: =src/./built_ins.cpp:910:0= @@ -304,7 +304,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =addr-of= - defined in :: =src/./built_ins.cpp:922:0= @@ -313,7 +313,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =generate-docs= - defined in :: =src/./built_ins.cpp:928:0= @@ -322,7 +322,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =print= - defined in :: =src/./built_ins.cpp:937:0= @@ -331,7 +331,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =read= - defined in :: =src/./built_ins.cpp:945:0= @@ -340,7 +340,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =exit= - defined in :: =src/./built_ins.cpp:962:0= @@ -349,7 +349,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =break= - defined in :: =src/./built_ins.cpp:973:0= @@ -358,7 +358,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =memstat= - defined in :: =src/./built_ins.cpp:978:0= @@ -367,7 +367,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =try= - defined in :: =src/./built_ins.cpp:982:0= @@ -376,7 +376,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =load= - defined in :: =src/./built_ins.cpp:997:0= @@ -385,7 +385,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =import= - defined in :: =src/./built_ins.cpp:1008:0= @@ -394,7 +394,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =copy= - defined in :: =src/./built_ins.cpp:1019:0= @@ -403,7 +403,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =error= - defined in :: =src/./built_ins.cpp:1027:0= @@ -412,7 +412,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =symbol->keyword= - defined in :: =src/./built_ins.cpp:1034:0= @@ -421,7 +421,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =string->symbol= - defined in :: =src/./built_ins.cpp:1043:0= @@ -430,7 +430,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =symbol->string= - defined in :: =src/./built_ins.cpp:1055:0= @@ -439,7 +439,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =concat-strings= - defined in :: =src/./built_ins.cpp:1064:0= @@ -448,7 +448,7 @@ TODO #+BEGIN: TODO #+END: - +\hrule * =pe= - defined in :: =pre.slime:2:40= @@ -456,31 +456,48 @@ TODO - arguments :: : - postitional :: =expr= - docu :: none - +\hrule * =when= - - defined in :: =pre.slime:8:37= + - defined in :: =pre.slime:21:37= - type :: =:macro= - arguments :: : - postitional :: =condition=: - rest :: =body= - docu :: #+BEGIN: -Doc String for `when' - #+END: +Special form for when multiple actions should be done if a +condition is true. + +{{{example_start}}} +(when (not ()) + (print "Hello ") + (print "from ") + (print "when!")) +(when () + (print "Goodbye ") + (print "World!")) +{{{example_end}}} + + #+END: +\hrule * =unless= - - defined in :: =pre.slime:13:41= + - defined in :: =pre.slime:28:41= - type :: =:macro= - arguments :: : - postitional :: =condition=: - rest :: =body= - - docu :: none - + - docu :: + #+BEGIN: +Special form for when multiple actions should be done if a +condition is false. + #+END: +\hrule * =n-times= - - defined in :: =pre.slime:20:35= + - defined in :: =pre.slime:35:35= - type :: =:macro= - arguments :: : - postitional :: =times=, =action= @@ -488,45 +505,47 @@ Doc String for `when' #+BEGIN: Executes action times times. #+END: - +\hrule * =let= - - defined in :: =pre.slime:37:64= + - defined in :: =pre.slime:52:64= - type :: =:macro= - arguments :: : - postitional :: =bindings=: - rest :: =body= - docu :: none - +\hrule * =cond= - - defined in :: =pre.slime:51:19= + - defined in :: =pre.slime:66:19= - type :: =:macro= - arguments :: : - rest :: =clauses= - docu :: none - +\hrule * =define-special= - - defined in :: =pre.slime:54:81= + - defined in :: =pre.slime:69:81= - type :: =:macro= - arguments :: : - postitional :: =name-and-args=: - rest :: =body= - docu :: none - +\hrule * =construct-list= - - defined in :: =pre.slime:94:14= + - defined in :: =pre.slime:110:14= - type :: =:macro= - arguments :: : - rest :: =body= - docu :: #+BEGIN: +{{{example_start}}} (construct-list i <- '(1 2 3 4 5) yield (* i i)) +{{{example_end}}} (construct-list i <- '(1 2 3 4) @@ -538,12 +557,11 @@ Executes action times times. when (evenp i) yield i) - #+END: - +\hrule * =apply= - - defined in :: =pre.slime:99:28= + - defined in :: =pre.slime:115:28= - type :: =:macro= - arguments :: : - postitional :: =fun=, =seq= @@ -552,17 +570,17 @@ Executes action times times. Applies the funciton to the sequence, as in calls the function with ithe sequence as arguemens. #+END: - +\hrule * =define-package= - - defined in :: =pre.slime:113:24= + - defined in :: =pre.slime:129:24= - type :: =:macro= - arguments :: : - postitional :: =name=: - rest :: =body= - docu :: none - -* =nil?= +\hrule +* =null?= - type :: =:lambda= - arguments :: : @@ -571,7 +589,7 @@ ithe sequence as arguemens. #+BEGIN: Checks if the argument is =nil=. #+END: - +\hrule * =number?= - type :: =:lambda= @@ -581,7 +599,7 @@ Checks if the argument is =nil=. #+BEGIN: Checks if the argument is a number. #+END: - +\hrule * =symbol?= - type :: =:lambda= @@ -591,7 +609,7 @@ Checks if the argument is a number. #+BEGIN: Checks if the argument is a symbol. #+END: - +\hrule * =keyword?= - type :: =:lambda= @@ -601,7 +619,7 @@ Checks if the argument is a symbol. #+BEGIN: Checks if the argument is a keyword. #+END: - +\hrule * =pair?= - type :: =:lambda= @@ -611,7 +629,7 @@ Checks if the argument is a keyword. #+BEGIN: Checks if the argument is a pair. #+END: - +\hrule * =string?= - type :: =:lambda= @@ -621,7 +639,7 @@ Checks if the argument is a pair. #+BEGIN: Checks if the argument is a string. #+END: - +\hrule * =lambda?= - type :: =:lambda= @@ -631,7 +649,7 @@ Checks if the argument is a string. #+BEGIN: Checks if the argument is a function. #+END: - +\hrule * =macro?= - type :: =:lambda= @@ -641,7 +659,7 @@ Checks if the argument is a function. #+BEGIN: Checks if the argument is a macro. #+END: - +\hrule * =special-lambda?= - type :: =:lambda= @@ -651,7 +669,7 @@ Checks if the argument is a macro. #+BEGIN: Checks if the argument is a special-lambda. #+END: - +\hrule * =built-in-function?= - type :: =:lambda= @@ -661,14 +679,14 @@ Checks if the argument is a special-lambda. #+BEGIN: Checks if the argument is a built-in function. #+END: - +\hrule * =callable?= - type :: =:lambda= - arguments :: : - postitional :: =x= - docu :: none - +\hrule * =end= - type :: =:lambda= @@ -677,8 +695,14 @@ Checks if the argument is a built-in function. - docu :: #+BEGIN: Returns the last pair in the sqeuence. - #+END: +{{{example_start}}} +(define a (list 1 2 3 4)) +(printf (end a)) +{{{example_end}}} + + #+END: +\hrule * =last= - type :: =:lambda= @@ -687,8 +711,14 @@ Returns the last pair in the sqeuence. - docu :: #+BEGIN: Returns the (first) of the last (pair) of the given sequence. - #+END: +{{{example_start}}} +(define a (list 1 2 3 4)) +(printf (last a)) +{{{example_end}}} + + #+END: +\hrule * =extend= - type :: =:lambda= @@ -699,7 +729,7 @@ Returns the (first) of the last (pair) of the given sequence. Extends a list with the given element, by putting it in the (rest) of the last element of the sequence. #+END: - +\hrule * =extend2= - type :: =:lambda= @@ -710,7 +740,7 @@ the (rest) of the last element of the sequence. Extends a list with the given element, by putting it in the (rest) of the last element of the sequence. #+END: - +\hrule * =append= - type :: =:lambda= @@ -721,7 +751,7 @@ the (rest) of the last element of the sequence. Appends an element to a sequence, by extendeing the list with (pair elem nil). #+END: - +\hrule * =length= - type :: =:lambda= @@ -731,7 +761,21 @@ with (pair elem nil). #+BEGIN: Returns the length of the given sequence. #+END: +\hrule +* =sublist-starting-at-index= + - type :: =:lambda= + - arguments :: : + - postitional :: =seq=, =index= + - docu :: none +\hrule +* =list-without-index= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq=, =index= + - docu :: none +\hrule * =increment= - type :: =:lambda= @@ -741,7 +785,7 @@ Returns the length of the given sequence. #+BEGIN: Adds one to the argument. #+END: - +\hrule * =decrement= - type :: =:lambda= @@ -751,7 +795,7 @@ Adds one to the argument. #+BEGIN: Subtracts one from the argument. #+END: - +\hrule * =range= - type :: =:lambda= @@ -762,7 +806,7 @@ Subtracts one from the argument. Returns a sequence of numbers starting with the number defined by the key =from= and ends with the number defined in =to=. #+END: - +\hrule * =range-while= - type :: =:lambda= @@ -773,7 +817,7 @@ key =from= and ends with the number defined in =to=. Returns a sequence of numbers starting with the number defined by the key 'from' and ends with the number defined in 'to'. #+END: - +\hrule * =map= - type :: =:lambda= @@ -785,7 +829,7 @@ Takes a function and a sequence as arguments and returns a new sequence which contains the results of using the first sequences elemens as argument to that function. #+END: - +\hrule * =reduce= - type :: =:lambda= @@ -799,7 +843,7 @@ given function accepts a variable amount of parameters. If your funciton is limited to two arguments, use [[=reduce-binary=]] instead. #+END: - +\hrule * =reduce-binary= - type :: =:lambda= @@ -807,12 +851,12 @@ instead. - postitional :: =fun=, =seq= - docu :: #+BEGIN: -Takes a function and a sequence as arguments and applies the -function to the argument sequence. reduce-binary applies the -arguments `pair-wise' which means it works with binary functions -as compared to `reduce'. +Takes a function and a sequence as arguments and applies the +function to the argument sequence. reduce-binary applies the arguments +*pair-wise* which means it works with binary functions as compared to +[[=reduce=]]. #+END: - +\hrule * =filter= - type :: =:lambda= @@ -825,43 +869,42 @@ function to every value in the sequence. If the result of that funciton application returns a truthy value, the original value is added to a list, which in the end is returned. #+END: - +\hrule * =zip= - type :: =:lambda= - arguments :: : - postitional :: =l1=, =l2= - docu :: none - +\hrule * =unzip= - type :: =:lambda= - arguments :: : - postitional :: =lists= - docu :: none - +\hrule * =enumerate= - type :: =:lambda= - arguments :: : - postitional :: =seq= - docu :: none - +\hrule * =printf= - type :: =:lambda= - arguments :: : - - keyword :: =sep= =(" ")=, =end= =(" -")=: + - keyword :: =sep= =(" ")=, =end= =("\n")=: - rest :: =args= - docu :: #+BEGIN: -A wrapper for the built-in (print) that accepts a variable number -of arguments and also provides keywords for specifying the printed -separators between the arguments and what should be printed after the -las argument. +A wrapper for the built-in function [[=print=]] that accepts a +variable number of arguments and also provides keywords for specifying +the printed separators (=sep=) between the arguments and what should +be printed after the last argument (=end=). #+END: - +\hrule * =define-class= - defined in :: =oo.slime:22:22= @@ -873,7 +916,7 @@ las argument. #+BEGIN: Macro for creating simple classes. #+END: - +\hrule * =->= - defined in :: =oo.slime:25:24= @@ -882,14 +925,14 @@ Macro for creating simple classes. - postitional :: =obj=, =meth=: - rest :: =args= - docu :: none - +\hrule * =math->= - type :: =:package= - arguments :: : - rest :: =args= - docu :: none - +\hrule * =math-> pi= - defined in :: =math.slime:5:4= @@ -899,7 +942,7 @@ Macro for creating simple classes. #+BEGIN: Tha famous circle constant. #+END: - +\hrule * =math-> abs= - defined in :: =math.slime:9:4= @@ -910,7 +953,7 @@ Tha famous circle constant. #+BEGIN: Accepts one argument and returns the absoulte value of it #+END: - +\hrule * =math-> sqrt= - defined in :: =math.slime:13:4= @@ -921,10 +964,10 @@ Accepts one argument and returns the absoulte value of it #+BEGIN: Accepts one argument and returns the square root of it #+END: - +\hrule * =math-> make-vector3= - - defined in :: =pre.slime:37:63= + - defined in :: =pre.slime:52:63= - type :: =:constructor= - arguments :: : - postitional :: =x=, =y=, =z= @@ -932,7 +975,7 @@ Accepts one argument and returns the square root of it #+BEGIN: This is the handle to an object of the class vector3 #+END: - +\hrule * =math-> make-vector3 define-class= - defined in :: =oo.slime:22:22= @@ -944,7 +987,7 @@ This is the handle to an object of the class vector3 #+BEGIN: Macro for creating simple classes. #+END: - +\hrule * =math-> make-vector3 ->= - defined in :: =oo.slime:25:24= diff --git a/manual/manual.html b/manual/manual.html new file mode 100644 index 0000000..4074ccd --- /dev/null +++ b/manual/manual.html @@ -0,0 +1,2722 @@ + + + +The Slime 1.0 Manual + + + + + + + + + + + + + + + + +
+

The Slime 1.0 Manual

+
+

+abstract +

+ +
+ +

+\tableofcontents +

+ +
+

1 Lisp languages

+
+

+Lisp is not one language but rather a family of programming languages. The family is devided by some +characteristics. There are Lisp-1 and Lisp-2 dialects and there is a difference between a Lisp with +lexical scoping as opposed to dynamic scoping. These differences will be explained in later +sections. +

+ +

+Like most Lisps, Slime is dynamically typed. That means that like in statically typed Languages +Slime has different data types, but they are associated not with variables but with the Lisp objects +themselves. Variables can be assigend Lisp objects of any internal type. +

+ +

+The Lisp language family is known to be highly flexible and applicable in all areas by creating +domain specific languages in Lisp itself through a powerful macro system. The central data structure +in Lisp is the list. The reason why lisp is so powerful is because the program source code itself is +represented as lists. The nested lists make up the syntax tree of the lisp program. It is therfore +computationally easy to parse lisp programs as the source code itself is already structured in the +form of the syntax tree; allowing for parsing in linear time. +

+ +

+The macro system in Slime works by recognizing macros at parse-time and running them, and replacing +the macro call in the program code with the return value of the macro and then checking if further +macros have to be expanded in the replaced code. Therefore the macros can be used to pre-compute +values or rewrite expressions (creating syntactic sugar) or themselves define macros. +

+
+
+ +
+

2 Lists

+
+

+As mentioned in Lisp languages, the central data structure in all Lisps is the list. Lists are +implemented as singly linked lists, made up of pairs (historically called cons-cells), each pair +has two slots, the first and the rest (historically car and cdr). A linked lsit ist then +constructed by the convention that the first field of a pair points to the first element of the +list and the rest field points to the rest of the list. Following this description, the list is a +recursive data structure. For the end of the list a special value nil is used in the rest field. +

+ +

+A helpful way to visualize lists made up of pairs is using box diagrams. A simple box diagram can be +seen in 1. Each rectangle is divided in two. The left part represents the first +field, the right part represents the rest. The arrows point to the values in these fields. +

+ +

+The diagram in 1 shows a simple list containing the values 1, 2 and 3. The first pair +stores the number 1 its first field and the rest points to the rest of the list. The last pair +points to the special value nil in its rest to denote the end of the list. +

+ +

+diagrams/list123.eps +

+ + +

+However the rest of a pair needs not to be a pair or nil, it could also point to any other value. +By doing this the list is no longer "well formed" but rather "ill formed". Ill formed lsits can be +used as an optimization when using the list for storing data. In 2 an ill formed list +can be seen, that also contains the values 1, 2 and 3 but stores them using only two pairs instead +of 3. +

+ +

+diagrams/list12.3.eps +

+
+ +
+

2.1 representing lists in Lisp

+
+

+In Slime and in most Lisps, lists are represented using round parenthesis where ( denotes the +start of the list and ) denotes the end. Eeach element inside these parenthesis separated by one +or more spaces will be interpreted as an element of that list. For example the list from +1 would be represented as (1 2 3). During parse time, the Lisp parser transforms +the parenthesised list into the pairs that are in the end stored in memory. +

+ +

+To also be able to represent ill formed lists in Lisp there is a special syntax using the . (dot +symbol). If the parser encounters a . inside of a list, it will treat the next element as the +rest. If there is no or more than one element after the . an parsing error will be thrown. Using +this syntax we can represent the ill formed list from 2 as (1 2 . 3). We can also +write well formed lists using the dot notation if we point the rest to another list. So the well +formed list from 1 can also be written as \[\texttt{(1 . (2 . (3)))}\] +

+
+
+ +
+

2.2 representing function calls in Lisp

+
+

+If we tried to enter the Lisp representation of the lists like (1 2 3) discussed in representing lists in Lisp directly into an Lisp interpreter we would get an error. That doesn't mean that the +explanation given in the section is wrong, it is in fact correct: the lisp parser will transform the +lisp syntax into the pairs in memory. The reason we would get an error is, that when reading Lisp +code, the Lisp interpreter first parses the code and then tries to evaluate it and return the result +back to the user. +

+ +

+In Lisp by default, a list corresponds to a function call. As mentioned in Lisp languages Lisp +represents lists and Lisp programms as lists. If a list is treated as a function call, the first +element will be treated as the function and the rest of the elements will be the arguments to that +function. If we would wnter (1 2 3) directly into the Lisp interpreter we would get an error +saying it cannot find the function 1. +

+ +

+If we would want to compute the sum of the numbers 5 and 3 we could do this by invoking the + +function with 5 and 3 as its arguments. (+ 5 3) will evaluate to 8. We can also nest functions +calls and use the return values as parameters to other functions: (+ (- 12 4) (/ 24 4)) will +evaluate to 14. The box diagramm showing the internal structure of that computation can be seen in +3. +

+ +

+diagrams/simpleMath.eps +

+
+
+
+ +
+

3 Evaluation order

+
+

+As a first step of evaluation of a regular function, all its arguments are getting evaluated, and +then the function is applied to the evaluated arguments. For example when evaluating the nested +expression in 1 the outermost function is the + function with three arguments: (* +3 4), (- 100 (+ 12 13 14 15)) and 2. So before the outhermost + gets invoked, the three +arguments are getting evaluated recursively. +

+ +
+ +
(print (+ (* 3 4)
+          (- 100 (+ 12 13 14 15))
+          2))
+
+
+ +
+evaluates to =>
+60
+
+
+ +
+

3.1 Special forms

+
+

+The given evaluation rule – to evaluate all the arguments first and then allpying them to the +funciton – as described in Evaluation order is only valid for regular functions. There is a class +of functions that do not follow this evaluation rule called special forms. Special forms are +needed when you do not wish to evaluate all arguments. For example the built-in if function should +only evaluate the "then-expression" if the condition evaluates to a truthy value and not otherwise. +Consider the example in 2. The if expression only evaluates the then-expression. If +the if function would follow the evaluation order of regular functions, first all three arguments +(< 1 2), (print "I knew it!!\n") but also (print "Oh, it is not?!\n") could get evaluated and +so both messages would be printed. In the given if expression, the condition evaluates to a truthy +value and only I knew it!! will be printed. +

+ +
+ +
(if (< 1 2)
+    (print "I knew it!!\n")
+  (print "Oh, it is not?!\n"))
+
+
+ +
+evaluates to =>
+I knew it!!
+
+ + +

+The programmer can also define their own special forms using special-lambda and macros, which will +be explained in Special lambdas and Macros. +

+
+
+
+ +
+

4 Symbols and keywords

+
+
+

5 Truthyness

+
+
+

6 Lambdas

+
+

+Slime allows for creating anonymous functions called lambdas. We did not talk about binding +variables, we will do this in Define, but we can still use lambdas now. Remember that Lisp +interpretes the first argument of a list in the source code as a function and the rest as the +arguments. The lambda special form evaluates to a regular function object that can then stand in +the first position of the function call list. The basic syntax for the lambda special form is: +\[\texttt{(lambda (arg1 arg2 ...) (body1) ...)}\] the first arguemnt to lambda is a list of the +arguments. All the following arguments will be the body of the lambda. They will be executed when +the lambda is invoked. The return value of a lambda is the value of the last evaluated expression in +the body. +

+ +

+Probably the simplest function to write as a lambda is the identity function. It takes one argument +and returns it. The identity lambda and a few other simple examples of lambdas can be seen in +3. +

+ +
+ +
(printf ((lambda (x) x) 1))
+(printf ((lambda (x y) (+ x y)) 3 5))
+(printf ((lambda (x y z) (list x y z)) 1 2 3))
+
+
+ +
+evaluates to =>
+1
+8
+(1 2 3)
+
+ + +

+Additionally Slime lambdas have the possibility to take optional arguments in the form of keyword +arguemnts as well as a rest argument which allows for accepting any number of arguments. Since +these concepts are most useful when the function is actually bound to a variable, they will be +introduced when we learned how to do that in Define. +

+
+ +
+

6.1 Special lambdas

+
+

+The lambda special form creates a function object that represents a regular function. So the basic +evaluation rules count: when the lambda is invoked all it's arguments are evaluated and then the +lambda is applied to the evaluated arguments. If this is not wanted in some rare cases, the +programmer also has the possibility to define a special form using special-lambda, which, when +invoked does not evaluare any argument. The programmer has to evaluate the arguments in the body +themselves using eval. The rest of the syntax between lambda and special-lambda are the same. +

+ +
+ +
((lambda         (x) (printf x)) (+ 1 2))
+((special-lambda (x) (printf x)) (+ 1 2))
+
+;; Special lambdas make it possible to write
+;; code that inspects code
+((special-lambda (expr)
+     (printf "The function to be called is"
+             (first expr)
+             "and the result is"
+             (eval expr)))
+ (+ 1 2))
+
+
+ +
+evaluates to =>
+3
+(+ 1 2)
+The function to be called is + and the result is 3
+
+
+
+
+ +
+

7 Define

+
+

+To assign a value to a symbol you can use the define built-in special form. The syntax for +define is: \[\texttt{(define symbol value)}\] and some usages can be seen in +5. +

+ +
+ +
(define var1 1)
+(define var2 "Hello World")
+(define var3 (+ 1 2))
+
+(printf var1 var2 var3)
+
+
+ +
+evaluates to =>
+1 Hello World 3
+
+
+ +
+

7.1 Defining functions

+
+

+In Lambdas we learned how to create function objects using the lambda built-in form. Using +define every Lisp Object can be assigned to a symbol making no exception for the function objects. +In 6 you can see what that would look like. +

+ +
+ +
(define hypothenuse
+  (lambda (a b)
+    (** (+ (* a a) (* b b)) 0.5)))
+
+(printf (hypothenuse 3 4))
+
+
+ +
+evaluates to =>
+5
+
+ + +

+Since defining functions is so common, there is a syntactic shorthand that does not require to write +out the whole lambda definition. In this case the first argument to the call to define is a +list. The frist element of the list is the name of the function to define and the other elemens are +the arguments to that function. An example can be seen in 7. Note that the +definition looks like a call to the function we are constructing, making it easier to see what a +call to that function will look like. +

+ +
+ +
(define (hypothenuse a b)
+  (** (+ (* a a) (* b b)) 0.5))
+
+(printf (hypothenuse 3 4))
+
+
+ +
+evaluates to =>
+5
+
+
+
+ +
+

7.2 Functions with keyword arguments

+
+

+A sometimes more convenient way of passing arguments to a function is using keyword arguments. Using +keyword arguments a function call could look like this: \[\texttt{(function :arg1 value1 :arg2 +value2)}\] here the function accepts two arguments named arg1 and arg2. The user of this +function can see more clearly excatly which argument will be assigned wich value. This notation also +allows for switching the argument order. The following function call is equivalent to the call +above. \[\texttt{(function :arg2 value2 :arg1 value1)}\]. +

+ +

+For this to work however, the function must be defined to accept these keyword arguments. To do this +the special marker :keys has to be inserted into the argument list of a lambda or a function +define. All following arguments must be supplied as keyword arguments, unless they are also +supplied with a default value, in which case they do not need to be supplied. To attach a default +value to a keyword argument, insert :defaults-to <value> after the keyword argument name. An +example of all of this can be seen in 8. Important note: keyword arguments must be +defined and supplied after all the regular arguments. +

+ +
+ +
(define (complex required1 required2 :keys
+                 key1
+                 key2 :defaults-to 3
+                 key3)
+  (* (+ required1 required2)
+     key1
+     key2
+     key3))
+
+(printf (complex 1 2 :key1 2 :key2 2 :key3 3))
+(printf (complex 1 2 :key1 2 :key3 3))
+(printf (complex 1 2 :key3 3 :key1 2))
+
+
+ +
+evaluates to =>
+36
+54
+54
+
+
+
+ +
+

7.3 Functions with rest arguments

+
+

+If the programmer wants to create a function that can accept any number of arguments, they can use +the rest argument. It is defined after the special marker :rest and after the rest argument, no +other arguments can be defined. In the execution of the fuction, the rest arguent will be assigned +to a list containing all the supplied values. The rest argument can be used in conjunction with the +other argument types, regular arguments and keyword arguments. +

+ +
+ +
(define (execute-operation operation
+                           :keys
+                           do-logging :defaults-to ()
+                           :rest values)
+  (define result (apply operation values))
+  (when do-logging
+    (printf "Executing operation"
+            operation
+            "agains the values"
+            values
+            "yielded:"
+            result))
+  result)
+
+(printf (execute-operation '+ 1 2 3))
+(printf (execute-operation '*
+                           :do-logging t
+                           10 11))
+
+
+ +
+evaluates to =>
+6
+Executing operation * agains the values (10 11) yielded: 110
+110
+
+
+
+
+ +
+

8 Environments

+
+
+

9 Macros

+
+
+

Built-in functions

+
+

+\hrule +

+
+
+

=

+
+
+
defined in
src/./built_ins.cpp:158:0 +
+
type
:cfunction +
+
docu

+Takes 0 or more arguments and returns t if all arguments are equal and () otherwise. +

+
+
+

+\hrule +

+
+
+
+

>

+
+
+
defined in
src/./built_ins.cpp:175:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

>=

+
+
+
defined in
src/./built_ins.cpp:193:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

<

+
+
+
defined in
src/./built_ins.cpp:211:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

<=

+
+
+
defined in
src/./built_ins.cpp:231:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

+

+
+
+
defined in
src/./built_ins.cpp:249:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

-

+
+
+
defined in
src/./built_ins.cpp:262:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

*

+
+
+
defined in
src/./built_ins.cpp:285:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

/

+
+
+
defined in
src/./built_ins.cpp:306:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

**

+
+
+
defined in
src/./built_ins.cpp:327:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

%

+
+
+
defined in
src/./built_ins.cpp:343:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

assert

+
+
+
defined in
src/./built_ins.cpp:359:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

define

+
+
+
defined in
src/./built_ins.cpp:371:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

mutate

+
+
+
defined in
src/./built_ins.cpp:433:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

if

+
+
+
defined in
src/./built_ins.cpp:458:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

quote

+
+
+
defined in
src/./built_ins.cpp:480:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

quasiquote

+
+
+
defined in
src/./built_ins.cpp:485:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

and

+
+
+
defined in
src/./built_ins.cpp:583:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

or

+
+
+
defined in
src/./built_ins.cpp:594:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

not

+
+
+
defined in
src/./built_ins.cpp:605:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

while

+
+
+
defined in
src/./built_ins.cpp:615:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

lambda

+
+
+
defined in
src/./built_ins.cpp:693:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

special-lambda

+
+
+
defined in
src/./built_ins.cpp:705:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

eval

+
+
+
defined in
src/./built_ins.cpp:713:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

begin

+
+
+
defined in
src/./built_ins.cpp:725:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

list

+
+
+
defined in
src/./built_ins.cpp:741:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

pair

+
+
+
defined in
src/./built_ins.cpp:745:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

first

+
+
+
defined in
src/./built_ins.cpp:755:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

rest

+
+
+
defined in
src/./built_ins.cpp:766:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

set-type

+
+
+
defined in
src/./built_ins.cpp:777:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

delete-type

+
+
+
defined in
src/./built_ins.cpp:789:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

type

+
+
+
defined in
src/./built_ins.cpp:796:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

info

+
+
+
defined in
src/./built_ins.cpp:828:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

show

+
+
+
defined in
src/./built_ins.cpp:910:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

addr-of

+
+
+
defined in
src/./built_ins.cpp:922:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

generate-docs

+
+
+
defined in
src/./built_ins.cpp:928:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

print

+
+
+
defined in
src/./built_ins.cpp:937:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

read

+
+
+
defined in
src/./built_ins.cpp:945:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

exit

+
+
+
defined in
src/./built_ins.cpp:962:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

break

+
+
+
defined in
src/./built_ins.cpp:973:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

memstat

+
+
+
defined in
src/./built_ins.cpp:978:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

try

+
+
+
defined in
src/./built_ins.cpp:982:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

load

+
+
+
defined in
src/./built_ins.cpp:997:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

import

+
+
+
defined in
src/./built_ins.cpp:1008:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

copy

+
+
+
defined in
src/./built_ins.cpp:1019:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

error

+
+
+
defined in
src/./built_ins.cpp:1027:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

symbol->keyword

+
+
+
defined in
src/./built_ins.cpp:1034:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

string->symbol

+
+
+
defined in
src/./built_ins.cpp:1043:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

symbol->string

+
+
+
defined in
src/./built_ins.cpp:1055:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

concat-strings

+
+
+
defined in
src/./built_ins.cpp:1064:0 +
+
type
:cfunction +
+
docu

+TODO +

+
+
+

+\hrule +

+
+
+
+

pe

+
+
+
defined in
pre.slime:2:40 +
+
type
:macro +
+
arguments
: +
+
postitional
expr +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

when

+
+
+
defined in
pre.slime:8:37 +
+
type
:macro +
+
arguments
: +
+
postitional
condition: +
+
rest
body +
+
+
+
docu

+Doc String for `when' +

+
+
+

+\hrule +

+
+
+
+

unless

+
+
+
defined in
pre.slime:13:41 +
+
type
:macro +
+
arguments
: +
+
postitional
condition: +
+
rest
body +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

n-times

+
+
+
defined in
pre.slime:20:35 +
+
type
:macro +
+
arguments
: +
+
postitional
times, action +
+
+
+
docu

+Executes action times times. +

+
+
+

+\hrule +

+
+
+
+

let

+
+
+
defined in
pre.slime:37:64 +
+
type
:macro +
+
arguments
: +
+
postitional
bindings: +
+
rest
body +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

cond

+
+
+
defined in
pre.slime:51:19 +
+
type
:macro +
+
arguments
: +
+
rest
clauses +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

define-special

+
+
+
defined in
pre.slime:54:81 +
+
type
:macro +
+
arguments
: +
+
postitional
name-and-args: +
+
rest
body +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

construct-list

+
+
+
defined in
pre.slime:94:14 +
+
type
:macro +
+
arguments
: +
+
rest
body +
+
+
+
docu

+(construct-list + i <- '(1 2 3 4 5) + yield (* i i)) +

+ +

+(construct-list + i <- '(1 2 3 4) + j <- '(A B) + yield (pair i j)) +

+ +

+(construct-list + i <- '(1 2 3 4 5 6 7 8) + when (evenp i) + yield i) +

+
+
+

+\hrule +

+
+
+
+

apply

+
+
+
defined in
pre.slime:99:28 +
+
type
:macro +
+
arguments
: +
+
postitional
fun, seq +
+
+
+
docu

+Applies the funciton to the sequence, as in calls the function with +ithe sequence as arguemens. +

+
+
+

+\hrule +

+
+
+
+

define-package

+
+
+
defined in
pre.slime:113:24 +
+
type
:macro +
+
arguments
: +
+
postitional
name: +
+
rest
body +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

nil?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is nil. +

+
+
+

+\hrule +

+
+
+
+

number?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a number. +

+
+
+

+\hrule +

+
+
+
+

symbol?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a symbol. +

+
+
+

+\hrule +

+
+
+
+

keyword?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a keyword. +

+
+
+

+\hrule +

+
+
+
+

pair?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a pair. +

+
+
+

+\hrule +

+
+
+
+

string?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a string. +

+
+
+

+\hrule +

+
+
+
+

lambda?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a function. +

+
+
+

+\hrule +

+
+
+
+

macro?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a macro. +

+
+
+

+\hrule +

+
+
+
+

special-lambda?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a special-lambda. +

+
+
+

+\hrule +

+
+
+
+

built-in-function?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Checks if the argument is a built-in function. +

+
+
+

+\hrule +

+
+
+
+

callable?

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

end

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq +
+
+
+
docu

+Returns the last pair in the sqeuence. +

+
+
+

+\hrule +

+
+
+
+

last

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq +
+
+
+
docu

+Returns the (first) of the last (pair) of the given sequence. +

+
+
+

+\hrule +

+
+
+
+

extend

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq, elem +
+
+
+
docu

+Extends a list with the given element, by putting it in +the (rest) of the last element of the sequence. +

+
+
+

+\hrule +

+
+
+
+

extend2

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq, elem +
+
+
+
docu

+Extends a list with the given element, by putting it in +the (rest) of the last element of the sequence. +

+
+
+

+\hrule +

+
+
+
+

append

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq, elem +
+
+
+
docu

+Appends an element to a sequence, by extendeing the list +with (pair elem nil). +

+
+
+

+\hrule +

+
+
+
+

length

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq +
+
+
+
docu

+Returns the length of the given sequence. +

+
+
+

+\hrule +

+
+
+
+

increment

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
val +
+
+
+
docu

+Adds one to the argument. +

+
+
+

+\hrule +

+
+
+
+

decrement

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
val +
+
+
+
docu

+Subtracts one from the argument. +

+
+
+

+\hrule +

+
+
+
+

range

+
+
+
type
:lambda +
+
arguments
: +
+
keyword
from (0), to +
+
+
+
docu

+Returns a sequence of numbers starting with the number defined by the +key from and ends with the number defined in to. +

+
+
+

+\hrule +

+
+
+
+

range-while

+
+
+
type
:lambda +
+
arguments
: +
+
keyword
from (0), to +
+
+
+
docu

+Returns a sequence of numbers starting with the number defined +by the key 'from' and ends with the number defined in 'to'. +

+
+
+

+\hrule +

+
+
+
+

map

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
fun, seq +
+
+
+
docu

+Takes a function and a sequence as arguments and returns a new +sequence which contains the results of using the first sequences +elemens as argument to that function. +

+
+
+

+\hrule +

+
+
+
+

reduce

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
fun, seq +
+
+
+
docu

+Takes a function and a sequence as arguments and applies the +function to the argument sequence. This only works correctly if the +given function accepts a variable amount of parameters. If your +funciton is limited to two arguments, use reduce-binary +instead. +

+
+
+

+\hrule +

+
+
+
+

reduce-binary

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
fun, seq +
+
+
+
docu

+Takes a function and a sequence as arguments and applies the +function to the argument sequence. reduce-binary applies the +arguments `pair-wise' which means it works with binary functions +as compared to `reduce'. +

+
+
+

+\hrule +

+
+
+
+

filter

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
fun, seq +
+
+
+
docu

+Takes a function and a sequence as arguments and applies the +function to every value in the sequence. If the result of that +funciton application returns a truthy value, the original value is +added to a list, which in the end is returned. +

+
+
+

+\hrule +

+
+
+
+

zip

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
l1, l2 +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

unzip

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
lists +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

enumerate

+
+
+
type
:lambda +
+
arguments
: +
+
postitional
seq +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

printf

+
+
+
type
:lambda +
+
arguments
: +
+
keyword
sep (" "), end ("\n"): +
+
rest
args +
+
+
+
docu

+A wrapper for the built-in print that accepts a variable +number of arguments and also provides keywords for specifying the +printed separators (sep) between the arguments and what should be +printed after the las argument (end). +

+
+
+

+\hrule +

+
+
+
+

define-class

+
+
+
defined in
oo.slime:22:22 +
+
type
:macro +
+
arguments
: +
+
postitional
name-and-members: +
+
rest
body +
+
+
+
docu

+Macro for creating simple classes. +

+
+
+

+\hrule +

+
+
+
+

->

+
+
+
defined in
oo.slime:25:24 +
+
type
:macro +
+
arguments
: +
+
postitional
obj, meth: +
+
rest
args +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

math->

+
+
+
type
:package +
+
arguments
: +
+
rest
args +
+
+
+
docu
none +
+
+

+\hrule +

+
+
+
+

math-> pi

+
+
+
defined in
math.slime:5:4 +
+
type
:number +
+
value
3.141593 +
+
docu

+Tha famous circle constant. +

+
+
+

+\hrule +

+
+
+
+

math-> abs

+
+
+
defined in
math.slime:9:4 +
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Accepts one argument and returns the absoulte value of it +

+
+
+

+\hrule +

+
+
+
+

math-> sqrt

+
+
+
defined in
math.slime:13:4 +
+
type
:lambda +
+
arguments
: +
+
postitional
x +
+
+
+
docu

+Accepts one argument and returns the square root of it +

+
+
+

+\hrule +

+
+
+
+

math-> make-vector3

+
+
+
defined in
pre.slime:37:63 +
+
type
:constructor +
+
arguments
: +
+
postitional
x, y, z +
+
+
+
docu

+This is the handle to an object of the class vector3 +

+
+
+

+\hrule +

+
+
+
+

math-> make-vector3 define-class

+
+
+
defined in
oo.slime:22:22 +
+
type
:macro +
+
arguments
: +
+
postitional
name-and-members: +
+
rest
body +
+
+
+
docu

+Macro for creating simple classes. +

+
+
+

+\hrule +

+
+
+
+

math-> make-vector3 ->

+
+
+
defined in
oo.slime:25:24 +
+
type
:macro +
+
arguments
: +
+
postitional
obj, meth: +
+
rest
args +
+
+
+
docu
none +
+
+
+
+
+
+ + + diff --git a/manual/manual.org b/manual/manual.org index 39b6c7f..d9d2a56 100644 --- a/manual/manual.org +++ b/manual/manual.org @@ -1,5 +1,8 @@ #+title: The Slime 1.0 Manual +#+macro: example_start (eval (concat "{{{slime_header}}}" "\n" "#+begin_src slime")) +#+macro: example_end (eval (concat "#+end_src")) + #+begin_abstract abstract #+end_abstract diff --git a/src/defines.cpp b/src/defines.cpp index f16f6bf..d4c1478 100644 --- a/src/defines.cpp +++ b/src/defines.cpp @@ -272,7 +272,9 @@ struct { #define assert_type(_node, _type) \ do { \ if (Memory::get_type(_node) != _type) { \ - create_type_missmatch_error("symbol", Lisp_Object_Type_to_string(Memory::get_type(_node))); \ + create_type_missmatch_error( \ + Lisp_Object_Type_to_string(_type), \ + Lisp_Object_Type_to_string(Memory::get_type(_node))); \ } \ } while(0) diff --git a/src/docgeneration.cpp b/src/docgeneration.cpp index 3221b18..389bb68 100644 --- a/src/docgeneration.cpp +++ b/src/docgeneration.cpp @@ -37,7 +37,7 @@ proc generate_docs(Environment* env, String* path) -> void { if (!we_already_printed) { append_to_array_list(visited, env); for (int i = 0; i < env->next_index; ++i) { - fprintf(f, "\n* =%s%s= \n" + fprintf(f, "\\hrule\n* =%s%s= \n" // " :PROPERTIES:\n" // " :UNNUMBERED: t\n" // " :END:" diff --git a/src/io.cpp b/src/io.cpp index 9394f53..633b707 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -32,6 +32,38 @@ proc get_nibble(char c) -> char { return (c - '0'); } +proc escape_string(char* in) -> char* { + // TODO(Felix): add more escape sequences + int i = 0, count = 0; + while (in[i] != '\0') { + switch (in[i]) { + case '\\': + case '\n': + case '\t': + ++count; + default: break; + } + ++i; + } + + char* ret = (char*)malloc((i+count+1)*sizeof(char)); + + // copy in + i = 0; + int j = 0; + while (in[i] != '\0') { + switch (in[i]) { + case '\\': ret[j++] = '\\'; ret[j++] = '\\'; break; + case '\n': ret[j++] = '\\'; ret[j++] = 'n'; break; + case '\t': ret[j++] = '\\'; ret[j++] = 't'; break; + default: ret[j++] = in[i]; + } + ++i; + } + ret[j++] = '\0'; + return ret; +} + proc unescape_string(char* in) -> bool { if (!in) return true; @@ -236,7 +268,7 @@ proc panic(char* message) -> void { exit(1); } -proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> void { +proc print(Lisp_Object* node, bool print_repr = false, FILE* file = stdout) -> void { switch (Memory::get_type(node)) { case (Lisp_Object_Type::Nil): fputs("()", file); break; @@ -251,10 +283,12 @@ proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> case (Lisp_Object_Type::Symbol): fprintf(file, "%s", Memory::get_c_str(node->value.symbol.identifier)); break; case (Lisp_Object_Type::CFunction): fputs("[C-function]", file); break; case (Lisp_Object_Type::String): { - if (print_quotes) { + if (print_repr) { putc('\"', file); - fputs(Memory::get_c_str(node->value.string), file); + char* escaped = escape_string(Memory::get_c_str(node->value.string)); + fputs(escaped, file); putc('\"', file); + free(escaped); } else fputs(Memory::get_c_str(node->value.string), file); @@ -293,13 +327,13 @@ proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> assert_type(head->value.pair.rest, Lisp_Object_Type::Pair); assert(head->value.pair.rest->value.pair.rest == Memory::nil); - print(head->value.pair.rest->value.pair.first, print_quotes, file); + print(head->value.pair.rest->value.pair.first, print_repr, file); break; } else if (string_equal(identifier, "quasiquote")) { putc('`', file); assert_type(head->value.pair.rest, Lisp_Object_Type::Pair); - print(head->value.pair.rest->value.pair.first, print_quotes, file); + print(head->value.pair.rest->value.pair.first, print_repr, file); break; } } @@ -310,7 +344,7 @@ proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> // we want to print a broken list (for logging the error) we // should do mo checks. while (head) { - print(head->value.pair.first, print_quotes, file); + print(head->value.pair.first, print_repr, file); head = head->value.pair.rest; if (!head) return; diff --git a/src/main.cpp b/src/main.cpp index 3f027e8..bead382 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,10 @@ #include "slime.h" int main(int argc, char* argv[]) { - if (argc > 1) { if (Slime::string_equal(argv[1], "--run-tests")) { return Slime::run_all_tests() ? 0 : 1; - } + } Slime::interprete_file(argv[1]); if (Slime::Globals::error) { diff --git a/src/testing.cpp b/src/testing.cpp index 01c72ca..89a34bf 100644 --- a/src/testing.cpp +++ b/src/testing.cpp @@ -629,6 +629,7 @@ proc run_all_tests() -> bool { printf("\n-- Test Files --\n"); + invoke_test_script("alists"); invoke_test_script("evaluation_of_default_args"); invoke_test_script("lexical_scope"); invoke_test_script("class_macro");