Decided to write down some ideas about z-talk.
Z-talk is, of course, a lisp. It's lisp-1. It will support traditional CL-style macros as well as first-class continuations. It will be much like PG's Arc and Clojure but differ in that it will not compile for JVM and will not use Racket (mzscheme) which will make it very lightweight much like Scheme48. But it will differ from Scheme48 in that it will support CL-style macros and will not require any top-level declarations that are inspected in compile time. It will support automatic compilation and storing byte-code cache much like in Python.
I've been back and forth on the question of what to implement z-talk in and now I think C++ (mostly plain C) will do just fine. Another option that is very attractive is to use PreScheme compiler... You know what? I just changed my mind back again. PreScheme is very small, easy to use and seems much more powerful than C++ or C. OK, back to PreScheme! Stick to it!
Anyway z-talk will compile to byte-code. Compilation unit is one expression (not one file). Conses, vectors and strings are mutable. But I'm thinking about making variable bindings to be fixed forever. This might greatly simplify the implementation of environment structures and allow inlining procedures. Users will be advised to use mutable boxes (or cells, whatever the name) to modify lexically bound values. But I'm still not sure about that.
Values in z-talk are ether immediate or non-immediate. Immediate values are represented by single machine word exactly as in Chicken scheme. But there are fewer types of them in z-talk: fixnums, characters and nil. Nil is of its own type and is not a symbol. There is however symbol nil bound to nil value. Lists are terminated by nil. No boolean type. Nil is false, any other value is true.
Non-immediate values are pointers to the objects stored in blocks. There is a separate list of blocks for each object type. Blocks are aligned so that it is easy to find the beginning of a block by dropping the last few bits in a pointer to an object. This is to avoid storing the type tags in every object. Type tag is stored in the header of each block instead.
Small objects of fixed size are stored just like that. Memory is allocated from a singly-linked lists of free cells.
Objects of variable size are stored differently. Vectors are referenced by descriptors very much like in STL vectors in C++. Descriptors are stored the same way as any other small fixed-sized objects. Strings are much like vectors. Symbols are unique in that all equal symbols are just pointers to the same location. Still haven't decided what is the best layout scheme for symbols but here is one important constraint: it must be easy to look them up by the representation. So they must be arranged in some kind of hash.