External features tutorial
I put together a couple guides for some of the extensive features that I added to my uLisp fork. Currently the ones there are for (catch)/(throw) and backquotes, which both are confirmed to work. I do have code for macros, but I haven't tested it yet, so no guide until I do that.
https://dragoncoder047.github.io/pages/ulisp_howto.html
Share it around if it would be any interest to the uLisp community...
Great! Is it OK if I put it on the uLisp Forum?
Is it OK if I put it on the uLisp Forum?
Sure!! Go right ahead.
Interested to see your point here:
I put the asterisk in pointer types next to the base type (e.g. object* foo) instead of next to the variable (e.g. object *foo) because the variable represents a pointer type in and of itself, and is not just a pointer to an instance of a base type.
The following article summarises the reason why I've adopted the opposite convention:
Just updated the page for the macro support, since it now appears to work.
What's the simplest way for me to download the version of uLisp with your macro support, so I can try it out?
Best option is probably to git clone my repository... it compiles for me. I do think I have the ESP32Servo library installed to provide non-dummy definition for tone() and analogWrite(), so you should get that installed.
...Merry Christmas!
I've got your version of ESP32 uLisp to compile, and I've been trying it out on some macros.
I'm impressed that most things work well, and you've even implemented macroexpand, macroexpand-1, and gensym.
The only thing that didn't quite work was:
(defmacro while (test &body body)
`(loop
(unless ,test (return))
,@body))
> (let ((x 3)) (while (plusp (decf x)) (print x)))
Error: too few arguments
Not sure why. Any ideas?
The only thing that didn't quite work was:
(defmacro while (test &body body) `(loop (unless ,test (return)) ,@body)) > (let ((x 3)) (while (plusp (decf x)) (print x))) Error: too few argumentsNot sure why. Any ideas?
I didn't implement &body, you have to use &rest. None of the fancy macro &XXX things are in because I just used closure() to handle the lambda body.
you've even implemented ... gensym.
I should note that gensym is in the extensions.hpp file, not the main ulisp.hpp file, since it doesn't require editing the ulisp engine. There is also intern there too.
Your implementation of macros works really well - I'm impressed. One of the things that put me off trying to add macros to uLisp was that I read somewhere that to add macros to Lisp you need to write a Lisp code walker. I assume somehow you've achieved it without doing that. Perhaps I misunderstood that original comment – any idea about that?
Well, the way it "walks" the code and expands macros is that it just macroexpand()'s the code before eval gets to evaluating it. macroexpand() in turn calls eval() (by way of closure()) on the macro body, which then ends up macroexpand()ing the nested macros. It's recursive and quite stupid, and doesn't do any TCO, so I added a "C stack overflow" error detector to protect against a crash.