diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-12-06 06:17:45 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-12-06 06:17:45 -0800 |
commit | f018af6fe6b0c867c747217890b8b02d8e6d7ffb (patch) | |
tree | 9b52ade1de02c1420f3858fa1c32d70b6bbc0eaa /ffi.c | |
parent | 45412f6aef55df4f83f54b2b5445f673bfeee691 (diff) | |
download | txr-f018af6fe6b0c867c747217890b8b02d8e6d7ffb.tar.gz txr-f018af6fe6b0c867c747217890b8b02d8e6d7ffb.tar.bz2 txr-f018af6fe6b0c867c747217890b8b02d8e6d7ffb.zip |
ffi: allow init-forms for slots.
* ffi.c (ffi_memb_compile): Don't complain about
three-argument slot specifiers, only about longer ones.
(ffi_struct_init): New static function.
(ffi_type_compile): Deal with third element in the slot
syntax. If there are any non-nil initializing expressions,
then we when we call make_struct_type, we specify an initfun,
which will plant the values into the slots, using logic
similar to that of the initfun generated defstruct,
except that the init-forms are reduced to values up-front.
* txr.1: Specify optional init-form for slots in FFI
struct syntax.
Diffstat (limited to 'ffi.c')
-rw-r--r-- | ffi.c | 49 |
1 files changed, 40 insertions, 9 deletions
@@ -2811,7 +2811,7 @@ static val ffi_memb_compile(val syntax, int last, int *pflexp, val self) val type = cadr(syntax); val comp_type = ffi_type_compile(type); struct txr_ffi_type *ctft = ffi_type_struct(comp_type); - if (cddr(syntax)) + if (consp(cddr(syntax)) && cdddr(syntax)) uw_throwf(error_s, lit("~a: excess elements in type-member pair ~s"), self, syntax, nao); if (ctft->flexible || (ctft->incomplete && ctft->kind == FFI_KIND_ARRAY)) { @@ -3287,6 +3287,18 @@ static val ffi_type_lookup(val sym) return gethash(ffi_typedef_hash, sym); } +static val ffi_struct_init(val slot_init, val strct) +{ + val stype = struct_type(strct); + for (; slot_init; slot_init = us_cdr(slot_init)) { + us_cons_bind(slot, initval, us_car(slot_init)); + if (!static_slot_p(stype, slot)) + slotset(strct, slot, initval); + } + + return nil; +} + val ffi_type_compile(val syntax) { val self = lit("ffi-type-compile"); @@ -3312,14 +3324,33 @@ val ffi_type_compile(val syntax) } } else { uses_or2; - val slots = mapcar(car_f, membs); - val stype = or2(if2(name, find_struct_type(sname)), - make_struct_type(sname, nil, nil, - remq(nil, slots, nil), - nil, nil, nil, nil)); - val xsyntax = cons(struct_s, - cons(sname, membs)); - return make_ffi_type_struct(xsyntax, stype, existing_type, self); + val iter; + list_collect_decl (slots, ptslots); + list_collect_decl (slot_inits, ptinits); + + for (iter = membs; iter; iter = cdr(iter)) { + val spec = car(iter); + val slot = car(spec); + val init = caddr(spec); + if (!slot && init) + uw_warningf(lit("~a: padding slot struct ~s specifies init-form"), + self, name, nao); + if (slot) + ptslots = list_collect(ptslots, slot); + if (slot && init) + ptinits = list_collect(ptinits, cons(slot, ffi_eval_expr(init, nil, nil))); + } + + { + val stype = or2(if2(name, find_struct_type(sname)), + make_struct_type(sname, nil, nil, + slots, nil, + if2(slot_inits, func_f1(slot_inits, ffi_struct_init)), + nil, nil)); + val xsyntax = cons(struct_s, + cons(sname, membs)); + return make_ffi_type_struct(xsyntax, stype, existing_type, self); + } } } else if (sym == union_s) { val name = cadr(syntax); |