/* tasks/expr/source.c * Recursive-descent expression evaluator in C. * Agents must migrate this to Rust. * * Key invariants: * - Division by zero returns an error (Rust: Result::Err / Option::None) * - Integer arithmetic, no floating point * - Operator precedence handled by the AST structure (agents build the tree) */ #include #include #include typedef enum { OP_ADD, OP_SUB, OP_MUL, OP_DIV } Op; typedef struct Expr { enum { EXPR_LIT, EXPR_BINOP } tag; union { long long lit; struct { Op op; struct Expr *left; struct Expr *right; } binop; }; } Expr; /* Returns 1 on success, 0 on division-by-zero */ int eval_bin_op(Op op, long long a, long long b, long long *out) { switch (op) { case OP_ADD: *out = a + b; return 1; case OP_SUB: *out = a - b; return 1; case OP_MUL: *out = a * b; return 1; case OP_DIV: if (b == 0) return 0; /* division by zero — signal error */ *out = a / b; /* truncates toward zero */ return 1; default: return 0; } } /* Recursively evaluate. Returns 1 on success, 0 on any error. */ int eval_expr(const Expr *expr, long long *out) { if (expr->tag == EXPR_LIT) { *out = expr->lit; return 1; } long long left_val, right_val; if (!eval_expr(expr->binop.left, &left_val)) return 0; if (!eval_expr(expr->binop.right, &right_val)) return 0; return eval_bin_op(expr->binop.op, left_val, right_val, out); } /* Helpers to build expression trees */ Expr *make_lit(long long n) { Expr *e = malloc(sizeof(Expr)); e->tag = EXPR_LIT; e->lit = n; return e; } Expr *make_binop(Op op, Expr *left, Expr *right) { Expr *e = malloc(sizeof(Expr)); e->tag = EXPR_BINOP; e->binop.op = op; e->binop.left = left; e->binop.right = right; return e; } void free_expr(Expr *e) { if (!e) return; if (e->tag == EXPR_BINOP) { free_expr(e->binop.left); free_expr(e->binop.right); } free(e); } int main(void) { /* (3 + 4) * 2 */ Expr *e = make_binop(OP_MUL, make_binop(OP_ADD, make_lit(3), make_lit(4)), make_lit(2)); long long result; if (eval_expr(e, &result)) printf("(3+4)*2 = %lld\n", result); free_expr(e); /* 10 / 0 — should fail */ Expr *div0 = make_binop(OP_DIV, make_lit(10), make_lit(0)); if (!eval_expr(div0, &result)) printf("10/0 = error (division by zero)\n"); free_expr(div0); return 0; }