mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +00:00 
			
		
		
		
	Add compiler optimizations for #1163 - eachp
Should result in much better bytecode in the simple case.
This commit is contained in:
		| @@ -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 */ | ||||
| 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; | ||||
|     JanetTable *tab = janet_table(2); | ||||
|     const char *binding_name = janet_type(argv[0]) == JANET_SYMBOL | ||||
|                                ? ((const char *)janet_unwrap_symbol(argv[0])) | ||||
|                                : "<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++) { | ||||
|         Janet attr = argv[i]; | ||||
|         switch (janet_type(attr)) { | ||||
| @@ -335,18 +339,51 @@ static JanetTable *handleattr(JanetCompiler *c, int32_t argn, const Janet *argv) | ||||
|     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); | ||||
|     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); | ||||
|  | ||||
|     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; | ||||
|     ret = janetc_value(subopts, argv[argn - 1]); | ||||
|     return ret; | ||||
|     JanetSlot ret = janetc_value(subopts, rhs); | ||||
|     SlotHeadPair shp = {lhs, ret}; | ||||
|     janet_v_push(into, shp); | ||||
|     return into; | ||||
| } | ||||
|  | ||||
| /* 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) { | ||||
|     JanetCompiler *c = opts.compiler; | ||||
|     Janet head; | ||||
|     JanetTable *attr_table = handleattr(c, argn, argv); | ||||
|     JanetSlot ret = dohead("var", c, opts, &head, argn, argv); | ||||
|     if (c->result.status == JANET_COMPILE_ERROR) | ||||
|     JanetTable *attr_table = handleattr(c, "var", argn, argv); | ||||
|     if (c->result.status == JANET_COMPILE_ERROR) { | ||||
|         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; | ||||
| } | ||||
|  | ||||
| @@ -461,13 +509,24 @@ static int defleaf( | ||||
|  | ||||
| static JanetSlot janetc_def(JanetFopts opts, int32_t argn, const Janet *argv) { | ||||
|     JanetCompiler *c = opts.compiler; | ||||
|     Janet head; | ||||
|     opts.flags &= ~JANET_FOPTS_HINT; | ||||
|     JanetTable *attr_table = handleattr(c, argn, argv); | ||||
|     JanetSlot ret = dohead("def", c, opts, &head, argn, argv); | ||||
|     if (c->result.status == JANET_COMPILE_ERROR) | ||||
|     JanetTable *attr_table = handleattr(c, "def", argn, argv); | ||||
|     if (c->result.status == JANET_COMPILE_ERROR) { | ||||
|         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; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose