Skip to content

Commit 2b05fb1

Browse files
committed
Add lisp primitive, remove and/or primitives
1 parent 9deb0ca commit 2b05fb1

File tree

5 files changed

+50
-74
lines changed

5 files changed

+50
-74
lines changed

README.md

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@ able to run on low powered devices.
1212

1313
The added primitives:
1414
* strings and conversion
15-
* predicates >, >=, <=, or, and, not,
16-
* functions atom, length, reverse, progn, load.
15+
* predicates >, >=, <=, not,
16+
* functions list, atom, length, reverse, progn, load.
1717

18-
This has the side effect of being much faster as well, since all these primitives are
19-
compiled instead of being interpreted.
18+
This has the side effect of being much faster as well, since all these primitives are compiled instead of being interpreted.
2019

2120
Among the bells and whistles, I've added a Read-Eval-Print-Loop (REPL) based on Justine Tunney (jart)'s bestline.
2221

@@ -86,9 +85,6 @@ The REPL also saves the history of commands in the file history.txt
8685
This file is loaded at startup, so one can recall previous commands.
8786

8887
Known bugs:
89-
* Operators "and" and "or" do not work like their typical Lisp counterpart
90-
because they evaluate all their operands at the same time instead of one
91-
by one. You may use the versions in the library.lisp file to correct this behavior.
9288
* recall of multiline commands does not work as expected.
9389
* this doesn't have tail call optimization, so expect crashes with sometimes with surprisingly short lists.
9490

@@ -180,16 +176,15 @@ car.
180176
(setcar cell 'x)
181177
cell ; -> (x . b)
182178

183-
`length` and `reverse` operate on a whole list or a string. They can also operate on their
184-
arguments when their number is > 1.
179+
`length` and `reverse` operate either on their arguments, or a single list or a string.
185180

186181
(length '(1 2 3)) ; -> 3
187182
(length 1 2 t) ; -> 3
188183
(length "1 2 3") ; -> 5
189184

190185
(reverse '(a b c)) ; -> (c b a)
191186
(reverse "1234") ; -> "4321"
192-
(reverse '((a) b "c") ; -> ("c" b (a))
187+
(reverse '((a) b "c")) ; -> (c b (a))
193188

194189
### Numeric operators
195190

@@ -223,26 +218,6 @@ the second.
223218

224219
The other numerical predicates `>`, `<=`, `>=` work in a similar fashion.
225220

226-
`and` takes two or more arguments, evaluates them, and returns the last argument
227-
that returns true, if all the arguments return true, or () otherwise.
228-
229-
(and 1 t 2) ; -> 2
230-
(and 1 t (- 3 4)) ; -> -1
231-
(and 1 () 2) ; -> ()
232-
(and) ; t
233-
234-
`or` takes two or more arguments, evaluates them, and returns the first argument
235-
that returns true.
236-
237-
(or 1 () 2) ; -> 1
238-
(or () ()) ; -> ()
239-
(or) ; -> ()
240-
241-
Nota Bene: because all the arguments are evaluated, `and` and `or` do not operate
242-
like their counterparts written in Lisp, as those stop evaluation at the first
243-
argument that returns. If the arguments have side effects, this may affect the
244-
program differently.
245-
246221
### Conditionals
247222

248223
`(if cond then else)` is the only conditional in the language. It first
@@ -277,7 +252,7 @@ contents but actually different are considered to not be the same by `eq`.
277252

278253
### String functions
279254

280-
`eq` compares two strings.
255+
`eq` can also compare two strings.
281256

282257
(eq "Hello" "Hello") ; -> t
283258
(eq "Hello" "hello") ; -> ()

examples/library.lisp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22
;; Simple library of useful functions and macros
33
;;
44

5-
(defun list (x . y)
6-
(cons x y))
7-
8-
(defmacro progn (expr . rest)
9-
(list (cons 'lambda (cons () (cons expr rest)))))
10-
115
;; (and e1 e2 ...)
126
;; => (if e1 (and e2 ...))
137
;; (and e1)

examples/life.lisp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
(load "examples/library.lisp")
66

7-
(define width 10)
8-
(define height 10)
7+
(define width 15)
8+
(define height 15)
99

1010
;; Returns location (x, y)'s element.
1111
(defun get (board x y)
@@ -44,24 +44,36 @@
4444
(or (= c 2) (= c 3))
4545
(= c 3))))
4646

47+
(define iter 1)
48+
(define idx_height (iota height))
49+
(define idx_width (iota width))
50+
4751
(defun run (board)
4852
(while t
4953
(print board)
50-
(println '*)
51-
(let newboard (map (iota height)
54+
(if (= iter 100)
55+
(exit 0)
56+
(setq iter (+ 1 iter)))
57+
(println iter)
58+
(let newboard (map idx_height
5259
(lambda (y)
53-
(map (iota width)
60+
(map idx_width
5461
(lambda (x)
5562
(if (next board x y) '@ '_)))))
5663
(setq board newboard))))
5764

58-
(run '((_ _ _ _ _ _ _ _ _ _)
59-
(_ _ _ _ _ _ _ _ _ _)
60-
(_ _ _ _ _ _ _ _ _ _)
61-
(_ _ _ _ _ _ _ _ _ _)
62-
(_ _ _ _ _ _ _ _ _ _)
63-
(_ _ _ _ _ _ _ _ _ _)
64-
(_ _ _ _ _ _ _ _ _ _)
65-
(_ @ @ @ _ _ _ _ _ _)
66-
(_ _ _ @ _ _ _ _ _ _)
67-
(_ _ @ _ _ _ _ _ _ _)))
65+
(run '((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
66+
(_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
67+
(_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
68+
(_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
69+
(_ _ _ _ _ _ _ _ @ _ _ _ _ _ _)
70+
(_ _ _ _ _ _ _ @ @ @ _ _ _ _ _)
71+
(_ _ _ _ @ @ _ @ @ _ _ _ _ _ _)
72+
(_ _ _ _ _ _ _ @ @ @ _ _ _ _ _)
73+
(_ _ _ _ _ _ _ _ @ _ _ _ _ _ _)
74+
(_ _ _ _ _ _ _ _ @ _ _ _ _ _ _)
75+
(_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
76+
(_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
77+
(_ @ @ @ _ _ _ _ _ _ _ _ _ _ _)
78+
(_ _ _ @ _ _ _ _ _ _ _ _ _ _ _)
79+
(_ _ @ _ _ _ _ _ _ _ _ _ _ _ _)))

src/minilisp.c

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,13 @@ static Obj *eval(void *root, Obj **env, Obj **obj) {
498498
// Primitive functions and special forms
499499
//======================================================================
500500

501+
// (list expr ...)
502+
static Obj *prim_list(void *root, Obj **env, Obj **list) {
503+
DEFINE1(root, values);
504+
*values = eval_list(root, env, list); // Evaluate all arguments
505+
return *values; // Return them as a list
506+
}
507+
501508
// 'expr
502509
static Obj *prim_quote(void *root, Obj **env, Obj **list) {
503510
if (length(*list) != 1)
@@ -694,26 +701,6 @@ static Obj *prim_not(void *root, Obj **env, Obj **list) {
694701
return values->car == Nil ? True : Nil;
695702
}
696703

697-
// (and ...)
698-
static Obj *prim_and(void *root, Obj **env, Obj **list) {
699-
Obj *car = True; // by default, return True if no args
700-
for (Obj *args = eval_list(root, env, list); args != Nil; args = args->cdr) {
701-
car = eval(root, env, &args->car);
702-
if (car == Nil) break;
703-
}
704-
return car;
705-
}
706-
707-
// (or ...)
708-
static Obj *prim_or(void *root, Obj **env, Obj **list) {
709-
Obj *car = Nil;
710-
for (Obj *args = eval_list(root, env, list); args != Nil; args = args->cdr) {
711-
car = eval(root, env, &args->car);
712-
if (car != Nil) break;
713-
}
714-
return car;
715-
}
716-
717704
extern void process_file(char *fname, Obj **env, Obj **expr);
718705

719706
static Obj *prim_load(void *root, Obj **env, Obj **list) {
@@ -1010,6 +997,7 @@ void process_file(char *fname, Obj **env, Obj **expr) {
1010997
}
1011998

1012999
static void define_primitives(void *root, Obj **env) {
1000+
add_primitive(root, env, "list", prim_list);
10131001
add_primitive(root, env, "quote", prim_quote);
10141002
add_primitive(root, env, "cons", prim_cons);
10151003
add_primitive(root, env, "car", prim_car);
@@ -1019,8 +1007,6 @@ static void define_primitives(void *root, Obj **env) {
10191007
add_primitive(root, env, "while", prim_while);
10201008
add_primitive(root, env, "gensym", prim_gensym);
10211009
add_primitive(root, env, "not", prim_not);
1022-
add_primitive(root, env, "and", prim_and);
1023-
add_primitive(root, env, "or", prim_or);
10241010
add_primitive(root, env, "+", prim_plus);
10251011
add_primitive(root, env, "-", prim_minus);
10261012
add_primitive(root, env, "*", prim_mult);

test.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,18 @@ run '<' t '(< 2 3)'
5252
run '<' '()' '(< 3 3)'
5353
run '<' '()' '(< 4 3)'
5454

55+
run list '(1 2 3 a b)' "(list 1 2 3 'a 'b)"
5556
run 'literal list' '(a b c)' "'(a b c)"
5657
run 'literal list' '(a b . c)' "'(a b . c)"
5758

59+
run reverse '(3 2 1)' '(reverse 1 2 3)'
60+
run reverse "(3 2 1)" "(reverse '(1 2 3))"
61+
run reverse "cba" '(reverse "abc")'
62+
63+
run length 5 '(length 1 2 3 4 5)'
64+
run length 5 "(length '(1 2 3 4 5))"
65+
run length 5 '(length "abcde")'
66+
5867
# List manipulation
5968
run cons "(a . b)" "(cons 'a 'b)"
6069
run cons "(a b c)" "(cons 'a (cons 'b (cons 'c ())))"

0 commit comments

Comments
 (0)