Hi Jason,

thanks a lot for your long post!

> '(struct ...)' can guess C native structure alignment wrong:
> ...
> So, please ammend 'struct' et al to get this
> alignment right.

I think we have a misunderstanding here. The 'struct' function does not "guess"
anything. It does not even have the slightest idea about how the structure on
the C level looks like.

'native' and 'struct' are completely generic. It is the programmer who must pass
all information about the sizes, layout and alignments of C data structures.
Otherwise, they would need to parse all involved include files, with relevant
environment definitions and constants properly set up.

All arguments to 'native' and 'struct' are elements of well-defined bit-sizes,
not nebulous types like 'int' which may have a different number of bits
depending on platform and C-compiler. The same holds for alignments of course,
which may depend on the optimization level the called library was compiled in.

Thus, the programmer or some frontend needs to find out these things for his
platform, and pass the right values. And an alignment is nothing more than a few
inserted bytes.

In fact, there is a rudimentary mechanism for this in the PicoLisp release.
It is the 'sysdefs' function

   https://software-lab.de/doc/refS.html#sysdefs

and the related @src/sysdefs.c and @lib/sysdefs files. It is used, for example,
in the system networking library @lib/net.l to acces network structures like
'sockaddr_in6' in a portable way.

The trick is to pass the task to the system C compiler via @src/sysdefs.c, and
this can also be done for other system-dependent parts. Also, there is probably
no other way, as only a C compiler can preprocess all defines and includes to
determine the right values.


> Since PicoLisp seems to be a mainly Linux-centric implementation,

I would not say so. PicoLisp is not specially aware of Linux, it just needs a
POSIX system.


> And why does 'struct, when given
> the full structure description and
> a list of arguments, insist on
> those argments being cons pairs
> of ( val size ) , when it already
> knows what the size MUST be from
> the structure description?

Hmm, I'm not sure what you mean. There is no redundancy, and no full structure
description. You can alway access only a part of a larger memory area.

'struct' expects a "result specification" (second argument), which has no total
size, but is a single atom or (recursively) a list of result specifications.
These may be cons pairs like (N . 4), but the 4 is no size but a count
(long[4]).

Or are you talking of 'native'? This does indeed take a total size, necessary
before any processing of the argument, to allow allocation of a local buffer. Or
do you want 'native' to traverse the whole list at *runtime* every time, just to
determine the size? So this size must be just large enough. No problem if it is
larger than the structure size.


> Also, lack of support for UNSIGNED integers
> of size < P (pointer) is a pain!
>
> Please support 'U (unsigned int) and 'H
> (unsigned short) atom types !

Unsiged numbers are fairly trivial to convert. Just ADD the base to the number
and and AND it with (base-1).

   (de unsigned (N)
      (& `(dec (** 2 32)) (+ N `(** 2 32))) )

This gives, after having been 'read':

   (de unsigned (N)
      (& 4294967295 (+ N 4294967296)) )


I want to keep some limit to the number of key-symbols supported by 'native'.
Keep in mind that all this is interpreted at runtime, and each new 'case' or
'if' slows it down!


> Also '(native) should be augmented to handle
> function parameters which are registers,

How do you mean that? Depending on the ABI of the runtime platform, the first
few arguments are *always* passed in registers, the rest on the stack.


> Also what about 128-bit integers ( __{,u}int128 ) ?
> and long doubles?


128-bit integers are also wasteful to be built-in. If really needed, just fetch
two 64-bit values, and SHIFT and OR them.

Tenbyte floats are a valid feature, and more difficult to emulate (though not
impossible, by accessing the mantissa and exponent separately). But they are
normally used for *intermediati* results, not as function arguments or structure
elements (again: alignment problems). So here too, I would not waste
runtime resources on them.


> PicoLisp is so far in advance of most alternatives, I'd really like
> to continue using it in projects,  but unless I can get this
> structure member alignment issue sorted easily,

Yes, but as I wrote above, this should (and can)not be done by 'native' and
'struct'. They are just the internal workhorses to interface to the
C-libraries. Think about extending the 'sysdef' principles.


> Thanks for PicoLisp, which is otherwise excellent, but yet
> can still be improved !

Very true! This is always possible and necessary :)

☺/ A!ex


P.S.

  : (eval (append (list 'struct 'Ptr  ''(B . 32)) (C~carsz '(( B . 32 )) (need 
32 0))))

Off topic, but note that calling 'eval' on a temporarily built list should never
be necessary in such situations. It is a waste to build a list only to execute
it once. More lispy is 'apply' or 'pass'. The above expression would be
something like:

   : (apply struct (C~carsz '((B . 32)) (need 32 0)) Ptr '(B . 32))

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

Reply via email to