(* Implementation of a simple, command-oriented language. *)
(* grammar ------------------------------------------------------------------ *)
(*
BNF grammar for this simple language:
<exp> ::=
| <X>
| <exp> + <exp>
| <exp> * <exp>
| <exp> < <exp>
| <integer constant>
| (<exp>)
<cmd> ::=
| skip
| <X> = <exp>
| ifNZ <exp> { <cmd> } else { <cmd> }
| whileNZ <exp> { <cmd> }
| <cmd>; <cmd>
*)
(* Abstract Syntax (AST) ---------------------------------------------------- *)
| Var of var
type cmd =
| Skip
| IfNZ
of exp * cmd
* cmd
| Seq of cmd * cmd
(* AST for Factorial Example ------------------------------------------------ *)
(*
X = 6;
ANS = 1;
whileNZ (x) {
ANS = ANS * X;
X = X + -1;
}
*)
let factorial : cmd =
let x = "X" in
let ans = "ANS" in
Seq (Assn (x, Lit 6),
Seq (Assn (ans, Lit 1),
WhileNZ(Var x,
Seq (Assn(ans, Mul(Var ans, Var x)),
Assn(x, Add(Var x, Lit (-1)))))))
(* Interpreter -------------------------------------------------------------- *)
let rec interpret_exp
(s
:state
) (e
:exp) : int = match e with
| Var x -> s x
| Add (e1, e2) -> (interpret_exp s e1) + (interpret_exp s e2)
| Mul (e1, e2) -> (interpret_exp s e1) * (interpret_exp s e2)
| Lt (e1, e2) -> if (interpret_exp s e1) < (interpret_exp s e2) then 1 else 0
| Lit n -> n
let update s x v =
fun y -> if x = y then v else s y
let rec interpret_cmd (s:state) (c:cmd) : state =
match c with
| Skip -> s
| Assn (x, e1) ->
let v = interpret_exp s e1 in
update s x v
| IfNZ (e1, c1, c2) ->
if (interpret_exp s e1) = 0 then interpret_cmd s c2 else interpret_cmd s c1
| WhileNZ (e, c) ->
if (interpret_exp s e) = 0 then s else interpret_cmd s (Seq(c, WhileNZ (e, c)))
| Seq (c1, c2) ->
let s1 = interpret_cmd s c1 in
interpret_cmd s1 c2
let init_state : state = fun _ -> 0
KCogSW1wbGVtZW50YXRpb24gb2YgYSBzaW1wbGUsIGNvbW1hbmQtb3JpZW50ZWQgbGFuZ3VhZ2UuICopCgoKKCogZ3JhbW1hciAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKikKKCoKIEJORiBncmFtbWFyIGZvciB0aGlzIHNpbXBsZSBsYW5ndWFnZToKICA8ZXhwPiA6Oj0gCiAgICAgICAgIHwgIDxYPgogICAgICAgICB8ICA8ZXhwPiArIDxleHA+CiAgICAgICAgIHwgIDxleHA+ICogPGV4cD4KICAgICAgICAgfCAgPGV4cD4gPCA8ZXhwPgogICAgICAgICB8ICA8aW50ZWdlciBjb25zdGFudD4KICAgICAgICAgfCAgKDxleHA+KQoKICA8Y21kPiA6Oj0gCiAgICAgICAgIHwgIHNraXAKICAgICAgICAgfCAgPFg+ID0gPGV4cD4KICAgICAgICAgfCAgaWZOWiA8ZXhwPiB7IDxjbWQ+IH0gZWxzZSB7IDxjbWQ+IH0KICAgICAgICAgfCAgd2hpbGVOWiA8ZXhwPiB7IDxjbWQ+IH0KICAgICAgICAgfCAgPGNtZD47IDxjbWQ+CiopCgooKiBBYnN0cmFjdCBTeW50YXggKEFTVCkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqKQoKdHlwZSB2YXIgPSBzdHJpbmcKCnR5cGUgZXhwID0KICB8IFZhciBvZiB2YXIKICB8IEFkZCBvZiAoZXhwICogZXhwKQogIHwgTXVsIG9mIChleHAgKiBleHApCiAgfCBMdCAgb2YgKGV4cCAqIGV4cCkKICB8IExpdCBvZiBpbnQKCnR5cGUgY21kID0KICB8IFNraXAKICB8IEFzc24gICAgb2YgdmFyICogZXhwCiAgfCBJZk5aICAgIG9mIGV4cCAqIGNtZCAqIGNtZAogIHwgV2hpbGVOWiBvZiBleHAgKiBjbWQKICB8IFNlcSAgICAgb2YgY21kICogY21kCgoKCigqIEFTVCBmb3IgRmFjdG9yaWFsIEV4YW1wbGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICopCigqCiAgICAgICAgWCA9IDY7CglBTlMgPSAxOwoJd2hpbGVOWiAoeCkgewogIAkJQU5TID0gQU5TICogWDsKICAJCVggPSBYICsgLTE7Cgl9IAogKikKCmxldCBmYWN0b3JpYWwgOiBjbWQgPQogIGxldCB4ID0gIlgiIGluCiAgbGV0IGFucyA9ICJBTlMiIGluCiAgU2VxIChBc3NuICh4LCBMaXQgNiksCiAgICAgICBTZXEgKEFzc24gKGFucywgTGl0IDEpLAogICAgICAgICAgICBXaGlsZU5aKFZhciB4LAogICAgICAgICAgICAgICAgICAgIFNlcSAoQXNzbihhbnMsIE11bChWYXIgYW5zLCBWYXIgeCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgQXNzbih4LCBBZGQoVmFyIHgsIExpdCAoLTEpKSkpKSkpCgooKiBJbnRlcnByZXRlciAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqKQoKdHlwZSBzdGF0ZSA9IHZhciAtPiBpbnQKCmxldCByZWMgaW50ZXJwcmV0X2V4cCAoczpzdGF0ZSkgKGU6ZXhwKSA6IGludCA9CiAgbWF0Y2ggZSB3aXRoCiAgfCBWYXIgeCAtPiBzIHgKICB8IEFkZCAoZTEsIGUyKSAtPiAoaW50ZXJwcmV0X2V4cCBzIGUxKSArIChpbnRlcnByZXRfZXhwIHMgZTIpCiAgfCBNdWwgKGUxLCBlMikgLT4gKGludGVycHJldF9leHAgcyBlMSkgKiAoaW50ZXJwcmV0X2V4cCBzIGUyKQogIHwgTHQgIChlMSwgZTIpIC0+IGlmIChpbnRlcnByZXRfZXhwIHMgZTEpIDwgKGludGVycHJldF9leHAgcyBlMikgdGhlbiAxIGVsc2UgMAogIHwgTGl0IG4gLT4gbgoKbGV0IHVwZGF0ZSBzIHggdiA9CiAgZnVuIHkgLT4gaWYgeCA9IHkgdGhlbiB2IGVsc2UgcyB5CgpsZXQgcmVjIGludGVycHJldF9jbWQgKHM6c3RhdGUpIChjOmNtZCkgOiBzdGF0ZSA9CiAgbWF0Y2ggYyB3aXRoCiAgfCBTa2lwIC0+IHMKICB8IEFzc24gKHgsIGUxKSAtPgogICAgbGV0IHYgPSBpbnRlcnByZXRfZXhwIHMgZTEgaW4KICAgIHVwZGF0ZSBzIHggdgogIHwgSWZOWiAoZTEsIGMxLCBjMikgLT4KICAgIGlmIChpbnRlcnByZXRfZXhwIHMgZTEpID0gMCB0aGVuIGludGVycHJldF9jbWQgcyBjMiBlbHNlIGludGVycHJldF9jbWQgcyBjMQogIHwgV2hpbGVOWiAoZSwgYykgLT4KICAgIGlmIChpbnRlcnByZXRfZXhwIHMgZSkgPSAwIHRoZW4gcyBlbHNlIGludGVycHJldF9jbWQgcyAoU2VxKGMsIFdoaWxlTlogKGUsIGMpKSkKICB8IFNlcSAoYzEsIGMyKSAtPgogICAgbGV0IHMxID0gaW50ZXJwcmV0X2NtZCBzIGMxIGluCiAgICBpbnRlcnByZXRfY21kIHMxIGMyCiAgCmxldCBpbml0X3N0YXRlIDogc3RhdGUgPSBmdW4gXyAtPiAwCiAgCg==