One technique in C for mapping incompatible pointer or alignment sizes
(for when you can't, or don't want to, convert directly between
pointer and `intptr_t`) is to use an intermediate array, and instead
of storing native pointers, store indexes into this array.

For your case you could put all the native functions in a C array, and
expose them to miniPicoLisp by taking the index in this array and
shifting it up by miniPicoLisp's _assumed_ alignment, to make space
for the tag bits (which becomes a "virtual" alignment with no special
connection to the C implementation). To dereference the mPL reference
to a native function, shift the tag bits away again, and look up the
function pointer at that index in the intermediate array.

While this does also impose a size cost, it doesn't impose that cost
on all Lisp-side objects the way changing the cell structure would,
only on native functions (or, on any other C-side object you wanted to
do this for), which will probably (hopefully?) only make up a very
small minority of the objects a Lisp program wants to manipulate, and
is also a constant-sized container in most programs. The shift and
indirection instead of no-op conversion from integer to callable
pointer introduces a runtime cost, but it wouldn't be all that high.

This is one way to simulate C function pointers on targets that don't
expose function pointers in a directly-convertible way at all (e.g.
JVM).

Using indices instead of native pointers generalizes to any object
kind for similar costs, e.g. you can translate a 16-bit Lisp word size
for a 64-bit C host program by doing the same thing for cells in
general, if you really want. One interesting consequence of this is
that if you put different base cell types into different heap arrays,
you get a reinterpretation of the tag bits as a heap-selection index
for different types, instead of as sub-cell pointers. This starts to
become a completely different model from picoLisp's very simple and
elegant word-offset manipulation, though (almost the exact opposite).

Whereas _limiting_ the idea to function pointers has the advantage
that since a function pointer is strictly supposed to be "opaque"
anyway from the C perspective - it's not data, it's not expected to be
accessible as data, the pointer's value isn't meaningful in
object/size/etc. terms, only as an identity - you don't fundamentally
change the meaning of the interpreter model on the C side, you just
change the cast operation from a no-op to an actual conversion. The
rest of the picoLisp word manipulation system remains untouched,
keeping the pointer adjustment concept and the homogeneous heap.

AlexG


On 27/08/2020, Alexander Burger <a...@software-lab.de> wrote:
> On Wed, Aug 26, 2020 at 11:16:48PM -0700, C K Kashyap wrote:
>> About why I am trying it - it's primarily just a learning exercise for
>> me.
>> What I am trying is expanding the cell to 4 words instead of two and use
>> the extra words as the meta data and not require tagged pointers. This
>> way
>
> I see.
>
>> I could even build it with TCC that does not seem to align functions at 4
>> byte boundary.
>
> OK, function pointer alignment is a different issue. You can however encode
> the
> pointer in different ways. Some versions of PicoLisp shift'ed and or'ed it.
>
>
>> Sorry if I am missing something, but wouldn't x-1 result in shifting the
>> pointer by 8 bytes instead of 4 (since size of cell is 8). Which is
>> probably why cdr is used instead of car?
>
> Yes. x-1 is minus 8 bytes, and the cdr adds 4 bytes. So the physical access
> goes
> to -4.
>
> ☺/ A!ex
>
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>

--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to