It seems that "any" is a typedef for a variable length array, which C
compilers often refuse to support.  Some C compilers are more permissive
regarding variable length arrays; gcc, for example, is more permissive.
Emscripten (or clang/llvm) is, apparently, not.

The normal thing to do, when encountering this problem, is to replace the
variable length arrays with pointers.  As in "char foo[]" -> "char * foo".
In Java that would be a lossy transformation (it would lose the length
information), but C doesn't expose the length of a variable-length array as
a runtime-accessible value (because of which, the language permits, but
does not require, compilers to collapse variable-length arrays into
pointers).  The upshot is that C code using variable-length arrays can
always be collapsed into code using pointers without loss.  (Said another
way, working C code which used variable-length arrays had to track the
length separately, often by using 0-termination.)

For a LISP VM, for specifically the case of the root type of the VM, it
might make more sense (than making "any" a typedef for "void *") to make
"any" a typedef for a tagged union along the lines of:

typedef union {
  char c;
  short s;
  int i;
  long l;
  float f;
  double d;
  void *h;
  void (*t)();
  env_type e;
  pair_type p;
  vec_type v;
} all_builtin_types_type;

typedef struct {
  tag_type tag;
  all_builtin_types_type value;
} any;

(Then one writes code like "switch (thing.tag) { case CHAR_TYPE_CODE:
frob_c(thing.value.c); break; case SHORT_TYPE_CODE: frob_s(thing.value.s);
break; ...}".)

..albeit, the normal thing in Lisp VMs is to steal tag bits from the
values themselves, rather than dedicate auxiliary bytes to storing run-time
type info.

Either way, one builds up a layer of macros so that code which accesses the
type tags isn't too aware of the precise representation, i.e., something
like "switch (get_tag(thing)) { case CHAR_TYPE_CODE:
frob_c(untag_c(thing)); ... }".

The downside of the union approach is that, for example, statically
allocating "any foo[100]" will allocate 100 *
sizeof(<largest_builtin_type>), which, for characters, would represent an
at-least 8 times constant-factor overhead.  If one doesn't use C's type
system to help you manage types, but rather roll your own, then it won't be
possible to statically allocate "any foo[100];" (at least, not by using
such simple syntax) --- but it will be possible to ensure that 100
instances of a builtin referred to by an "any" take up exactly as much
space as 100 instances of that builtin + tag bits for the array type + tag
bits for the element type.

If the Picolisp implementation is already that internally complicated, then
the easiest way forward to get emscripten to work is one of:
  (1) make  "any" a typedef for a "void *" (or "char *" if you want to
lessen the amount of type-casting needed), or,
  (2) make "any" a typedef for a "char" and change all of the formal
parameter lists to pass "any *" rather than "any".

Probably the first is what will work, but if the code uses "sizeof(any)",
then something like the second may be needed in order to achieve the
desired effect (to wit, don't use 8 bytes to store an ASCII character).


On Sun, May 11, 2014 at 8:31 AM, Christophe Gragnic <> wrote:

> On Fri, May 9, 2014 at 7:59 PM, Rick Lyman <> wrote:
> > below are a few of the errors generated [compiling miniPicoLisp with
> emscripten]:
> >
> > flow.c:41:62: warning: '&&' within '||' [-Wlogical-op-parentheses]
> >    if (isNum(x = EVAL(x)) || isNil(x) || x == T || isCell(x) &&
> > isNum(car(x)))
> >                                                 ~~
> > ~~~~~~~~~~^~~~~~~~~~~~~~~~
> > flow.c:41:62: note: place parentheses around the '&&' expression to
> silence
> > this
> >
> >       warning
> >    if (isNum(x = EVAL(x)) || isNil(x) || x == T || isCell(x) &&
> > isNum(car(x)))
> >
> > ~~~~~~~~~~^~~~~~~~~~~~~~~~
> > flow.c:60:37: error: fields must have a constant size: 'variable length
> > array in
> >
> >       structure' extension will never be supported
> >          struct {any sym; any val;} bnd[length(x)];
> >                                     ^
> > flow.c:77:18: warning: using the result of an assignment as a condition
> > without
> >       parentheses [-Wparentheses]
> >       } while (p = p->link);
> >                ~~^~~~~~~~~
> I investigated a bit, with my very limited C knowledge.
> Parens are (very) easy to fix, but the Ā«fields must have a constant sizeĀ»
> leaves me clueless, even after dozens of minutes googling.
> chri
> --
> (site pro)
> (liens, favoris)
> --

Reply via email to