aboutsummaryrefslogtreecommitdiff
path: root/ocaml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml')
-rw-r--r--ocaml/Makefile5
-rw-r--r--ocaml/core.ml14
-rw-r--r--ocaml/printer.ml14
-rw-r--r--ocaml/step1_read_print.ml2
-rw-r--r--ocaml/step2_eval.ml2
-rw-r--r--ocaml/step3_env.ml2
-rw-r--r--ocaml/step4_if_fn_do.ml8
-rw-r--r--ocaml/types.ml4
8 files changed, 36 insertions, 15 deletions
diff --git a/ocaml/Makefile b/ocaml/Makefile
index 5e8b62a..bad3f60 100644
--- a/ocaml/Makefile
+++ b/ocaml/Makefile
@@ -1,5 +1,6 @@
-STEPS = step0_repl.ml step1_read_print.ml step2_eval.ml step3_env.ml
-MODULES = types.ml reader.ml printer.ml env.ml
+STEPS = step0_repl.ml step1_read_print.ml step2_eval.ml step3_env.ml \
+ step4_if_fn_do.ml
+MODULES = types.ml reader.ml printer.ml env.ml core.ml
LIBS = str.cmxa
MAL_LIB = mal_lib.cmxa
diff --git a/ocaml/core.ml b/ocaml/core.ml
index 4cec7f1..c11c9f9 100644
--- a/ocaml/core.ml
+++ b/ocaml/core.ml
@@ -28,5 +28,19 @@ let init env = begin
Env.set env (Types.Symbol "=")
(Types.Fn (function [a; b] -> Types.Bool (a = b) | _ -> Types.Bool false));
+ Env.set env (Types.Symbol "pr-str")
+ (Types.Fn (function xs ->
+ Types.String (Printer.join " " (List.map (fun s -> Printer.pr_str s true) xs))));
+ Env.set env (Types.Symbol "str")
+ (Types.Fn (function xs ->
+ Types.String (Printer.join "" (List.map (fun s -> Printer.pr_str s false) xs))));
+ Env.set env (Types.Symbol "prn")
+ (Types.Fn (function xs ->
+ print_endline (Printer.join " " (List.map (fun s -> Printer.pr_str s true) xs));
+ Types.Nil));
+ Env.set env (Types.Symbol "println")
+ (Types.Fn (function xs ->
+ print_endline (Printer.join " " (List.map (fun s -> Printer.pr_str s false) xs));
+ Types.Nil));
end
diff --git a/ocaml/printer.ml b/ocaml/printer.ml
index e87b3eb..fc9e47b 100644
--- a/ocaml/printer.ml
+++ b/ocaml/printer.ml
@@ -1,7 +1,7 @@
let join sep xs =
List.fold_left (fun a x -> if a = "" then x else a ^ sep ^ x) "" xs
-let rec pr_str mal_obj =
+let rec pr_str mal_obj print_readably =
match mal_obj with
| Types.Int i -> string_of_int i
| Types.Symbol s -> s
@@ -9,8 +9,10 @@ let rec pr_str mal_obj =
| Types.Nil -> "nil"
| Types.Bool true -> "true"
| Types.Bool false -> "false"
- | Types.String s -> "\""
- ^ (Str.global_replace (Str.regexp "\"") "\\\"" s)
- ^ "\""
- | Types.MalList xs -> "(" ^ (join " " (List.map pr_str xs)) ^ ")"
- | Types.Fn f -> "<fn>"
+ | Types.String s ->
+ if print_readably
+ then "\"" ^ (Str.global_replace (Str.regexp "\\([\"\\]\\)") "\\\\\\1" s) ^ "\""
+ else s
+ | Types.MalList xs ->
+ "(" ^ (join " " (List.map (fun s -> pr_str s print_readably) xs)) ^ ")"
+ | Types.Fn f -> "#<fn>"
diff --git a/ocaml/step1_read_print.ml b/ocaml/step1_read_print.ml
index 6cbbb16..1735e11 100644
--- a/ocaml/step1_read_print.ml
+++ b/ocaml/step1_read_print.ml
@@ -1,6 +1,6 @@
let read str = Reader.read_str str
let eval ast any = ast
-let print exp = Printer.pr_str exp
+let print exp = Printer.pr_str exp true
let rep str = print (eval (read str) "")
let rec main =
diff --git a/ocaml/step2_eval.ml b/ocaml/step2_eval.ml
index 02866eb..af8667c 100644
--- a/ocaml/step2_eval.ml
+++ b/ocaml/step2_eval.ml
@@ -32,7 +32,7 @@ and eval ast env =
| _ -> result
let read str = Reader.read_str str
-let print exp = Printer.pr_str exp
+let print exp = Printer.pr_str exp true
let rep str env = print (eval (read str) env)
let rec main =
diff --git a/ocaml/step3_env.ml b/ocaml/step3_env.ml
index 862cae6..d7939bf 100644
--- a/ocaml/step3_env.ml
+++ b/ocaml/step3_env.ml
@@ -39,7 +39,7 @@ and eval ast env =
| _ -> eval_ast ast env
let read str = Reader.read_str str
-let print exp = Printer.pr_str exp
+let print exp = Printer.pr_str exp true
let rep str env = print (eval (read str) env)
let rec main =
diff --git a/ocaml/step4_if_fn_do.ml b/ocaml/step4_if_fn_do.ml
index 1e5e87d..6580dd6 100644
--- a/ocaml/step4_if_fn_do.ml
+++ b/ocaml/step4_if_fn_do.ml
@@ -30,15 +30,15 @@ and eval ast env =
Types.Fn
(function args ->
let sub_env = Env.make (Some env) in
- let rec bind_args = (fun a b ->
+ let rec bind_args a b =
(match a, b with
| [Types.Symbol "&"; name], args -> Env.set sub_env name (Types.MalList args);
| (name :: names), (arg :: args) ->
Env.set sub_env name arg;
bind_args names args;
| [], [] -> ()
- | _ -> raise (Invalid_argument "Bad param count in fn call")))
- in (bind_args arg_names args);
+ | _ -> raise (Invalid_argument "Bad param count in fn call"))
+ in bind_args arg_names args;
eval expr sub_env)
| Types.MalList _ ->
(match eval_ast ast env with
@@ -47,7 +47,7 @@ and eval ast env =
| _ -> eval_ast ast env
let read str = Reader.read_str str
-let print exp = Printer.pr_str exp
+let print exp = Printer.pr_str exp true
let rep str env = print (eval (read str) env)
let rec main =
diff --git a/ocaml/types.ml b/ocaml/types.ml
index 60d3725..badfee3 100644
--- a/ocaml/types.ml
+++ b/ocaml/types.ml
@@ -7,3 +7,7 @@ type mal_type =
| Bool of bool
| String of string
| Fn of (mal_type list -> mal_type)
+
+let to_bool x = match x with
+ | Nil | Bool false -> false
+ | _ -> true