ulisp icon indicating copy to clipboard operation
ulisp copied to clipboard

External features tutorial

Open dragoncoder047 opened this issue 2 years ago • 12 comments

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...

dragoncoder047 avatar Jul 06 '23 17:07 dragoncoder047

Great! Is it OK if I put it on the uLisp Forum?

technoblogy avatar Jul 06 '23 18:07 technoblogy

Is it OK if I put it on the uLisp Forum?

Sure!! Go right ahead.

dragoncoder047 avatar Jul 06 '23 18:07 dragoncoder047

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:

Position of the star when declaring C pointers

technoblogy avatar Jul 14 '23 11:07 technoblogy

Mentioned on the forum here:

uLisp extensions add catch, throw, and backquote

technoblogy avatar Jul 14 '23 11:07 technoblogy

Just updated the page for the macro support, since it now appears to work.

dragoncoder047 avatar Dec 22 '23 17:12 dragoncoder047

What's the simplest way for me to download the version of uLisp with your macro support, so I can try it out?

technoblogy avatar Dec 24 '23 13:12 technoblogy

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!

dragoncoder047 avatar Dec 25 '23 02:12 dragoncoder047

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?

technoblogy avatar Jan 03 '24 18:01 technoblogy

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?

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.

dragoncoder047 avatar Jan 03 '24 20:01 dragoncoder047

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.

dragoncoder047 avatar Jan 03 '24 22:01 dragoncoder047

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?

technoblogy avatar Jan 04 '24 19:01 technoblogy

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.

dragoncoder047 avatar Jan 04 '24 19:01 dragoncoder047