void Expr::partial_eval_primitive_application() { Expr* lhs = arg1; Expr* rhs = arg2->drop_i1(); // arg1 and arg2 are now uninitialized space switch (lhs->type) { case K: type = K1; arg1 = rhs; arg2 = 0; break; case K1: type = I1; arg1 = lhs->arg1->dup(); arg2 = 0; rhs->deref(); break; case S: type = S1; arg1 = rhs; arg2 = 0; break; case S1: type = S2; arg1 = lhs->arg1->dup(); arg2 = rhs; break; case LazyRead: lhs->type = S2; lhs->arg1 = new Expr(S2, I.dup(), new Expr(K1, make_church_char(getchar()))); lhs->arg2 = new Expr(K1, new Expr(LazyRead)); // fall thru case S2: //type = A; arg1 = partial_apply(lhs->arg1->dup(), rhs->dup()); arg2 = partial_apply(lhs->arg2->dup(), rhs); break; case Inc: rhs = rhs->partial_eval(); type = Num; numeric_arg1 = rhs->to_number() + 1; if (numeric_arg1 == 0) { fputs("Runtime error: invalid output format (attempted to apply inc to a non-number)\n", stderr); exit(3); } arg2 = 0; break; case Num: fputs("Runtime error: invalid output format (attempted to apply a number)\n", stderr); exit(3); default: fprintf(stderr, "INTERNAL ERROR: invalid type in partial_eval_primitive_application (%d)\n", lhs->type); exit(4); } lhs->deref(); }
Expr* Expr::partial_eval() { Expr* prev = 0; Expr* cur = this; for (;;) { cur = cur->drop_i1(); while (cur->type == A) { Expr* next = cur->arg1->drop_i1(); cur->arg1 = prev; prev = cur; cur = next; } if (!prev) { return cur; } Expr* next = cur; cur = prev; prev = cur->arg1; cur->arg1 = next; cur->partial_eval_primitive_application(); } }