summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-07-11 06:44:36 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-07-11 06:44:36 -0700
commit81c97fcb7736ee17d581d6c78af567e2f7d25ca0 (patch)
tree28dbfe5937cad52ed9f2b2f5cf97d1c5da3f01a3
parent46ae35f5b87efa3582aa8564839b30acbeeffe57 (diff)
downloadtxr-81c97fcb7736ee17d581d6c78af567e2f7d25ca0.tar.gz
txr-81c97fcb7736ee17d581d6c78af567e2f7d25ca0.tar.bz2
txr-81c97fcb7736ee17d581d6c78af567e2f7d25ca0.zip
ffi: two-argument form of sizeof.
If sizeof is given an extra argument (an expression which evaluates to an object), it can calculate the dynamic size of the FFI type in relation to representing that object. * ffi.c (dyn_size): New static function. (ffi_init): Register sys:dyn-size intrinsic. * share/txr/stdlib/ffi.tl (sizeof): Support additional argument, avoiding run-time compilation of the type expression with the help of load-time. * txr.1: Update documentation for sizeof macro.
-rw-r--r--ffi.c8
-rw-r--r--share/txr/stdlib/ffi.tl8
-rw-r--r--txr.133
3 files changed, 42 insertions, 7 deletions
diff --git a/ffi.c b/ffi.c
index d411dda7..c18b7efe 100644
--- a/ffi.c
+++ b/ffi.c
@@ -5494,6 +5494,13 @@ val fill_obj(val obj, val type, val stream)
return tft->in(tft, 1, data, obj, self);
}
+static val dyn_size(val type, val obj)
+{
+ val self = lit("sizeof");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(self, type);
+ return num(tft->dynsize(tft, obj, self));
+}
+
void ffi_init(void)
{
prot1(&ffi_typedef_hash);
@@ -5625,6 +5632,7 @@ void ffi_init(void)
reg_fun(intern(lit("put-obj"), user_package), func_n3o(put_obj, 2));
reg_fun(intern(lit("get-obj"), user_package), func_n2o(get_obj, 1));
reg_fun(intern(lit("fill-obj"), user_package), func_n3o(fill_obj, 2));
+ reg_fun(intern(lit("dyn-size"), system_package), func_n2(dyn_size));
ffi_typedef_hash = make_hash(nil, nil, nil);
ffi_init_types();
ffi_init_extra_types();
diff --git a/share/txr/stdlib/ffi.tl b/share/txr/stdlib/ffi.tl
index cf5bd8a1..99c0da72 100644
--- a/share/txr/stdlib/ffi.tl
+++ b/share/txr/stdlib/ffi.tl
@@ -122,8 +122,12 @@
(defvarl ,var-sym (carray-cptr ,var-ref ,type-sym 1))
(defsymacro ,name (carray-ref ,var-sym 0)))))
-(defmacro sizeof (type)
- (ffi-size (ffi-type-compile type)))
+(defmacro sizeof (type : (obj nil obj-p) :env menv)
+ (if obj-p
+ (if (constantp obj menv)
+ (sys:dyn-size (ffi-type-compile type) obj)
+ ^(sys:dyn-size (load-time (ffi-type-compile ',type)) ,obj))
+ (ffi-size (ffi-type-compile type))))
(defmacro alignof (type)
(ffi-alignof (ffi-type-compile type)))
diff --git a/txr.1 b/txr.1
index 8f826635..86520746 100644
--- a/txr.1
+++ b/txr.1
@@ -64059,17 +64059,40 @@ as its value.
.coNP Macro @ sizeof
.synb
-.mets (sizeof << type-syntax )
+.mets (sizeof < type-syntax <> [ object-expr ])
.syne
.desc
The macro
.code sizeof
calculates the size of the FFI type denoted by
+.codn type-syntax .
+
+The
+.meta type-syntax
+expression is compiled to a type using
+.codn ffi-type-compile .
+The
+.meta object-expr
+expression is evaluated to an object value.
+
+If
.code type-syntax
-at macro-expansion time, and produces that
-integer value as its expansion, such that there is no
-run-time computation. It uses the
-.code ffi-sizeof
+denotes a variable length type, and the
+.meta object-expr
+argument is present, then a
+.I "dynamic size" is computed: the actual number of bytes required to store
+that object value as a foreign representation of the specified variable length
+type.
+
+The
+.code sizeof
+macro arranges for the size calculation to be carried out at macro-expansion
+time, if possible, so that the
+.code sizeof
+form is replaced by an integer constant. This is possible when the
+.meta object-expr
+is omitted, or if it is a constant expression according to the
+.code constantp
function.
.coNP Macro @ alignof