File size: 2,518 Bytes
bf9c466
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>

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;
}