summaryrefslogtreecommitdiff
path: root/src/runtime/c/pgf/evaluator.c
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2014-10-31 14:16:11 +0000
committerkr.angelov <kr.angelov@gmail.com>2014-10-31 14:16:11 +0000
commitb1e6a21c56c5aef62716c35546d4596e11bbbf94 (patch)
tree2436602f1eb48f198ebab5ad389a4ea027415f8d /src/runtime/c/pgf/evaluator.c
parent9b0f354c7cef175c172edae582dcfa48817db7ba (diff)
now (+) in the abstract syntax works, i.e. it knows how to deal with partial sums
Diffstat (limited to 'src/runtime/c/pgf/evaluator.c')
-rw-r--r--src/runtime/c/pgf/evaluator.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/runtime/c/pgf/evaluator.c b/src/runtime/c/pgf/evaluator.c
index 62fe0bdd5..dcff1e854 100644
--- a/src/runtime/c/pgf/evaluator.c
+++ b/src/runtime/c/pgf/evaluator.c
@@ -313,6 +313,48 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
PgfExprVar,
&expr, pool);
evar->var = level - fun->level - 1;
+ } else if (val->fun->code == state->eval_gates->evaluate_sum) {
+ PgfValueSum* sum = (PgfValueSum*) val->fun;
+
+ PgfExpr e1,e2;
+ PgfExprFun *efun =
+ gu_new_flex_variant(PGF_EXPR_FUN,
+ PgfExprFun,
+ fun, 2,
+ &e1, pool);
+ strcpy(efun->fun, "+");
+
+ PgfExprLit *elit =
+ gu_new_variant(PGF_EXPR_LIT,
+ PgfExprLit,
+ &e2, pool);
+ elit->lit = sum->lit;
+
+ PgfExprApp* eapp =
+ gu_new_variant(PGF_EXPR_APP,
+ PgfExprApp,
+ &expr, pool);
+ eapp->fun = e1;
+ eapp->arg = e2;
+
+ size_t n_consts = gu_buf_length(sum->consts);
+ for (size_t i = 0; i < n_consts; i++) {
+ PgfClosure* con =
+ gu_buf_get(sum->consts, PgfClosure*, i);
+
+ PgfExpr fun = expr;
+ PgfExpr arg =
+ pgf_value2expr(state, level, con, pool);
+ if (gu_variant_is_null(arg))
+ return gu_null_variant;
+
+ PgfExprApp* e =
+ gu_new_variant(PGF_EXPR_APP,
+ PgfExprApp,
+ &expr, pool);
+ e->fun = fun;
+ e->arg = arg;
+ }
} else {
PgfAbsFun* absfun = gu_container(val->fun, PgfAbsFun, closure);
expr = absfun->ep.expr;
@@ -370,3 +412,118 @@ pgf_compute(PgfPGF* pgf, PgfExpr expr, GuExn* err, GuPool* pool, GuPool* out_poo
return pgf_value2expr(state, 0, &thunk->header, out_pool);
}
+
+void
+pgf_evaluate_accum_init_int(PgfEvalState* state,
+ PgfEvalAccum* accum, int val)
+{
+ PgfLiteralInt *lit_int =
+ gu_new_variant(PGF_LITERAL_INT,
+ PgfLiteralInt,
+ &accum->lit,
+ state->pool);
+ lit_int->val = val;
+ accum->consts = NULL;
+}
+
+void
+pgf_evaluate_accum_init_str(PgfEvalState* state,
+ PgfEvalAccum* accum, GuString val)
+{
+ if (val == NULL)
+ val = "";
+
+ PgfLiteralStr *lit_str =
+ gu_new_flex_variant(PGF_LITERAL_STR,
+ PgfLiteralStr,
+ val, strlen(val)+1,
+ &accum->lit, state->pool);
+ strcpy((char*) lit_str->val, (char*) val);
+ accum->consts = NULL;
+}
+
+void
+pgf_evaluate_accum_init_flt(PgfEvalState* state,
+ PgfEvalAccum* accum, float val)
+{
+ PgfLiteralFlt *lit_flt =
+ gu_new_variant(PGF_LITERAL_FLT,
+ PgfLiteralFlt,
+ &accum->lit,
+ state->pool);
+ lit_flt->val = val;
+ accum->enter_stack_ptr = state->enter_stack_ptr;
+ state->enter_stack_ptr = ((void*)accum)-sizeof(void*)*2;
+ accum->consts = NULL;
+}
+
+static void
+pgf_evaluate_accum_add_helper(PgfEvalAccum* accum, PgfLiteral lit)
+{
+ GuVariantInfo ei = gu_variant_open(lit);
+ switch (ei.tag) {
+ case PGF_LITERAL_INT: {
+ PgfLiteralInt* lint = ei.data;
+ ((PgfLiteralInt*)gu_variant_data(accum->lit))->val += lint->val;
+ break;
+ }
+ case PGF_LITERAL_STR: {
+ PgfLiteralStr* lstr = ei.data;
+ break;
+ }
+ case PGF_LITERAL_FLT: {
+ PgfLiteralFlt* lflt = ei.data;
+ ((PgfLiteralFlt*)gu_variant_data(accum->lit))->val += lflt->val;
+ break;
+ }
+ }
+}
+
+void
+pgf_evaluate_accum_add(PgfEvalState* state,
+ PgfEvalAccum* accum, PgfClosure* closure)
+{
+ if (closure->code == state->eval_gates->evaluate_value_lit) {
+ PgfValueLit* val = (PgfValueLit*) closure;
+ pgf_evaluate_accum_add_helper(accum, val->lit);
+ } else if (closure->code == state->eval_gates->evaluate_value_const) {
+ if (accum->consts == NULL)
+ accum->consts = gu_new_buf(PgfClosure*, state->pool);
+
+ PgfValuePAP* pap = (PgfValuePAP*) closure;
+
+ if (pap->fun->code == state->eval_gates->evaluate_sum) {
+ PgfValueSum* val = (PgfValueSum*) ((PgfValuePAP*) closure)->fun;
+ pgf_evaluate_accum_add_helper(accum, val->lit);
+
+ size_t n_consts = gu_buf_length(val->consts);
+ for (size_t i = 0; i < n_consts; i++) {
+ PgfClosure* clos = gu_buf_get(val->consts, PgfClosure*, i);
+ gu_buf_push(accum->consts, PgfClosure*, clos);
+ }
+ } else {
+ gu_buf_push(accum->consts, PgfClosure*, closure);
+ }
+ } else {
+ gu_impossible();
+ }
+}
+
+PgfClosure*
+pgf_evaluate_accum_done(PgfEvalState* state, PgfEvalAccum* accum)
+{
+ state->enter_stack_ptr = accum->enter_stack_ptr;
+
+ if (accum->consts == NULL) {
+ PgfValueLit* val = gu_new(PgfValueLit, state->pool);
+ val->header.code = state->eval_gates->evaluate_value_lit;
+ val->lit = accum->lit;
+ return &val->header;
+ } else {
+ PgfValueSum* val = gu_new(PgfValueSum, state->pool);
+ val->header.code = state->eval_gates->evaluate_sum;
+ val->lit = accum->lit;
+ val->consts = accum->consts;
+ return &val->header;
+ }
+}