diff options
| author | kr.angelov <kr.angelov@gmail.com> | 2014-10-31 14:16:11 +0000 |
|---|---|---|
| committer | kr.angelov <kr.angelov@gmail.com> | 2014-10-31 14:16:11 +0000 |
| commit | b1e6a21c56c5aef62716c35546d4596e11bbbf94 (patch) | |
| tree | 2436602f1eb48f198ebab5ad389a4ea027415f8d /src/runtime/c/pgf/evaluator.c | |
| parent | 9b0f354c7cef175c172edae582dcfa48817db7ba (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.c | 157 |
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; + } +} |
