summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2014-08-09 20:47:03 -0500
committerNicolas Williams <nico@cryptonector.com>2014-08-09 20:47:03 -0500
commitc321c3b86bb319156502985ee5174e3476a5ca8c (patch)
tree4ca3ff4f2bad85ee6f03de4ddd806866ed0f4e17
parentf87521183f5c499b3c58e016c5936ade14819fd3 (diff)
Constant fold objects
-rw-r--r--compile.c46
-rw-r--r--compile.h1
-rw-r--r--parser.y6
3 files changed, 51 insertions, 2 deletions
diff --git a/compile.c b/compile.c
index 612920c0..6005f7c3 100644
--- a/compile.c
+++ b/compile.c
@@ -499,7 +499,51 @@ block gen_both(block a, block b) {
return c;
}
-block gen_const_array(block expr) {
+block gen_const_object(block expr) {
+ int is_const = 1;
+ jv o = jv_object();
+ jv k = jv_null();
+ jv v = jv_null();
+ for (inst *i = expr.first; i; i = i->next) {
+ if (i->op != SUBEXP_BEGIN ||
+ i->next == NULL ||
+ i->next->op != LOADK ||
+ i->next->next == NULL ||
+ i->next->next->op != SUBEXP_END) {
+ is_const = 0;
+ break;
+ }
+ k = jv_copy(i->next->imm.constant);
+ i = i->next->next->next;
+ if (i == NULL ||
+ i->op != SUBEXP_BEGIN ||
+ i->next == NULL ||
+ i->next->op != LOADK ||
+ i->next->next == NULL ||
+ i->next->next->op != SUBEXP_END) {
+ is_const = 0;
+ break;
+ }
+ v = jv_copy(i->next->imm.constant);
+ i = i->next->next->next;
+ if (i == NULL || i->op != INSERT) {
+ is_const = 0;
+ break;
+ }
+ o = jv_object_set(o, k, v);
+ }
+ if (!is_const) {
+ jv_free(o);
+ jv_free(k);
+ jv_free(v);
+ block b = {0,0};
+ return b;
+ }
+ block_free(expr);
+ return gen_const(o);
+}
+
+static block gen_const_array(block expr) {
/*
* An expr of all constant elements looks like this:
*
diff --git a/compile.h b/compile.h
index ff8b8972..b0162ae2 100644
--- a/compile.h
+++ b/compile.h
@@ -36,6 +36,7 @@ block gen_lambda(block body);
block gen_call(const char* name, block body);
block gen_subexp(block a);
block gen_both(block a, block b);
+block gen_const_object(block expr);
block gen_collect(block expr);
block gen_reduce(const char* varname, block source, block init, block body);
block gen_foreach(const char* varname, block source, block init, block update, block extract);
diff --git a/parser.y b/parser.y
index 8fffb7cc..9f925948 100644
--- a/parser.y
+++ b/parser.y
@@ -631,7 +631,11 @@ FORMAT {
$$ = gen_const(jv_array());
} |
'{' MkDict '}' {
- $$ = BLOCK(gen_subexp(gen_const(jv_object())), $2, gen_op_simple(POP));
+ block o = gen_const_object($2);
+ if (o.first != NULL)
+ $$ = o;
+ else
+ $$ = BLOCK(gen_subexp(gen_const(jv_object())), $2, gen_op_simple(POP));
} |
'$' IDENT {
$$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($2)));