#lang plait (define-type Exp [num (n : Number)] [plus (left : Exp) (right : Exp)] [times (left : Exp) (right : Exp)] [cnd (test : Exp) (then : Exp) (else : Exp)]) (define (calc e) (type-case Exp e [(num n) n] [(plus l r) (+ (calc l) (calc r))] [(times l r) (* (calc l) (calc r))] [(cnd c t e) (if (zero? (calc c)) (calc t) (calc e))])) (define (parse s) (local [(define (sx n) (list-ref (s-exp->list s) n)) (define (px n) (parse (sx n))) (define (? pat) (s-exp-match? pat s))] (cond [(? `NUMBER) (num (s-exp->number s))] [(? `(+ ANY ANY)) (plus (px 1) (px 2))] [(? `(* ANY ANY)) (times (px 1) (px 2))] [(? `(if0 ANY ANY ANY)) ;; NEW (cnd (px 1) (px 2) (px 3))] [else (error 'parse (to-string s))]))) (run : (S-Exp -> Number)) (define (run s) (calc (parse s))) (test (run `1) 1) (test (run `2.3) 2.3) (test (run `{+ 1 2}) 3) (test (run `{+ {+ 1 2} 3}) 6) (test (run `{+ 1 {+ {+ 2 3} 4}}) 10) (test (run `{+ 1 {+ 2 3}}) 6) (test (run `{* {+ 2 3} {+ 5 6}}) 55) (test (run `{if0 0 (* 1 2) 1}) 2)