UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture02/ run.rkt
#lang plait
(define-type Exp
  [num (n : Number)]
  [plus (left : Exp) (right : Exp)]
  [times (left : Exp) (right : 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))]))

(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))]
      [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)