summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-06-02 21:55:23 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-06-02 21:55:23 -0700
commite538d15b836c6931bbd14b5fb26f57899a3bff54 (patch)
tree657f1a8cddd8e105a88e6b8eebcbb8f82be92756 /ffi.c
parent9cf108dc6e06fbf22e4af312cb0164dc099038a3 (diff)
downloadtxr-e538d15b836c6931bbd14b5fb26f57899a3bff54.tar.gz
txr-e538d15b836c6931bbd14b5fb26f57899a3bff54.tar.bz2
txr-e538d15b836c6931bbd14b5fb26f57899a3bff54.zip
ffi: evaluate expressions in type notation.
Places where an integer constant was previously allowed now allow an expression. The way enum syntax works is now different. A temporary lexical environment is created, and each enumeration is bound in that environment. The value expressions are evaluated in that environment. The decision to allow keyword symbols to be enumeration contants is retracted. * eval.h (special_s): Declared. * ffi.c (ffi_eval_expr): New static function. (make_ffi_type_enum): Enums are introduced into a temporary environment, in which the value expressions are evaluated. By this means, the expressions can refer can refer to previous enums and do arbitrary computation. Also, we drop the requirement that enums can be keyword symbols. (ffi_type_compile): Array dimension and buf size are evaluated as expresions. Array and buffer syntax is transformed by substitution of the evaluated size. * txr.1: Documented use of expressions in FFI type notation.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/ffi.c b/ffi.c
index 44ffc3bf..db7ae8cd 100644
--- a/ffi.c
+++ b/ffi.c
@@ -2064,6 +2064,12 @@ static val make_ffi_type_array(val syntax, val lisp_type,
return obj;
}
+static val ffi_eval_expr(val expr, val menv, val env)
+{
+ val expr_ex = expand(expr, menv);
+ return eval(expr_ex, env, expr_ex);
+}
+
static val make_ffi_type_enum(val syntax, val enums, val self)
{
struct txr_ffi_type *tft = coerce(struct txr_ffi_type *,
@@ -2077,6 +2083,8 @@ static val make_ffi_type_enum(val syntax, val enums, val self)
val iter;
val sym_num = make_hash(nil, nil, t);
val num_sym = make_hash(nil, nil, nil);
+ val enum_env = make_env(nil, nil, nil);
+ val shadow_menv = make_env(nil, nil, nil);
tft->ft = &ffi_type_sint;
tft->syntax = syntax;
@@ -2097,8 +2105,8 @@ static val make_ffi_type_enum(val syntax, val enums, val self)
val nn;
if (symbolp(en)) {
val sym = en;
- if (!bindable(sym) && !keywordp(sym))
- uw_throwf(error_s, lit("~s: ~s member ~s isn't bindable or a keyword"),
+ if (!bindable(sym))
+ uw_throwf(error_s, lit("~s: ~s member ~s isn't a bindable symbol"),
self, syntax, sym, nao);
if (cur == INT_MAX)
uw_throwf(error_s, lit("~s: ~s overflow at member ~s"),
@@ -2108,23 +2116,24 @@ static val make_ffi_type_enum(val syntax, val enums, val self)
self, syntax, sym, nao);
sethash(num_sym, sym, nn = num(++cur));
sethash(sym_num, nn, sym);
+ env_vbind(enum_env, sym, nn);
+ env_vbind(shadow_menv, sym, special_s);
if (cur > highest)
highest = cur;
} else {
- val n = cadr(en);
+ val expr = cadr(en);
val sym = car(en);
- if (!bindable(sym) && !keywordp(sym))
- uw_throwf(error_s, lit("~s: ~s member ~s isn't bindable or a keyword"),
+ val n;
+ if (!bindable(sym))
+ uw_throwf(error_s, lit("~s: ~s member ~s isn't a bindable symbol"),
self, syntax, sym, nao);
if (gethash(num_sym, sym))
uw_throwf(error_s, lit("~s: ~s duplicate member ~s"),
self, syntax, sym, nao);
- if (symbolp(n)) {
- n = gethash(num_sym, n);
- if (!n)
- uw_throwf(error_s, lit("~s: ~s member ~s value ~s not defined"),
- self, syntax, n, nao);
- } else if (!integerp(n)) {
+
+ n = ffi_eval_expr(expr, shadow_menv, enum_env);
+
+ if (!integerp(n)) {
uw_throwf(error_s, lit("~s: ~s member ~s value ~s not integer"),
self, syntax, n, nao);
}
@@ -2135,6 +2144,8 @@ static val make_ffi_type_enum(val syntax, val enums, val self)
self, syntax, n, nao);
sethash(num_sym, sym, nn = num(cur));
sethash(sym_num, nn, sym);
+ env_vbind(enum_env, sym, nn);
+ env_vbind(shadow_menv, sym, special_s);
if (cur < lowest)
lowest = cur;
}
@@ -2217,9 +2228,10 @@ val ffi_type_compile(val syntax)
tft->size = 0;
return type;
} else if (length(syntax) == three) {
- val dim = cadr(syntax);
+ val dim = ffi_eval_expr(cadr(syntax), nil, nil);
val eltype_syntax = caddr(syntax);
val eltype = ffi_type_compile(eltype_syntax);
+ val xsyntax = list(sym, dim, eltype_syntax, nao);
struct txr_ffi_type *etft = ffi_type_struct(eltype);
if (etft->size == 0)
@@ -2232,7 +2244,7 @@ val ffi_type_compile(val syntax)
self, syntax, nao);
{
- val type = make_ffi_type_array(syntax, vec_s, dim, eltype);
+ val type = make_ffi_type_array(xsyntax, vec_s, dim, eltype);
struct txr_ffi_type *tft = ffi_type_struct(type);
if (sym == zarray_s) {
@@ -2291,8 +2303,10 @@ val ffi_type_compile(val syntax)
ffi_ptr_out_s_in, ffi_ptr_out_out,
0, target_type);
} else if (sym == buf_s || sym == buf_d_s) {
- cnum nelem = c_num(cadr(syntax));
- val type = make_ffi_type_builtin(syntax, buf_s,
+ val size = ffi_eval_expr(cadr(syntax), nil, nil);
+ val xsyntax = list(sym, size, nao);
+ cnum nelem = c_num(size);
+ val type = make_ffi_type_builtin(xsyntax, buf_s,
sizeof (mem_t *),
alignof (mem_t *),
&ffi_type_pointer,