mirror of
https://github.com/janet-lang/janet
synced 2025-07-07 04:22:54 +00:00
Add compiler optimizations for #1163 - eachp
Should result in much better bytecode in the simple case.
This commit is contained in:
parent
77189b6e66
commit
644ac8caf8
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user