Skip to content
Snippets Groups Projects
Commit ba7dc02c authored by Augustin Jaujay's avatar Augustin Jaujay
Browse files

WIP question 9

parent 33646397
No related branches found
No related tags found
No related merge requests found
(library
(name funExpr)
(libraries utils common basicPfx)
(modules Ast Lexer Parser Eval toPfx))
(ocamllex lexer)
(menhir
(modules parser)
(flags --explain))
open Ast
exception RuntimeError of string
let rec eval env = function
| Const c -> c
| Var v -> (try List.assoc v env with Not_found -> raise(RuntimeError("Unbound variable "^v)))
| Binop(op,e1,e2) ->
begin
match op,eval env e2 with
| (Bdiv | Bmod), 0 -> raise(RuntimeError("division by zero"))
| _, v -> (BinOp.eval op) (eval env e1) v
end
| Uminus e -> - (eval env e)
(* Exception that may be raised on error at run time by the function eval *)
exception RuntimeError of string
(* Function that evaluates an expression in a given environment *)
val eval : (string * int) list -> Ast.expression -> int
open Ast
open BasicPfx.Ast
(* Question 5.2 *)
let rec generate = function
| Const x -> [Push x]
| Binop(Badd,a,b) -> (generate b) @ (generate a) @ [Add]
| Binop(Bsub,a,b) -> (generate b) @ (generate a) @ [Sub]
| Binop(Bmul,a,b) -> (generate b) @ (generate a) @ [Mul]
| Binop(Bdiv,a,b) -> (generate b) @ (generate a) @ [Div]
| Binop(Bmod,a,b) -> (generate b) @ (generate a) @ [Rem]
| Uminus x -> (generate x) @ [Push 0] @ [Sub]
| Var _ -> failwith "Not yet supported"
(* Function that generate a Pfx program from an Expr program *)
val generate : Ast.expression -> BasicPfx.Ast.command list
(* Question 4.1 *)
type command = Push of int | Pop | Swap | Add | Sub | Mul | Div | Rem
type command = Push of int | Pop | Swap | Add | Sub | Mul | Div | Rem | Exec | Get
type program = int * command list
......
......
(* The type of the commands for the stack machine *)
type command = Push of int | Pop | Swap | Add | Sub | Mul | Div | Rem
type command = Push of int | Pop | Swap | Add | Sub | Mul | Div | Rem | Exec | Get
(* The type for programs *)
type program = int * command list
......
......
......@@ -29,6 +29,8 @@ let step state =
| Rem::_, _::[] -> Error("Nothing to divide",state)
| Rem::_, [] -> Error("Nothing to divide",state)
| Rem::_, _::0::_ -> Error("Forbidden operation",state)
| Get::_, i::stack when (List.length stack) < i -> Error("Invalid get operation", state)
| Get::_, i::_ when i < O -> Error("Cannot get negative index", state)
(* Valid configurations *)
| (Push x)::q, stack -> Ok (q, x::stack)
| Pop::q, _::stack -> Ok (q, stack)
......@@ -38,6 +40,7 @@ let step state =
| Mul::q, x::y::stack -> Ok (q, (x * y)::stack)
| Div::q, x::y::stack -> Ok (q, (x / y)::stack)
| Rem::q, x::y::stack -> Ok (q, (x mod y)::stack)
| Get::q, i::stack -> Ok (q, (List.nth stack i)::stack)
let eval_program (numargs, cmds) args =
let rec execute = function
......
......
......@@ -34,5 +34,7 @@ rule token = parse
| "mul" {MUL}
| "div" {DIV}
| "rem" {REM}
| "exec" {EXEC}
| "get" {GET}
(* illegal characters *)
| _ { failwith (Location.string_of (Location.curr lexbuf)) }
\ No newline at end of file
......@@ -6,7 +6,7 @@
* The tokens *
**************)
%token EOF PUSH POP SWAP ADD SUB MUL DIV REM
%token EOF PUSH POP SWAP ADD SUB MUL DIV REM EXEC GET
%token <int> INT
......@@ -36,6 +36,8 @@ command:
| MUL c=command { Mul::c }
| DIV c=command { Div::c }
| REM c=command { Rem::c }
| EXEC c=command { Exec::c }
| GET c=command { Get::c }
| EOF { [] }
%%
0 push 2 push 4 swap
0 push 2 push 7 push 3 add div -- -5
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment