mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +00:00 
			
		
		
		
	Refactor dst_view_* functions.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -32,7 +32,7 @@ BINDIR=$(PREFIX)/bin | ||||
| # TODO - when api is finalized, only export public symbols instead of using rdynamic | ||||
| # which exports all symbols. Saves a few KB in binary. | ||||
|  | ||||
| CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -Os -s | ||||
| CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -O2 | ||||
| CLIBS=-lm -ldl | ||||
| PREFIX=/usr/local | ||||
| DST_TARGET=dst | ||||
|   | ||||
| @@ -183,7 +183,7 @@ static int cfun_slice(DstArgs args) { | ||||
|     int32_t start, end; | ||||
|     DST_MINARITY(args, 1); | ||||
|     DST_MAXARITY(args, 3); | ||||
|     if (!dst_seq_view(args.v[0], &vals, &len)) | ||||
|     if (!dst_indexed_view(args.v[0], &vals, &len)) | ||||
|         DST_THROW(args, "expected array|tuple"); | ||||
|     /* Get start */ | ||||
|     if (args.n < 2) { | ||||
| @@ -231,7 +231,7 @@ static int cfun_concat(DstArgs args) { | ||||
|                 { | ||||
|                     int32_t j, len; | ||||
|                     const Dst *vals; | ||||
|                     dst_seq_view(args.v[i], &vals, &len); | ||||
|                     dst_indexed_view(args.v[i], &vals, &len); | ||||
|                     for (j = 0; j < len; j++) | ||||
|                         dst_array_push(array, vals[j]); | ||||
|                 } | ||||
|   | ||||
| @@ -554,7 +554,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { | ||||
|  | ||||
|     /* Create slot aliases */ | ||||
|     x = dst_get(s, dst_csymbolv("slots")); | ||||
|     if (dst_seq_view(x, &arr, &count)) { | ||||
|     if (dst_indexed_view(x, &arr, &count)) { | ||||
|         for (i = 0; i < count; i++) { | ||||
|             Dst v = arr[i]; | ||||
|             if (dst_checktype(v, DST_TUPLE)) { | ||||
| @@ -575,7 +575,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { | ||||
|  | ||||
|     /* Parse constants */ | ||||
|     x = dst_get(s, dst_csymbolv("constants")); | ||||
|     if (dst_seq_view(x, &arr, &count)) { | ||||
|     if (dst_indexed_view(x, &arr, &count)) { | ||||
|         def->constants_length = count; | ||||
|         def->constants = malloc(sizeof(Dst) * count); | ||||
|         if (NULL == def->constants) { | ||||
| @@ -610,7 +610,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { | ||||
|  | ||||
|     /* Parse sub funcdefs */ | ||||
|     x = dst_get(s, dst_csymbolv("closures")); | ||||
|     if (dst_seq_view(x, &arr, &count)) { | ||||
|     if (dst_indexed_view(x, &arr, &count)) { | ||||
|         int32_t i; | ||||
|         for (i = 0; i < count; i++) { | ||||
|             DstAssembleResult subres; | ||||
| @@ -640,7 +640,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { | ||||
|  | ||||
|     /* Parse bytecode and labels */ | ||||
|     x = dst_get(s, dst_csymbolv("bytecode")); | ||||
|     if (dst_seq_view(x, &arr, &count)) { | ||||
|     if (dst_indexed_view(x, &arr, &count)) { | ||||
|         /* Do labels and find length */ | ||||
|         int32_t blength = 0; | ||||
|         for (i = 0; i < count; ++i) { | ||||
| @@ -696,7 +696,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { | ||||
|  | ||||
|     /* Check for source mapping */ | ||||
|     x = dst_get(s, dst_csymbolv("sourcemap")); | ||||
|     if (dst_seq_view(x, &arr, &count)) { | ||||
|     if (dst_indexed_view(x, &arr, &count)) { | ||||
|         dst_asm_assert(&a, count == def->bytecode_length, "sourcemap must have the same length as the bytecode"); | ||||
|         def->sourcemap = malloc(sizeof(DstSourceMapping) * count); | ||||
|         for (i = 0; i < count; i++) { | ||||
|   | ||||
| @@ -48,24 +48,6 @@ void dstc_cerror(DstCompiler *c, const char *m) { | ||||
|     dstc_error(c, dst_cstring(m)); | ||||
| } | ||||
|  | ||||
| /* Check error */ | ||||
| int dstc_iserr(DstFopts *opts) { | ||||
|     return (opts->compiler->result.status == DST_COMPILE_ERROR); | ||||
| } | ||||
|  | ||||
| /* Get the next key in an associative data structure. Used for iterating through an | ||||
|  * associative data structure. */ | ||||
| const DstKV *dstc_next(Dst ds, const DstKV *kv) { | ||||
|     switch(dst_type(ds)) { | ||||
|         default: | ||||
|             return NULL; | ||||
|         case DST_TABLE: | ||||
|             return (const DstKV *) dst_table_next(dst_unwrap_table(ds), kv); | ||||
|         case DST_STRUCT: | ||||
|             return dst_struct_next(dst_unwrap_struct(ds), kv); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Free a slot */ | ||||
| void dstc_freeslot(DstCompiler *c, DstSlot s) { | ||||
|     if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF | DST_SLOT_NAMED)) return; | ||||
| @@ -318,11 +300,14 @@ DstSlot *dstc_toslots(DstCompiler *c, const Dst *vals, int32_t len) { | ||||
| /* Get a bunch of slots for function arguments */ | ||||
| DstSlot *dstc_toslotskv(DstCompiler *c, Dst ds) { | ||||
|     DstSlot *ret = NULL; | ||||
|     const DstKV *kv = NULL; | ||||
|     DstFopts subopts = dstc_fopts_default(c); | ||||
|     while ((kv = dstc_next(ds, kv))) { | ||||
|         dst_v_push(ret, dstc_value(subopts, kv->key)); | ||||
|         dst_v_push(ret, dstc_value(subopts, kv->value)); | ||||
|     const DstKV *kvs = NULL; | ||||
|     int32_t cap, i, len; | ||||
|     dst_dictionary_view(ds, &kvs, &len, &cap); | ||||
|     for (i = 0; i < cap; i++) { | ||||
|         if (dst_checktype(kvs[i].key, DST_NIL)) continue; | ||||
|         dst_v_push(ret, dstc_value(subopts, kvs[i].key)); | ||||
|         dst_v_push(ret, dstc_value(subopts, kvs[i].value)); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| @@ -500,7 +485,7 @@ DstSlot dstc_value(DstFopts opts, Dst x) { | ||||
|     c->recursion_guard--; | ||||
|  | ||||
|     /* Guard against previous errors and unbounded recursion */ | ||||
|     if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil()); | ||||
|     if (c->result.status == DST_COMPILE_ERROR) return dstc_cslot(dst_wrap_nil()); | ||||
|     if (c->recursion_guard <= 0) { | ||||
|         dstc_cerror(c, "recursed too deeply"); | ||||
|         return dstc_cslot(dst_wrap_nil()); | ||||
| @@ -509,8 +494,10 @@ DstSlot dstc_value(DstFopts opts, Dst x) { | ||||
|     /* Macro expand. Also gets possible special form and | ||||
|      * refines source mapping cursor if possible. */ | ||||
|     const DstSpecial *spec = NULL; | ||||
|     int macroi = DST_RECURSION_GUARD; | ||||
|     while (macroi && !dstc_iserr(&opts) && macroexpand1(c, x, &x, &spec)) | ||||
|     int macroi = DST_MAX_MACRO_EXPAND; | ||||
|     while (macroi && | ||||
|             c->result.status != DST_COMPILE_ERROR && | ||||
|             macroexpand1(c, x, &x, &spec)) | ||||
|         macroi--; | ||||
|     if (macroi == 0) { | ||||
|         dstc_cerror(c, "recursed too deeply in macro expansion"); | ||||
| @@ -559,13 +546,11 @@ DstSlot dstc_value(DstFopts opts, Dst x) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (dstc_iserr(&opts)) { | ||||
|     if (c->result.status == DST_COMPILE_ERROR) | ||||
|         return dstc_cslot(dst_wrap_nil()); | ||||
|     } | ||||
|     c->current_mapping = last_mapping; | ||||
|     if (opts.flags & DST_FOPTS_TAIL) { | ||||
|     if (opts.flags & DST_FOPTS_TAIL) | ||||
|         ret = dstc_return(opts.compiler, ret); | ||||
|     } | ||||
|     if (opts.flags & DST_FOPTS_HINT) { | ||||
|         dstc_copy(opts.compiler, opts.hint, ret); | ||||
|         ret = opts.hint; | ||||
|   | ||||
| @@ -175,12 +175,6 @@ const DstFunOptimizer *dstc_funopt(uint32_t flags); | ||||
| /* Get a special. Return NULL if none exists */ | ||||
| const DstSpecial *dstc_special(const uint8_t *name); | ||||
|  | ||||
| /* Check error */ | ||||
| int dstc_iserr(DstFopts *opts); | ||||
|  | ||||
| /* Helper for iterating tables and structs */ | ||||
| const DstKV *dstc_next(Dst ds, const DstKV *kv); | ||||
|  | ||||
| void dstc_freeslot(DstCompiler *c, DstSlot s); | ||||
| void dstc_nameslot(DstCompiler *c, const uint8_t *sym, DstSlot s); | ||||
| DstSlot dstc_farslot(DstCompiler *c); | ||||
|   | ||||
| @@ -57,7 +57,7 @@ static int destructure(DstCompiler *c, | ||||
|             { | ||||
|                 int32_t i, len; | ||||
|                 const Dst *values; | ||||
|                 dst_seq_view(left, &values, &len); | ||||
|                 dst_indexed_view(left, &values, &len); | ||||
|                 for (i = 0; i < len; i++) { | ||||
|                     DstSlot nextright = dstc_farslot(c); | ||||
|                     Dst subval = values[i]; | ||||
| @@ -75,12 +75,15 @@ static int destructure(DstCompiler *c, | ||||
|         case DST_TABLE: | ||||
|         case DST_STRUCT: | ||||
|             { | ||||
|                 const DstKV *kv = NULL; | ||||
|                 while ((kv = dstc_next(left, kv))) { | ||||
|                 const DstKV *kvs = NULL; | ||||
|                 int32_t i, cap, len; | ||||
|                 dst_dictionary_view(left, &kvs, &len, &cap); | ||||
|                 for (i = 0; i < cap; i++) { | ||||
|                     if (dst_checktype(kvs[i].key, DST_NIL)) continue; | ||||
|                     DstSlot nextright = dstc_farslot(c); | ||||
|                     DstSlot k = dstc_value(dstc_fopts_default(c), kv->key); | ||||
|                     DstSlot k = dstc_value(dstc_fopts_default(c), kvs[i].key); | ||||
|                     dstc_emit_sss(c, DOP_GET, nextright, right, k, 1); | ||||
|                     if (destructure(c, kv->value, nextright, leaf, attr)) | ||||
|                     if (destructure(c, kvs[i].value, nextright, leaf, attr)) | ||||
|                         dstc_freeslot(c, nextright); | ||||
|                 } | ||||
|             } | ||||
| @@ -190,7 +193,8 @@ DstSlot dstc_var(DstFopts opts, int32_t argn, const Dst *argv) { | ||||
|     DstCompiler *c = opts.compiler; | ||||
|     Dst head; | ||||
|     DstSlot ret = dohead(c, opts, &head, argn, argv); | ||||
|     if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil()); | ||||
|     if (c->result.status == DST_COMPILE_ERROR) | ||||
|         return dstc_cslot(dst_wrap_nil()); | ||||
|     if (destructure(c, argv[0], ret, varleaf, handleattr(c, argn, argv))) | ||||
|         dstc_freeslot(c, ret); | ||||
|     return dstc_cslot(dst_wrap_nil()); | ||||
| @@ -223,7 +227,8 @@ DstSlot dstc_def(DstFopts opts, int32_t argn, const Dst *argv) { | ||||
|     Dst head; | ||||
|     opts.flags &= ~DST_FOPTS_HINT; | ||||
|     DstSlot ret = dohead(c, opts, &head, argn, argv); | ||||
|     if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil()); | ||||
|     if (c->result.status == DST_COMPILE_ERROR) | ||||
|         return dstc_cslot(dst_wrap_nil()); | ||||
|     if (destructure(c, argv[0], ret, defleaf, handleattr(c, argn, argv))) | ||||
|         dstc_freeslot(c, ret); | ||||
|     return dstc_cslot(dst_wrap_nil()); | ||||
| @@ -454,7 +459,7 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) { | ||||
|         goto error; | ||||
|     } | ||||
|     paramv = argv[parami]; | ||||
|     if (dst_seq_view(paramv, ¶ms, ¶mcount)) { | ||||
|     if (dst_indexed_view(paramv, ¶ms, ¶mcount)) { | ||||
|         int32_t i; | ||||
|         for (i = 0; i < paramcount; i++) { | ||||
|             Dst param = params[i]; | ||||
| @@ -494,7 +499,7 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) { | ||||
|     } else for (argi = parami + 1; argi < argn; argi++) { | ||||
|         subopts.flags = (argi == (argn - 1)) ? DST_FOPTS_TAIL : DST_FOPTS_DROP; | ||||
|         dstc_value(subopts, argv[argi]); | ||||
|         if (dstc_iserr(&opts)) | ||||
|         if (c->result.status == DST_COMPILE_ERROR) | ||||
|             goto error2; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -937,7 +937,7 @@ static int cfun_join(DstArgs args) { | ||||
|     for (i = 0; i < partslen; i++) { | ||||
|         const uint8_t *chunk; | ||||
|         int32_t chunklen = 0; | ||||
|         if (!dst_chararray_view(parts[i], &chunk, &chunklen)) { | ||||
|         if (!dst_bytes_view(parts[i], &chunk, &chunklen)) { | ||||
|             DST_THROW(args, "expected string|symbol|buffer"); | ||||
|         } | ||||
|         if (i) finallen += joinerlen; | ||||
| @@ -951,7 +951,7 @@ static int cfun_join(DstArgs args) { | ||||
|             memcpy(out, joiner, joinerlen); | ||||
|             out += joinerlen; | ||||
|         } | ||||
|         dst_chararray_view(parts[i], &chunk, &chunklen); | ||||
|         dst_bytes_view(parts[i], &chunk, &chunklen); | ||||
|         memcpy(out, chunk, chunklen); | ||||
|         out += chunklen; | ||||
|     } | ||||
|   | ||||
| @@ -44,7 +44,7 @@ const Dst *dst_tuple_end(Dst *tuple) { | ||||
| } | ||||
|  | ||||
| /* Build a tuple with n values */ | ||||
| const Dst *dst_tuple_n(Dst *values, int32_t n) { | ||||
| const Dst *dst_tuple_n(const Dst *values, int32_t n) { | ||||
|     Dst *t = dst_tuple_begin(n); | ||||
|     memcpy(t, values, sizeof(Dst) * n); | ||||
|     return dst_tuple_end(t); | ||||
| @@ -97,7 +97,7 @@ static int cfun_slice(DstArgs args) { | ||||
|     Dst *ret; | ||||
|     int32_t start, end; | ||||
|     DST_MINARITY(args, 1); | ||||
|     if (!dst_seq_view(args.v[0], &vals, &len)) DST_THROW(args, "expected array/tuple"); | ||||
|     if (!dst_indexed_view(args.v[0], &vals, &len)) DST_THROW(args, "expected array/tuple"); | ||||
|     /* Get start */ | ||||
|     if (args.n < 2) { | ||||
|         start = 0; | ||||
| @@ -133,7 +133,7 @@ static int cfun_prepend(DstArgs args) { | ||||
|     int32_t len; | ||||
|     Dst *n; | ||||
|     DST_FIXARITY(args, 2); | ||||
|     if (!dst_seq_view(args.v[0], &t, &len)) DST_THROW(args, "expected tuple/array"); | ||||
|     if (!dst_indexed_view(args.v[0], &t, &len)) DST_THROW(args, "expected tuple/array"); | ||||
|     n = dst_tuple_begin(len + 1); | ||||
|     memcpy(n + 1, t, sizeof(Dst) * len); | ||||
|     n[0] = args.v[1]; | ||||
| @@ -145,7 +145,7 @@ static int cfun_append(DstArgs args) { | ||||
|     int32_t len; | ||||
|     Dst *n; | ||||
|     DST_FIXARITY(args, 2); | ||||
|     if (!dst_seq_view(args.v[0], &t, &len)) DST_THROW(args, "expected tuple/array"); | ||||
|     if (!dst_indexed_view(args.v[0], &t, &len)) DST_THROW(args, "expected tuple/array"); | ||||
|     n = dst_tuple_begin(len + 1); | ||||
|     memcpy(n, t, sizeof(Dst) * len); | ||||
|     n[len] = args.v[1]; | ||||
|   | ||||
| @@ -202,7 +202,7 @@ DstTable *dst_env_arg(DstArgs args) { | ||||
|  | ||||
| /* Read both tuples and arrays as c pointers + int32_t length. Return 1 if the | ||||
|  * view can be constructed, 0 if an invalid type. */ | ||||
| int dst_seq_view(Dst seq, const Dst **data, int32_t *len) { | ||||
| int dst_indexed_view(Dst seq, const Dst **data, int32_t *len) { | ||||
|     if (dst_checktype(seq, DST_ARRAY)) { | ||||
|         *data = dst_unwrap_array(seq)->data; | ||||
|         *len = dst_unwrap_array(seq)->count; | ||||
| @@ -217,7 +217,7 @@ int dst_seq_view(Dst seq, const Dst **data, int32_t *len) { | ||||
|  | ||||
| /* Read both strings and buffer as unsigned character array + int32_t len. | ||||
|  * Returns 1 if the view can be constructed and 0 if the type is invalid. */ | ||||
| int dst_chararray_view(Dst str, const uint8_t **data, int32_t *len) { | ||||
| int dst_bytes_view(Dst str, const uint8_t **data, int32_t *len) { | ||||
|     if (dst_checktype(str, DST_STRING) || dst_checktype(str, DST_SYMBOL)) { | ||||
|         *data = dst_unwrap_string(str); | ||||
|         *len = dst_string_length(dst_unwrap_string(str)); | ||||
| @@ -233,7 +233,7 @@ int dst_chararray_view(Dst str, const uint8_t **data, int32_t *len) { | ||||
| /* Read both structs and tables as the entries of a hashtable with | ||||
|  * identical structure. Returns 1 if the view can be constructed and | ||||
|  * 0 if the type is invalid. */ | ||||
| int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap) { | ||||
| int dst_dictionary_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap) { | ||||
|     if (dst_checktype(tab, DST_TABLE)) { | ||||
|         *data = dst_unwrap_table(tab)->data; | ||||
|         *cap = dst_unwrap_table(tab)->capacity; | ||||
|   | ||||
| @@ -708,7 +708,7 @@ static void *op_lookup[255] = { | ||||
|     { | ||||
|         const Dst *vals; | ||||
|         int32_t len; | ||||
|         if (dst_seq_view(stack[oparg(1, 0xFFFFFF)], &vals, &len)) { | ||||
|         if (dst_indexed_view(stack[oparg(1, 0xFFFFFF)], &vals, &len)) { | ||||
|             dst_fiber_pushn(fiber, vals, len); | ||||
|         } else { | ||||
|             retreg = stack[oparg(1, 0xFFFFFF)]; | ||||
|   | ||||
| @@ -136,13 +136,21 @@ extern "C" { | ||||
| /* Maximum depth to follow table prototypes before giving up and returning nil. */ | ||||
| #define DST_MAX_PROTO_DEPTH 200 | ||||
|  | ||||
| /* Maximum depth to follow table prototypes before giving up and returning nil. */ | ||||
| #define DST_MAX_MACRO_EXPAND 200 | ||||
|  | ||||
| /* Define max stack size for stacks before raising a stack overflow error. | ||||
|  * If this is not defined, fiber stacks can grow without limit (until memory | ||||
|  * runs out) */ | ||||
| #define DST_STACK_MAX 8192 | ||||
|  | ||||
| /* Use nanboxed values - uses 8 bytes per value instead of 12 or 16. */ | ||||
| /* Use nanboxed values - uses 8 bytes per value instead of 12 or 16. | ||||
|  * To turn of nanboxing, for debugging purposes or for certain | ||||
|  * architectures (Nanboxing only tested on x86 and x64), comment out | ||||
|  * the DST_NANBOX define.*/ | ||||
| #define DST_NANBOX | ||||
|  | ||||
| /* Further refines the type of nanboxing to use. */ | ||||
| #define DST_NANBOX_47 | ||||
|  | ||||
| /* Alignment for pointers */ | ||||
| @@ -895,7 +903,7 @@ int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x); | ||||
| #define dst_tuple_sm_col(t) ((dst_tuple_raw(t)[3])) | ||||
| Dst *dst_tuple_begin(int32_t length); | ||||
| const Dst *dst_tuple_end(Dst *tuple); | ||||
| const Dst *dst_tuple_n(Dst *values, int32_t n); | ||||
| const Dst *dst_tuple_n(const Dst *values, int32_t n); | ||||
| int dst_tuple_equal(const Dst *lhs, const Dst *rhs); | ||||
| int dst_tuple_compare(const Dst *lhs, const Dst *rhs); | ||||
|  | ||||
| @@ -965,9 +973,9 @@ DstFiber *dst_fiber(DstFunction *callee, int32_t capacity); | ||||
| #define dst_fiber_status(f) (((f)->flags & DST_FIBER_STATUS_MASK) >> DST_FIBER_STATUS_OFFSET) | ||||
|  | ||||
| /* Treat similar types through uniform interfaces for iteration */ | ||||
| int dst_seq_view(Dst seq, const Dst **data, int32_t *len); | ||||
| int dst_chararray_view(Dst str, const uint8_t **data, int32_t *len); | ||||
| int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap); | ||||
| int dst_indexed_view(Dst seq, const Dst **data, int32_t *len); | ||||
| int dst_bytes_view(Dst str, const uint8_t **data, int32_t *len); | ||||
| int dst_dictionary_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap); | ||||
|  | ||||
| /* Abstract */ | ||||
| #define dst_abstract_header(u) ((DstAbstractHeader *)(u) - 1) | ||||
| @@ -1107,14 +1115,14 @@ int dst_lib_compile(DstArgs args); | ||||
|  | ||||
| #define DST_ARG_BYTES(DESTBYTES, DESTLEN, A, N) do {\ | ||||
|     if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_BYTES);\ | ||||
|     if (!dst_chararray_view((A).v[(N)], &(DESTBYTES), &(DESTLEN))) {\ | ||||
|     if (!dst_bytes_view((A).v[(N)], &(DESTBYTES), &(DESTLEN))) {\ | ||||
|         return dst_typemany_err(A, N, DST_TFLAG_BYTES);\ | ||||
|     }\ | ||||
| } while (0) | ||||
|  | ||||
| #define DST_ARG_INDEXED(DESTVALS, DESTLEN, A, N) do {\ | ||||
|     if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_INDEXED);\ | ||||
|     if (!dst_seq_view((A).v[(N)], &(DESTVALS), &(DESTLEN))) {\ | ||||
|     if (!dst_indexed_view((A).v[(N)], &(DESTVALS), &(DESTLEN))) {\ | ||||
|         return dst_typemany_err(A, N, DST_TFLAG_INDEXED);\ | ||||
|     }\ | ||||
| } while (0) | ||||
|   | ||||
| @@ -194,4 +194,8 @@ | ||||
|  | ||||
| (assert (= 7 (case :a :b 5 :c 6 :u 10 7)), "case with default") | ||||
|  | ||||
| # Testing the loop and for macros | ||||
| (def xs (apply1 tuple (for [x :range [0 10] :when (even? x)] (tuple (/ x 2) x)))) | ||||
| (assert (= xs '((0 0) (1 2) (2 4) (3 6) (4 8))) "for macro 1") | ||||
|  | ||||
| (end-suite) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose