diff --git a/.dir-locals.el b/.dir-locals.el index 3ae24d0..bb706a5 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -26,7 +26,7 @@ (font-lock-add-keywords 'c++-mode - '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\|try\\|try_void\\|for_array_list\\|for_lisp_vector\\|for_lisp_list\\|ignore_logging\\|dont_break_on_errors\\)\\>" . + '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\|try\\|try_void\\|for_array_list\\|for_lisp_vector\\|in_caller_env\\|for_lisp_list\\|ignore_logging\\|dont_break_on_errors\\)\\>" . font-lock-keyword-face))))))) (c++-mode . ((eval . (company-clang-set-prefix "slime.h")) diff --git a/bin/alist.slime b/bin/alist.slime index d843cd6..9b277d8 100644 --- a/bin/alist.slime +++ b/bin/alist.slime @@ -28,12 +28,12 @@ (define key-not-found-index -1) (define (make-alist) - (set-type + (set-type! '(()) :alist)) (define (make-plist) - (set-type + (set-type! '(()) :plist)) @@ -41,9 +41,9 @@ (let ((associations (first alist))) (define (pprint-intern associations) (when associations - (printf " " - (caar associations) "->" - (cdar associations)) + (print " " + (caar associations) "->" + (cdar associations)) (pprint-intern (rest associations)))) (print "(") (when associations @@ -55,9 +55,9 @@ (let ((props (first plist))) (define (pprint-intern props) (when props - (printf " " - (car props) "->" - (cadr props)) + (print " " + (car props) "->" + (cadr props)) (pprint-intern (cddr props)))) (print "(") (when props @@ -113,7 +113,7 @@ (define (alist-set! alist key value) - (mutate alist (set-type (pair (pair (pair key value) + (mutate alist (set-type! (pair (pair (pair key value) (car alist)) ()) :alist))) @@ -142,7 +142,7 @@ (plist-get-intern props prop))) (define (plist-set! plist prop value) - (mutate plist (set-type (pair (pair prop (pair value (first plist))) ()) + (mutate plist (set-type! (pair (pair prop (pair value (first plist))) ()) :plist))) (define (plist-set-overwrite! plist prop value) diff --git a/bin/pre.slime b/bin/pre.slime index 47b4776..f4242a4 100644 --- a/bin/pre.slime +++ b/bin/pre.slime @@ -1,10 +1,8 @@ - - (define-syntax (pe expr) - `(printf ',expr "evaluates to" ,expr)) + `(print ',expr "evaluates to" ,expr)) -(define-syntax (when condition :rest body) - "Special form for when multiple actions should be done if a +(define-syntax (when condition . body) + :doc "Special form for when multiple actions should be done if a condition is true. {{{example_start}}} @@ -22,22 +20,23 @@ condition is true. `(if ,condition @body nil) `(if ,condition (begin @body) nil))) -(define-syntax (unless condition :rest body) - "Special form for when multiple actions should be done if a +(define-syntax (unless condition . body) + :doc "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)))) (define-syntax (n-times times action) - "Executes action times times." + :doc "Executes action times times." (define (repeat times elem) (unless (> 1 times) (pair elem (repeat (- times 1) elem)))) `(begin @(repeat times action))) -(define-syntax (let bindings :rest body) +(define-syntax (let bindings . body) (define (unzip lists) + (break) (when lists (define (iter lists l1 l2) (define elem (first lists)) @@ -51,9 +50,9 @@ condition is false." (define unzipped (unzip bindings)) - `((lambda ,(first unzipped) @body) @(first (rest unzipped)))) + `((,lambda ,(first unzipped) @body) @(first (rest unzipped)))) -(define-syntax (cond :rest clauses) +(define-syntax (cond . clauses) (define (rec clauses) (if (= nil clauses) nil @@ -68,7 +67,7 @@ condition is false." (rec clauses)) -(define-syntax (case var :rest clauses) +(define-syntax (case var . clauses) (define (rec clauses) (if (= nil clauses) nil @@ -82,11 +81,11 @@ condition is false." ,(rec (rest clauses)))))) (rec clauses)) -(define-syntax (define-special name-and-args :rest body) +(define-syntax (define-special name-and-args . body) `(define ,(first name-and-args) (special-lambda ,(rest name-and-args) @body))) -(define-syntax (construct-list :rest body) - " +(define-syntax (construct-list . body) + :doc " {{{example_start}}} (construct-list i <- '(1 2 3 4 5) @@ -127,11 +126,11 @@ condition is false." (rec body)) (define-syntax (apply fun seq) - "Applies the function to the sequence, as in calls the function with + :doc "Applies the function to the sequence, as in calls the function with ithe sequence as arguemens." `(eval (pair ,fun ,seq))) -(define-syntax (define-typed args :rest body) +(define-syntax (define-typed args . body) (define (get-arg-names args) (when args (pair (first args) @@ -144,7 +143,7 @@ ithe sequence as arguemens." @body))) -(define-syntax (define-module module-name :keys exports :rest body) +(define-syntax (define-module module-name :exports . body) (let ((module-prefix (concat-strings (symbol->string module-name) "::"))) (eval `(begin @body)) (pair 'begin @@ -159,14 +158,14 @@ ithe sequence as arguemens." (define (null? x) - "Checks if the argument is =nil=." + :doc "Checks if the argument is =nil=." (= x ())) (define (type=? obj typ) - "Checks if the argument =obj= is of type =typ=" + :doc "Checks if the argument =obj= is of type =typ=" (= (type obj) typ)) -(define (types=? :rest objs) +(define (types=? . objs) (define (inner objs) (if objs (let ((actual-type (type (first objs))) @@ -177,7 +176,7 @@ ithe sequence as arguemens." t)) (inner objs)) -(define (assert-types= :rest objs) +(define (assert-types= . objs) (define (inner objs) (when objs (let ((actual-type (type (first objs))) @@ -188,39 +187,39 @@ ithe sequence as arguemens." (inner objs)) (define (number? x) - "Checks if the argument is a number." + :doc "Checks if the argument is a number." (type=? x :number)) (define (symbol? x) - "Checks if the argument is a symbol." + :doc "Checks if the argument is a symbol." (type=? x :symbol)) (define (keyword? x) - "Checks if the argument is a keyword." + :doc "Checks if the argument is a keyword." (type=? x :keyword)) (define (pair? x) - "Checks if the argument is a pair." + :doc "Checks if the argument is a pair." (type=? x :pair)) (define (string? x) - "Checks if the argument is a string." + :doc "Checks if the argument is a string." (type=? x :string)) (define (lambda? x) - "Checks if the argument is a function." + :doc "Checks if the argument is a function." (type=? x :lambda)) (define (macro? x) - "Checks if the argument is a macro." + :doc "Checks if the argument is a macro." (type=? x :macro)) (define (special-lambda? x) - "Checks if the argument is a special-lambda." + :doc "Checks if the argument is a special-lambda." (type=? x :dynamic-macro)) (define (built-in-function? x) - "Checks if the argument is a built-in function." + :doc "Checks if the argument is a built-in function." (type=? x :built-in-function)) (define (callable? x) @@ -230,11 +229,11 @@ ithe sequence as arguemens." (built-in-function? x))) (define (end seq) - "Returns the last pair in the sqeuence. + :doc "Returns the last pair in the sqeuence. {{{example_start}}} (define a (list 1 2 3 4)) -(printf (end a)) +(print (end a)) {{{example_end}}} " (if (or (null? seq) (not (pair? (rest seq)))) @@ -242,17 +241,17 @@ ithe sequence as arguemens." (end (rest seq)))) (define (last seq) - "Returns the (first) of the last (pair) of the given sequence. + :doc "Returns the (first) of the last (pair) of the given sequence. {{{example_start}}} (define a (list 1 2 3 4)) -(printf (last a)) +(print (last a)) {{{example_end}}} " (first (end seq))) (define (extend seq elem) - "Extends a list with the given element, by putting it in + :doc "Extends a list with the given element, by putting it in the (rest) of the last element of the sequence." (if (pair? seq) (begin @@ -262,23 +261,23 @@ the (rest) of the last element of the sequence." elem)) (define (extend2 seq elem) - "Extends a list with the given element, by putting it in + :doc "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))) + (print "addr of (end seq)" (addr-of (end seq))) (if (pair? seq) (let ((e (end seq))) - (printf "addr if e inner" (addr-of e)) + (print "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 + :doc "Appends an element to a sequence, by extendeing the list with (pair elem nil)." (extend seq (pair elem ()))) (define (length seq) - "Returns the length of the given sequence." + :doc "Returns the length of the given sequence." (if (null? seq) 0 (+ 1 (length (rest seq))))) @@ -303,21 +302,21 @@ with (pair elem nil)." (else (pair (first seq) (list-without-index (rest seq) (- index 1)))))) (define (increment val) - "Adds one to the argument." + :doc "Adds one to the argument." (+ val 1)) (define (decrement val) - "Subtracts one from the argument." + :doc "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=." +(define (range (:from 0) :to) + :doc "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-while :keys from :defaults-to 0 to) - "Returns a sequence of numbers starting with the number defined +(define (range-while (:from 0) to) + :doc "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) @@ -330,7 +329,7 @@ by the key 'from' and ends with the number defined in 'to'." result) (define (map fun seq) - "Takes a function and a sequence as arguments and returns a new + :doc "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 (null? seq) @@ -339,17 +338,17 @@ elemens as argument to that function." (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=]] + :doc "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-binary fun seq) - "Takes a function and a sequence as arguments and applies the + :doc "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 +*pair-wise* which means it works with binary functions as compared to [[=reduce=]]." (if (null? (rest seq)) (first seq) @@ -357,7 +356,7 @@ function to the argument sequence. reduce-binary applies the arguments (reduce-binary fun (rest seq))))) (define (filter fun seq) - "Takes a function and a sequence as arguments and applies the + :doc "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." @@ -392,20 +391,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 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) - ()) +;; (define (print (:sep " ") (:end "\n") . 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 (print-inner args) +;; (if args +;; (begin +;; (print (first args)) +;; (when (rest args) +;; (print sep)) +;; (print-inner (rest args))) +;; ; else +;; (print end))) + +;; (print-inner args) +;; ()) diff --git a/bin/pre.slime.expanded b/bin/pre.slime.expanded index d365a54..9e5f834 100644 --- a/bin/pre.slime.expanded +++ b/bin/pre.slime.expanded @@ -1,42 +1,66 @@ -(define (null? x) "Checks if the argument is =nil=." (= x ())) +(define-syntax (pe expr) `(print ',expr "evaluates to" ,expr)) -(define (type=? obj typ) "Checks if the argument =obj= is of type =typ=" (= (type obj) typ)) +(define-syntax (when condition . body) :doc "Special form for when multiple actions should be done if a\ncondition is true.\n\n{{{example_start}}}\n(when (not ())\n (print "Hello ")\n (print "from ")\n (print "when!"))\n\n(when ()\n (print "Goodbye ")\n (print "World!"))\n{{{example_end}}}\n" (if (= (rest body) ()) `(if ,condition (unquote-splicing body) nil) `(if ,condition (begin (unquote-splicing body)) nil))) -(define (types=? :rest objs) (define (inner objs) (if objs (let ((actual-type (type (first objs))) (desired-type (first (rest objs)))) (if (= actual-type desired-type) (inner (rest (rest objs))) ())) t)) (inner objs)) +(define-syntax (unless condition . body) :doc "Special form for when multiple actions should be done if a\ncondition is false." (if (= (rest body) ()) `(if ,condition nil (unquote-splicing body)) `(if ,condition nil (begin (unquote-splicing body))))) -(define (assert-types= :rest objs) (define (inner objs) (when objs (let ((actual-type (type (first objs))) (desired-type (first (rest objs)))) (if (= actual-type desired-type) (inner (rest (rest objs))) (error "type missmatch" actual-type desired-type))))) (inner objs)) +(define-syntax (n-times times action) :doc "Executes action times times." (define (repeat times elem) (unless (> 1 times) (pair elem (repeat (- times 1) elem)))) `(begin (unquote-splicing (repeat times action)))) -(define (number? x) "Checks if the argument is a number." (type=? x :number)) +(define-syntax (let bindings . body) (define (unzip lists) (break) (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 unzipped (unzip bindings)) `((,lambda ,(first unzipped) (unquote-splicing body)) (unquote-splicing (first (rest unzipped))))) -(define (symbol? x) "Checks if the argument is a symbol." (type=? x :symbol)) +(define-syntax (cond . clauses) (define (rec clauses) (if (= nil clauses) nil (if (= (first (first clauses)) 'else) (begin (if (not (= (rest clauses) ())) (error "There are additional clauses after the else clause!") (pair 'begin (rest (first clauses))))) `(if ,(first (first clauses)) (begin (unquote-splicing (rest (first clauses)))) ,(rec (rest clauses)))))) (rec clauses)) -(define (keyword? x) "Checks if the argument is a keyword." (type=? x :keyword)) +(define-syntax (case var . clauses) (define (rec clauses) (if (= nil clauses) nil (if (= (first (first clauses)) 'else) (begin (if (not (= (rest clauses) ())) (error "There are additional clauses after the else clause!") (pair 'begin (rest (first clauses))))) `(if (member? ,var ',(first (first clauses))) (begin (unquote-splicing (rest (first clauses)))) ,(rec (rest clauses)))))) (rec clauses)) -(define (pair? x) "Checks if the argument is a pair." (type=? x :pair)) +(define-syntax (define-special name-and-args . body) `(define ,(first name-and-args) (special-lambda ,(rest name-and-args) (unquote-splicing body)))) -(define (string? x) "Checks if the argument is a string." (type=? x :string)) +(define-syntax (construct-list . body) :doc "\n{{{example_start}}}\n(construct-list\n i <- '(1 2 3 4 5)\n yield (* i i))\n{{{example_end}}}\n\n(construct-list\n i <- '(1 2 3 4)\n j <- '(A B)\n yield (pair i j))\n\n(construct-list\n i <- '(1 2 3 4 5 6 7 8)\n if (= 0 (% i 2))\n yield i)\n" (define (append-map f ll) (unless (= ll ()) (define val (f (first ll))) (if (= (first val) ()) (append-map f (rest ll)) (extend val (append-map f (rest ll)))))) (define (rec body) (cond ((= () body) ()) ((= () (rest body)) (first body)) ((= (first (rest body)) '<-) `(,append-map (lambda (,(first body)) (list ,(rec (rest (rest (rest body)))))) ,(first (rest (rest body))))) ((= (first body) 'if) `(when ,(first (rest body)) ,(rec (rest (rest body))))) ((= (first (rest body)) 'yield) (first (rest body))) (else (error "Not a do-able expression")))) (rec body)) -(define (lambda? x) "Checks if the argument is a function." (type=? x :lambda)) +(define-syntax (apply fun seq) :doc "Applies the function to the sequence, as in calls the function with\nithe sequence as arguemens." `(eval (pair ,fun ,seq))) -(define (macro? x) "Checks if the argument is a macro." (type=? x :macro)) +(define-syntax (define-typed args . body) (define (get-arg-names args) (when args (pair (first args) (get-arg-names (rest (rest args)))))) (let ((name (first args)) (lambda-list (rest args)) (arg-names (get-arg-names (rest args)))) `(define (,name (unquote-splicing arg-names)) (assert-types= (unquote-splicing lambda-list)) (unquote-splicing body)))) -(define (special-lambda? x) "Checks if the argument is a special-lambda." (type=? x :dynamic-macro)) +(define-syntax (define-module module-name :exports . body) (let ((module-prefix (concat-strings (symbol->string module-name) "::"))) (eval `(begin (unquote-splicing body))) (pair 'begin (map (lambda (orig-export-name) (let ((export-name (string->symbol (concat-strings module-prefix (symbol->string orig-export-name))))) `(define ,export-name ,(try (eval orig-export-name) (error "The module does not contain" orig-export-name))))) exports)))) -(define (built-in-function? x) "Checks if the argument is a built-in function." (type=? x :built-in-function)) +(define (null? x) :doc "Checks if the argument is =nil=." (= x ())) + +(define (type=? obj typ) :doc "Checks if the argument =obj= is of type =typ=" (= (type obj) typ)) + +(define (types=? . objs) (define (inner objs) (if objs (let ((actual-type (type (first objs))) (desired-type (first (rest objs)))) (if (= actual-type desired-type) (inner (rest (rest objs))) ())) t)) (inner objs)) + +(define (assert-types= . objs) (define (inner objs) (when objs (let ((actual-type (type (first objs))) (desired-type (first (rest objs)))) (if (= actual-type desired-type) (inner (rest (rest objs))) (error "type missmatch" actual-type desired-type))))) (inner objs)) + +(define (number? x) :doc "Checks if the argument is a number." (type=? x :number)) + +(define (symbol? x) :doc "Checks if the argument is a symbol." (type=? x :symbol)) + +(define (keyword? x) :doc "Checks if the argument is a keyword." (type=? x :keyword)) + +(define (pair? x) :doc "Checks if the argument is a pair." (type=? x :pair)) + +(define (string? x) :doc "Checks if the argument is a string." (type=? x :string)) + +(define (lambda? x) :doc "Checks if the argument is a function." (type=? x :lambda)) + +(define (macro? x) :doc "Checks if the argument is a macro." (type=? x :macro)) + +(define (special-lambda? x) :doc "Checks if the argument is a special-lambda." (type=? x :dynamic-macro)) + +(define (built-in-function? x) :doc "Checks if the argument is a built-in function." (type=? x :built-in-function)) (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.\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 (end seq) :doc "Returns the last pair in the sqeuence.\n\n{{{example_start}}}\n(define a (list 1 2 3 4))\n(print (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.\n\n{{{example_start}}}\n(define a (list 1 2 3 4))\n(printf (last a))\n{{{example_end}}}\n" (first (end seq))) +(define (last seq) :doc "Returns the (first) of the last (pair) of the given sequence.\n\n{{{example_start}}}\n(define a (list 1 2 3 4))\n(print (last a))\n{{{example_end}}}\n" (first (end seq))) -(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 (extend seq elem) :doc "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\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 (extend2 seq elem) :doc "Extends a list with the given element, by putting it in\nthe (rest) of the last element of the sequence." (print "addr of (end seq)" (addr-of (end seq))) (if (pair? seq) (let ((e (end seq))) (print "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\nwith (pair elem nil)." (extend seq (pair elem ()))) +(define (append seq elem) :doc "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 (null? seq) 0 (+ 1 (length (rest seq))))) +(define (length seq) :doc "Returns the length of the given sequence." (if (null? seq) 0 (+ 1 (length (rest seq))))) (define (member? elem seq) (when (pair? seq) (if (= elem (first seq)) t (member? elem (rest seq))))) @@ -44,21 +68,21 @@ (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 (increment val) :doc "Adds one to the argument." (+ val 1)) -(define (decrement val) "Subtracts one from the argument." (- val 1)) +(define (decrement val) :doc "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\nkey =from= and ends with the number defined in =to=." (when (< from to) (pair from (range :from (+ 1 from) :to to)))) +(define (range (:from 0) :to) :doc "Returns a sequence of numbers starting with the number defined\nby the key =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\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 (range-while (:from 0) to) :doc "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\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 (map fun seq) :doc "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\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 fun seq) :doc "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\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 (reduce-binary fun seq) :doc "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\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 (filter fun seq) :doc "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 (null? l1) (null? l2)) (pair (list (first l1) (first l2)) (zip (rest l1) (rest l2))))) @@ -66,5 +90,3 @@ (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 "\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/class_macro.slime.expanded b/bin/tests/class_macro.slime.expanded index 976cb0b..c30a550 100644 --- a/bin/tests/class_macro.slime.expanded +++ b/bin/tests/class_macro.slime.expanded @@ -1,14 +1,14 @@ -(import "oo.slime") - -(define-class (vector3 x y z) (define (set-x new-x) (mutate x new-x)) (define (set-y new-y) (mutate y new-y)) (define (set-z new-z) (mutate z new-z)) (define (length) (** (+ (* x x) (* y y) (* z z)) 0.500000)) (define (scale fac) (mutate x (* fac x)) (mutate y (* fac y)) (mutate z (* fac z)) fac) (define (add other) (make-vector3 (+ (-> other x) x) (+ (-> other y) y) (+ (-> other z) z))) (define (subtract other) (make-vector3 (- (-> other x) x) (- (-> other y) y) (- (-> other z) z))) (define (equal? other) (and (= (-> other x) x) (= (-> other y) y) (= (-> other z) z))) (define (scalar-product other) (+ (* (-> other x) x) (* (-> other y) y) (* (-> other z) z))) (define (cross-product other) (make-vector3 (- (* (-> other z) y) (* (-> other y) z)) (- (* (-> other x) z) (* (-> other z) x)) (- (* (-> other y) x) (* (-> other x) y)))) (define (print) (printf :sep " " "[vector3] (" x y z ")"))) - -(define v1 (make-vector3 1 2 3)) - -(define v2 (make-vector3 3 2 1)) - -(assert (= (type v1) (type v2) :vector3)) - -(assert (= (v1 'scalar-product v2) 10)) - -(assert (-> (-> v1 cross-product v2) equal? (make-vector3 -4 8 -4))) - +(import "oo.slime") + +(define-class (vector3 x y z) (define (set-x new-x) (mutate x new-x)) (define (set-y new-y) (mutate y new-y)) (define (set-z new-z) (mutate z new-z)) (define (length) (** (+ (* x x) (* y y) (* z z)) 0.500000)) (define (scale fac) (mutate x (* fac x)) (mutate y (* fac y)) (mutate z (* fac z)) fac) (define (add other) (make-vector3 (+ (-> other x) x) (+ (-> other y) y) (+ (-> other z) z))) (define (subtract other) (make-vector3 (- (-> other x) x) (- (-> other y) y) (- (-> other z) z))) (define (equal? other) (and (= (-> other x) x) (= (-> other y) y) (= (-> other z) z))) (define (scalar-product other) (+ (* (-> other x) x) (* (-> other y) y) (* (-> other z) z))) (define (cross-product other) (make-vector3 (- (* (-> other z) y) (* (-> other y) z)) (- (* (-> other x) z) (* (-> other z) x)) (- (* (-> other y) x) (* (-> other x) y)))) (define (print) (printf :sep " " "[vector3] (" x y z ")"))) + +(define v1 (make-vector3 1 2 3)) + +(define v2 (make-vector3 3 2 1)) + +(assert (= (type v1) (type v2) :vector3)) + +(assert (= (v1 'scalar-product v2) 10)) + +(assert (-> (-> v1 cross-product v2) equal? (make-vector3 -4 8 -4))) + diff --git a/bin/tests/lexical_scope.slime.expanded b/bin/tests/lexical_scope.slime.expanded index 26a9c39..2d897de 100644 --- a/bin/tests/lexical_scope.slime.expanded +++ b/bin/tests/lexical_scope.slime.expanded @@ -1,54 +1,54 @@ -(define (make-counter) (let ((var 0)) (lambda () (set! var (+ 1 var))))) - -(define counter1 (make-counter)) - -(assert (= (counter1) 1)) - -(define counter2 (make-counter)) - -(assert (= (counter2) 1)) - -(assert (= (counter2) 2)) - -(assert (= (counter1) 2)) - -(assert (= (counter1) 3)) - -(assert (= (counter2) 3)) - -(assert (= (counter2) 4)) - -(assert (= (counter2) 5)) - -(assert (= (counter1) 4)) - -(assert (= (counter1) 5)) - -(define (g) (define x 0) (lambda () (define temp x) (mutate x (+ x 1)) temp)) - -(define (make-key-counter) ((lambda (:keys var) (lambda () (mutate var (+ 1 var)) var)) :var 0)) - -(define key-counter1 (make-key-counter)) - -(assert (= (key-counter1) 1)) - -(define key-counter2 (make-key-counter)) - -(assert (= (key-counter2) 1)) - -(assert (= (key-counter2) 2)) - -(assert (= (key-counter1) 2)) - -(assert (= (key-counter1) 3)) - -(assert (= (key-counter2) 3)) - -(assert (= (key-counter2) 4)) - -(assert (= (key-counter2) 5)) - -(assert (= (key-counter1) 4)) - -(assert (= (key-counter1) 5)) - +(define (make-counter) (let ((var 0)) (lambda () (set! var (+ 1 var))))) + +(define counter1 (make-counter)) + +(assert (= (counter1) 1)) + +(define counter2 (make-counter)) + +(assert (= (counter2) 1)) + +(assert (= (counter2) 2)) + +(assert (= (counter1) 2)) + +(assert (= (counter1) 3)) + +(assert (= (counter2) 3)) + +(assert (= (counter2) 4)) + +(assert (= (counter2) 5)) + +(assert (= (counter1) 4)) + +(assert (= (counter1) 5)) + +(define (g) (define x 0) (lambda () (define temp x) (mutate x (+ x 1)) temp)) + +(define (make-key-counter) ((lambda (:keys var) (lambda () (mutate var (+ 1 var)) var)) :var 0)) + +(define key-counter1 (make-key-counter)) + +(assert (= (key-counter1) 1)) + +(define key-counter2 (make-key-counter)) + +(assert (= (key-counter2) 1)) + +(assert (= (key-counter2) 2)) + +(assert (= (key-counter1) 2)) + +(assert (= (key-counter1) 3)) + +(assert (= (key-counter2) 3)) + +(assert (= (key-counter2) 4)) + +(assert (= (key-counter2) 5)) + +(assert (= (key-counter1) 4)) + +(assert (= (key-counter1) 5)) + diff --git a/build.sh b/build.sh index 10fbafc..f319bb5 100644 --- a/build.sh +++ b/build.sh @@ -10,10 +10,6 @@ echo "" pushd ./bin > /dev/null time ./slime --run-tests -echo "" -echo "generating docs" -time ./slime generate-docs.slime - popd > /dev/null popd > /dev/null unset TIMEFORMAT diff --git a/manual/built-in-docs.org b/manual/built-in-docs.org index 77b4afc..9944bde 100644 --- a/manual/built-in-docs.org +++ b/manual/built-in-docs.org @@ -1,1311 +1,1311 @@ -\hrule -* === - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:166:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -Takes 0 or more arguments and returns =t= if all arguments are equal and =()= otherwise. - #+END: -\hrule -* =>= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:182:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =>== - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:199:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =<= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:216:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =<== - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:235:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =+= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:252:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =-= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:264:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =*= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:286:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =/= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:306:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =**= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:326:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =%= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:341:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =assert= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:356:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =define= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:367:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =mutate= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:429:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =vector-length= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:454:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =vector-ref= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:462:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =vector-set!= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:479:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =set!= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:499:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =set-car!= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:521:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =set-cdr!= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:532:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =if= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:543:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =quote= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:563:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =quasiquote= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:568:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =and= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:665:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =or= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:676:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =not= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:687:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =while= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:697:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =lambda= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:775:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =special-lambda= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:787:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =eval= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:795:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =begin= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:807:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =list= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:823:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =vector= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:827:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =pair= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:833:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =first= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:843:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =rest= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:854:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =set-type= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:865:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =delete-type= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:877:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =type= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:884:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =info= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:918:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =show= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:999:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =addr-of= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1011:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =generate-docs= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1017:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =print= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1026:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =read= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1034:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =exit= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1051:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =break= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1062:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =memstat= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1067:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =try= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1071:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =load= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1086:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =import= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1097:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =copy= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1108:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =error= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1116:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =symbol->keyword= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1123:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =string->symbol= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1132:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =symbol->string= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1144:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =concat-strings= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1153:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =pe= - - - defined in :: =pre.slime:4:40= - - type :: =:macro= - - arguments :: : - - postitional :: =expr= - - docu :: none -\hrule -* =when= - - - defined in :: =pre.slime:23:41= - - type :: =:macro= - - arguments :: : - - postitional :: =condition=: - - rest :: =body= - - docu :: - #+BEGIN: -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:30:41= - - type :: =:macro= - - arguments :: : - - postitional :: =condition=: - - rest :: =body= - - docu :: - #+BEGIN: -Special form for when multiple actions should be done if a -condition is false. - #+END: -\hrule -* =n-times= - - - defined in :: =pre.slime:37:35= - - type :: =:macro= - - arguments :: : - - postitional :: =times=, =action= - - docu :: - #+BEGIN: -Executes action times times. - #+END: -\hrule -* =let= - - - defined in :: =pre.slime:54:64= - - type :: =:macro= - - arguments :: : - - postitional :: =bindings=: - - rest :: =body= - - docu :: none -\hrule -* =cond= - - - defined in :: =pre.slime:68:17= - - type :: =:macro= - - arguments :: : - - rest :: =clauses= - - docu :: none -\hrule -* =case= - - - defined in :: =pre.slime:83:17= - - type :: =:macro= - - arguments :: : - - postitional :: =var=: - - rest :: =clauses= - - docu :: none -\hrule -* =define-special= - - - defined in :: =pre.slime:86:81= - - type :: =:macro= - - arguments :: : - - postitional :: =name-and-args=: - - rest :: =body= - - docu :: none -\hrule -* =construct-list= - - - defined in :: =pre.slime:127: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) - j <- '(A B) - yield (pair i j)) - -(construct-list - i <- '(1 2 3 4 5 6 7 8) - if (= 0 (% i 2)) - yield i) - - #+END: -\hrule -* =apply= - - - defined in :: =pre.slime:132:28= - - type :: =:macro= - - arguments :: : - - postitional :: =fun=, =seq= - - docu :: - #+BEGIN: -Applies the function to the sequence, as in calls the function with -ithe sequence as arguemens. - #+END: -\hrule -* =define-typed= - - - defined in :: =pre.slime:144:16= - - type :: =:macro= - - arguments :: : - - postitional :: =args=: - - rest :: =body= - - docu :: none -\hrule -* =define-module= - - - defined in :: =pre.slime:158:27= - - type :: =:macro= - - arguments :: : - - postitional :: =module-name=: - - keyword :: =exports=: - - rest :: =body= - - docu :: none -\hrule -* =null?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is =nil=. - #+END: -\hrule -* =type=?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =obj=, =typ= - - docu :: - #+BEGIN: -Checks if the argument =obj= is of type =typ= - #+END: -\hrule -* =types=?= - - - type :: =:lambda= - - arguments :: : - - rest :: =objs= - - docu :: none -\hrule -* =assert-types== - - - type :: =:lambda= - - arguments :: : - - rest :: =objs= - - docu :: none -\hrule -* =number?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a number. - #+END: -\hrule -* =symbol?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a symbol. - #+END: -\hrule -* =keyword?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a keyword. - #+END: -\hrule -* =pair?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a pair. - #+END: -\hrule -* =string?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a string. - #+END: -\hrule -* =lambda?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a function. - #+END: -\hrule -* =macro?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a macro. - #+END: -\hrule -* =special-lambda?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a special-lambda. - #+END: -\hrule -* =built-in-function?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Checks if the argument is a built-in function. - #+END: -\hrule -* =callable?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: none -\hrule -* =end= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: - #+BEGIN: -Returns the last pair in the sqeuence. - -{{{example_start}}} -(define a (list 1 2 3 4)) -(printf (end a)) -{{{example_end}}} - - #+END: -\hrule -* =last= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: - #+BEGIN: -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}}} - - #+END: -\hrule -* =extend= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq=, =elem= - - docu :: - #+BEGIN: -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= - - arguments :: : - - postitional :: =seq=, =elem= - - docu :: - #+BEGIN: -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= - - arguments :: : - - postitional :: =seq=, =elem= - - docu :: - #+BEGIN: -Appends an element to a sequence, by extendeing the list -with (pair elem nil). - #+END: -\hrule -* =length= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: - #+BEGIN: -Returns the length of the given sequence. - #+END: -\hrule -* =member?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =elem=, =seq= - - docu :: none -\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= - - arguments :: : - - postitional :: =val= - - docu :: - #+BEGIN: -Adds one to the argument. - #+END: -\hrule -* =decrement= - - - type :: =:lambda= - - arguments :: : - - postitional :: =val= - - docu :: - #+BEGIN: -Subtracts one from the argument. - #+END: -\hrule -* =range= - - - type :: =:lambda= - - arguments :: : - - keyword :: =from= =(0)=, =to= - - docu :: - #+BEGIN: -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= - - arguments :: : - - keyword :: =from= =(0)=, =to= - - docu :: - #+BEGIN: -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= - - arguments :: : - - postitional :: =fun=, =seq= - - docu :: - #+BEGIN: -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= - - arguments :: : - - postitional :: =fun=, =seq= - - docu :: - #+BEGIN: -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. - #+END: -\hrule -* =reduce-binary= - - - type :: =:lambda= - - arguments :: : - - 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=]]. - #+END: -\hrule -* =filter= - - - type :: =:lambda= - - arguments :: : - - postitional :: =fun=, =seq= - - docu :: - #+BEGIN: -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. - #+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= =("\n")=: - - rest :: =args= - - docu :: - #+BEGIN: -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 -* =key-not-found-index= - - - defined in :: =alist.slime:28:31= - - type :: =:number= - - value :: =-1= - - docu :: none -\hrule -* =make-alist= - - - type :: =:lambda= - - arguments :: none. - - docu :: none -\hrule -* =make-plist= - - - type :: =:lambda= - - arguments :: none. - - docu :: none -\hrule -* =pprint-alist= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist= - - docu :: none -\hrule -* =pprint-plist= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist= - - docu :: none -\hrule -* =alist-get= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist=, =key= - - docu :: none -\hrule -* =alist-find= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist=, =key= - - docu :: none -\hrule -* =alist-key-exists?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist=, =key= - - docu :: none -\hrule -* =alist-remove!= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist=, =key= - - docu :: none -\hrule -* =alist-set!= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist=, =key=, =value= - - docu :: none -\hrule -* =alist-set-overwrite!= - - - type :: =:lambda= - - arguments :: : - - postitional :: =alist=, =key=, =value= - - docu :: none -\hrule -* =plist-get= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist=, =prop= - - docu :: none -\hrule -* =plist-set!= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist=, =prop=, =value= - - docu :: none -\hrule -* =plist-set-overwrite!= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist=, =prop=, =value= - - docu :: none -\hrule -* =plist-find= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist=, =prop= - - docu :: none -\hrule -* =plist-prop-exists?= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist=, =prop= - - docu :: none -\hrule -* =plist-remove!= - - - type :: =:lambda= - - arguments :: : - - postitional :: =plist=, =prop= - - docu :: none -\hrule -* =cons= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:833:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =car= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:843:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =cdr= - - - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:854:0= - - type :: =:cfunction= - - docu :: - #+BEGIN: -TODO - #+END: -\hrule -* =caar= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cddr= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cadr= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cdar= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =caaar= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =caadr= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cadar= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =caddr= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cdaar= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cdadr= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cddar= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =cdddr= - - - type :: =:lambda= - - arguments :: : - - postitional :: =seq= - - docu :: none -\hrule -* =define-class= - - - defined in :: =oo.slime:22:22= - - type :: =:macro= - - arguments :: : - - postitional :: =name-and-members=: - - rest :: =body= - - docu :: - #+BEGIN: -Macro for creating simple classes. - #+END: -\hrule -* =->= - - - defined in :: =oo.slime:25:24= - - type :: =:macro= - - arguments :: : - - postitional :: =obj=, =meth=: - - rest :: =args= - - docu :: none -\hrule -* =math::pi= - - - defined in :: =pre.slime:338:12= - - type :: =:number= - - value :: =3.141593= - - docu :: - #+BEGIN: -Tha famous circle constant. - #+END: -\hrule -* =math::abs= - - - defined in :: =pre.slime:338:12= - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Accepts one argument and returns the absoulte value of it - #+END: -\hrule -* =math::sqrt= - - - defined in :: =pre.slime:338:12= - - type :: =:lambda= - - arguments :: : - - postitional :: =x= - - docu :: - #+BEGIN: -Accepts one argument and returns the square root of it - #+END: -\hrule -* =math::make-vector3= - - - defined in :: =pre.slime:338:12= - - type :: =:constructor= - - arguments :: : - - postitional :: =x=, =y=, =z= - - docu :: - #+BEGIN: -This is the handle to an object of the class vector3 - #+END: +\hrule +* === + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:166:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +Takes 0 or more arguments and returns =t= if all arguments are equal and =()= otherwise. + #+END: +\hrule +* =>= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:182:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =>== + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:199:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =<= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:216:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =<== + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:235:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =+= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:252:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =-= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:264:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =*= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:286:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =/= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:306:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =**= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:326:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =%= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:341:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =assert= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:356:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =define= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:367:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =mutate= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:429:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =vector-length= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:454:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =vector-ref= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:462:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =vector-set!= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:479:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =set!= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:499:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =set-car!= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:521:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =set-cdr!= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:532:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =if= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:543:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =quote= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:563:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =quasiquote= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:568:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =and= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:665:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =or= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:676:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =not= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:687:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =while= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:697:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =lambda= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:775:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =special-lambda= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:787:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =eval= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:795:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =begin= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:807:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =list= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:823:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =vector= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:827:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =pair= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:833:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =first= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:843:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =rest= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:854:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =set-type= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:865:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =delete-type= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:877:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =type= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:884:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =info= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:918:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =show= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:999:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =addr-of= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1011:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =generate-docs= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1017:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =print= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1026:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =read= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1034:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =exit= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1051:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =break= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1062:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =memstat= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1067:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =try= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1071:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =load= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1086:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =import= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1097:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =copy= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1108:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =error= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1116:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =symbol->keyword= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1123:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =string->symbol= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1132:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =symbol->string= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1144:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =concat-strings= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:1153:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =pe= + + - defined in :: =pre.slime:4:40= + - type :: =:macro= + - arguments :: : + - postitional :: =expr= + - docu :: none +\hrule +* =when= + + - defined in :: =pre.slime:23:41= + - type :: =:macro= + - arguments :: : + - postitional :: =condition=: + - rest :: =body= + - docu :: + #+BEGIN: +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:30:41= + - type :: =:macro= + - arguments :: : + - postitional :: =condition=: + - rest :: =body= + - docu :: + #+BEGIN: +Special form for when multiple actions should be done if a +condition is false. + #+END: +\hrule +* =n-times= + + - defined in :: =pre.slime:37:35= + - type :: =:macro= + - arguments :: : + - postitional :: =times=, =action= + - docu :: + #+BEGIN: +Executes action times times. + #+END: +\hrule +* =let= + + - defined in :: =pre.slime:54:64= + - type :: =:macro= + - arguments :: : + - postitional :: =bindings=: + - rest :: =body= + - docu :: none +\hrule +* =cond= + + - defined in :: =pre.slime:68:17= + - type :: =:macro= + - arguments :: : + - rest :: =clauses= + - docu :: none +\hrule +* =case= + + - defined in :: =pre.slime:83:17= + - type :: =:macro= + - arguments :: : + - postitional :: =var=: + - rest :: =clauses= + - docu :: none +\hrule +* =define-special= + + - defined in :: =pre.slime:86:81= + - type :: =:macro= + - arguments :: : + - postitional :: =name-and-args=: + - rest :: =body= + - docu :: none +\hrule +* =construct-list= + + - defined in :: =pre.slime:127: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) + j <- '(A B) + yield (pair i j)) + +(construct-list + i <- '(1 2 3 4 5 6 7 8) + if (= 0 (% i 2)) + yield i) + + #+END: +\hrule +* =apply= + + - defined in :: =pre.slime:132:28= + - type :: =:macro= + - arguments :: : + - postitional :: =fun=, =seq= + - docu :: + #+BEGIN: +Applies the function to the sequence, as in calls the function with +ithe sequence as arguemens. + #+END: +\hrule +* =define-typed= + + - defined in :: =pre.slime:144:16= + - type :: =:macro= + - arguments :: : + - postitional :: =args=: + - rest :: =body= + - docu :: none +\hrule +* =define-module= + + - defined in :: =pre.slime:158:27= + - type :: =:macro= + - arguments :: : + - postitional :: =module-name=: + - keyword :: =exports=: + - rest :: =body= + - docu :: none +\hrule +* =null?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is =nil=. + #+END: +\hrule +* =type=?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =obj=, =typ= + - docu :: + #+BEGIN: +Checks if the argument =obj= is of type =typ= + #+END: +\hrule +* =types=?= + + - type :: =:lambda= + - arguments :: : + - rest :: =objs= + - docu :: none +\hrule +* =assert-types== + + - type :: =:lambda= + - arguments :: : + - rest :: =objs= + - docu :: none +\hrule +* =number?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a number. + #+END: +\hrule +* =symbol?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a symbol. + #+END: +\hrule +* =keyword?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a keyword. + #+END: +\hrule +* =pair?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a pair. + #+END: +\hrule +* =string?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a string. + #+END: +\hrule +* =lambda?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a function. + #+END: +\hrule +* =macro?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a macro. + #+END: +\hrule +* =special-lambda?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a special-lambda. + #+END: +\hrule +* =built-in-function?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Checks if the argument is a built-in function. + #+END: +\hrule +* =callable?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: none +\hrule +* =end= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: + #+BEGIN: +Returns the last pair in the sqeuence. + +{{{example_start}}} +(define a (list 1 2 3 4)) +(printf (end a)) +{{{example_end}}} + + #+END: +\hrule +* =last= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: + #+BEGIN: +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}}} + + #+END: +\hrule +* =extend= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq=, =elem= + - docu :: + #+BEGIN: +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= + - arguments :: : + - postitional :: =seq=, =elem= + - docu :: + #+BEGIN: +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= + - arguments :: : + - postitional :: =seq=, =elem= + - docu :: + #+BEGIN: +Appends an element to a sequence, by extendeing the list +with (pair elem nil). + #+END: +\hrule +* =length= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: + #+BEGIN: +Returns the length of the given sequence. + #+END: +\hrule +* =member?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =elem=, =seq= + - docu :: none +\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= + - arguments :: : + - postitional :: =val= + - docu :: + #+BEGIN: +Adds one to the argument. + #+END: +\hrule +* =decrement= + + - type :: =:lambda= + - arguments :: : + - postitional :: =val= + - docu :: + #+BEGIN: +Subtracts one from the argument. + #+END: +\hrule +* =range= + + - type :: =:lambda= + - arguments :: : + - keyword :: =from= =(0)=, =to= + - docu :: + #+BEGIN: +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= + - arguments :: : + - keyword :: =from= =(0)=, =to= + - docu :: + #+BEGIN: +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= + - arguments :: : + - postitional :: =fun=, =seq= + - docu :: + #+BEGIN: +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= + - arguments :: : + - postitional :: =fun=, =seq= + - docu :: + #+BEGIN: +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. + #+END: +\hrule +* =reduce-binary= + + - type :: =:lambda= + - arguments :: : + - 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=]]. + #+END: +\hrule +* =filter= + + - type :: =:lambda= + - arguments :: : + - postitional :: =fun=, =seq= + - docu :: + #+BEGIN: +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. + #+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= =("\n")=: + - rest :: =args= + - docu :: + #+BEGIN: +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 +* =key-not-found-index= + + - defined in :: =alist.slime:28:31= + - type :: =:number= + - value :: =-1= + - docu :: none +\hrule +* =make-alist= + + - type :: =:lambda= + - arguments :: none. + - docu :: none +\hrule +* =make-plist= + + - type :: =:lambda= + - arguments :: none. + - docu :: none +\hrule +* =pprint-alist= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist= + - docu :: none +\hrule +* =pprint-plist= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist= + - docu :: none +\hrule +* =alist-get= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist=, =key= + - docu :: none +\hrule +* =alist-find= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist=, =key= + - docu :: none +\hrule +* =alist-key-exists?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist=, =key= + - docu :: none +\hrule +* =alist-remove!= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist=, =key= + - docu :: none +\hrule +* =alist-set!= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist=, =key=, =value= + - docu :: none +\hrule +* =alist-set-overwrite!= + + - type :: =:lambda= + - arguments :: : + - postitional :: =alist=, =key=, =value= + - docu :: none +\hrule +* =plist-get= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist=, =prop= + - docu :: none +\hrule +* =plist-set!= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist=, =prop=, =value= + - docu :: none +\hrule +* =plist-set-overwrite!= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist=, =prop=, =value= + - docu :: none +\hrule +* =plist-find= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist=, =prop= + - docu :: none +\hrule +* =plist-prop-exists?= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist=, =prop= + - docu :: none +\hrule +* =plist-remove!= + + - type :: =:lambda= + - arguments :: : + - postitional :: =plist=, =prop= + - docu :: none +\hrule +* =cons= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:833:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =car= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:843:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =cdr= + + - defined in :: =d:\code\gitlab\slime\src\./built_ins.cpp:854:0= + - type :: =:cfunction= + - docu :: + #+BEGIN: +TODO + #+END: +\hrule +* =caar= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cddr= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cadr= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cdar= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =caaar= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =caadr= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cadar= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =caddr= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cdaar= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cdadr= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cddar= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =cdddr= + + - type :: =:lambda= + - arguments :: : + - postitional :: =seq= + - docu :: none +\hrule +* =define-class= + + - defined in :: =oo.slime:22:22= + - type :: =:macro= + - arguments :: : + - postitional :: =name-and-members=: + - rest :: =body= + - docu :: + #+BEGIN: +Macro for creating simple classes. + #+END: +\hrule +* =->= + + - defined in :: =oo.slime:25:24= + - type :: =:macro= + - arguments :: : + - postitional :: =obj=, =meth=: + - rest :: =args= + - docu :: none +\hrule +* =math::pi= + + - defined in :: =pre.slime:338:12= + - type :: =:number= + - value :: =3.141593= + - docu :: + #+BEGIN: +Tha famous circle constant. + #+END: +\hrule +* =math::abs= + + - defined in :: =pre.slime:338:12= + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Accepts one argument and returns the absoulte value of it + #+END: +\hrule +* =math::sqrt= + + - defined in :: =pre.slime:338:12= + - type :: =:lambda= + - arguments :: : + - postitional :: =x= + - docu :: + #+BEGIN: +Accepts one argument and returns the square root of it + #+END: +\hrule +* =math::make-vector3= + + - defined in :: =pre.slime:338:12= + - type :: =:constructor= + - arguments :: : + - postitional :: =x=, =y=, =z= + - docu :: + #+BEGIN: +This is the handle to an object of the class vector3 + #+END: diff --git a/src/built_ins.cpp b/src/built_ins.cpp index c69ea16..1a49e49 100644 --- a/src/built_ins.cpp +++ b/src/built_ins.cpp @@ -1,3 +1,11 @@ +inline proc maybe_wrap_body_in_begin(Lisp_Object* body) -> Lisp_Object* { + static Lisp_Object* begin_symbol = Memory::get_or_create_lisp_object_symbol("begin"); + if (body->value.pair.rest == Memory::nil) + return body->value.pair.first; + else + return Memory::create_lisp_object_pair(begin_symbol, body); +} + proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { if (n1 == n2) return true; @@ -93,1085 +101,957 @@ proc built_in_import(String* file_name) -> Lisp_Object* { } proc load_built_ins_into_environment() -> void { - int arguments_length = 0; - Lisp_Object* evaluated_arguments = nullptr; - String* file_name_built_ins = Memory::create_string(__FILE__); + static String* file_name_built_ins = Memory::create_string(__FILE__); + + +#define fetch1(var) \ + static Lisp_Object* var##_symbol = Memory::get_or_create_lisp_object_symbol(#var); \ + Lisp_Object* var = lookup_symbol(var##_symbol, get_current_environment()) + +#define fetch2(var1, var2) fetch1(var1); fetch1(var2) +#define fetch3(var1, var2, var3) fetch2(var1, var2); fetch1(var3) +#define fetch4(var1, var2, var3, var4) fetch3(var1, var2, var3); fetch1(var4) +#define fetch5(var1, var2, var3, var4, var5) fetch3(var1, var2, var3, var4); fetch1(var5) +#define fetch6(var1, var2, var3, var4, var5, var6) fetch5(var1, var2, var3, var4, var5); fetch1(var6) + +#define GET_MACRO(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#ifdef _MSC_VER +#define EXPAND( x ) x +#define fetch(...) EXPAND(GET_MACRO(__VA_ARGS__, fetch6, fetch5, fetch4, fetch3, fetch2, fetch1)(__VA_ARGS__)) +#else +#define fetch(...) GET_MACRO(__VA_ARGS__, fetch6, fetch5, fetch4, fetch3, fetch2, fetch1)(__VA_ARGS__) +#endif + +// NOTE(Felix): we have to copy the string because we need +// it to be mutable for the parser to work, because the +// parser relys on being able to temporaily put in markers +// in the code +#define _define_helper(def, docs, special) \ + static Lisp_Object* label(params,__LINE__) = Parser::parse_single_expression( \ + Memory::get_c_str(Memory::create_string(#def)) \ + ); \ + assert_type(label(params,__LINE__), Lisp_Object_Type::Pair); \ + assert_type(label(params,__LINE__)->value.pair.first, Lisp_Object_Type::Symbol); \ + static auto label(sym,__LINE__) = label(params,__LINE__)->value.pair.first; \ + auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(special); \ + /*NOTE(Felix): for evaluating default args*/ \ + push_environment(get_root_environment()); \ + try_void create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \ + pop_environment(); \ + label(sfun,__LINE__)->sourceCodeLocation = new(Source_Code_Location); \ + label(sfun,__LINE__)->sourceCodeLocation->file = file_name_built_ins; \ + label(sfun,__LINE__)->sourceCodeLocation->line = __LINE__; \ + label(sfun,__LINE__)->sourceCodeLocation->column = 0; \ + label(sfun,__LINE__)->docstring = Memory::create_string(docs); \ + define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ + label(sfun,__LINE__)->value.cFunction->body = (std::function)[&]() -> Lisp_Object* + +#define define(def, docs) _define_helper(def, docs, false) +#define define_special(def, docs) _define_helper(def, docs, true) +#define in_caller_env fluid_let( \ + Globals::Current_Execution::envi_stack.next_index, \ + Globals::Current_Execution::envi_stack.next_index-1) + + + define((= . args), + "Takes 0 or more arguments and returns =t= if all arguments are equal " + "and =()= otherwise.") + { + fetch(args); -#define cLambda [=](Lisp_Object* arguments) mutable -> Lisp_Object* + if (args == Memory::nil) + return Memory::t; - proc defun = [&](const char* name, const char* docs, int linenum, auto fun) { - auto sym = Memory::get_or_create_lisp_object_symbol(name); - auto sfun = Memory::create_lisp_object_cfunction(fun); + Lisp_Object* first = args->value.pair.first; - sfun->sourceCodeLocation = new(Source_Code_Location); - sfun->sourceCodeLocation->file = file_name_built_ins; - sfun->sourceCodeLocation->line = linenum; - sfun->sourceCodeLocation->column = 0; + for_lisp_list (args) { + if (!lisp_object_equal(it, first)) + return Memory::nil; + } - sfun->docstring = Memory::create_string(docs); - define_symbol(sym, sfun); + return Memory::t; }; - - proc parse_lambda_starting_from_args = [&](Lisp_Object* arguments, bool is_special = false) -> Lisp_Object* { - Environment* env = get_current_environment(); - // Function* function = new(Function); - Lisp_Object* ret; - try ret = Memory::create_lisp_object(); - Memory::set_type(ret, Lisp_Object_Type::Function); - - ret->value.function.parent_environment = env; - - if (is_special) - ret->value.function.type = Function_Type::Special_Lambda; - else - ret->value.function.type = Function_Type::Lambda; - - // if parameters were specified - if (arguments->value.pair.first != Memory::nil) { - try { - assert_type(arguments->value.pair.first, Lisp_Object_Type::Pair); - } - try { - parse_argument_list(arguments->value.pair.first, &ret->value.function); - } - } else { - ret->value.function.args.positional = create_positional_argument_list(1); - ret->value.function.args.keyword = create_keyword_argument_list(1); - ret->value.function.args.rest = nullptr; + define((> . args), "TODO") + { + fetch(args); + double last_number = strtod("Inf", NULL); + + for_lisp_list (args) { + try assert_type(it, Lisp_Object_Type::Number); + if (it->value.number >= last_number) + return Memory::nil; + last_number = it->value.number; } - arguments = arguments->value.pair.rest; - // if there is a docstring, use it - if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::String) { - ret->docstring = arguments->value.pair.first->value.string; - arguments = arguments->value.pair.rest; - } else { - ret->docstring = nullptr; + return Memory::t; + }; + define((>= . args), "TODO") + { + fetch(args); + double last_number = strtod("Inf", NULL); + + for_lisp_list (args) { + try assert_type(it, Lisp_Object_Type::Number); + if (it->value.number > last_number) + return Memory::nil; + last_number = it->value.number; } - // we are now in the function body, just wrap it in an - // implicit begin - try ret->value.function.body = Memory::create_lisp_object_pair( - Memory::get_or_create_lisp_object_symbol("begin"), - arguments); - - - // ret->value.function = function; - return ret; + return Memory::t; }; + define((< . args), "TODO") + { + fetch(args); + double last_number = strtod("-Inf", NULL); + + for_lisp_list (args) { + try assert_type(it, Lisp_Object_Type::Number); + if (it->value.number <= last_number) + return Memory::nil; + last_number = it->value.number; + } - defun("=", - "Takes 0 or more arguments and returns =t= if all arguments are equal " - "and =()= otherwise.", - __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); - - if (arguments == Memory::nil) - return Memory::t; - - Lisp_Object* first = arguments->value.pair.first; + return Memory::t; + }; + define((<= . args), "TODO") + { + fetch(args); + double last_number = strtod("-Inf", NULL); + + for_lisp_list (args) { + try assert_type(it, Lisp_Object_Type::Number); + if (it->value.number < last_number) + return Memory::nil; + last_number = it->value.number; + } - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - if (!lisp_object_equal(arguments->value.pair.first, first)) - return Memory::nil; - arguments = arguments->value.pair.rest; - } + return Memory::t; + }; + define((+ . args), "TODO") + { + fetch(args); + double sum = 0; + + for_lisp_list (args) { + try assert_type(it, Lisp_Object_Type::Number); + sum += it->value.number; + } - return Memory::t; - }); - defun(">", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); + return Memory::create_lisp_object_number(sum); + }; + define((- . args), "TODO") + { + fetch(args); + if (args == Memory::nil) + return Memory::create_lisp_object_number(0); - double last_number = strtod("Inf", NULL); - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + try assert_type(args->value.pair.first, Lisp_Object_Type::Number); + double difference = args->value.pair.first->value.number; - if (arguments->value.pair.first->value.number >= last_number) - return Memory::nil; + if (args->value.pair.rest == Memory::nil) { + return Memory::create_lisp_object_number(-difference); + } - last_number = arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - } + for_lisp_list (args->value.pair.rest) { + try assert_type(it, Lisp_Object_Type::Number); + difference -= it->value.number; + } - return Memory::t; - }); - defun(">=", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); + return Memory::create_lisp_object_number(difference); + }; + define((* . args), "TODO") + { + fetch(args); - double last_number = strtod("Inf", NULL); + if (args == Memory::nil) { + return Memory::create_lisp_object_number(1); + } - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + double product = 1; - if (arguments->value.pair.first->value.number > last_number) - return Memory::nil; + for_lisp_list (args) { + try assert_type(it, Lisp_Object_Type::Number); + product *= it->value.number; + } - last_number = arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - } + return Memory::create_lisp_object_number(product); + }; + define((/ . args), "TODO") + { + fetch(args); - return Memory::t; - }); - defun("<", "TODO", __LINE__, cLambda { - try { - arguments = eval_arguments(arguments, &arguments_length); - } + if (args == Memory::nil) { + return Memory::create_lisp_object_number(1); + } - double last_number = strtod("-Inf", NULL); + try assert_type(args->value.pair.first, Lisp_Object_Type::Number); - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + double quotient = args->value.pair.first->value.number; - if (arguments->value.pair.first->value.number <= last_number) - return Memory::nil; + for_lisp_list (args->value.pair.rest) { + try assert_type(it, Lisp_Object_Type::Number); + quotient /= it->value.number; + } - last_number = arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - } + return Memory::create_lisp_object_number(quotient); + }; + define((** a b), "TODO") { + fetch(a, b); + try assert_type(a, Lisp_Object_Type::Number); + try assert_type(b, Lisp_Object_Type::Number); + return Memory::create_lisp_object_number(pow(a->value.number, + b->value.number)); + }; + define((% a b), "TODO") { + fetch(a, b); + try assert_type(a, Lisp_Object_Type::Number); + try assert_type(b, Lisp_Object_Type::Number); + return Memory::create_lisp_object_number((int)a->value.number % + (int)b->value.number); + }; + define((assert test), "TODO") { + fetch(test); + if (is_truthy(test)) return Memory::t; - }); - defun("<=", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); - - double last_number = strtod("-Inf", NULL); - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - if (arguments->value.pair.first->value.number < last_number) - return Memory::nil; - - last_number = arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - } - - return Memory::t; - }); - defun("+", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); + create_generic_error("Userland assertion."); + return nullptr; + }; + define_special((define-syntax form (:doc "") . body), "TODO") { + // fetch(form, doc, body); - double sum = 0; - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + static Lisp_Object *form_symbol = Memory::get_or_create_lisp_object_symbol("form"); + static Lisp_Object *doc_symbol = Memory::get_or_create_lisp_object_symbol("doc"); + static Lisp_Object *body_symbol = Memory::get_or_create_lisp_object_symbol("body"); - sum += arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - } - return Memory::create_lisp_object_number(sum); - }); - defun("-", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); + printf("\n\nin define-syntax:: envi stack depth: %d\n", + Globals::Current_Execution::envi_stack.next_index); + print_environment(get_current_environment()); - if (arguments_length == 0) - return Memory::create_lisp_object_number(0); + Lisp_Object *form = lookup_symbol(form_symbol, get_current_environment()); + Lisp_Object *doc = lookup_symbol(doc_symbol, get_current_environment()); + Lisp_Object *body = lookup_symbol(body_symbol, get_current_environment()); - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - double difference = arguments->value.pair.first->value.number; + assert_type(doc, Lisp_Object_Type::String); + // if no doc string, we dont have to store it + if (Memory::get_c_str(doc)[0] == '\0') { + doc = nullptr; + } - if (arguments_length == 1) { - return Memory::create_lisp_object_number(-difference); - } + if (Memory::get_type(form) != Lisp_Object_Type::Pair) { + create_parsing_error("You can only create function macros."); + return nullptr; + } - arguments = arguments->value.pair.rest; - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + Lisp_Object* symbol = form->value.pair.first; + Lisp_Object* lambdalist = form->value.pair.rest; - difference -= arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - } - return Memory::create_lisp_object_number(difference); - }); - defun("*", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); + // creating new lisp object and setting type + Lisp_Object* func; + try func = Memory::create_lisp_object(); + Memory::set_type(func, Lisp_Object_Type::Function); + func->value.function.type = Function_Type::Macro; - if (arguments_length == 0) { - return Memory::create_lisp_object_number(1); - } + if (doc) func->docstring = doc->value.string; - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + in_caller_env { + // setting parent env + func->value.function.parent_environment = get_current_environment(); + create_arguments_from_lambda_list_and_inject(lambdalist, func); + func->value.function.body = maybe_wrap_body_in_begin(body); + define_symbol(symbol, func); + } + return Memory::nil; + }; + define_special((define definee (:doc "") . body), "TODO") { + fetch(definee, doc, body); - double product = arguments->value.pair.first->value.number; + assert_type(doc, Lisp_Object_Type::String); - arguments = arguments->value.pair.rest; - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); + // if no doc string, we dont have to store it + if (Memory::get_c_str(doc)[0] == '\0') { + doc = nullptr; + } - product *= arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; + if (Memory::get_type(definee) == Lisp_Object_Type::Symbol) { + if (body == Memory::nil) { + create_parsing_error("You at least have to put a value when " + "you are trying to define a variable."); + return nullptr; + } else if (body->value.pair.rest != Memory::nil) { + create_parsing_error("You cannot define more than one thing " + "for one variable."); + return nullptr; } - return Memory::create_lisp_object_number(product); - }); - defun("/", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); - - if (arguments_length == 0) { - return Memory::create_lisp_object_number(1); + auto value = body->value.pair.first; + in_caller_env { + value = eval_expr(value); + define_symbol(definee, value); } - - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - double quotient = arguments->value.pair.first->value.number; - - arguments = arguments->value.pair.rest; - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - quotient /= arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; + } else if (Memory::get_type(definee) == Lisp_Object_Type::Pair) { + // definee: (sym . lambdalist) + Lisp_Object* symbol = definee->value.pair.first; + Lisp_Object* lambdalist = definee->value.pair.rest; + + // creating new lisp object and setting type + Lisp_Object* func; + try func = Memory::create_lisp_object(); + Memory::set_type(func, Lisp_Object_Type::Function); + func->value.function.type = Function_Type::Lambda; + + if (doc) + func->docstring = doc->value.string; + + in_caller_env { + // setting parent env + func->value.function.parent_environment = get_current_environment(); + create_arguments_from_lambda_list_and_inject(lambdalist, func); + func->value.function.body = maybe_wrap_body_in_begin(body); + define_symbol(symbol, func); } - return Memory::create_lisp_object_number(quotient); - }); - defun("**", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - double base = arguments->value.pair.first->value.number; - arguments = arguments->value.pair.rest; - - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - double exponent = arguments->value.pair.first->value.number; - - return Memory::create_lisp_object_number(pow(base, exponent)); - }); - defun("%", "TODO", __LINE__, cLambda { - try arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - double a = arguments->value.pair.first->value.number; - - arguments = arguments->value.pair.rest; - - try assert_type(arguments->value.pair.first, Lisp_Object_Type::Number); - - double b = arguments->value.pair.first->value.number; - - return Memory::create_lisp_object_number((int)a % (int)b); - }); - defun("assert", "TODO", __LINE__, cLambda { - - try arguments = eval_arguments(arguments, &arguments_length); - try assert(arguments_length == 1); - - if (is_truthy(arguments->value.pair.first)) - return Memory::t; - - create_generic_error("Userland assertion."); + } else { + create_parsing_error("The to be defined object has to be a " + "symbol or a list. But got a %s.", + Lisp_Object_Type_to_string( + Memory::get_type(definee))); return nullptr; - }); - defun("define", "TODO", __LINE__, cLambda { - - try arguments_length = list_length(arguments); - try assert_arguments_length_greater_equal(2, arguments_length); - - Lisp_Object* symbol = arguments->value.pair.first; - Lisp_Object* value; - - if (Memory::get_type(symbol) == Lisp_Object_Type::Pair) { - /* - 1: arguments - 2: symbol - 3: real_symbol - - (define (f x) "docs" (+ 1 x)) - - [ | ] -> [1| ] -> [ | ] -> [ |/] - | | | | - V | V V - define | "docs" [ | ] -> [ | ] -> [ |/] - | | | | - V V V V - [2| ] -> [ |/] + 1 x - | | - V V - f(3) x - */ - - Lisp_Object* real_symbol = symbol->value.pair.first; - - try assert_type(real_symbol, Lisp_Object_Type::Symbol); - - Lisp_Object* fake_lambda; - try fake_lambda = Memory::create_lisp_object_pair( - symbol ->value.pair.rest, - arguments->value.pair.rest); - - value = parse_lambda_starting_from_args(fake_lambda); - symbol = real_symbol; - } else { - try assert_arguments_length_greater_equal(2, arguments_length); - try assert_arguments_length_less_equal(3, arguments_length); - String* doc = nullptr; - if (arguments_length == 3) { - try assert_type(arguments->value.pair.rest->value.pair.first, Lisp_Object_Type::String); - doc = arguments->value.pair.rest->value.pair.first->value.string; - arguments = arguments->value.pair.rest; - } + } + return Memory::nil; + }; + define((mutate target source), "TODO") { + fetch(target, source); + + if (target == Memory::nil || + target == Memory::t || + Memory::get_type(target) == Lisp_Object_Type::Keyword || + Memory::get_type(target) == Lisp_Object_Type::Symbol) + { + create_generic_error("You cannot mutate to nil, t, keywords or symbols because they have to be unique"); + } - try assert_type(symbol, Lisp_Object_Type::Symbol); + if (source == Memory::nil || + source == Memory::t || + Memory::get_type(source) == Lisp_Object_Type::Keyword || + Memory::get_type(source) == Lisp_Object_Type::Symbol) + { + create_generic_error("You cannot mutate nil, t, keywords or symbols"); + } - value = arguments->value.pair.rest->value.pair.first; + *target = *source; + return target; + }; + define((vector-length v), "TODO") { + fetch(v); + assert_type(v, Lisp_Object_Type::Vector); + return Memory::create_lisp_object_number((double)v->value.vector.length); + }; + define((vector-ref vec idx), "TODO") { + fetch(vec, idx); - try value = eval_expr(value); - if (doc) - value->docstring = doc; - } + try assert_type(vec, Lisp_Object_Type::Vector); + try assert_type(idx, Lisp_Object_Type::Number); - define_symbol(symbol, value); + int int_idx = ((int)idx->value.number); - return value; - }); - defun("mutate", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); - Lisp_Object* target = evaluated_arguments->value.pair.first; - Lisp_Object* source = evaluated_arguments->value.pair.rest->value.pair.first; + try assert(int_idx >= 0); + try assert(int_idx < vec->value.vector.length); - if (target == Memory::nil || - target == Memory::t || - Memory::get_type(target) == Lisp_Object_Type::Keyword || - Memory::get_type(target) == Lisp_Object_Type::Symbol) - { - create_generic_error("You cannot mutate to nil, t, keywords or symbols because they have to be unique"); - } + return vec->value.vector.data+int_idx; + }; + define((vector-set! vec idx val), "TODO") { + fetch(vec, idx, val); - if (source == Memory::nil || - source == Memory::t || - Memory::get_type(source) == Lisp_Object_Type::Keyword || - Memory::get_type(source) == Lisp_Object_Type::Symbol) - { - create_generic_error("You cannot mutate nil, t, keywords or symbols"); - } + try assert_type(vec, Lisp_Object_Type::Vector); + try assert_type(idx, Lisp_Object_Type::Number); - *target = *source; - return target; - }); - defun("vector-length", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - Lisp_Object* vec = evaluated_arguments->value.pair.first; - assert_type(vec, Lisp_Object_Type::Vector); + int int_idx = ((int)idx->value.number); - return Memory::create_lisp_object_number((double)vec->value.vector.length); - }); - defun("vector-ref", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); + try assert(int_idx >= 0); + try assert(int_idx < vec->value.vector.length); - Lisp_Object* vec = evaluated_arguments->value.pair.first; - Lisp_Object* idx = evaluated_arguments->value.pair.rest->value.pair.first; + vec->value.vector.data[int_idx] = *val; - try assert_type(vec, Lisp_Object_Type::Vector); - try assert_type(idx, Lisp_Object_Type::Number); + return val; + }; + define_special((set! sym val), "TODO") { + fetch(sym, val); - int int_idx = ((int)idx->value.number); + try assert_type(sym, Lisp_Object_Type::Symbol); - try assert(int_idx >= 0); - try assert(int_idx < vec->value.vector.length); + in_caller_env { + val = eval_expr(val); + } - return vec->value.vector.data+int_idx; - }); - defun("vector-set!", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(3, arguments_length); + Environment* target_env = find_binding_environment(sym->value.symbol.identifier, get_current_environment()); + try assert(target_env); - Lisp_Object* vec = evaluated_arguments->value.pair.first; - Lisp_Object* idx = evaluated_arguments->value.pair.rest->value.pair.first; - Lisp_Object* val = evaluated_arguments->value.pair.rest->value.pair.rest->value.pair.first; + push_environment(target_env); + { + define_symbol(sym, val); + } + pop_environment(); - try assert_type(vec, Lisp_Object_Type::Vector); - try assert_type(idx, Lisp_Object_Type::Number); + return val; + }; + define((set-car! target source), "TODO") { + fetch(target, source); - int int_idx = ((int)idx->value.number); + assert_type(target, Lisp_Object_Type::Pair); - try assert(int_idx >= 0); - try assert(int_idx < vec->value.vector.length); + *target->value.pair.first = *source; + return source; + }; + define((set-cdr! target source), "TODO") { + fetch(target, source); - vec->value.vector.data[int_idx] = *val; + assert_type(target, Lisp_Object_Type::Pair); - return val; - }); - defun("set!", "TODO", __LINE__, cLambda { - try assert_arguments_length(2, list_length(arguments)); - Lisp_Object* target_symbol = arguments->value.pair.first; - try assert(target_symbol); - try assert(arguments->value.pair.rest->value.pair.first); - Lisp_Object* source = eval_expr(arguments->value.pair.rest->value.pair.first); + *target->value.pair.rest = *source; + return source; + }; + define_special((if test then_part else_part), "TODO") { + fetch(test, then_part, else_part); - try assert(source); - try assert_type(target_symbol, Lisp_Object_Type::Symbol); + bool truthy; + Lisp_Object* result; - Environment* target_env = find_binding_environment(target_symbol->value.symbol.identifier, get_current_environment()); - try assert(target_env); + in_caller_env { + try truthy = is_truthy(test); + if (truthy) try result = eval_expr(then_part); + else try result = eval_expr(else_part); + } - push_environment(target_env); - defer { - pop_environment(); - }; + return result; + }; + define_special((quote datum), "TODO") { + fetch(datum); + return datum; + }; + define_special((quasiquote expr), "TODO") { + fetch(expr); + /* recursive lambdas in lambdas yay!! */ + // NOTE(Felix): first we have to initialize the variable + // with a garbage lambda, so that we can then overwrite it + // a recursive lambda + std::function unquoteSomeExpressions; // = [] (Lisp_Object* expr) -> Lisp_Object* {return nullptr;}; + unquoteSomeExpressions = [&unquoteSomeExpressions] (Lisp_Object* expr) -> Lisp_Object* { + // if it is an atom, return it + if (Memory::get_type(expr) != Lisp_Object_Type::Pair) + return Memory::copy_lisp_object(expr); + + // it is a pair! + Lisp_Object* originalPair = expr->value.pair.first; + if (Memory::get_type(originalPair) == Lisp_Object_Type::Symbol && + (string_equal(originalPair->value.symbol.identifier, "unquote") || + string_equal(originalPair->value.symbol.identifier, "unquote-splicing"))) + { + // eval replace the stuff - define_symbol(target_symbol, source); - - return source; - }); - defun("set-car!", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); - Lisp_Object* target = evaluated_arguments->value.pair.first; - Lisp_Object* source = evaluated_arguments->value.pair.rest->value.pair.first; - - assert_type(target, Lisp_Object_Type::Pair); - - *target->value.pair.first = *source; - return source; - }); - defun("set-cdr!", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); - Lisp_Object* target = evaluated_arguments->value.pair.first; - Lisp_Object* source = evaluated_arguments->value.pair.rest->value.pair.first; - - assert_type(target, Lisp_Object_Type::Pair); - - *target->value.pair.rest = *source; - return source; - }); - defun("if", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length_greater_equal(2, arguments_length); - try assert_arguments_length_less_equal(3, arguments_length); - - Lisp_Object* condition = arguments->value.pair.first; - Lisp_Object* then_part = arguments->value.pair.rest; - Lisp_Object* else_part = then_part->value.pair.rest; - - bool truthy; - try truthy = is_truthy(condition); - // printf("arg len is: %d\n", arguments_length); - Lisp_Object* result; - if (truthy) - try result = eval_expr(then_part->value.pair.first); - else - try result = eval_expr(else_part->value.pair.first); - - return result; - }); - defun("quote", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length(1, arguments_length); - return arguments->value.pair.first; - }); - defun("quasiquote", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length(1, arguments_length); - // print(arguments); - // printf("\n"); - - /* recursive lambdas in lambdas yay!! */ - // NOTE(Felix): first we have to initialize the variable - // with a garbage lambda, so that we can then overwrite it - // a recursive lambda - std::function unquoteSomeExpressions; // = [] (Lisp_Object* expr) -> Lisp_Object* {return nullptr;}; - unquoteSomeExpressions = [&unquoteSomeExpressions] (Lisp_Object* expr) -> Lisp_Object* { - // if it is an atom, return it - if (Memory::get_type(expr) != Lisp_Object_Type::Pair) - return Memory::copy_lisp_object(expr); - - // it is a pair! - Lisp_Object* originalPair = expr->value.pair.first; - if (Memory::get_type(originalPair) == Lisp_Object_Type::Symbol && - (string_equal(originalPair->value.symbol.identifier, "unquote") || - string_equal(originalPair->value.symbol.identifier, "unquote-splicing"))) - { - // eval replace the stuff - return eval_expr(expr->value.pair.rest->value.pair.first); + Lisp_Object* ret; + in_caller_env { + ret = eval_expr(expr->value.pair.rest->value.pair.first); } - // it is a list but not starting with the symbol - // unquote, so search in there for stuff to unquote. - // While copying the list - - //NOTE(Felix): Of fucking course we have to copy the - // list. The quasiquote will be part of the body of a - // funciton, we can't just modify it because otherwise - // we modify the body of the function and would bake - // in the result... - Lisp_Object* newPair = Memory::nil; - Lisp_Object* newPairHead = newPair; - Lisp_Object* head = expr; - - while (Memory::get_type(head) == Lisp_Object_Type::Pair) { - // if it is ,@ we have to actually do more work - // and inline the result - if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair && - Memory::get_type(head->value.pair.first->value.pair.first) == Lisp_Object_Type::Symbol && - string_equal(head->value.pair.first->value.pair.first->value.symbol.identifier, "unquote-splicing")) - { - Lisp_Object* spliced = unquoteSomeExpressions(head->value.pair.first); - - if (spliced == Memory::nil) { - head = head->value.pair.rest; - continue; - } + return ret; + } - try assert_type(spliced, Lisp_Object_Type::Pair); - if (newPair == Memory::nil) { - try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); - newPairHead = newPair; - } else { - try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); - newPairHead = newPairHead->value.pair.rest; - newPairHead->value.pair.first = spliced->value.pair.first; - newPairHead->value.pair.rest = spliced->value.pair.rest; + // it is a list but not starting with the symbol + // unquote, so search in there for stuff to unquote. + // While copying the list + + //NOTE(Felix): Of fucking course we have to copy the + // list. The quasiquote will be part of the body of a + // funciton, we can't just modify it because otherwise + // we modify the body of the function and would bake + // in the result... + Lisp_Object* newPair = Memory::nil; + Lisp_Object* newPairHead = newPair; + Lisp_Object* head = expr; + + while (Memory::get_type(head) == Lisp_Object_Type::Pair) { + // if it is ,@ we have to actually do more work + // and inline the result + if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair && + Memory::get_type(head->value.pair.first->value.pair.first) == Lisp_Object_Type::Symbol && + string_equal(head->value.pair.first->value.pair.first->value.symbol.identifier, "unquote-splicing")) + { + Lisp_Object* spliced = unquoteSomeExpressions(head->value.pair.first); - // now skip to the end - while (newPairHead->value.pair.rest != Memory::nil) { - newPairHead = newPairHead->value.pair.rest; - } - } + if (spliced == Memory::nil) { + head = head->value.pair.rest; + continue; + } + try assert_type(spliced, Lisp_Object_Type::Pair); + if (newPair == Memory::nil) { + try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); + newPairHead = newPair; } else { - if (newPair == Memory::nil) { - try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); - newPairHead = newPair; - } else { - try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); + try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); + newPairHead = newPairHead->value.pair.rest; + newPairHead->value.pair.first = spliced->value.pair.first; + newPairHead->value.pair.rest = spliced->value.pair.rest; + + // now skip to the end + while (newPairHead->value.pair.rest != Memory::nil) { newPairHead = newPairHead->value.pair.rest; } - newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first); } - // if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) { - // break; - // } - - head = head->value.pair.rest; - + } else { + if (newPair == Memory::nil) { + try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); + newPairHead = newPair; + } else { + try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); + newPairHead = newPairHead->value.pair.rest; + } + newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first); } - newPairHead->value.pair.rest = Memory::nil; - - return newPair; - }; - Lisp_Object* ret = arguments->value.pair.first; + // if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) { + // break; + // } - ret = unquoteSomeExpressions(ret); - return ret; - }); - defun("and", "TODO", __LINE__, cLambda { - bool result = true; - while (arguments != Memory::nil) { - try assert_type(arguments, Lisp_Object_Type::Pair); - try result &= is_truthy(arguments->value.pair.first); + head = head->value.pair.rest; - arguments = arguments->value.pair.rest; - if (!result) return Memory::nil; - } - return Memory::t; - }); - defun("or", "TODO", __LINE__, cLambda { - bool result = false; - while (arguments != Memory::nil) { - try assert_type(arguments, Lisp_Object_Type::Pair); - try result |= is_truthy(arguments->value.pair.first); - - arguments = arguments->value.pair.rest; - if (result) return Memory::t; } - return Memory::nil; - }); - defun("not", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length(1, arguments_length); + newPairHead->value.pair.rest = Memory::nil; - bool truthy; - - try truthy = is_truthy(arguments->value.pair.first); - - return (truthy) ? Memory::nil : Memory::t; - }); - defun("while", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert(arguments_length >= 2); - - Lisp_Object* condition_part = arguments->value.pair.first; - Lisp_Object* condition; - Lisp_Object* then_part = arguments->value.pair.rest; - Lisp_Object* wrapped_then_part; - - try wrapped_then_part = Memory::create_lisp_object_pair( - Memory::get_or_create_lisp_object_symbol("begin"), - then_part); - - Lisp_Object* result = Memory::nil; - - while (true) { - try condition = eval_expr(condition_part); - - if (condition == Memory::nil) - break; + return newPair; + }; - try result = eval_expr(wrapped_then_part); + expr = unquoteSomeExpressions(expr); + return expr; + }; + define_special((and . args), "TODO") { + fetch(args); + bool result = true; + in_caller_env { + for_lisp_list (args) { + try result &= is_truthy(it); + if (!result) + return Memory::nil; } - return result; - - }); - // defun("let", "TODO", __LINE__, cLambda { - // // (let ((a 10)(b 20)) (body1) (body2)) - // try arguments_length = list_length(arguments); - // try assert_arguments_length_greater_equal(1, arguments_length); - - // Environment* let_env; - // try let_env = Memory::create_child_environment(env); - // Lisp_Object* bindings = arguments->value.pair.first; - // while (true) { - // if (bindings == Memory::nil) { - // break; - // } - - // try assert_type(bindings, Lisp_Object_Type::Pair); - - // Lisp_Object* sym = bindings->value.pair.first->value.pair.first; - - // try assert_type(sym, Lisp_Object_Type::Symbol); - - // Lisp_Object* rest_sym = bindings->value.pair.first->value.pair.rest; - - // try assert_type(rest_sym, Lisp_Object_Type::Pair); - // try assert_type(rest_sym->value.pair.rest, Lisp_Object_Type::Nil); - - // Lisp_Object* value = eval_expr(rest_sym->value.pair.first, env); - - // // NOTE(Felix): We have to copy the value here because - // // if the let body modifies the value, it would bake - // // in... bad bad... - // define_symbol(sym, Memory::copy_lisp_object(value), let_env); - - // bindings = bindings->value.pair.rest; - // } - - // arguments = arguments->value.pair.rest; - - // Lisp_Object* evaluated_arguments; - // try evaluated_arguments = eval_arguments(arguments, let_env, &arguments_length); - - // if (evaluated_arguments == Memory::nil) - // return evaluated_arguments; - - // // skip to the last evaluated operand and return it, - // // we use eval_arguments here instead of doing it - // // manually, because we want to increase code reuse, - // // but at the cost that we have to find the end of the - // // list again - // while (Memory::get_type(evaluated_arguments->value.pair.rest) == Lisp_Object_Type::Pair) { - // evaluated_arguments = evaluated_arguments->value.pair.rest; - // } - // return evaluated_arguments->value.pair.first; - // }); - defun("lambda", "TODO", __LINE__, cLambda { - /* TODO(Felix): first one crashes - * (lambda ()) - * (lambda (x d) (+ 1 2) (- 1 2) (* 1 2)) - */ - try arguments_length = list_length(arguments); - try assert_arguments_length_greater_equal(1, arguments_length); - - Lisp_Object* function = parse_lambda_starting_from_args(arguments, false); - - return function; - }); - defun("special-lambda", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length_greater_equal(1, arguments_length); + } + return Memory::t; + }; + define_special((or . args), "TODO") { + fetch(args); + bool result = false; + in_caller_env { + for_lisp_list (args) { + try result |= is_truthy(it); + if (result) + return Memory::t; + } + } + return Memory::nil; + }; + define_special((not test), "TODO") { + fetch(test); + bool truthy; + in_caller_env { + try truthy = is_truthy(test); + } + return (truthy) ? Memory::nil : Memory::t; + }; + // // defun("while", "TODO", __LINE__, cLambda { + // // try arguments_length = list_length(arguments); + // // try assert(arguments_length >= 2); - Lisp_Object* function = parse_lambda_starting_from_args(arguments, true); + // // Lisp_Object* condition_part = arguments->value.pair.first; + // // Lisp_Object* condition; + // // Lisp_Object* then_part = arguments->value.pair.rest; + // // Lisp_Object* wrapped_then_part; - return function; - }); - defun("eval", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); + // // try wrapped_then_part = Memory::create_lisp_object_pair( + // // Memory::get_or_create_lisp_object_symbol("begin"), + // // then_part); - Lisp_Object* result; + // // Lisp_Object* result = Memory::nil; - try result = eval_expr(evaluated_arguments->value.pair.first); + // // while (true) { + // // try condition = eval_expr(condition_part); - return result; - }); + // // if (condition == Memory::nil) + // // break; + // // try result = eval_expr(wrapped_then_part); + // // } + // // return result; - defun("begin", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); + // // }); + define_special((lambda args . body), "TODO") { + fetch(args, body); - if (evaluated_arguments == Memory::nil) - return Memory::nil; + Lisp_Object* fun; + try fun = Memory::create_lisp_object(); + Memory::set_type(fun, Lisp_Object_Type::Function); + fun->value.function.type = Function_Type::Lambda; - // skip to the last evaluated operand and return it, - // we use eval_arguments here instead of doing it - // manually, because we want to increase code reuse, - // but at the cost that we have to find the end of the - // list again - while (Memory::get_type(evaluated_arguments->value.pair.rest) == Lisp_Object_Type::Pair) { - evaluated_arguments = evaluated_arguments->value.pair.rest; - } - return evaluated_arguments->value.pair.first; - }); - defun("list", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - return evaluated_arguments; - }); - defun("vector", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - Lisp_Object* ret; - try ret = Memory::create_lisp_object_vector(arguments_length, evaluated_arguments); - return ret; - }); - defun("pair", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); - - Lisp_Object* ret; - try ret = Memory::create_lisp_object_pair( - evaluated_arguments->value.pair.first, - evaluated_arguments->value.pair.rest->value.pair.first); - return ret; - }); - defun("first", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - - if (evaluated_arguments->value.pair.first == Memory::nil) - return Memory::nil; + in_caller_env { + fun->value.function.parent_environment = get_current_environment(); + } - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Pair); + try create_arguments_from_lambda_list_and_inject(args, fun); + fun->value.function.body = maybe_wrap_body_in_begin(body); + return fun; + }; + define_special((special-lambda args . body), "TODO") { + fetch(args, body); - return evaluated_arguments->value.pair.first->value.pair.first; - }); - defun("rest", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); + Lisp_Object* fun; + try fun = Memory::create_lisp_object(); + Memory::set_type(fun, Lisp_Object_Type::Function); + fun->value.function.type = Function_Type::Special_Lambda; - if (evaluated_arguments->value.pair.first == Memory::nil) - return Memory::nil; + in_caller_env { + fun->value.function.parent_environment = get_current_environment(); + } - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Pair); + try create_arguments_from_lambda_list_and_inject(args, fun); + fun->value.function.body = maybe_wrap_body_in_begin(body); + return fun; + }; + define((eval expr), "TODO") { + fetch(expr); + Lisp_Object* result; - return evaluated_arguments->value.pair.first->value.pair.rest; - }); - defun("set-type", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(2, arguments_length); + in_caller_env { + try result = eval_expr(expr); + } - Lisp_Object* object = evaluated_arguments->value.pair.first; - Lisp_Object* type = evaluated_arguments->value.pair.rest->value.pair.first; + return result; + }; + define((begin . args), "TODO") { + fetch(args); + Lisp_Object* result = Memory::nil; + for_lisp_list(args) { + try result = eval_expr(it); + } - try assert_type(type, Lisp_Object_Type::Keyword); + return result; + }; + define((list . args), "TODO") { + fetch(args); + return args; + }; + define((vector . args), "TODO") { + fetch(args); + Lisp_Object* ret; + int length = list_length(args); + try ret = Memory::create_lisp_object_vector(length, args); + return ret; + }; + define((pair car cdr), "TODO") { + fetch(car, cdr); - object->userType = type; - return object; - }); - defun("delete-type", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); + Lisp_Object* ret; + try ret = Memory::create_lisp_object_pair(car, cdr); + return ret; + }; + define((first seq), "TODO") { + fetch(seq); + if (seq == Memory::nil) + return Memory::nil; + try assert_type(seq, Lisp_Object_Type::Pair); + return seq->value.pair.first; + }; + define((rest seq), "TODO") { + fetch(seq); + if (seq == Memory::nil) + return Memory::nil; + try assert_type(seq, Lisp_Object_Type::Pair); + return seq->value.pair.rest; + }; + define((set-type! node new_type), "TODO") { + fetch(node, new_type); + try assert_type(new_type, Lisp_Object_Type::Keyword); + node->userType = new_type; + return node; + }; + define((delete-type! n), "TODO") { + fetch(n); + n->userType = nullptr; + return Memory::t; + }; + define((type n), "TODO") { + fetch(n); - evaluated_arguments->value.pair.first->userType = nullptr; - return Memory::t; - }); - defun("type", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); + if (n->userType) { + return n->userType; + } - if (evaluated_arguments->value.pair.first->userType) { - return evaluated_arguments->value.pair.first->userType; - } + Lisp_Object_Type type = Memory::get_type(n); + + switch (type) { + case Lisp_Object_Type::Continuation: return Memory::get_or_create_lisp_object_keyword("continuation"); + case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction"); + case Lisp_Object_Type::Function: { + Function* fun = &n->value.function; + if (fun->type == Function_Type::Lambda) + return Memory::get_or_create_lisp_object_keyword("lambda"); + else if (fun->type == Function_Type::Special_Lambda) + return Memory::get_or_create_lisp_object_keyword("special-lambda"); + else if (fun->type == Function_Type::Macro) + return Memory::get_or_create_lisp_object_keyword("macro"); + else return Memory::get_or_create_lisp_object_keyword("unknown"); + } + case Lisp_Object_Type::Keyword: return Memory::get_or_create_lisp_object_keyword("keyword"); + case Lisp_Object_Type::Nil: return Memory::get_or_create_lisp_object_keyword("nil"); + case Lisp_Object_Type::T: return Memory::get_or_create_lisp_object_keyword("t"); + case Lisp_Object_Type::Number: return Memory::get_or_create_lisp_object_keyword("number"); + case Lisp_Object_Type::Pair: return Memory::get_or_create_lisp_object_keyword("pair"); + case Lisp_Object_Type::Vector: return Memory::get_or_create_lisp_object_keyword("vector"); + case Lisp_Object_Type::String: return Memory::get_or_create_lisp_object_keyword("string"); + case Lisp_Object_Type::Symbol: return Memory::get_or_create_lisp_object_keyword("symbol"); + } + return Memory::get_or_create_lisp_object_keyword("unknown"); + }; + // NOTE(Felix): we need to define_special because the docstring is + // attached to the symbol. Because some object are singletons + // (symbols, keyowrds, nil, t) we dont want to store docs on the + // object. Otherwise (define k :doc "hallo" :keyword) would modify + // the global keyword + define_special((info n), "TODO") { + fetch(n); + + print(n); + + Lisp_Object* type; + in_caller_env { + try type = eval_expr(Memory::create_list(Memory::get_or_create_lisp_object_symbol("type"), n)); + } - Lisp_Object_Type type = Memory::get_type(evaluated_arguments->value.pair.first); - - switch (type) { - case Lisp_Object_Type::Continuation: return Memory::get_or_create_lisp_object_keyword("continuation"); - case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction"); - case Lisp_Object_Type::Function: { - Function* fun = &evaluated_arguments->value.pair.first->value.function; - if (fun->type == Function_Type::Lambda) - return Memory::get_or_create_lisp_object_keyword("lambda"); - else if (fun->type == Function_Type::Special_Lambda) - return Memory::get_or_create_lisp_object_keyword("special-lambda"); - else if (fun->type == Function_Type::Macro) - return Memory::get_or_create_lisp_object_keyword("macro"); - else return Memory::get_or_create_lisp_object_keyword("unknown"); + if (type) { + Lisp_Object* val; + in_caller_env { + try Lisp_Object* val = eval_expr(n); } - case Lisp_Object_Type::Keyword: return Memory::get_or_create_lisp_object_keyword("keyword"); - case Lisp_Object_Type::Nil: return Memory::get_or_create_lisp_object_keyword("nil"); - case Lisp_Object_Type::T: return Memory::get_or_create_lisp_object_keyword("t"); - case Lisp_Object_Type::Number: return Memory::get_or_create_lisp_object_keyword("number"); - case Lisp_Object_Type::Pair: return Memory::get_or_create_lisp_object_keyword("pair"); - case Lisp_Object_Type::Vector: return Memory::get_or_create_lisp_object_keyword("vector"); - case Lisp_Object_Type::String: return Memory::get_or_create_lisp_object_keyword("string"); - case Lisp_Object_Type::Symbol: return Memory::get_or_create_lisp_object_keyword("symbol"); - } - return Memory::get_or_create_lisp_object_keyword("unknown"); - }); - defun("info", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length(1, arguments_length); - - print(arguments->value.pair.first); - - Lisp_Object* type; - try type = eval_expr( - Memory::create_lisp_object_pair( - Memory::get_or_create_lisp_object_symbol("type"), - Memory::create_lisp_object_pair(arguments->value.pair.first, Memory::nil))); - - if (type) { - Lisp_Object* val = eval_expr(arguments->value.pair.first); - printf(" is of type "); - print(type); - printf("\nand is printed as: "); - print(val); - printf("\n\ndocs: \n %s\n", - (val->docstring) - ? Memory::get_c_str(val->docstring) - : "No docs avaliable"); - - // TODO(Felix): Maybe don't compare strings here?? Wtf - if (Memory::get_type(type) == Lisp_Object_Type::Keyword && - (string_equal(type->value.symbol.identifier, "lambda") || - string_equal(type->value.symbol.identifier, "special-lambda") || - string_equal(type->value.symbol.identifier, "macro"))) - { - Lisp_Object* fun = eval_expr(arguments->value.pair.first); - - if (fun->docstring) - printf("Docstring:\n==========\n%s\n\n", Memory::get_c_str(fun->docstring)); - else - printf("No docstring avaliable\n"); - - printf("Arguments:\n==========\n"); - printf("Postitional: {"); - if (fun->value.function.args.positional.symbols.next_index != 0) { - printf("%s", - Memory::get_c_str(fun->value.function.args.positional.symbols.data[0]->value.symbol.identifier)); - for (int i = 1; i < fun->value.function.args.positional.symbols.next_index; ++i) { - printf(", %s", - Memory::get_c_str(fun->value.function.args.positional.symbols.data[i]->value.symbol.identifier)); - } + printf(" is of type "); + print(type); + printf("\nand is printed as: "); + print(val); + printf("\n\ndocs: \n %s\n", + (val->docstring) + ? Memory::get_c_str(val->docstring) + : "No docs avaliable"); + + // TODO(Felix): Maybe don't compare strings here?? Wtf + if (Memory::get_type(type) == Lisp_Object_Type::Keyword && + (string_equal(type->value.symbol.identifier, "lambda") || + string_equal(type->value.symbol.identifier, "special-lambda") || + string_equal(type->value.symbol.identifier, "macro"))) + { + Lisp_Object* fun = eval_expr(n); + + if (fun->docstring) + printf("Docstring:\n==========\n%s\n\n", Memory::get_c_str(fun->docstring)); + else + printf("No docstring avaliable\n"); + + printf("Arguments:\n==========\n"); + printf("Postitional: {"); + if (fun->value.function.args.positional.symbols.next_index != 0) { + printf("%s", + Memory::get_c_str(fun->value.function.args.positional.symbols.data[0]->value.symbol.identifier)); + for (int i = 1; i < fun->value.function.args.positional.symbols.next_index; ++i) { + printf(", %s", + Memory::get_c_str(fun->value.function.args.positional.symbols.data[i]->value.symbol.identifier)); + } + } + printf("}\n"); + printf("Keyword: {"); + if (fun->value.function.args.keyword.values.next_index != 0) { + printf("%s", + Memory::get_c_str(fun->value.function.args.keyword.keywords.data[0]->value.symbol.identifier)); + if (fun->value.function.args.keyword.values.data[0]) { + printf(" ("); + print(fun->value.function.args.keyword.values.data[0]); + printf(")"); } - printf("}\n"); - printf("Keyword: {"); - if (fun->value.function.args.keyword.values.next_index != 0) { - printf("%s", - Memory::get_c_str(fun->value.function.args.keyword.keywords.data[0]->value.symbol.identifier)); - if (fun->value.function.args.keyword.values.data[0]) { + for (int i = 1; i < fun->value.function.args.keyword.values.next_index; ++i) { + printf(", %s", + Memory::get_c_str(fun->value.function.args.keyword.keywords.data[i]->value.symbol.identifier)); + if (fun->value.function.args.keyword.values.data[i]) { printf(" ("); - print(fun->value.function.args.keyword.values.data[0]); + print(fun->value.function.args.keyword.values.data[i]); printf(")"); } - for (int i = 1; i < fun->value.function.args.keyword.values.next_index; ++i) { - printf(", %s", - Memory::get_c_str(fun->value.function.args.keyword.keywords.data[i]->value.symbol.identifier)); - if (fun->value.function.args.keyword.values.data[i]) { - printf(" ("); - print(fun->value.function.args.keyword.values.data[i]); - printf(")"); - } - } } - printf("}\n"); - printf("Rest: {"); - if (fun->value.function.args.rest) - printf("%s", - Memory::get_c_str(fun->value.function.args.rest)); - printf("}\n"); - } - } else { - printf(" is not defined\n"); - delete_error(); + printf("}\n"); + printf("Rest: {"); + if (fun->value.function.args.rest) + printf("%s", + Memory::get_c_str(fun->value.function.args.rest)); + printf("}\n"); + } + } else { + printf(" is not defined\n"); + delete_error(); + } - return Memory::nil; - }); - defun("show", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Function); + return Memory::nil; + }; + define((show n), "TODO") { + fetch(n); + try assert_type(n, Lisp_Object_Type::Function); - puts("body:\n"); - print(evaluated_arguments->value.pair.first->value.function.body); - puts("\n"); - printf("parent_env: %lld\n", (long long)evaluated_arguments->value.pair.first->value.function.parent_environment); + puts("body:\n"); + print(n->value.function.body); + puts("\n"); + printf("parent_env: %lld\n", + (long long)n->value.function.parent_environment); - return Memory::nil; - }); - defun("addr-of", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); + return Memory::nil; + }; + define((addr-of var), "TODO") { + fetch(var); + return Memory::create_lisp_object_number( + (float)((u64)&(var))); + }; + define((generate-docs file_name), "TODO") { + fetch(file_name); + try assert_type(file_name, Lisp_Object_Type::String); + try generate_docs(file_name->value.string); + return Memory::t; + }; + define((print (:sep " ") (:end "\n") . things), "TODO") { + fetch(sep, end, things); - return Memory::create_lisp_object_number((float)((u64)&(evaluated_arguments->value.pair.first->value))); - }); - defun("generate-docs", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length(1, arguments_length); - try assert_type(arguments->value.pair.first, Lisp_Object_Type::String); + if (things != Memory::nil) { + print(things->value.pair.first); - try generate_docs(arguments->value.pair.first->value.string); + for_lisp_list(things->value.pair.rest) { + print(sep); + print(it); + } + } - return Memory::t; - }); - defun("print", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); + print(end); + return Memory::nil; + }; + define((read (:prompt ">")), "TODO") { + fetch(prompt); + print(prompt); - print(evaluated_arguments->value.pair.first); + // TODO(Felix): make read_line return a String* + char* line = read_line(); + defer { + free(line); + }; + String* strLine = Memory::create_string(line); + return Memory::create_lisp_object_string(strLine); + }; + define((exit (:code 0)), "TODO") { + fetch(code); + try assert_type(code, Lisp_Object_Type::Number); + exit((int)code->value.number); + }; + define((break), "TODO") { + in_caller_env { + print_environment(get_current_environment()); + } + return Memory::nil; + }; + define((memstat), "TODO") { + Memory::print_status(); + return Memory::nil; + }; + // // defun("try", "TODO", __LINE__, cLambda { + // // try arguments_length = list_length(arguments); + // // try assert_arguments_length(2, arguments_length); + + // // Lisp_Object* try_part = arguments->value.pair.first; + // // Lisp_Object* catch_part = arguments->value.pair.rest->value.pair.first; + // // Lisp_Object* result; + + // // result = eval_expr(try_part); + // // if (Globals::error) { + // // delete_error(); + // // try result = eval_expr(catch_part); + // // } + // // return result; + // // }); + define((load file), "TODO") { + fetch(file); + try assert_type(file, Lisp_Object_Type::String); + + Lisp_Object* result; + in_caller_env { + try result = built_in_load(file->value.string); + } + return result; + }; + define((import f), "TODO") { + fetch(f); + try assert_type(f, Lisp_Object_Type::String); - return Memory::nil; - }); - defun("read", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length_less_equal(1, arguments_length); - - if (arguments_length == 1) { - Lisp_Object* prompt = evaluated_arguments->value.pair.first; - print(prompt); - } + Lisp_Object *result; + in_caller_env { + try result = built_in_import(f->value.string); + } - // TODO(Felix): make read_line return a String* - char* line = read_line(); - defer { - free(line); - }; - String* strLine = Memory::create_string(line); - return Memory::create_lisp_object_string(strLine); - }); - defun("exit", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length_less_equal(1, arguments_length); - - if (arguments_length == 1) { - Lisp_Object* error_code = evaluated_arguments->value.pair.first; - try assert_type(error_code, Lisp_Object_Type::Number); - exit((int)error_code->value.number); - } - exit(0); - }); - defun("break", "TODO", __LINE__, cLambda { - print_environment(get_current_environment()); - debug_break(); - return Memory::nil; - }); - defun("memstat", "TODO", __LINE__, cLambda { - Memory::print_status(); - return Memory::nil; - }); - defun("try", "TODO", __LINE__, cLambda { - try arguments_length = list_length(arguments); - try assert_arguments_length(2, arguments_length); - - Lisp_Object* try_part = arguments->value.pair.first; - Lisp_Object* catch_part = arguments->value.pair.rest->value.pair.first; - Lisp_Object* result; - - result = eval_expr(try_part); - if (Globals::error) { - delete_error(); - try result = eval_expr(catch_part); - } - return result; - }); - defun("load", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); - - Lisp_Object* result; - try result = built_in_load(evaluated_arguments->value.pair.first->value.string); - - return result; - - }); - defun("import", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); - - Lisp_Object* result; - try result = built_in_import(evaluated_arguments->value.pair.first->value.string); - - return result; - - }); - defun("copy", "TODO", __LINE__, cLambda { - // TODO(Felix): if we are copying string nodes, then - // shouldn't the string itself also get copied?? - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - - return Memory::copy_lisp_object(evaluated_arguments->value.pair.first); - }); - defun("error", "TODO", __LINE__, cLambda { - // TODO(Felix): make the error function useful - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(0, arguments_length); - create_generic_error("Userlanderror"); - return nullptr; - }); - defun("symbol->keyword", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Symbol); - - Lisp_Object* source = evaluated_arguments->value.pair.first; - - return Memory::get_or_create_lisp_object_keyword(source->value.symbol.identifier); - }); - defun("string->symbol", "TODO", __LINE__, cLambda { - // TODO(Felix): do some sanity checks on the string. For - // example, numbers are not valid symbols. - - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::String); - - Lisp_Object* source = evaluated_arguments->value.pair.first; - - return Memory::get_or_create_lisp_object_symbol(Memory::duplicate_string(source->value.string)); - }); - defun("symbol->string", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length(1, arguments_length); - try assert_type(evaluated_arguments->value.pair.first, Lisp_Object_Type::Symbol); - - Lisp_Object* source = evaluated_arguments->value.pair.first; - - return Memory::create_lisp_object_string(Memory::duplicate_string(source->value.symbol.identifier)); - }); - defun("concat-strings", "TODO", __LINE__, cLambda { - try evaluated_arguments = eval_arguments(arguments, &arguments_length); - try assert_arguments_length_greater_equal(1, arguments_length); - - int resulting_string_len = 0; - - for_lisp_list (evaluated_arguments) { - try assert_type(it, Lisp_Object_Type::String); - resulting_string_len += it->value.string->length; - } + return Memory::t; + }; + define((copy obj), "TODO") { + fetch(obj); + // TODO(Felix): if we are copying string nodes, then + // shouldn't the string itself also get copied?? + return Memory::copy_lisp_object(obj); + }; + // // defun("error", "TODO", __LINE__, cLambda { + // // // TODO(Felix): make the error function useful + // // try evaluated_arguments = eval_arguments(arguments, &arguments_length); + // // try assert_arguments_length(0, arguments_length); + // // create_generic_error("Userlanderror"); + // // return nullptr; + // // }); + define((symbol->keyword sym), "TODO") { + fetch(sym); + try assert_type(sym, Lisp_Object_Type::Symbol); + return Memory::get_or_create_lisp_object_keyword(sym->value.symbol.identifier); + }; + define((string->symbol str), "TODO") { + fetch(str); + // TODO(Felix): do some sanity checks on the string. For + // example, numbers are not valid symbols. + + try assert_type(str, Lisp_Object_Type::String); + return Memory::get_or_create_lisp_object_symbol( + Memory::duplicate_string(str->value.string)); + }; + define((symbol->string sym), "TODO") { + fetch(sym); - String* resulting_string = Memory::create_string("", resulting_string_len); - int index_in_string = 0; + try assert_type(sym, Lisp_Object_Type::Symbol); + return Memory::create_lisp_object_string( + Memory::duplicate_string(sym->value.symbol.identifier)); + }; + define((concat-strings . strings), "TODO") { + fetch(strings); - for_lisp_list (evaluated_arguments) { - strcpy((&resulting_string->data)+index_in_string, - Memory::get_c_str(it->value.string)); - index_in_string += it->value.string->length; - } + int resulting_string_len = 0; + for_lisp_list (strings) { + try assert_type(it, Lisp_Object_Type::String); + resulting_string_len += it->value.string->length; + } - return Memory::create_lisp_object_string(resulting_string); - }); + String* resulting_string = Memory::create_string("", resulting_string_len); + int index_in_string = 0; -#undef cLambda + for_lisp_list (strings) { + strcpy((&resulting_string->data)+index_in_string, + Memory::get_c_str(it->value.string)); + index_in_string += it->value.string->length; + } + + return Memory::create_lisp_object_string(resulting_string); + }; } diff --git a/src/env.cpp b/src/env.cpp index 9e03d11..16b6941 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -84,6 +84,8 @@ inline proc get_current_environment() -> Environment* { } proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { + assert_type(node, Lisp_Object_Type::Symbol); + Lisp_Object* result = try_lookup_symbol(node, env); if (result) @@ -110,8 +112,8 @@ proc print_environment_indent(Environment* env, int indent) -> void { } for (int i = 0; i < env->next_index; ++i) { print_indent(indent); + printf("-> %s :: ", env->keys[i]); print(env->values[i]); - printf(" %s", env->keys[i]); printf(" (%lld)", (long long)env->values[i]); puts(""); } diff --git a/src/error.cpp b/src/error.cpp index 9b57dd5..124c63e 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -9,10 +9,10 @@ proc delete_error() -> void { proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void { - if (Globals::log_level > Log_Level::None) { - printf("Error created in:\n %s:%d\n", c_file_name, c_file_line); - printf(" -> %s\n", Memory::get_c_str(message)); - } + if (Globals::log_level > Log_Level::None) { + printf("Error created in:\n %s:%d\n", c_file_name, c_file_line); + printf(" -> %s\n", Memory::get_c_str(message)); + } delete_error(); if (Globals::breaking_on_errors) { diff --git a/src/eval.cpp b/src/eval.cpp index f1ad83f..a0ab2f9 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -1,30 +1,68 @@ -proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> Lisp_Object* { +proc create_extended_environment_for_function_application( + Lisp_Object* unevaluated_arguments, + Lisp_Object* function) -> Environment* +{ profile_this; - + bool is_c_function = Memory::get_type(function) == Lisp_Object_Type::CFunction; Environment* new_env; - try new_env = Memory::create_child_environment(function->parent_environment); + Lisp_Object* arguments = unevaluated_arguments; + Arguments* arg_spec; + + // NOTE(Felix): Step 1. + // - setting the parent environment + // - setting the arg_spec + // - potentially evaluating the arguments + if (is_c_function) { + new_env = Memory::create_child_environment(get_root_environment()); + arg_spec = &function->value.cFunction->args; + // if it is not a special form, evaluate the arguments + if (!function->value.cFunction->is_special_form) { + try arguments = eval_arguments(arguments); + } + } else { + new_env = Memory::create_child_environment(function->value.function.parent_environment); + arg_spec = &function->value.function.args; + // if it is a lambda + if (function->value.function.type == Function_Type::Lambda) { + try arguments = eval_arguments(arguments); + } + } + + // NOTE(Felix): Even though we will return the environment at the + // end, for defining symbols here for the parameters, it has to be + // on the envi stack. push_environment(new_env); defer { pop_environment(); }; + + // NOTE(Felix): Step 2. + // Reading the argument spec and fill in the environment + // for the function call + Lisp_Object* sym, *val; // used as temp storage to use `try` String_Array_List read_in_keywords; int obligatory_keywords_count = 0; int read_obligatory_keywords_count = 0; proc read_positional_args = [&]() -> void { - for (int i = 0; i < function->args.positional.symbols.next_index; ++i) { + for (int i = 0; i < arg_spec->positional.symbols.next_index; ++i) { if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { - create_wrong_number_of_arguments_error(function->args.positional.symbols.next_index, i); + create_wrong_number_of_arguments_error(arg_spec->positional.symbols.next_index, i); return; } - // NOTE(Felix): We have to copy all the arguments, otherwise - // we change the program code. - try_void sym = function->args.positional.symbols.data[i]; - define_symbol( - sym, - Memory::copy_lisp_object_except_pairs(arguments->value.pair.first)); + // NOTE(Felix): We have to copy all the arguments, + // otherwise we change the program code. XXX(Felix): T C + // functions we pass by reference... + try_void sym = arg_spec->positional.symbols.data[i]; + if (is_c_function) { + define_symbol(sym, arguments->value.pair.first); + } else { + define_symbol( + sym, + Memory::copy_lisp_object_except_pairs(arguments->value.pair.first)); + } arguments = arguments->value.pair.rest; } @@ -41,8 +79,8 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> return; // find out how many keyword args we /have/ to read - for (int i = 0; i < function->args.keyword.values.next_index; ++i) { - if (function->args.keyword.values.data[i] == nullptr) + for (int i = 0; i < arg_spec->keyword.values.next_index; ++i) { + if (arg_spec->keyword.values.data[i] == nullptr) ++obligatory_keywords_count; else break; @@ -52,10 +90,10 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> while (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { // check if this one is even an accepted keyword bool accepted = false; - for (int i = 0; i < function->args.keyword.values.next_index; ++i) { + for (int i = 0; i < arg_spec->keyword.values.next_index; ++i) { if (string_equal( arguments->value.pair.first->value.symbol.identifier, - function->args.keyword.keywords.data[i]->value.symbol.identifier)) + arg_spec->keyword.keywords.data[i]->value.symbol.identifier)) { accepted = true; break; @@ -108,9 +146,13 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> // if not set it and then add it to the array list try_void sym = Memory::get_or_create_lisp_object_symbol(arguments->value.pair.first->value.symbol.identifier); // NOTE(Felix): It seems we do not need to evaluate the argument here... - try_void define_symbol( - sym, - Memory::copy_lisp_object_except_pairs(arguments->value.pair.rest->value.pair.first)); + if (is_c_function) { + try_void define_symbol(sym, arguments->value.pair.rest->value.pair.first); + } else { + try_void define_symbol( + sym, + Memory::copy_lisp_object_except_pairs(arguments->value.pair.rest->value.pair.first)); + } append_to_array_list(&read_in_keywords, arguments->value.pair.first->value.symbol.identifier); ++read_obligatory_keywords_count; @@ -126,8 +168,8 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> proc check_keyword_args = [&]() -> void { // check if all necessary keywords have been read in - for (int i = 0; i < function->args.keyword.values.next_index; ++i) { - String* defined_keyword = function->args.keyword.keywords.data[i]->value.symbol.identifier; + for (int i = 0; i < arg_spec->keyword.values.next_index; ++i) { + String* defined_keyword = arg_spec->keyword.keywords.data[i]->value.symbol.identifier; bool was_set = false; for (int j = 0; j < read_in_keywords.next_index; ++j) { // TODO(Felix): Later compare the keywords, not their strings!! @@ -139,7 +181,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> break; } } - if (function->args.keyword.values.data[i] == nullptr) { + if (arg_spec->keyword.values.data[i] == nullptr) { // if this one does not have a default value if (!was_set) { create_generic_error( @@ -153,7 +195,11 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> // to use it or if the user supplied his own if (!was_set) { try_void sym = Memory::get_or_create_lisp_object_symbol(defined_keyword); - try_void val = Memory::copy_lisp_object_except_pairs(function->args.keyword.values.data[i]); + if (is_c_function) { + try_void val = arg_spec->keyword.values.data[i]; + } else { + try_void val = Memory::copy_lisp_object_except_pairs(arg_spec->keyword.values.data[i]); + } define_symbol(sym, val); } } @@ -162,13 +208,13 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> proc read_rest_arg = [&]() -> void { if (arguments == Memory::nil) { - if (function->args.rest) { - define_symbol(function->args.rest, Memory::nil); + if (arg_spec->rest) { + define_symbol(arg_spec->rest, Memory::nil); } } else { - if (function->args.rest) { + if (arg_spec->rest) { define_symbol( - function->args.rest, + arg_spec->rest, // NOTE(Felix): arguments will be a list, and I THINK // we do not need to copy it... arguments); @@ -187,157 +233,112 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> try check_keyword_args(); try read_rest_arg(); + return new_env; +} + +proc apply_arguments_to_function(Lisp_Object* arguments, Lisp_Object* function) -> Lisp_Object* { + profile_this; + Environment* new_env; + try new_env = create_extended_environment_for_function_application(arguments, function); + push_environment(new_env); + defer { + pop_environment(); + }; + Lisp_Object* result; - try result = eval_expr(function->body); + // if c function: + if (Memory::get_type(function) == Lisp_Object_Type::CFunction) + try result = function->value.cFunction->body(); + else // if lisp function + try result = eval_expr(function->value.function.body); + return result; } - /** This parses the argument specification of funcitons into their Function struct. It does this by allocating new positional_arguments, keyword_arguments and rest_argument and filling it in */ -proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { +proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_Object* function) -> void { + Arguments* result; + if (Memory::get_type(function) == Lisp_Object_Type::CFunction) { + result = &function->value.cFunction->args; + } else { + result = &function->value.function.args; + } + // first init the fields - function->args.positional = create_positional_argument_list(16); - function->args.keyword = create_keyword_argument_list(16); - function->args.rest = nullptr; + result->positional = create_positional_argument_list(16); + result->keyword = create_keyword_argument_list(16); + result->rest = nullptr; // okay let's try to read some positional arguments while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { - if (string_equal(arguments->value.pair.first->value.symbol.identifier, "keys") || - string_equal(arguments->value.pair.first->value.symbol.identifier, "rest")) + // if we encounter a keyword or a list (for keywords with + // defualt args), the positionals are done + if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword || + Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Pair) { break; - else { - create_parsing_error("A non recognized marker was found " - "in the lambda list: ':%s'", - &arguments->value.pair.first->value.symbol.identifier->data); - return; - } } + // if we encounter something that is neither a symbol nor a + // keyword arg, it's an error if (Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol) { - create_parsing_error("Only symbols and keywords can be " - "parsed here, but found '%s'", + create_parsing_error("Only symbols and keywords " + "(with or without default args) " + "can be parsed here, but found '%s'", Lisp_Object_Type_to_string(Memory::get_type(arguments->value.pair.first))); return; } - // okay wow we found an actual symbol + // okay we found an actual symbol append_to_positional_argument_list( - &function->args.positional, + &result->positional, arguments->value.pair.first); arguments = arguments->value.pair.rest; } - // okay we are done with positional arguments, lets check for - // keywords, - if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { - if (arguments != Memory::nil) - create_parsing_error("The lambda list must be nil terminated."); - return; - } - - if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword && - string_equal(arguments->value.pair.first->value.symbol.identifier, "keys")) - { - arguments = arguments->value.pair.rest; - if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { - create_parsing_error("Actual keys have to follow the :keys indicator."); - } - // if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) { - // create_parsing_error( - // "Only symbols can be parsed here, but found '%s'.", - // Lisp_Object_Type_to_string(arguments->value.pair.first->type)); - // return; - // } - - while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { - if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { - if (string_equal(arguments->value.pair.first->value.symbol.identifier, "rest")) - break; - else { - create_parsing_error( - "Only the :rest keyword can be parsed here, but got ':%s'.", - &arguments->value.pair.first->value.symbol.identifier->data); - return; - } - } - - if (Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol) { - create_parsing_error( - "Only symbols can be parsed here, but found '%s'.", - Lisp_Object_Type_to_string(Memory::get_type(arguments->value.pair.first))); - return; + // if we reach here, we are on a keyword or a pair wher a keyword + // should be in first + while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { + if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { + // if we are on a actual keyword (with no default arg) + auto keyword = arguments->value.pair.first; + append_to_keyword_argument_list(&result->keyword, keyword, nullptr); + } else if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Pair) { + // if we are on a keyword with a default value + + auto keyword = arguments->value.pair.first->value.pair.first; + if (Memory::get_type(keyword) != Lisp_Object_Type::Keyword) { + create_parsing_error("Default args must be keywords"); } - - // we found a symbol (arguments->value.pair->first) for - // the keyword args! Let's check if the next arguement is - // :defaults-to - Lisp_Object* next = arguments->value.pair.rest; - if (Memory::get_type(next) == Lisp_Object_Type::Pair && - Memory::get_type(next->value.pair.first) == Lisp_Object_Type::Keyword && - string_equal(next->value.pair.first->value.symbol.identifier, - "defaults-to")) + if (Memory::get_type(arguments->value.pair.first->value.pair.rest) + != Lisp_Object_Type::Pair) { - // check if there is a next argument too, otherwise it - // would be an error - next = next->value.pair.rest; - if (Memory::get_type(next) == Lisp_Object_Type::Pair) { - Lisp_Object* ret; - push_environment(function->parent_environment); - defer { - pop_environment(); - }; - try_void ret = eval_expr(next->value.pair.first); - append_to_keyword_argument_list(&function->args.keyword, - arguments->value.pair.first, - ret); - arguments = next->value.pair.rest; - } else { - create_parsing_error("Expecting a value after 'defaults-to'"); - return; - } - } else { - // No :defaults-to, so just add it to the list - append_to_keyword_argument_list(&function->args.keyword, - arguments->value.pair.first, - nullptr); - arguments = next; + create_parsing_error("Default args must be a list of 2."); } + auto value = arguments->value.pair.first->value.pair.rest->value.pair.first; + if (arguments->value.pair.first->value.pair.rest->value.pair.rest != Memory::nil) { + create_parsing_error("Default args must be a list of 2."); + } + + append_to_keyword_argument_list(&result->keyword, keyword, value); } + arguments = arguments->value.pair.rest; } - // Now we are also done with keyword arguments, lets check for // if there is a rest argument if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { - if (arguments != Memory::nil) - create_parsing_error("The lambda list must be nil terminated."); - return; - } - - if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword && - string_equal(arguments->value.pair.first->value.symbol.identifier, "rest")) - { - arguments = arguments->value.pair.rest; - if (// arguments->type != Lisp_Object_Type::Pair || - Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol) - { - create_parsing_error("After the 'rest' marker there must follow a symbol."); + if (arguments == Memory::nil) return; - } - function->args.rest = arguments->value.pair.first; - if (arguments->value.pair.rest != Memory::nil) { - create_parsing_error("The lambda list must end after the rest symbol"); - } - } else { - printf("this should not happen?"); - create_generic_error("What is happening?"); + if (Memory::get_type(arguments) == Lisp_Object_Type::Symbol) + result->rest = arguments; + else + create_parsing_error("The rest argument must be a symbol."); } } @@ -361,11 +362,11 @@ proc list_length(Lisp_Object* node) -> int { return 0; } -proc eval_arguments(Lisp_Object* arguments, int *out_arguments_length) -> Lisp_Object* { +proc eval_arguments(Lisp_Object* arguments) -> Lisp_Object* { profile_this; - int my_out_arguments_length = 0; + // int my_out_arguments_length = 0; if (arguments == Memory::nil) { - *(out_arguments_length) = 0; + // *(out_arguments_length) = 0; return arguments; } @@ -390,9 +391,9 @@ proc eval_arguments(Lisp_Object* arguments, int *out_arguments_length) -> Lisp_O create_parsing_error("Attempting to evaluate ill formed argument list."); return nullptr; } - ++my_out_arguments_length; + // ++my_out_arguments_length; } - *(out_arguments_length) = my_out_arguments_length; + // *(out_arguments_length) = my_out_arguments_length; return evaluated_arguments; } @@ -435,12 +436,10 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* { } Lisp_Object* arguments = node->value.pair.rest; - int arguments_length; - // check for c function if (Memory::get_type(lispOperator) == Lisp_Object_Type::CFunction) { Lisp_Object* result; - try result = lispOperator->value.cFunction->function(arguments); + try result = apply_arguments_to_function(arguments, lispOperator); return result; } @@ -449,12 +448,9 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* { // only for lambdas we evaluate the arguments before // apllying, for the other types, special-lambda and macro // we do not need. - if (lispOperator->value.function.type == Function_Type::Lambda) { - try arguments = eval_arguments(arguments, &arguments_length); - } Lisp_Object* result; - try result = apply_arguments_to_function(arguments, &lispOperator->value.function); + try result = apply_arguments_to_function(arguments, lispOperator); // NOTE(Felix): The parser does not understnad (import ..) // so it cannot expand imported macros at read time @@ -464,7 +460,9 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* { // and bake them in, so they do not have to be expanded // later again. We will call this "lazy macro expansion" if (lispOperator->value.function.type == Function_Type::Macro) { + // bake in the macro expansion: *node = *result; + // eval again because macro try result = eval_expr(result); } diff --git a/src/forward_decls.cpp b/src/forward_decls.cpp index debe07b..7353940 100644 --- a/src/forward_decls.cpp +++ b/src/forward_decls.cpp @@ -4,12 +4,12 @@ proc built_in_import(String*) -> Lisp_Object*; proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void; proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...) -> void; proc create_error(Lisp_Object* type, const char* message, const char* c_file_name, int c_file_line) -> void; -proc eval_arguments(Lisp_Object*, int*) -> Lisp_Object*; +proc eval_arguments(Lisp_Object*) -> Lisp_Object*; proc eval_expr(Lisp_Object*) -> Lisp_Object*; proc is_truthy (Lisp_Object*) -> bool; proc list_length(Lisp_Object*) -> int; proc load_built_ins_into_environment() -> void; -proc parse_argument_list(Lisp_Object*, Function*) -> void; +proc create_arguments_from_lambda_list_and_inject(Lisp_Object* formal_arguments, Lisp_Object* function) -> void; proc print_environment(Environment*) -> void; @@ -36,6 +36,8 @@ namespace Parser { extern String* parser_file; extern int parser_line; extern int parser_col; + + proc parse_single_expression(char* text) -> Lisp_Object*; } namespace Globals { diff --git a/src/gc.cpp b/src/gc.cpp index cfed6a3..2eeb38e 100644 --- a/src/gc.cpp +++ b/src/gc.cpp @@ -1,93 +1,94 @@ -namespace GC { - proc maybe_mark(Environment* env) -> void; - - int current_mark; - - Lisp_Object_Array_List marked_objects; - String_Array_List marked_strings; - Environment_Array_List marked_environments; - Environment_Array_List protected_environments; - - proc marked(Lisp_Object* node) -> bool { - return false; - } - - proc marked(Environment* env) -> bool { - return false; - } - - proc maybe_mark(Lisp_Object* node) -> void { - if (marked(node)) - return; - - // mark object itself - append_to_array_list(&marked_objects, node); - - // mark docstring - if (node->docstring) - append_to_array_list(&marked_strings, node->docstring); - - // mark type specific data - switch (Memory::get_type(node)) { - case Lisp_Object_Type::Pair: { - for_lisp_list (node) { - maybe_mark(it); - } - } break; - case Lisp_Object_Type::Vector: { - for_lisp_vector (node) { - maybe_mark(it); - } - } break; - case Lisp_Object_Type::String: { - append_to_array_list(&marked_strings, node->value.string); - } break; - case Lisp_Object_Type::Function: { - // NOTE(Felix): We dont have to mark the symbols, keywords - // for parameter names, as symbols and keywords are never - // garbage collected - maybe_mark(node->value.function.parent_environment); - maybe_mark(node->value.function.body); - // mark the default arguemnt values: - for_array_list (node->value.function.args.keyword.values) { - if (it) maybe_mark(it); - } - } break; - } - - } - - proc maybe_mark(Environment* env) -> void { - if (marked(env)) - return; - - append_to_array_list(&marked_environments, env); - - for_array_list (env->parents) { - maybe_mark(it); - } - - Lisp_Object* it = env->values[0]; - for (int i = 0; i < env->next_index; it = env->values[++i]) { - maybe_mark(it); - } - } - - proc garbage_collect() -> void { - profile_this; - ++current_mark; - - for_array_list (protected_environments) maybe_mark(it); - for_array_list (Globals::Current_Execution::envi_stack) maybe_mark(it); - } - - proc gc_init_and_go() -> void { - current_mark = 0; - marked_objects = create_Lisp_Object_array_list(1024); - marked_environments = create_Environment_array_list(1024); - - while (1) { - garbage_collect(); - } - } -} +namespace GC { + proc maybe_mark(Environment* env) -> void; + + int current_mark; + + Lisp_Object_Array_List marked_objects; + String_Array_List marked_strings; + Environment_Array_List marked_environments; + Environment_Array_List protected_environments; + + proc marked(Lisp_Object* node) -> bool { + return false; + } + + proc marked(Environment* env) -> bool { + return false; + } + + proc maybe_mark(Lisp_Object* node) -> void { + if (marked(node)) + return; + + // mark object itself + append_to_array_list(&marked_objects, node); + + // mark docstring + if (node->docstring) + append_to_array_list(&marked_strings, node->docstring); + + // mark type specific data + switch (Memory::get_type(node)) { + case Lisp_Object_Type::Pair: { + for_lisp_list (node) { + maybe_mark(it); + } + } break; + case Lisp_Object_Type::Vector: { + for_lisp_vector (node) { + maybe_mark(it); + } + } break; + case Lisp_Object_Type::String: { + append_to_array_list(&marked_strings, node->value.string); + } break; + case Lisp_Object_Type::Function: { + // NOTE(Felix): We dont have to mark the symbols, keywords + // for parameter names, as symbols and keywords are never + // garbage collected + maybe_mark(node->value.function.parent_environment); + maybe_mark(node->value.function.body); + // mark the default arguemnt values: + for_array_list (node->value.function.args.keyword.values) { + if (it) maybe_mark(it); + } + } break; + default: break; + } + + } + + proc maybe_mark(Environment* env) -> void { + if (marked(env)) + return; + + append_to_array_list(&marked_environments, env); + + for_array_list (env->parents) { + maybe_mark(it); + } + + Lisp_Object* it = env->values[0]; + for (int i = 0; i < env->next_index; it = env->values[++i]) { + maybe_mark(it); + } + } + + proc garbage_collect() -> void { + profile_this; + ++current_mark; + + for_array_list (protected_environments) maybe_mark(it); + for_array_list (Globals::Current_Execution::envi_stack) maybe_mark(it); + } + + proc gc_init_and_go() -> void { + current_mark = 0; + marked_objects = create_Lisp_Object_array_list(1024); + marked_environments = create_Environment_array_list(1024); + + while (1) { + garbage_collect(); + } + } +} diff --git a/src/io.cpp b/src/io.cpp index a3162c0..4e5d5f7 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -366,7 +366,7 @@ proc print(Lisp_Object* node, bool print_repr = false, FILE* file = stdout) -> v if (Memory::get_type(head) != Lisp_Object_Type::Nil) { fputs(" . ", file); - print(head); + print(head, print_repr, file); } putc(')', file); @@ -376,7 +376,7 @@ proc print(Lisp_Object* node, bool print_repr = false, FILE* file = stdout) -> v proc print_single_call(Lisp_Object* obj) -> void { printf(console_cyan); - print(obj); + print(obj, true); printf(console_normal); printf("\n at "); if (obj->sourceCodeLocation) { diff --git a/src/main.cpp b/src/main.cpp index 79561b3..51cc2b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,11 @@ #include "slime.h" int main(int argc, char* argv[]) { + if (argc > 1) { if (Slime::string_equal(argv[1], "--run-tests")) { int res = Slime::run_all_tests(); - Slime::interprete_file("generate-docs.slime"); + Slime::interprete_file((char*)"generate-docs.slime"); return res ? 0 : 1; } diff --git a/src/memory.cpp b/src/memory.cpp index 801717a..c20e9ec 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -184,8 +184,8 @@ namespace Memory { try_void Parser::standard_in = create_string("stdin"); - try_void Globals::Current_Execution::envi_stack.data[0] = create_built_ins_environment(); - try_void Globals::Current_Execution::envi_stack.next_index = 1; + Globals::Current_Execution::envi_stack.next_index = 0; + push_environment(create_built_ins_environment()); } proc reset() -> void { @@ -198,8 +198,8 @@ namespace Memory { next_index_in_environment_memory = 0; next_free_spot_in_string_memory = string_memory; - try_void Globals::Current_Execution::envi_stack.data[0] = create_built_ins_environment(); - try_void Globals::Current_Execution::envi_stack.next_index = 1; + Globals::Current_Execution::envi_stack.next_index = 0; + push_environment(create_built_ins_environment()); } proc create_lisp_object_number(double number) -> Lisp_Object* { @@ -306,13 +306,14 @@ namespace Memory { Memory::create_string(keyword)); } - proc create_lisp_object_cfunction(std::function function) -> Lisp_Object* { + proc create_lisp_object_cfunction(bool is_special) -> Lisp_Object* { Lisp_Object* node; try node = create_lisp_object(); set_type(node, Lisp_Object_Type::CFunction); // node->value.lambdaWrapper = new Lambda_Wrapper(function); node->value.cFunction = new(cFunction); - node->value.cFunction->function = function; + node->value.cFunction->args = {}; + node->value.cFunction->is_special_form = is_special; return node; } @@ -402,17 +403,17 @@ namespace Memory { load_built_ins_into_environment(); - // // save the current working directory - // char* cwd = get_cwd(); - // defer { - // change_cwd(cwd); - // free(cwd); - // }; - - // // get the direction of the exe - // char* exe_path = get_exe_dir(); - // change_cwd(exe_path); - // free(exe_path); + // save the current working directory + //char* cwd = get_cwd(); + //defer { + // change_cwd(cwd); + // free(cwd); + //}; + + //// get the direction of the exe + //char* exe_path = get_exe_dir(); + //change_cwd(exe_path); + //free(exe_path); built_in_load(Memory::create_string("pre.slime")); diff --git a/src/parse.cpp b/src/parse.cpp index b918c22..76f9dcd 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -366,118 +366,118 @@ namespace Parser { } // check if we have to create or delete or run macros - while (Memory::get_type(expression->value.pair.first) == Lisp_Object_Type::Symbol) { - Lisp_Object* parsed_symbol = expression->value.pair.first; - if (string_equal("define-syntax", parsed_symbol->value.symbol.identifier)) { - // create a new macro - Lisp_Object* arguments = expression->value.pair.rest; - Lisp_Object* body; - int arguments_length; - - // HACK(Felix): almost code duplicate from - // `built_ins.cpp`: special-lambda - try arguments_length = list_length(arguments); - - // (define-syntax (defun name args :rest body) (...)) - if (arguments_length < 2) { - create_wrong_number_of_arguments_error(3, arguments_length); - return nullptr; - } - - assert_type(arguments->value.pair.first, Lisp_Object_Type::Pair); - - // extract the name - Lisp_Object* symbol_for_macro = arguments->value.pair.first->value.pair.first; - body = arguments->value.pair.rest; - arguments = arguments->value.pair.first->value.pair.rest; - - // Function* function = new(Function); - Lisp_Object* macro; - try macro = Memory::create_lisp_object(); - Memory::set_type(macro, Lisp_Object_Type::Function); - macro->value.function.parent_environment = get_current_environment(); - macro->value.function.type = Function_Type::Macro; - - // if parameters were specified - if (arguments != Memory::nil) { - try assert_type(arguments, Lisp_Object_Type::Pair); - try parse_argument_list(arguments, ¯o->value.function); - } else { - macro->value.function.args.positional = create_positional_argument_list(1); - macro->value.function.args.keyword = create_keyword_argument_list(1); - macro->value.function.args.rest = nullptr; - } - - // arguments = arguments->value.pair.rest; - // if there is a docstring, use it - if (Memory::get_type(body->value.pair.first) == Lisp_Object_Type::String) { - macro->docstring = body->value.pair.first->value.string; - body = body->value.pair.rest; - } else { - macro->docstring = nullptr; - } - - // we are now in the function body, just wrap it in an - // implicit begin - try macro->value.function.body = Memory::create_lisp_object_pair( - Memory::get_or_create_lisp_object_symbol("begin"), - body); - - inject_scl(macro); - // macro->value.function = function; - define_symbol(symbol_for_macro, macro); - - // print_environment(environment_for_macros); - return Memory::nil; - - } else if (string_equal("delete-syntax", parsed_symbol->value.symbol.identifier)) { - /* --- deleting an existing macro --- */ - // TODO(Felix): this is a hard one because when - // environments will be made from hashmaps, how can we - // delete stuff from hashmaps? If we do probing on - // collision and then delte the first colliding entry, - // how can we find the second one? How many probes do - // we have to do to know for sure that an elemenet is - // not in the hashmap? It would be much easier if we - // never deleted any elements from the hashmap, so - // that, when an entry is not found immidiately, we - // know for sure that it does not exist in the table. - - create_generic_error("deleting macros has not yet be implemented," - "and I don't know if it is a good idea to do so."); - return nullptr; - } else { - // if threre is a macro named like this, then macroexpand - // if not it is regular code, dont touch. - break; - - Lisp_Object* macro = try_lookup_symbol(parsed_symbol, get_current_environment()); - if (macro && - Memory::get_type(macro) == Lisp_Object_Type::Function && - macro->value.function.type == Function_Type::Macro) - { - // printf("pretending to expand macro at %s %d %d: ", - // Memory::get_c_str(parser_file), - // parser_line, parser_col); - // print(parsed_symbol); - // printf("\n"); - // NOTE(Felix): Execute it as a special lambda, - // because if we keep it as a macro, the evaluator - // will think it is a stray macro that was not yet - // expanded, and attempt to evaluate it twice (1. - // for expanding, and 2. for evaluating) - macro->value.function.type = Function_Type::Special_Lambda; - // NOTE(Felix): deferred so even if eval expr - // fails, and returns, the type will be be - // resetted to macro. - defer { - macro->value.function.type = Function_Type::Macro; - }; - try expression = eval_expr(expression); - break; - } else break; - } - } + // while (Memory::get_type(expression->value.pair.first) == Lisp_Object_Type::Symbol) { + // Lisp_Object* parsed_symbol = expression->value.pair.first; + // if (string_equal("define-syntax", parsed_symbol->value.symbol.identifier)) { + // // create a new macro + // Lisp_Object* arguments = expression->value.pair.rest; + // Lisp_Object* body; + // int arguments_length; + + // // HACK(Felix): almost code duplicate from + // // `built_ins.cpp`: special-lambda + // try arguments_length = list_length(arguments); + + // // (define-syntax (defun name args :rest body) (...)) + // if (arguments_length < 2) { + // create_wrong_number_of_arguments_error(3, arguments_length); + // return nullptr; + // } + + // assert_type(arguments->value.pair.first, Lisp_Object_Type::Pair); + + // // extract the name + // Lisp_Object* symbol_for_macro = arguments->value.pair.first->value.pair.first; + // body = arguments->value.pair.rest; + // arguments = arguments->value.pair.first->value.pair.rest; + + // // Function* function = new(Function); + // Lisp_Object* macro; + // try macro = Memory::create_lisp_object(); + // Memory::set_type(macro, Lisp_Object_Type::Function); + // macro->value.function.parent_environment = get_current_environment(); + // macro->value.function.type = Function_Type::Macro; + + // // if parameters were specified + // if (arguments != Memory::nil) { + // try assert_type(arguments, Lisp_Object_Type::Pair); + // try create_arguments_from_lambda_list_and_inject(arguments, macro); + // } else { + // macro->value.function.args.positional = create_positional_argument_list(1); + // macro->value.function.args.keyword = create_keyword_argument_list(1); + // macro->value.function.args.rest = nullptr; + // } + + // // arguments = arguments->value.pair.rest; + // // if there is a docstring, use it + // if (Memory::get_type(body->value.pair.first) == Lisp_Object_Type::String) { + // macro->docstring = body->value.pair.first->value.string; + // body = body->value.pair.rest; + // } else { + // macro->docstring = nullptr; + // } + + // // we are now in the function body, just wrap it in an + // // implicit begin + // try macro->value.function.body = Memory::create_lisp_object_pair( + // Memory::get_or_create_lisp_object_symbol("begin"), + // body); + + // inject_scl(macro); + // // macro->value.function = function; + // define_symbol(symbol_for_macro, macro); + + // // print_environment(environment_for_macros); + // return Memory::nil; + + // } else if (string_equal("delete-syntax", parsed_symbol->value.symbol.identifier)) { + // /* --- deleting an existing macro --- */ + // // TODO(Felix): this is a hard one because when + // // environments will be made from hashmaps, how can we + // // delete stuff from hashmaps? If we do probing on + // // collision and then delte the first colliding entry, + // // how can we find the second one? How many probes do + // // we have to do to know for sure that an elemenet is + // // not in the hashmap? It would be much easier if we + // // never deleted any elements from the hashmap, so + // // that, when an entry is not found immidiately, we + // // know for sure that it does not exist in the table. + + // create_generic_error("deleting macros has not yet be implemented," + // "and I don't know if it is a good idea to do so."); + // return nullptr; + // } else { + // // if threre is a macro named like this, then macroexpand + // // if not it is regular code, dont touch. + // break; + + // Lisp_Object* macro = try_lookup_symbol(parsed_symbol, get_current_environment()); + // if (macro && + // Memory::get_type(macro) == Lisp_Object_Type::Function && + // macro->value.function.type == Function_Type::Macro) + // { + // // printf("pretending to expand macro at %s %d %d: ", + // // Memory::get_c_str(parser_file), + // // parser_line, parser_col); + // // print(parsed_symbol); + // // printf("\n"); + // // NOTE(Felix): Execute it as a special lambda, + // // because if we keep it as a macro, the evaluator + // // will think it is a stray macro that was not yet + // // expanded, and attempt to evaluate it twice (1. + // // for expanding, and 2. for evaluating) + // macro->value.function.type = Function_Type::Special_Lambda; + // // NOTE(Felix): deferred so even if eval expr + // // fails, and returns, the type will be be + // // resetted to macro. + // defer { + // macro->value.function.type = Function_Type::Macro; + // }; + // try expression = eval_expr(expression); + // break; + // } else break; + // } + // } return expression; } diff --git a/src/structs.cpp b/src/structs.cpp index be58c2d..5fe52be 100644 --- a/src/structs.cpp +++ b/src/structs.cpp @@ -121,13 +121,15 @@ struct Environment { struct Function { Function_Type type; - Arguments args; - Lisp_Object* body; // implicit begin + Arguments args; + Lisp_Object* body; // maybe implicit begin Environment* parent_environment; // we are doing closures now!! }; struct cFunction { - std::function function; + std::function body; + Arguments args; + bool is_special_form; }; struct Lisp_Object { diff --git a/src/testing.cpp b/src/testing.cpp index 36e8483..e18889d 100644 --- a/src/testing.cpp +++ b/src/testing.cpp @@ -196,8 +196,7 @@ proc test_array_lists_searching() -> testresult { proc test_eval_operands() -> testresult { char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))"; Lisp_Object* operands = Parser::parse_single_expression(operands_string); - int operands_length; - try operands = eval_arguments(operands, &operands_length); + try operands = eval_arguments(operands); assert_no_error(); assert_equal_int(list_length(operands), 4); @@ -504,7 +503,7 @@ proc test_built_in_type() -> testresult { assert_equal_string(result->value.symbol.identifier, "number"); // setting user type - char exp_string2[] = "(begin (set-type a :my-type)(type a))"; + char exp_string2[] = "(begin (set-type! a :my-type)(type a))"; expression = Parser::parse_single_expression(exp_string2); result = eval_expr(expression); @@ -514,7 +513,7 @@ proc test_built_in_type() -> testresult { assert_equal_string(result->value.symbol.identifier, "my-type"); // trying to set invalid user type - char exp_string3[] = "(begin (set-type a \"wrong tpye\")(type a))"; + char exp_string3[] = "(begin (set-type! a \"wrong tpye\")(type a))"; expression = Parser::parse_single_expression(exp_string3); assert_no_error(); @@ -528,7 +527,7 @@ proc test_built_in_type() -> testresult { delete_error(); // deleting user type - char exp_string4[] = "(begin (delete-type a)(type a))"; + char exp_string4[] = "(begin (delete-type! a)(type a))"; expression = Parser::parse_single_expression(exp_string4); result = eval_expr(expression); @@ -598,13 +597,19 @@ proc run_all_tests() -> bool { bool result = true; + Memory::init(4096 * 2000, 1024 * 32, 4096 * 16 * 10); + Environment* root_env = get_root_environment(); + Environment* user_env = Memory::create_child_environment(root_env); + push_environment(user_env); + defer{ + pop_environment(); + }; + printf("-- Util --\n"); invoke_test(test_array_lists_adding_and_removing); invoke_test(test_array_lists_sorting); invoke_test(test_array_lists_searching); - Memory::init(4096 * 2000, 1024 * 32, 4096 * 16 * 10); - printf("\n -- Parsing --\n"); invoke_test(test_parse_atom); invoke_test(test_parse_expression); diff --git a/todo.org b/todo.org index e0e0c7c..f3c1528 100644 --- a/todo.org +++ b/todo.org @@ -18,3 +18,22 @@ ;; should output 6 ;; outputs 0 #+END_SRC +* TODO BUG 3: unnecessary copying? +define((test val),"") { + fetch(val) ; + printf("addr of arg: %lld\n", (unsigned long long)&val); + return Memory::nil; +}; + +then: +#+begin_src slime +(define a "a") +(test a) ;; will output an adress +(if 1 (test a) 2) ;; will output a different adress +#+end_src +* TODO BUG 4: arg parsing +#+begin_src slime +(define (range (:from 0) to) ...) +#+end_src +should error since we can't have positional args after keywords. right now, 'to' is silently +ignored.. diff --git a/vs/slime.vcxproj b/vs/slime.vcxproj index 27f07f3..e0bae6d 100644 --- a/vs/slime.vcxproj +++ b/vs/slime.vcxproj @@ -1,182 +1,182 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - run tests - Win32 - - - run tests - x64 - - - - 15.0 - {1A47A3ED-871F-4CB4-875B-8CAA385B1771} - slime - 10.0.15063.0 - slime - - - - Application - true - v141 - MultiByte - - - Application - true - v141 - MultiByte - - - Application - false - v141 - true - MultiByte - - - Application - true - v141 - MultiByte - - - Application - true - v141 - MultiByte - - - Application - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)$(Platform)\$(Configuration)\ - - - - Level3 - Disabled - true - - - true - - - - - Level3 - Disabled - true - - - true - - - - - Level3 - Disabled - true - Default - stdcpplatest - - - true - - - - - Level3 - Disabled - true - Default - stdcpplatest - _PROFILING;%(PreprocessorDefinitions) - - - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - - - Level3 - MaxSpeed - true - true - true - Default - stdcpplatest - - - true - true - NotSet - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + run tests + Win32 + + + run tests + x64 + + + + 15.0 + {1A47A3ED-871F-4CB4-875B-8CAA385B1771} + slime + 10.0.15063.0 + slime + + + + Application + true + v141 + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + + + + Level3 + Disabled + true + + + true + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + Disabled + true + Default + stdcpplatest + + + true + + + + + Level3 + Disabled + true + Default + stdcpplatest + _PROFILING;%(PreprocessorDefinitions) + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + Default + stdcpplatest + + + true + true + NotSet + + + + + + + + \ No newline at end of file