Shells in OCaml
at main 58 lines 1.8 kB view raw
1(* We handle _very_ simple arithmetic expressions. 2 Really nothing crazy yet, hopefully enough to handle 3 most [while x < 10 do x = x + 1 done] loops! *) 4type operator = Add | Sub | Mul | Div | Mod | Lt | Gt | Eq 5[@@deriving to_yojson] 6 7let exec_op = function 8 | Add -> Int.add 9 | Sub -> Int.sub 10 | Mul -> Int.mul 11 | Div -> Int.div 12 | Mod -> ( mod ) 13 | Lt -> fun a b -> if a < b then 1 else 0 14 | Gt -> fun a b -> if a > b then 1 else 0 15 | Eq -> fun a b -> if Int.equal a b then 1 else 0 16 17type expr = 18 | Int of int 19 | Var of string 20 | Binop of operator * expr * expr 21 | Neg of expr 22 | Assign of operator * string * expr 23 | Ternary of (expr * expr * expr) 24[@@deriving to_yojson] 25 26module Make (S : Types.State) = struct 27 let eval initial_state expr = 28 let lookup state s = 29 match S.lookup state ~param:s with 30 | Some n when Option.is_some (int_of_string_opt n) -> int_of_string n 31 | _ -> 0 32 in 33 let update state s i = 34 match S.update state ~param:s (string_of_int i) with 35 | Ok s -> s 36 | Error m -> failwith m 37 in 38 let rec calc state = function 39 | Int i -> (state, i) 40 | Var v -> (state, lookup state v) 41 | Binop (op, e1, e2) -> 42 let state, v1 = calc state e1 in 43 let state, v2 = calc state e2 in 44 (state, exec_op op v1 v2) 45 | Neg n -> 46 let state, v1 = calc state n in 47 (state, Int.neg v1) 48 | Assign (op, var, e) -> 49 let current_v = lookup state var in 50 let state, v1 = calc state e in 51 let nv = exec_op op current_v v1 in 52 (update state var nv, nv) 53 | Ternary (e1, e2, e3) -> 54 let state, v1 = calc state e1 in 55 if Int.equal v1 Int.zero then calc state e3 else calc state e2 56 in 57 calc initial_state expr 58end