#author Matthias Benkard #date 2008-06-14 - (format-time-string "%Y-%m-%d") #title Toilet Lisp Development Diary #desc Random news and stuff about just another random pet project ; Time-stamp: <2008-08-11 02:35:35 mulk> ; ; C-c i t insert-time-stamp ; C-c C-t muse-project-publish-this-file ; C-c C-e muse-edit-link-at-point ; C-c C-i muse-insert-thing ---- Context: [[http://matthias.benkard.de/toilet][The Toilet Lisp Project]]. ---- * 2008-10-02, 16:38:15 CEST ** Multiple-Value Returns Multiple-value returns are now implemented in the most C-friendly way that I can imagine. The way they work is: - Every compiled function gets an additional argument that points to a cell which the caller has allocated. The cell may be set to point to a list (i.e., either =nil= or an instance of =MLKCons=) by the callee, in which case the caller will use the list as the list of return values. - The argument that points to the return value list cell may be =NULL=, in which case the callee must assume a single-return convention. - Return-value setting may be delegated to a subform by simply passing the pointer on. - The compiler always passes =NULL= as the list pointer when it neither uses nor delegates the return values. - The compiler occasionally sets the =llvm:Value= that represents the list pointer to =NULL=. It thereby communicates to itself that no multiple-return value handling is needed in the current lexical context. This should speed some things up. - A function implemented in C may choose to simply ignore the list pointer. Similarly, it may choose to always pass a list pointer of =NULL= to callees if it does not care about return values other than the primary one. - A function that does not return multiple values simply ignores the list pointer, which is guaranteed to contain a value that the caller can identify as signifying that no multiple-value return has occurred. In the current implementation, this role is filled by the =MLKEndOfArgumentsMarker=. - Regardless of multiple-value returns happening or not, the primary value of a function call is always its normal return value. When there is no primary value, =nil= is to be used. * 2008-08-11, 02:09:21 CEST ** Function Calling, 2nd Take More thoughts: - Fat pointers are =MLKClosure= instances. =(funcall x a b c)= is compiled into: %tmp1 = x->code %tmp2 = x->closure_data_pointer tail call %tmp1 (%tmp2, a, b, c) Of course, the =code= and =closure_data_pointer= ivar offsets have to be known in advance, but that should be doable. - Contrary to what I said earlier, I now think it should be possible to not always require the use of varargs. Simply accept one more argument than we really expect, then look for the end-of-arguments marker in the supplied arguments. If it's there, determine whether it's in an expected place (i.e. not at a position that a required argument was expected at), if not, signal an error. - It should also be possible to skip argument list checking entirely, either by providing another thread-local flag or by putting the same =BasicBlock= into two different functions so that there are two entry points (a safe one and an unsafe one). - **lambda** is just as dumb as **flet**: Neither operator causes an =MLKClosure= object to be created at runtime. Both yield two values upon compilation: a =Value*= that contains the closure data value at runtime (i.e. the first argument of the function to call) and a code pointer. Now, where do =MLKClosure= objects come from, then? Easy: **function** is the one that creates them from all that information. * 2008-08-06, 11:08:30 CEST ** Function Calling I'm pondering function call conventions. My current design looks like this: *** Entry Points - For each function, provide two distinct entry points: a trampoline for use by C code and the “direct” entry point. - The direct entry point requires supplying the closure variable vector to be passed explicitly as the first argument, while the trampoline doesn't. - The trampoline uses the normal C calling convention. The direct entry point may use a different one (it's not clear to me that LLVM allows such, though). *** Arguments - All functions are varargs, because there is no other way to ensure the safety of passing more arguments than are expected. Should we provide yet a third entry point for unsafe code? - There is a thread-local global variable that controls the use of multiple value returns. The caller sets it to 1 if they want to have multiple values returned to them. In this case, the callee immediately sets the variable to 0 again and before returning either arranges for the thread-local variable to contain a pointer to a vector of values (along with their number or an end-of-vector marker, of course) or it leaves it as 0 if there is exactly one return value. The caller is responsible for freeing the memory used by the return vector. *** Return Values - (multiple-value-call ... (values ...)) is handled specially by the compiler, because (values ...) isn't a function call. *** Foreign Functions - C functions may simply be placed in the global environment as-is as long as they only take =id= arguments and return a single id value. - Other C functions are wrapped in a Lisp-to-C trampoline that does the needed conversions of arguments and return values. * 2008-08-02, 13:46:14 CEST ** Exception Handling Crashes on Debian Systems On Debian systems using the ffcall-compiled GNUstep Base libraries from the **libgnustep-base1.16** package, an exception raised from within a method called by way of an **NSInvocation** object causes the Objective-C runtime to crash with a **SIGABRT** by calling **abort()** from **objc_exception_throw()**. Installing **libgnustep-base1.16-libffi** (which diverts the shared libraries installed by **libgnustep-base1.16**) or compiling your own custom version of GNUstep Base fixes the problem. I have reported this bug as [[http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=493250][#493250]]. So if Toilet Lisp crashes when you type =(send 'a "isEqualToString:" 'b)= at the REPL, please consider switching GNUstep Base installations. =sudo apt-get install libgnustep-base1.16-libffi= should do the trick. * 2008-07-27, 16:51:13 CEST ** DESTRUCTURING-BIND and DEFUN and DEFMACRO, Oh My! We've now got **defun** and **defmacro** in all their lambda-list destructuring glory. Finally! So yeah, they're missing a bit of error handling here and there when parsing lambda lists. Too permissive to be conforming. But hey, at least your missing arguments will merely be =nil= instead of crashing the interpreter (the hard way, I mean, not by catchable exceptions). Isn't that an improvement? * 2008-06-14, 16:41:55 CEST ** Another Random Piece of Vaporware is Born Here I go again, starting yet another little pet software project whose chance of surviving for more than a few months is limited, but hey, it'd not be me if I didn't start bragging about it before having written even a single line of code, right? So here we go! I intend Mulklisp (which is obviously a preliminary, WebShaka-style proto-name) to become a Lisp compiler for the Étoilé runtime (and maybe Mac OS X as well, but that's of a lower priority) with the following features: - A proper subset of ANSI Common Lisp, with an eye towards full ANSI compliance in the far future. - CFFI support. - Lexical **and** dynamic scoping. - Integration with the Étoilé object system. - DEFMACRO. - Hygienic macros by way of Explicit Renaming and Syntactic Closures. - Read macros. (?) - TAGBODY and GO. (?) - CATCH and THROW. (?) - Places (that is, SETF). - A package system. - Arrays and hash tables compatible with their Common Lisp counterparts, but based on the Étoilé/GNUstep ones. - Direct compilation to Étoilé runtime code (as with Étoilé Smalltalk). - A REPL. - Conditions and restarts. - Multiple namespaces. - Bignums and rationals. - JIT and explicit compilation (COMPILE) via LLVM. (?) - Optional static typing with Cells-based/Hindley-Milner/whatever type inference. (?) Well, that's what I'm dreaming of. At least now you have something new to joke about in place of Duke Nukem Forever (which is coming out Practically Tomorrow! Preorder today!). Maybe I ought to change my nickname from Kompottkin to Master Vaporware. ---- *Matthias Benkard, (format-time-string "%Y-%m-%d, %k:%M %Z")* http://matthias.benkard.de/ ; Local Variables: ; mode: muse ; End: