c-mera
c-mera copied to clipboard
Macro weirdness issue
I'm not sure that an issue tracker is the appropriate place to ask this, but I do understand it's a convenient place for you.
I'm having trouble figuring what is going on here (I've hacked this out of my larger code base to try and get rid of stuff that should be irrelevant):
(defmacro decl% ((&rest bindings) &body body)
`(if true
(decl (,@bindings)
,@body)))
;#+nil
(defmacro with-unsuccessful-cleanup (cleanup &body protected)
(let ((label (gensym "CLEANUP_"))
(result (gensym "RESULT-")))
`(decl% ((int ,result = 0))
(macrolet ((return (value)
(let ((result ',result)
(label ',label))
`(progn
(= ,result ,value)
(goto ,label)))))
,@protected)
(label ,label)
(when (< ,result 0)
,cleanup)
(return ,result))))
(function add-connection ((struct identity* id))
-> int
(with-unsuccessful-cleanup
(free node)
(with-unsuccessful-cleanup
(fclose (pref node stream))
(move-identity (& (pref node id))
id)
(return 0))))
If I run cm c++
then I get the following output (and no C++ output):
cm c++ test.lisp
;Compiler warnings :
; In an anonymous lambda form: Undefined function move-identity
; In an anonymous lambda form: Undeclared free variable id
Unbound variable: id
The message makes it sound like sbcl is expecting to be able to invoke move-identity
, but that shouldn't be the case, surely?
If you delete the semi-colon on line 9 (to neuter with-unsuccessful-cleanup
) then it stops complaining.
Thats a little tricky:
Calls to undefined/unknown functions, that shall yield a call in the resulting/generated code can only be captured correctly inside a c-mera-function-body (function
, decl
, progn
, ...), but not inside a lisp-function-body (macrolet
..)
Therefore, we need a extra progn
inside the macrolet.
(c-mera's progn
generates a block of statements where unkown functions are captured and passed to the generated code as function-calls, in contrast to lisp's progn
that returns the last element)
The following adjustment should do the trick:
(defmacro with-unsuccessful-cleanup (cleanup &body protected)
(let ((label (gensym "CLEANUP_"))
(result (gensym "RESULT-")))
`(decl% ((int ,result = 0))
(macrolet ((return (value)
(let ((result ',result)
(label ',label))
`(progn
(= ,result ,value)
(goto ,label)))))
(progn ,@protected))
(label ,label)
(when (< ,result 0)
,cleanup)
(return ,result))))
I think you are now hitting the things that would make a README file into a manual :)
We are actually working on something like that, but are swamped right now so progress is slow. That's also the reason I prefer having those discussions here where we can easily find them again :)