diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-06-02 21:55:23 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-06-02 21:55:23 -0700 |
commit | e538d15b836c6931bbd14b5fb26f57899a3bff54 (patch) | |
tree | 657f1a8cddd8e105a88e6b8eebcbb8f82be92756 /ffi.c | |
parent | 9cf108dc6e06fbf22e4af312cb0164dc099038a3 (diff) | |
download | txr-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.c | 44 |
1 files changed, 29 insertions, 15 deletions
@@ -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, |