diff options
-rw-r--r-- | eval.h | 1 | ||||
-rw-r--r-- | ffi.c | 44 | ||||
-rw-r--r-- | txr.1 | 39 |
3 files changed, 59 insertions, 25 deletions
@@ -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))) @@ -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, @@ -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 |