initial commit
This commit is contained in:
commit
3545f2430e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
_build
|
||||||
1
dune-project
Normal file
1
dune-project
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
(lang dune 3.21)
|
||||||
11
shell.nix
Normal file
11
shell.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
let
|
||||||
|
pkgs = import <nixpkgs> {};
|
||||||
|
in
|
||||||
|
pkgs.mkShell {
|
||||||
|
packages = with pkgs.ocamlPackages; [
|
||||||
|
ocaml
|
||||||
|
dune_3
|
||||||
|
findlib
|
||||||
|
ppx_deriving
|
||||||
|
];
|
||||||
|
}
|
||||||
6
src/dune
Normal file
6
src/dune
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
(executable
|
||||||
|
(name main)
|
||||||
|
(preprocess (pps ppx_deriving.show)))
|
||||||
|
|
||||||
|
(ocamllex lexer)
|
||||||
|
(ocamlyacc parser)
|
||||||
49
src/exec.ml
Normal file
49
src/exec.ml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
open Types
|
||||||
|
|
||||||
|
let update m x v = fun y -> if x=y then v else m y
|
||||||
|
|
||||||
|
let rec builtin_iop f =
|
||||||
|
let iop1 m v =
|
||||||
|
match m "", v with
|
||||||
|
| VInt a, VInt b -> EInt (f a b)
|
||||||
|
| _, _ -> raise (Failure "iop: not int") in
|
||||||
|
VFn (builtin, "", EFnB iop1)
|
||||||
|
and builtin_bop f =
|
||||||
|
let bop1 m v =
|
||||||
|
match m "", v with
|
||||||
|
| VBool a, VBool b -> EBool (f a b)
|
||||||
|
| _, _ -> raise (Failure "bop: not bool") in
|
||||||
|
VFn (builtin, "", EFnB bop1)
|
||||||
|
and builtin = function
|
||||||
|
| "add" -> builtin_iop (+)
|
||||||
|
| "sub" -> builtin_iop (-)
|
||||||
|
| "mul" -> builtin_iop ( * )
|
||||||
|
| "div" -> builtin_iop (/)
|
||||||
|
| "and" -> builtin_bop (&&)
|
||||||
|
| "or" -> builtin_bop (||)
|
||||||
|
| _ -> raise (Failure "undefined var")
|
||||||
|
|
||||||
|
let rec eval (m: mem) (e: exp) : value =
|
||||||
|
match e with
|
||||||
|
| EInt i -> VInt i
|
||||||
|
| EBool b -> VBool b
|
||||||
|
| EVar x -> m x
|
||||||
|
| EFn (x, e) -> VFn (m, x, e)
|
||||||
|
| EFnB f -> VFnB (m, f)
|
||||||
|
| EApp (e1, e2) ->
|
||||||
|
(match eval m e1, eval m e2 with
|
||||||
|
| VFn (m, x, body), v -> eval (update m x v) body
|
||||||
|
| VFnB (m, f), v -> eval m (f m v)
|
||||||
|
| v, _ -> raise (Failure ("not a func")))
|
||||||
|
| EIf (b, e1, e2) ->
|
||||||
|
(match eval m b with
|
||||||
|
| VBool b -> eval m (if b then e1 else e2)
|
||||||
|
| _ -> raise (Failure "not a bool"))
|
||||||
|
| EScope s -> fst (exec m s)
|
||||||
|
and exec (m: mem) (s: stmt) =
|
||||||
|
match s with
|
||||||
|
| SExp e -> eval m e, m
|
||||||
|
| SAsgn (x, e) ->
|
||||||
|
let v = eval m e in
|
||||||
|
v, update m x v
|
||||||
|
| SSeq (s1, s2) -> exec (snd (exec m s1)) s2
|
||||||
28
src/lexer.mll
Normal file
28
src/lexer.mll
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
open Parser
|
||||||
|
}
|
||||||
|
rule token = parse
|
||||||
|
[' ' '\t' '\n']
|
||||||
|
{ token lexbuf }
|
||||||
|
| '(' { LPAREN }
|
||||||
|
| ')' { RPAREN }
|
||||||
|
(* | '{' { LBRACE } *)
|
||||||
|
(* | '}' { RBRACE } *)
|
||||||
|
| ';' { SEMICOLON }
|
||||||
|
| '=' { EQUAL }
|
||||||
|
| '+' { PLUS }
|
||||||
|
| '-' { MINUS }
|
||||||
|
| '*' { TIMES }
|
||||||
|
| '/' { DIVIDE }
|
||||||
|
| "&&" { AND }
|
||||||
|
| "||" { OR }
|
||||||
|
| "if" { IF }
|
||||||
|
| "then" { THEN }
|
||||||
|
| "else" { ELSE }
|
||||||
|
| "true" { TRUE }
|
||||||
|
| "false" { FALSE }
|
||||||
|
| "fn" { FN }
|
||||||
|
| ['0'-'9']+ { NUM (int_of_string (Lexing.lexeme lexbuf)) }
|
||||||
|
| ['A'-'Z' 'a'-'z' '_'] (['A'-'Z' 'a'-'z' '0'-'9' '_'])*
|
||||||
|
{ VAR (Lexing.lexeme lexbuf) }
|
||||||
|
| eof { EOF }
|
||||||
6
src/main.ml
Normal file
6
src/main.ml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
let main () =
|
||||||
|
let s = Parser.parse_stmt Lexer.token
|
||||||
|
(Lexing.from_channel (open_in Sys.argv.(1))) in
|
||||||
|
print_endline (Types.show_stmt s);
|
||||||
|
print_endline (Types.show_value (fst (Exec.exec Exec.builtin s)));;
|
||||||
|
main ();;
|
||||||
59
src/parser.mly
Normal file
59
src/parser.mly
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
%{
|
||||||
|
open Types
|
||||||
|
let app2 x a b = EApp (EApp (EVar x, a), b)
|
||||||
|
%}
|
||||||
|
%token LPAREN RPAREN SEMICOLON EQUAL OR AND PLUS MINUS TIMES DIVIDE EOF
|
||||||
|
%token IF THEN ELSE TRUE FALSE FN
|
||||||
|
%token<int> NUM
|
||||||
|
%token<string> VAR
|
||||||
|
|
||||||
|
%nonassoc EQUAL IF THEN ELSE
|
||||||
|
%left OR
|
||||||
|
%left AND
|
||||||
|
%right NOT
|
||||||
|
%nonassoc TRUE FALSE
|
||||||
|
%left PLUS MINUS
|
||||||
|
%left TIMES DIVIDE
|
||||||
|
%nonassoc NUM VAR
|
||||||
|
%right LPAREN RPAREN
|
||||||
|
%nonassoc EOF
|
||||||
|
|
||||||
|
%start parse_stmt
|
||||||
|
%type<Types.stmt> parse_stmt
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
parse_stmt:
|
||||||
|
| stmt { $1 }
|
||||||
|
| stmt SEMICOLON parse_stmt { SSeq ($1,$3) }
|
||||||
|
|
||||||
|
stmt:
|
||||||
|
| parse_exp { SExp $1 }
|
||||||
|
| VAR EQUAL parse_exp { SAsgn ($1,$3) }
|
||||||
|
|
||||||
|
parse_exp:
|
||||||
|
| exp { $1 }
|
||||||
|
| parse_exp exp { EApp ($1,$2) }
|
||||||
|
| IF parse_exp THEN parse_exp ELSE parse_exp
|
||||||
|
{ EIf ($2,$4,$6) }
|
||||||
|
| parse_exp AND parse_exp
|
||||||
|
{ app2 "and" $1 $3 }
|
||||||
|
| parse_exp OR parse_exp
|
||||||
|
{ app2 "or" $1 $3 }
|
||||||
|
| parse_exp PLUS parse_exp
|
||||||
|
{ app2 "add" $1 $3 }
|
||||||
|
| parse_exp MINUS parse_exp
|
||||||
|
{ app2 "sub" $1 $3 }
|
||||||
|
| parse_exp TIMES parse_exp
|
||||||
|
{ app2 "mul" $1 $3 }
|
||||||
|
| parse_exp DIVIDE parse_exp
|
||||||
|
{ app2 "div" $1 $3 }
|
||||||
|
| FN VAR parse_exp
|
||||||
|
{ EFn ($2,$3) }
|
||||||
|
|
||||||
|
exp:
|
||||||
|
| NUM { EInt $1 }
|
||||||
|
| TRUE { EBool true }
|
||||||
|
| FALSE { EBool false }
|
||||||
|
| VAR { EVar $1 }
|
||||||
|
| LPAREN parse_exp RPAREN { $2 }
|
||||||
26
src/types.ml
Normal file
26
src/types.ml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
type var = string
|
||||||
|
[@@deriving show]
|
||||||
|
|
||||||
|
type exp =
|
||||||
|
| EInt of int
|
||||||
|
| EBool of bool
|
||||||
|
| EVar of var
|
||||||
|
| EFn of (var * exp)
|
||||||
|
| EFnB of fnb
|
||||||
|
| EApp of (exp * exp)
|
||||||
|
| EIf of (exp * exp * exp)
|
||||||
|
| EScope of stmt
|
||||||
|
[@@deriving show]
|
||||||
|
and stmt =
|
||||||
|
| SExp of exp
|
||||||
|
| SAsgn of (var * exp)
|
||||||
|
| SSeq of (stmt * stmt)
|
||||||
|
[@@deriving show]
|
||||||
|
and mem = var -> value
|
||||||
|
and fnb = mem -> value -> exp
|
||||||
|
and value =
|
||||||
|
| VInt of int
|
||||||
|
| VBool of bool
|
||||||
|
| VFn of (mem * var * exp)
|
||||||
|
| VFnB of (mem * fnb)
|
||||||
|
[@@deriving show]
|
||||||
Loading…
Reference in a new issue