summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.h1
-rw-r--r--ffi.c44
-rw-r--r--txr.139
3 files changed, 59 insertions, 25 deletions
diff --git a/eval.h b/eval.h
index 75cf2c75..4fb46426 100644
--- a/eval.h
+++ b/eval.h
@@ -32,6 +32,7 @@ extern val eq_s, eql_s, equal_s;
extern val car_s, cdr_s;
extern val last_form_evaled, last_form_expanded;
extern val load_path_s, load_recursive_s;
+extern val special_s;
#define load_path (deref(lookup_var_l(nil, load_path_s)))
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,
diff --git a/txr.1 b/txr.1
index 99b49a25..a9ba02de 100644
--- a/txr.1
+++ b/txr.1
@@ -53539,6 +53539,12 @@ are instantiated with parameters. Each such expression has a type constructor
symbol in the operator position, from a limited, fixed vocabulary, which cannot
be extended.
+Some constituents of compound type syntax are expressions which evaluate to
+integer values: the dimension value for array types, the size for buffers,
+and the value expressions for enumeration constants are such expressions.
+These expressions allow full use of \*(TL. They are evaluated without
+visibility into any apparent surrounding lexical scope.
+
Some predefined types which are provided are in fact typedef names.
For instance, the
.code size-t
@@ -53963,15 +53969,20 @@ type. The remaining arguments specify the enumeration constants.
In the enumeration constant syntax, each occurrence of
.meta sym
-They must be either a keyword symbol, or a symbols for which the
+They must be a bindable symbol according to the
.code bindable
-function returns true. The symbols may not repeat.
+function. The symbols may not repeat within the same enumerated type.
+Unlike in the C language, different enumerations may use the same symbols;
+they are in separate spaces.
If a
.meta sym
is given, it is associated with an integer value which is one greater
than the integer value associated with the previous symbol.
-If there is no previous symbol, then the value is zero.
+If there is no previous symbol, then the value is zero. If the previous
+symbol has been assigned the highest possible value of the FFI
+.code int
+type, then an error exception is thrown.
If
.meti >> ( sym << value )
@@ -53979,12 +53990,13 @@ is given, then
.code sym
is given the specified value. The
.meta value
-argument may be either an integer token, or a symbol. If it is an integer
-token, then the value must be in range of the FFI
+is an expression which must evaluate to an integer value in range of the FFI
.code int
-type. If a symbol is given, it must be be one of the symbols already defined
-in the same enumerated type. The new symbol is given the same value as that
-symbol.
+type.
+It is evaluated in an environment in which the previous
+symbols from the same enumeration appear as variables whose binding are the
+their enumeration values, making it possible to use earlier enumerations in the
+definition of later enumerations.
The FFI
.code enum
@@ -54089,6 +54101,11 @@ Since Lisp arrays and C arrays do not share the same representation,
temporary buffers are automatically created and destroyed by FFI
to manage the conversion.
+The
+.code dim
+argument is an ordinary Lisp expression expanded and evaluated in the
+top-level environment. It must produce a non-negative integer value.
+
In addition, several types are treated specially: when
.meta type
is one of
@@ -54539,8 +54556,10 @@ and
.codn buf-d ,
respectively. The
.meta size
-argument must be an integer literal, which specifies the buffer
-size. Because they have a size, these types have useful get
+argument is an expression which is evaluated in the top-level
+environment, and must produce a non-negative integer.
+
+Because they have a size, these types have useful get
semantics.
The get semantics of