* fixed and wrote test for lambda and function as arg case

* added license to userlib tests
* added map impl to userlib
* userlib tests now run and pass
* all args are evaluated individually
This commit is contained in:
Ava Apples Affine 2023-03-20 16:22:51 -07:00
parent 8a91560921
commit dcb2969b0a
Signed by: affine
GPG key ID: 3A4645B8CF806069
7 changed files with 148 additions and 40 deletions

View file

@ -1,11 +1,30 @@
#!/bin/relish
;; relish: versatile lisp shell
;; Copyright (C) 2021 Aidan Hahn
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;; USERLIB-TESTS
;; this file implements unit tests for handwritten userlib functions
(def passed
(def passed
'prints if a test has passed'
(test)
(echo (concat "PASSED: " test)))
(def failed
(def failed
'prints if a test has failed'
(test)
(echo (concat "FAILED: " test)))
@ -14,30 +33,32 @@
(('set updates var'
(quote
(let ((test-val 0))
(set test-val 3)
(set (q test-val) 3)
(eq? test-val 3))))
('prepend prepends to list'
(quote
(let ((list (2 3 4))
(list (prepend 1 list))
(list-head (head list)))
(list-head (pop list)))
(eq? (car list-head) 1))))
('map applies function across list'
(quote
(let ((list (1 2 3))
(adder (lambda (x) (add 1 x))))
(eq? (map adder list) (2 3 4)))))
;; add more test cases here
))
(def test-iter 'iterates over test cases'
(head test-cases))
;; run all test cases, print output
(while (gt? (len (cdr test-iter))
0)
(let ((test (car test-iter))
(remaining (cdr test-iter))
(test-name (car test))
(test-body (cdr test)))
(if (eval test-body)
(passed test-name)
(failed test-name))
(def test-iter '' (head remaining))))
(let ((test-iter (pop test-cases)))
(while (gt? (len test-iter) 1)
(let ((test (car test-iter))
(remaining (cdr test-iter))
(test-name (car test))
(test-body (cdr test)))
(if (eval test-body)
(passed test-name)
(failed test-name))
(set (q test-iter) (pop remaining)))))

View file

@ -1,3 +1,5 @@
#!/bin/relish
;; relish: versatile lisp shell
;; Copyright (C) 2021 Aidan Hahn
;;
@ -15,16 +17,50 @@
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;; USERLIB
;; This file contains a plethora of useful features that are not shipped in the STL
;; This file contains useful features that are not shipped in the STL
;; this would be way faster as code in stl
;; but stl already suffers scope creep
(def prepend
'takes a list and appends an element to the back of it.
returns prepended list'
(elem list)
(reverse (append (reverse list) elem)))
(reverse (cons (reverse list) elem)))
;; please dont misuse this tool
(def set
'sets an existing variable without touching its docstring'
'sets an existing variable without touching its docstring.
WARNING: abandon hope all ye who declare and then modify global variables!
If you find yourself struggling to debug a complex error in state access,
or you are having issues re-running commands in the shell consider the
following advice:
It is very much an anti pattern to mutate global variable that contain state
refactor your program: put iterators, counters, procedurally generated code,
and all other mutable state into a let loop.
A zen script in relish is one where each root level form (or eval at repl)
is self contained, and does not permanently modify any other one.
See the userlib tests for an easy to follow example of this.'
(var val)
(let ((doc (get-doc var)))
(def (eval var) doc val)))
(def (eval var) doc val)))
(def map
'Takes two arguments: a function and a list.
for each element in the list, the function is applied and the
result is added to a new list. Returns the new list.'
(func list)
(let ((list-iter (pop list))
(result ()))
(while (gt? (len list-iter) 1)
(let ((current (car list-iter))
(remaining (cdr list-iter))
(current-res (func current)))
(set (q result) (cons result current-res))
(set (q list-iter) (pop remaining))))
result))