Skip to content

Commit e8f0b51

Browse files
committed
1.0 Release!
Added standard leeb ! Stdleeb contains a lot of the usual delicious Lisp functionality such as the various breeds of _fold_, _map_ and _filter_, _reduce_. As well as some true hotness in the form of _curry_ and _apply_. I've left off the pile of _cdddddr_ and _caaaadr_ functions for the time being.
1 parent 22f30e3 commit e8f0b51

File tree

5 files changed

+142
-37
lines changed

5 files changed

+142
-37
lines changed

README.md

+14-9
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,19 @@ car, cdr, and friends are there. As well as _cons_, _if_, _cond_, _case_, a whol
3434

3535
### UPDATES
3636

37-
- 01/11/2013 Added support for loading text files as source files and the following file functions:
38-
-- ```open-input-file```
39-
-- ```open-output-file```
40-
-- ```close-input-port```
41-
-- ```close-output-port```
42-
-- ```read```
43-
-- ```write```
44-
-- ```read-contents```
45-
-- ```read-all```
37+
- 01/11/2013 ADDED A STANDARD LIBRARY! OMG!! This was incredibly exciting. Now it really feels like a Lisp! (There is even closure support and everything. o.O). After pulling the cord on the REPL just run the following ```(load "leebs/stdleeb.leesp")``` or ```path/to/leeb/stdleeb.leesp``` and you should have everything in the stdleeb!
38+
- 01/11/2013 Added support for loading text files as source files and the following file functions:```open-input-file```, ```open-output-file```, ```close-input-port```, ```close-output-port```, ```read```, ```write```, ```read-contents```, ```read-all```.
4639
- 01/11/2013 Added the ability to create and store functions using ```define``` and ```lambda```.
4740
- 31/10/2013 Added persistent variables from scheme, namely: ```define``` and ```set!```.
41+
42+
## TODO
43+
44+
* Add concurrency and parallel processing primitives (__selfTodo__: read Hoare's CSP paper, Actor Model papers, learn more Erlang)
45+
* MACROS! Yeah that's right.. I went there.
46+
* add granular imports for leeb functionality (only, except)
47+
* try to implement more leebrary support (include, import, require)
48+
* add load process for REPL to include files (like stdleeb)
49+
* make it emit compilable code (ooooooo!)
50+
* clean up the core source
51+
* add support for comments. This is inexplicably annoying.
52+
* ~~add standard library~~

leebs/stdleeb.leesp

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
(define (not x) (if x #f #t))
2+
(define (null? obj) (if (eqv? obj '()) #t #f))
3+
(define (list . objs) objs)
4+
(define (id x) x)
5+
(define (curry func arg1) (lambda (arg) (func arg1 arg)))
6+
(define zero? (curry = 0))
7+
(define positive? (curry < 0))
8+
(define negative? (curry > 0))
9+
(define (odd? num) (= (mod num 2) 1))
10+
(define (even? num) (= (mod num 2) 0))
11+
12+
(define (flip func)
13+
(lambda (arg1 arg2)
14+
(func arg2 arg1)))
15+
16+
(define (compose f g)
17+
(lambda (arg)
18+
(f (g arg))))
19+
20+
(define (sum . lst)
21+
(fold + 0 lst))
22+
23+
(define (product . lst)
24+
(fold * 1 lst))
25+
26+
(define (and . lst)
27+
(fold && #t lst))
28+
29+
(define (or . lst)
30+
(fold || #f lst))
31+
32+
(define (max first . num-list)
33+
(fold
34+
(lambda (old new) (if (> old new) old new))
35+
first
36+
num-list))
37+
38+
(define (min first . num-list)
39+
(fold
40+
(lambda (old new) (if (< old new) old new))
41+
first
42+
num-list))
43+
44+
(define (length lst)
45+
(fold
46+
(lambda (x y) (+ x 1))
47+
0
48+
lst))
49+
50+
(define (reverse lst)
51+
(fold (flip cons) '() lst))
52+
53+
(define (mem-helper pred op)
54+
(lambda (acc next)
55+
(if (and (not acc)
56+
(pred (op next)))
57+
next
58+
acc)))
59+
60+
(define (memq obj lst)
61+
(fold (mem-helper (curry eq? obj) id) #f lst))
62+
63+
(define (memv obj lst)
64+
(fold (mem-helper (curry eqv? obj) id) #f lst))
65+
66+
(define (member obj lst)
67+
(fold (mem-helper (curry equal? obj) id) #f lst))
68+
69+
(define (assq obj alist)
70+
(fold (mem-helper (curry eqv? obj) car) #f alist))
71+
72+
(define (assv obj alist)
73+
(fold (mem-helper (curry eqv? obj) car) #f alist))
74+
75+
(define (assoc obj alist)
76+
(fold (mem-helper (curry equal? obj) car) #f alist))
77+
78+
(define (map func lst)
79+
(foldr (lambda (x y) (cons (func x) y)) '() lst))
80+
81+
(define (filter pred lst)
82+
(foldr (lambda (x y) (if (pred x) (cons x y) y)) '() lst))
83+
84+
(define (foldr func end lst)
85+
(if (null? lst)
86+
end
87+
(func (car lst) (foldr func end (cdr lst)))))
88+
89+
(define (foldl func accum lst)
90+
(if (null? lst)
91+
accum
92+
(foldl func (func accum (car lst)) (cdr lst))))
93+
94+
(define (unfold func init pred)
95+
(if (pred init)
96+
(cons init '())
97+
(cons init (unfold func (func init) pred))))
98+
99+
(define fold foldl)
100+
(define reduce fold)

src/leespparser.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ parseExpr = parseAtom
102102
<|> try parseCharacter
103103
<|> parseQuoted
104104
<|> do char '('
105-
x <- try parseList <|> parseDottedList
105+
x <- (try parseList) <|> parseDottedList
106106
char ')'
107107
return x
108108

src/leesptypes.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ showError (UnboundVar message varname) = message ++ ":" ++ varname
5353
showError (BadSpecialForm message form) = message ++ ":" ++ show form
5454
showError (NotFunction message func) = message ++ ":" ++ show func
5555
showError (NumArgs expected found) = "Expected " ++ show expected ++ " args: found values " ++ unWordsList found
56-
showError (TypeMismatch expected found) = "Invalid trype: expected " ++ expected ++ ", found " ++ show found
56+
showError (TypeMismatch expected found) = "Invalid type: expected " ++ expected ++ ", found " ++ show found
5757
showError (TypeMismatches expected found) = "Invalid type: expected " ++ expected ++ ", found " ++ unWordsList found
5858
showError (Parser parseErr) = "Parse error at " ++ show parseErr
5959
showError (Default message) = message
@@ -69,7 +69,7 @@ showVal (List contents) = "(" ++ unWordsList contents ++ ")"
6969
showVal (DottedList head tail) = "(" ++ unWordsList head ++ " . " ++ showVal tail ++ ")"
7070
showVal (Keyword kword) = kword
7171
showVal (PrimitiveFunc _) = "<PrimitiveFunc>"
72-
showVal (Func {params = args, vararg = varargs, body = body, closure = env}) =
72+
showVal (Func {params = args, vararg = varargs, body = body, closure = env}) =
7373
"(lambda (" ++ unwords (map show args) ++ (case varargs of
7474
Nothing -> ""
7575
Just arg -> " . " ++ arg) ++ ") ...)"

src/main.hs

+25-25
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,6 @@ readExpr = readOrThrow parseExpr
7070
readExprList :: String -> ThrowsError [LispVal]
7171
readExprList = readOrThrow (endBy parseExpr spaces)
7272

73-
--readExpr :: String -> ThrowsError LispVal
74-
--readExpr input = case parse parseExpr "lisp" input of
75-
-- Left err -> throwError $ Parser err
76-
-- Right val -> return val
77-
7873
apply :: LispVal -> [LispVal] -> IOThrowsError LispVal
7974
apply (PrimitiveFunc func) args = liftThrows $ func args
8075
apply (Func params varargs body closure) args =
@@ -83,7 +78,7 @@ apply (Func params varargs body closure) args =
8378
else (liftIO $ bindVars closure $ zip params args) >>= bindVarArgs varargs >>= evalBody
8479
where
8580
remainingArgs = drop (length params) args
86-
num = L.genericLength
81+
num = toInteger . length
8782
evalBody env = liftM last $ mapM (eval env) body
8883
bindVarArgs arg env = case arg of
8984
Just argName -> liftIO $ bindVars env [(argName, List $ remainingArgs)]
@@ -97,18 +92,22 @@ eval env val@(Bool _) = return val
9792
eval env val@(Character _) = return val
9893
eval env val@(Keyword _) = return val
9994
eval env (Atom id) = getVar env id
95+
-- Handled Quoting.
96+
eval env (List [Atom "quote", val]) = return val
10097
-- Load a file and eval the contents
10198
eval env (List [Atom "load", String filename]) =
10299
load filename >>= liftM last . mapM (eval env)
103-
-- Handled Quoting.
104-
eval env (List [Atom "quote", val]) = return val
105100
-- Flow Control Functions.
106-
eval env (List [Atom "if", pred, conseq, alt]) = myIfFun env pred conseq alt
107-
eval env (List (Atom "cond" : items)) = myCondFun env items
108-
eval env (List (Atom "case" : sel : choices)) =
101+
eval env (List [Atom "if", pred, conseq, alt]) =
102+
myIfFun env pred conseq alt
103+
eval env (List (Atom "cond" : items)) =
104+
myCondFun env items
105+
eval env (List (Atom "case" : sel : choices)) =
109106
eval env sel >>= myCaseFun env choices
110-
eval env (List [Atom "set!", Atom var, form]) = eval env form >>= setVar env var
111-
eval env (List [Atom "define", Atom var, form])= eval env form >>= defineVar env var
107+
eval env (List [Atom "set!", Atom var, form]) =
108+
eval env form >>= setVar env var
109+
eval env (List [Atom "define", Atom var, form]) =
110+
eval env form >>= defineVar env var
112111
eval env (List (Atom "define" : List (Atom var : params) : body)) =
113112
makeNormalFunc env params body >>= defineVar env var
114113
eval env (List (Atom "define" : DottedList (Atom var : params) varargs : body)) =
@@ -124,7 +123,7 @@ eval env (List (function : args)) = do
124123
argVals <- mapM (eval env) args
125124
apply func argVals
126125
-- Yer done gone f**ked up.
127-
eval env badForm =
126+
eval env badForm =
128127
throwError $ BadSpecialForm "Unrecognised special form" badForm
129128

130129
myCaseFun :: Env -> [LispVal] -> LispVal -> IOThrowsError LispVal
@@ -160,14 +159,15 @@ myCondFun env (pred:conseq:rest) = do
160159
otherwise -> liftThrows . throwError $ TypeMismatch "boolean" pred
161160

162161
primitives :: [(String, [LispVal] -> ThrowsError LispVal)]
163-
primitives = [("+", numericBinop (+)),
162+
primitives =
164163
-- Basic Maths Functions
165-
("-", numericBinop (-)),
166-
("*", numericBinop (*)),
167-
("/", numericBinop div),
168-
("mod", numericBinop mod),
169-
("quotient", numericBinop quot),
170-
("remainder", numericBinop rem),
164+
[("+", numericBinop (+)),
165+
("-", numericBinop (-)),
166+
("*", numericBinop (*)),
167+
("/", numericBinop div),
168+
("mod", numericBinop mod),
169+
("quotient", numericBinop quot),
170+
("remainder", numericBinop rem),
171171
-- Comparison Functions
172172
("=", numBoolBinop (==)),
173173
("<", numBoolBinop (<)),
@@ -252,9 +252,9 @@ stringLength badArgList = throwError $ NumArgs 1 badArgList
252252

253253
makeStringN :: [LispVal] -> ThrowsError LispVal
254254
makeStringN [Number n, Character c] = (return . String . L.genericTake n) $ repeat c
255-
makeStringN [Number n, _] = (return . String . L.genericTake n) ['a'..]
256-
makeStringN [bad, _] = throwError $ TypeMismatch "number [char]" bad
257-
makeStringN badArgList = throwError $ NumArgs 1 badArgList
255+
makeStringN [Number n, _] = (return . String . L.genericTake n) ['a'..]
256+
makeStringN [bad, _] = throwError $ TypeMismatch "number [char]" bad
257+
makeStringN badArgList = throwError $ NumArgs 1 badArgList
258258

259259
numericBinop :: (Integer -> Integer -> Integer) -> [LispVal] -> ThrowsError LispVal
260260
numericBinop op singleVal@[_] = throwError $ NumArgs 2 singleVal
@@ -311,7 +311,7 @@ eqv [Number arg1, Number arg2] = return $ Bool $ arg1 == arg2
311311
eqv [String arg1, String arg2] = return $ Bool $ arg1 == arg2
312312
eqv [Atom arg1, Atom arg2] = return $ Bool $ arg1 == arg2
313313
eqv [DottedList xs x, DottedList ys y] = eqv [List $ xs ++ [x], List $ ys ++ [y]]
314-
eqv [List arg1, List arg2] = return
314+
eqv [List arg1, List arg2] = return
315315
$ Bool
316316
$ (length arg1 == length arg2) && and (zipWith (curry eqvPair) arg1 arg2)
317317
where

0 commit comments

Comments
 (0)