Add Bool and If
This commit is contained in:
parent
1f91d214ee
commit
a752932913
4 changed files with 52 additions and 20 deletions
12
ast.ml
12
ast.ml
|
@ -2,6 +2,7 @@
|
||||||
type t =
|
type t =
|
||||||
| Nint of int
|
| Nint of int
|
||||||
| Nfloat of float
|
| Nfloat of float
|
||||||
|
| Nbool of bool
|
||||||
| Nstring of string
|
| Nstring of string
|
||||||
| Nsymbol of string
|
| Nsymbol of string
|
||||||
| Nfunction of string list * t
|
| Nfunction of string list * t
|
||||||
|
@ -10,6 +11,7 @@ type t =
|
||||||
| Let of string * t
|
| Let of string * t
|
||||||
| Unary of operator * t
|
| Unary of operator * t
|
||||||
| Binop of t * operator * t
|
| Binop of t * operator * t
|
||||||
|
| If of t * t * t (* cond then else *)
|
||||||
| Apply of t * t list (* function application *)
|
| Apply of t * t list (* function application *)
|
||||||
(* these will be seperated into (toplevel) directives. *)
|
(* these will be seperated into (toplevel) directives. *)
|
||||||
| Set_binop_pre of operator * t
|
| Set_binop_pre of operator * t
|
||||||
|
@ -44,12 +46,13 @@ let print ast =
|
||||||
let rec aux = function
|
let rec aux = function
|
||||||
| Nint n -> pr "%d" n
|
| Nint n -> pr "%d" n
|
||||||
| Nfloat n -> pr "%f" n
|
| Nfloat n -> pr "%f" n
|
||||||
|
| Nbool b -> pr "%b" b
|
||||||
| Nstring s -> pr "\"%s\"" s
|
| Nstring s -> pr "\"%s\"" s
|
||||||
| Nsymbol s -> pr "#%s" s
|
| Nsymbol s -> pr "#%s" s
|
||||||
| Nfunction (args, e) ->
|
| Nfunction (args, e) ->
|
||||||
pr "lambda (%s" @@ List.hd args;
|
pr "(lambda (%s" @@ List.hd args;
|
||||||
List.iter (pr " %s") @@ List.tl args;
|
List.iter (pr " %s") @@ List.tl args;
|
||||||
pr ") ("; aux e; pr")"
|
pr ") "; aux e; pr ")"
|
||||||
| Nexternal e -> pr "(extern %s)" e
|
| Nexternal e -> pr "(extern %s)" e
|
||||||
| Var v -> pr "%s" v
|
| Var v -> pr "%s" v
|
||||||
| Let (v, e) ->
|
| Let (v, e) ->
|
||||||
|
@ -60,8 +63,11 @@ let print ast =
|
||||||
| Binop (left, op, right) ->
|
| Binop (left, op, right) ->
|
||||||
let op = op_to_string op in
|
let op = op_to_string op in
|
||||||
pr "(%s " op; aux left; pr " "; aux right; pr ")"
|
pr "(%s " op; aux left; pr " "; aux right; pr ")"
|
||||||
|
| If (co, th, el) ->
|
||||||
|
let f e = pr " "; aux e in
|
||||||
|
pr "(if"; f co; f th; f el; pr ")"
|
||||||
| Apply (f, args) ->
|
| Apply (f, args) ->
|
||||||
pr "("; List.iter aux @@ f::args; pr ")"
|
pr "("; aux f; List.iter (fun a -> pr " "; aux a) args; pr ")"
|
||||||
|
|
||||||
| Set_binop_pre (op, pre) ->
|
| Set_binop_pre (op, pre) ->
|
||||||
pr "(set_pre %s " (op_to_string op);
|
pr "(set_pre %s " (op_to_string op);
|
||||||
|
|
14
eval.ml
14
eval.ml
|
@ -1,8 +1,10 @@
|
||||||
open Ast
|
open Ast
|
||||||
|
|
||||||
|
(* resulting value of eval *)
|
||||||
type value =
|
type value =
|
||||||
| Int of int
|
| Int of int
|
||||||
| Float of float
|
| Float of float
|
||||||
|
| Bool of bool
|
||||||
| String of string
|
| String of string
|
||||||
| Symbol of string
|
| Symbol of string
|
||||||
| Function of string list * expr
|
| Function of string list * expr
|
||||||
|
@ -11,6 +13,7 @@ type value =
|
||||||
|
|
||||||
and expr = Ast.t
|
and expr = Ast.t
|
||||||
|
|
||||||
|
(* environment for eval *)
|
||||||
and env = {
|
and env = {
|
||||||
vars : (string, value) Hashtbl.t;
|
vars : (string, value) Hashtbl.t;
|
||||||
parent : env option;
|
parent : env option;
|
||||||
|
@ -23,6 +26,7 @@ module Type = struct
|
||||||
type t =
|
type t =
|
||||||
| Int
|
| Int
|
||||||
| Float
|
| Float
|
||||||
|
| Bool
|
||||||
| String
|
| String
|
||||||
| Symbol
|
| Symbol
|
||||||
| Function
|
| Function
|
||||||
|
@ -33,6 +37,7 @@ module Type = struct
|
||||||
let to_string = function
|
let to_string = function
|
||||||
| Int -> "int"
|
| Int -> "int"
|
||||||
| Float -> "float"
|
| Float -> "float"
|
||||||
|
| Bool -> "bool"
|
||||||
| String -> "string"
|
| String -> "string"
|
||||||
| Symbol -> "symbol"
|
| Symbol -> "symbol"
|
||||||
| Function -> "fun"
|
| Function -> "fun"
|
||||||
|
@ -49,6 +54,7 @@ module Value = struct
|
||||||
let to_string = function
|
let to_string = function
|
||||||
| Int n -> string_of_int n
|
| Int n -> string_of_int n
|
||||||
| Float n -> string_of_float n
|
| Float n -> string_of_float n
|
||||||
|
| Bool b -> string_of_bool b
|
||||||
| String s -> "\"" ^ s ^ "\""
|
| String s -> "\"" ^ s ^ "\""
|
||||||
| Symbol s -> "symbol " ^ s
|
| Symbol s -> "symbol " ^ s
|
||||||
| Function (vars, _) ->
|
| Function (vars, _) ->
|
||||||
|
@ -59,6 +65,7 @@ module Value = struct
|
||||||
let typeof = function
|
let typeof = function
|
||||||
| Int _ -> Type.Int
|
| Int _ -> Type.Int
|
||||||
| Float _ -> Type.Float
|
| Float _ -> Type.Float
|
||||||
|
| Bool _ -> Type.Bool
|
||||||
| String _ -> Type.String
|
| String _ -> Type.String
|
||||||
| Symbol _ -> Type.Symbol
|
| Symbol _ -> Type.Symbol
|
||||||
| Function _ -> Type.Function
|
| Function _ -> Type.Function
|
||||||
|
@ -217,6 +224,7 @@ let rec eval env ast : string * value =
|
||||||
let rec aux = function
|
let rec aux = function
|
||||||
| Nint n -> Int n
|
| Nint n -> Int n
|
||||||
| Nfloat n -> Float n
|
| Nfloat n -> Float n
|
||||||
|
| Nbool b -> Bool b
|
||||||
| Nstring s -> String s
|
| Nstring s -> String s
|
||||||
| Nsymbol s -> Symbol s
|
| Nsymbol s -> Symbol s
|
||||||
| Nfunction (args, e) -> Function (args, e)
|
| Nfunction (args, e) -> Function (args, e)
|
||||||
|
@ -232,6 +240,12 @@ let rec eval env ast : string * value =
|
||||||
| Binop (l, op, r) ->
|
| Binop (l, op, r) ->
|
||||||
let l = aux l and r = aux r in
|
let l = aux l and r = aux r in
|
||||||
binop op l r
|
binop op l r
|
||||||
|
| If (co, th, el) ->
|
||||||
|
begin match aux co with
|
||||||
|
| Bool true -> aux th
|
||||||
|
| Bool false -> aux el
|
||||||
|
| v -> raise @@ Type.Invalid (Value.typeof v)
|
||||||
|
end
|
||||||
| Apply (v, args) ->
|
| Apply (v, args) ->
|
||||||
begin match aux v with
|
begin match aux v with
|
||||||
| Function (vars, e) ->
|
| Function (vars, e) ->
|
||||||
|
|
10
main.ml
10
main.ml
|
@ -2,6 +2,7 @@ open Printf
|
||||||
open Eval
|
open Eval
|
||||||
|
|
||||||
let version = "%%VERSION%%"
|
let version = "%%VERSION%%"
|
||||||
|
let debug = ref false
|
||||||
|
|
||||||
let error_to_string e =
|
let error_to_string e =
|
||||||
try raise e with
|
try raise e with
|
||||||
|
@ -36,12 +37,9 @@ let rep env : unit =
|
||||||
printf "> ";
|
printf "> ";
|
||||||
let line = read_line () in
|
let line = read_line () in
|
||||||
if line = "quit" then raise Exit;
|
if line = "quit" then raise Exit;
|
||||||
let var, v =
|
let ast = line |> Lex.tokenize |> Parser.parse in
|
||||||
line
|
if !debug then Ast.print ast;
|
||||||
|> Lex.tokenize
|
let var, v = Eval.eval env ast in
|
||||||
|> Parser.parse
|
|
||||||
|> Eval.eval env
|
|
||||||
in
|
|
||||||
match v with
|
match v with
|
||||||
| Nop -> ()
|
| Nop -> ()
|
||||||
| _ ->
|
| _ ->
|
||||||
|
|
36
parser.ml
36
parser.ml
|
@ -148,6 +148,14 @@ let rec decl seq =
|
||||||
expr min_int;
|
expr min_int;
|
||||||
]
|
]
|
||||||
|
|
||||||
|
(* let_value := "let" ident "=" expr *)
|
||||||
|
and let_value seq =
|
||||||
|
let _, seq = ident "let" seq in
|
||||||
|
let id, seq = any_ident seq in
|
||||||
|
let _, seq = token Token.Equal seq in
|
||||||
|
let e, seq = expr min_int seq in
|
||||||
|
Let (id, e), seq
|
||||||
|
|
||||||
(* expr := level
|
(* expr := level
|
||||||
* | assoc
|
* | assoc
|
||||||
* | apply
|
* | apply
|
||||||
|
@ -155,12 +163,13 @@ let rec decl seq =
|
||||||
*)
|
*)
|
||||||
and expr pre seq =
|
and expr pre seq =
|
||||||
seq |> oneof [
|
seq |> oneof [
|
||||||
|
(either unary value) @> binop pre;
|
||||||
|
ifexpr;
|
||||||
level;
|
level;
|
||||||
assoc;
|
assoc;
|
||||||
lambda;
|
lambda;
|
||||||
extern_value;
|
extern_value;
|
||||||
apply;
|
apply;
|
||||||
(either unary value) @> binop pre;
|
|
||||||
]
|
]
|
||||||
|
|
||||||
(* level := "level" {"get" | "set"} [op] *)
|
(* level := "level" {"get" | "set"} [op] *)
|
||||||
|
@ -189,14 +198,6 @@ and assoc seq =
|
||||||
else
|
else
|
||||||
failwith "Parser.assoc"
|
failwith "Parser.assoc"
|
||||||
|
|
||||||
(* let_value := "let" ident "=" expr *)
|
|
||||||
and let_value seq =
|
|
||||||
let _, seq = ident "let" seq in
|
|
||||||
let id, seq = any_ident seq in
|
|
||||||
let _, seq = token Token.Equal seq in
|
|
||||||
let e, seq = expr min_int seq in
|
|
||||||
Let (id, e), seq
|
|
||||||
|
|
||||||
(* lambda := "fun" [ident]+ "->" expr *)
|
(* lambda := "fun" [ident]+ "->" expr *)
|
||||||
and lambda seq =
|
and lambda seq =
|
||||||
let _, seq = ident "fun" seq in
|
let _, seq = ident "fun" seq in
|
||||||
|
@ -206,6 +207,16 @@ and lambda seq =
|
||||||
let e, seq = expr min_int seq in
|
let e, seq = expr min_int seq in
|
||||||
Nfunction (v0::vars, e), seq
|
Nfunction (v0::vars, e), seq
|
||||||
|
|
||||||
|
(* ifexpr := "if" expr "then" expr "else" expr *)
|
||||||
|
and ifexpr seq =
|
||||||
|
let _, seq = ident "if" seq in
|
||||||
|
let co, seq = expr min_int seq in
|
||||||
|
let _, seq = ident "then" seq in
|
||||||
|
let th, seq = expr min_int seq in
|
||||||
|
let _, seq = ident "else" seq in
|
||||||
|
let el, seq = expr min_int seq in
|
||||||
|
If (co, th, el), seq
|
||||||
|
|
||||||
(* apply := value [value]+ *)
|
(* apply := value [value]+ *)
|
||||||
and apply seq =
|
and apply seq =
|
||||||
let v, seq = value seq in
|
let v, seq = value seq in
|
||||||
|
@ -237,7 +248,9 @@ and value seq =
|
||||||
match seq () with
|
match seq () with
|
||||||
| Seq.Nil -> raise End_of_tokens
|
| Seq.Nil -> raise End_of_tokens
|
||||||
| Seq.Cons (x, seq) -> begin match x with
|
| Seq.Cons (x, seq) -> begin match x with
|
||||||
| Token.Ident id -> Var id, seq
|
| Ident "true" -> Nbool true, seq
|
||||||
|
| Ident "false" -> Nbool false, seq
|
||||||
|
| Ident id -> Var id, seq
|
||||||
| Int x -> Nint x, seq
|
| Int x -> Nint x, seq
|
||||||
| Float x -> Nfloat x, seq
|
| Float x -> Nfloat x, seq
|
||||||
| String x -> Nstring x, seq
|
| String x -> Nstring x, seq
|
||||||
|
@ -268,7 +281,8 @@ and binop pre left seq =
|
||||||
else
|
else
|
||||||
left, Seq.cons x seq
|
left, Seq.cons x seq
|
||||||
|
|
||||||
| Token.RParen -> left, Seq.cons x seq
|
| RParen | Ident "then" | Ident "else" ->
|
||||||
|
left, Seq.cons x seq
|
||||||
| _ -> unexpected_token x
|
| _ -> unexpected_token x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue