[9th August 2008]
So I've been playing with the Eden library again, and I finished putting in some very cool functionality while watching China put on a phenomenal show for the Olympic Games Opening Ceremony...
Eden now supports cons
! So we can build and return lists now, such as the following examples:
(cons 'maple' (list 'birch' 'oak' 'larch')) => ('maple' 'birch' 'oak' 'larch')
(list 'maple' (list 'birch' 'oak' 'larch')) => ('maple' ('birch' 'oak' 'larch'))
Date
is now a first class atom-type, so we can do things like:
(defun next_sunday (x? f?)
(prog
(setq d (if (nil-p x) today x))
(date (+ d (- 7 (day_of_week d))) f)))
To make the programmer's life easier, we also supports optional arguments to defun
! To designate the formal parameter as optional, append it with a question mark. All formal parameters after the first optional one are implicitly optional. If no argument is bound to an optional parameter, it is initialised with nil
.
Of course, +
now handles dates and time-spans :)
[Ten days later]
OK. cons
works, as do car
, cdr
and all the test functions like listp
(which has an alias, a-la Scheme, of list?
), atom?
and nil?
.
I've spent the last few days re-implementing the evaluation engine to dynamically support new native functions using reflection and cleaning up various odd-bits (yes, I was watching the Olympic Games and it did reduce my productivity a bit).
(defun make-list (x)
(cond
((list? x) x)
(t (cons x nil))))
(defun append (l x)
(cond
((atom? l) (cons l (make-list x)))
((nil? l) (make-list x))
(t (cons (car l) (append (cdr l) x)))
))
(defun reverse (l)
(cond
((nil? l) l)
((atom? l) nil)
((list? (car l)) (append (reverse (cdr l)) (list (reverse (car l)))))
(t
(append (reverse (cdr l)) (car l))
)
))
allows us to call
(reverse (list 'a' 'b' (list 'c' 'd') 'e' 'f'))
, which returns with (f e (d c) b a)
as we expect!
In addition to optional parameters, easy-to-integrate native functions, properly stacked evaluation of (mutually) recursive functions, scoped parameters and variables, and multiple-statement defun definitions, we have all the makings of a full-blown, yet neat and compact LISP interpreter!
Next, I think I'll get it to support lambdas and mapcar!
While I'm at it, let me stress on the importance of writing unit tests, specially while developing foundational pieces like this one.
I've been using the native testing framework in Visual Studio 2008, and it's a breeze to be able to run off a whole suite of tests to make sure that a fix I put in for one bug didn't break something else somewhere.
Furthermore, as the tests get more and more complex and involved, it's comforting to know that the system is just growing stronger every time a feature gets added without anything being broken! I now have over 200 test expressions which are run after every major recompile, assuring that all the functionality is working as it should be...
Stay tuned!