mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Add compiler optimizations for #1163 - eachp
Should result in much better bytecode in the simple case.
This commit is contained in:
		| @@ -445,7 +445,7 @@ | |||||||
|            ,(case kind |            ,(case kind | ||||||
|               :each ~(,in ,ds ,k) |               :each ~(,in ,ds ,k) | ||||||
|               :keys k |               :keys k | ||||||
|               :pairs ~(,tuple ,k (,in ,ds ,k)))) |               :pairs ~[,k (,in ,ds ,k)])) | ||||||
|          ,;body |          ,;body | ||||||
|          (set ,k (,next ,ds ,k)))))) |          (set ,k (,next ,ds ,k)))))) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -306,12 +306,16 @@ static JanetSlot janetc_varset(JanetFopts opts, int32_t argn, const Janet *argv) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Add attributes to a global def or var table */ | /* Add attributes to a global def or var table */ | ||||||
| static JanetTable *handleattr(JanetCompiler *c, int32_t argn, const Janet *argv) { | static JanetTable *handleattr(JanetCompiler *c, const char *kind, int32_t argn, const Janet *argv) { | ||||||
|     int32_t i; |     int32_t i; | ||||||
|     JanetTable *tab = janet_table(2); |     JanetTable *tab = janet_table(2); | ||||||
|     const char *binding_name = janet_type(argv[0]) == JANET_SYMBOL |     const char *binding_name = janet_type(argv[0]) == JANET_SYMBOL | ||||||
|                                ? ((const char *)janet_unwrap_symbol(argv[0])) |                                ? ((const char *)janet_unwrap_symbol(argv[0])) | ||||||
|                                : "<multiple bindings>"; |                                : "<multiple bindings>"; | ||||||
|  |     if (argn < 2) { | ||||||
|  |         janetc_error(c, janet_formatc("expected at least 2 arguments to %s", kind)); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|     for (i = 1; i < argn - 1; i++) { |     for (i = 1; i < argn - 1; i++) { | ||||||
|         Janet attr = argv[i]; |         Janet attr = argv[i]; | ||||||
|         switch (janet_type(attr)) { |         switch (janet_type(attr)) { | ||||||
| @@ -335,18 +339,51 @@ static JanetTable *handleattr(JanetCompiler *c, int32_t argn, const Janet *argv) | |||||||
|     return tab; |     return tab; | ||||||
| } | } | ||||||
|  |  | ||||||
| static JanetSlot dohead(const char *kind, JanetCompiler *c, JanetFopts opts, Janet *head, int32_t argn, const Janet *argv) { | typedef struct SlotHeadPair { | ||||||
|  |     Janet lhs; | ||||||
|  |     JanetSlot rhs; | ||||||
|  | } SlotHeadPair; | ||||||
|  |  | ||||||
|  | SlotHeadPair *dohead_destructure(JanetCompiler *c, SlotHeadPair *into, JanetFopts opts, Janet lhs, Janet rhs) { | ||||||
|  |  | ||||||
|  |     /* Detect if we can do an optimization to avoid some allocations */ | ||||||
|  |     int can_destructure_lhs = janet_checktype(lhs, JANET_TUPLE) | ||||||
|  |                               || janet_checktype(lhs, JANET_ARRAY); | ||||||
|  |     int rhs_is_indexed = janet_checktype(rhs, JANET_ARRAY) | ||||||
|  |                          || (janet_checktype(rhs, JANET_TUPLE) && (janet_tuple_flag(janet_unwrap_tuple(rhs)) & JANET_TUPLE_FLAG_BRACKETCTOR)); | ||||||
|  |     uint32_t has_drop = opts.flags & JANET_FOPTS_DROP; | ||||||
|  |  | ||||||
|     JanetFopts subopts = janetc_fopts_default(c); |     JanetFopts subopts = janetc_fopts_default(c); | ||||||
|     JanetSlot ret; |  | ||||||
|     if (argn < 2) { |  | ||||||
|         janetc_error(c, janet_formatc("expected at least 2 arguments to %s", kind)); |  | ||||||
|         return janetc_cslot(janet_wrap_nil()); |  | ||||||
|     } |  | ||||||
|     *head = argv[0]; |  | ||||||
|     subopts.flags = opts.flags & ~(JANET_FOPTS_TAIL | JANET_FOPTS_DROP); |     subopts.flags = opts.flags & ~(JANET_FOPTS_TAIL | JANET_FOPTS_DROP); | ||||||
|  |  | ||||||
|  |     if (has_drop && can_destructure_lhs && rhs_is_indexed) { | ||||||
|  |         /* Code is of the form (def [a b] [1 2]), avoid the allocation of two tuples */ | ||||||
|  |         JanetView view_lhs, view_rhs; | ||||||
|  |         janet_indexed_view(lhs, &view_lhs.items, &view_lhs.len); | ||||||
|  |         janet_indexed_view(rhs, &view_rhs.items, &view_rhs.len); | ||||||
|  |         int found_amp = 0; | ||||||
|  |         for (int32_t i = 0; i < view_lhs.len; i++) { | ||||||
|  |             if (janet_symeq(view_lhs.items[i], "&")) { | ||||||
|  |                 found_amp = 1; | ||||||
|  |                 /* Good error will be generated later. */ | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (!found_amp) { | ||||||
|  |             for (int32_t i = 0; i < view_lhs.len; i++) { | ||||||
|  |                 Janet sub_rhs = view_rhs.len <= i ? janet_wrap_nil() : view_rhs.items[i]; | ||||||
|  |                 into = dohead_destructure(c, into, subopts, view_lhs.items[i], sub_rhs); | ||||||
|  |             } | ||||||
|  |             return into; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* No optimization, do the simple way */ | ||||||
|     subopts.hint = opts.hint; |     subopts.hint = opts.hint; | ||||||
|     ret = janetc_value(subopts, argv[argn - 1]); |     JanetSlot ret = janetc_value(subopts, rhs); | ||||||
|     return ret; |     SlotHeadPair shp = {lhs, ret}; | ||||||
|  |     janet_v_push(into, shp); | ||||||
|  |     return into; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Def or var a symbol in a local scope */ | /* Def or var a symbol in a local scope */ | ||||||
| @@ -412,12 +449,23 @@ static int varleaf( | |||||||
|  |  | ||||||
| static JanetSlot janetc_var(JanetFopts opts, int32_t argn, const Janet *argv) { | static JanetSlot janetc_var(JanetFopts opts, int32_t argn, const Janet *argv) { | ||||||
|     JanetCompiler *c = opts.compiler; |     JanetCompiler *c = opts.compiler; | ||||||
|     Janet head; |     JanetTable *attr_table = handleattr(c, "var", argn, argv); | ||||||
|     JanetTable *attr_table = handleattr(c, argn, argv); |     if (c->result.status == JANET_COMPILE_ERROR) { | ||||||
|     JanetSlot ret = dohead("var", c, opts, &head, argn, argv); |  | ||||||
|     if (c->result.status == JANET_COMPILE_ERROR) |  | ||||||
|         return janetc_cslot(janet_wrap_nil()); |         return janetc_cslot(janet_wrap_nil()); | ||||||
|     destructure(c, argv[0], ret, varleaf, attr_table); |     } | ||||||
|  |     SlotHeadPair *into = NULL; | ||||||
|  |     into = dohead_destructure(c, into, opts, argv[0], argv[argn - 1]); | ||||||
|  |     if (c->result.status == JANET_COMPILE_ERROR) { | ||||||
|  |         janet_v_free(into); | ||||||
|  |         return janetc_cslot(janet_wrap_nil()); | ||||||
|  |     } | ||||||
|  |     JanetSlot ret; | ||||||
|  |     janet_assert(janet_v_count(into) > 0, "bad destructure"); | ||||||
|  |     for (int32_t i = 0; i < janet_v_count(into); i++) { | ||||||
|  |         destructure(c, into[i].lhs, into[i].rhs, varleaf, attr_table); | ||||||
|  |         ret = into[i].rhs; | ||||||
|  |     } | ||||||
|  |     janet_v_free(into); | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -461,13 +509,24 @@ static int defleaf( | |||||||
|  |  | ||||||
| static JanetSlot janetc_def(JanetFopts opts, int32_t argn, const Janet *argv) { | static JanetSlot janetc_def(JanetFopts opts, int32_t argn, const Janet *argv) { | ||||||
|     JanetCompiler *c = opts.compiler; |     JanetCompiler *c = opts.compiler; | ||||||
|     Janet head; |     JanetTable *attr_table = handleattr(c, "def", argn, argv); | ||||||
|     opts.flags &= ~JANET_FOPTS_HINT; |     if (c->result.status == JANET_COMPILE_ERROR) { | ||||||
|     JanetTable *attr_table = handleattr(c, argn, argv); |  | ||||||
|     JanetSlot ret = dohead("def", c, opts, &head, argn, argv); |  | ||||||
|     if (c->result.status == JANET_COMPILE_ERROR) |  | ||||||
|         return janetc_cslot(janet_wrap_nil()); |         return janetc_cslot(janet_wrap_nil()); | ||||||
|     destructure(c, argv[0], ret, defleaf, attr_table); |     } | ||||||
|  |     opts.flags &= ~JANET_FOPTS_HINT; | ||||||
|  |     SlotHeadPair *into = NULL; | ||||||
|  |     into = dohead_destructure(c, into, opts, argv[0], argv[argn - 1]); | ||||||
|  |     if (c->result.status == JANET_COMPILE_ERROR) { | ||||||
|  |         janet_v_free(into); | ||||||
|  |         return janetc_cslot(janet_wrap_nil()); | ||||||
|  |     } | ||||||
|  |     JanetSlot ret; | ||||||
|  |     janet_assert(janet_v_count(into) > 0, "bad destructure"); | ||||||
|  |     for (int32_t i = 0; i < janet_v_count(into); i++) { | ||||||
|  |         destructure(c, into[i].lhs, into[i].rhs, defleaf, attr_table); | ||||||
|  |         ret = into[i].rhs; | ||||||
|  |     } | ||||||
|  |     janet_v_free(into); | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose