ref: b34fba0e5b9e39fc5120f06b6c335033472f81ca
dir: /m9.ml/
(* Martian Scheme Copyright 2020, McKay Marston This is a project for me to 1) Get more familiar with OCaml. 2) Try to provide a natively supported scheme for Plan9. It is heavily inspired by s9fes (http://www.t3x.org/s9fes), and the make a lisp project (https://github.com/kanaka/mal) *) module T = Types.Types module Env = Map.Make (String (*(struct type t = Types.Symbol let compare (Types.Symbol a) (Types.Symbol b) = compare a b end)*)) (* replace me *) let num_fun f = Types.proc (function | [ T.Number a; T.Number b ] -> T.Number (f a b) | _ -> raise (Invalid_argument "Expected numeric argument")) ;; (* replace me *) let repl_env = ref (List.fold_left (fun a b -> b a) Env.empty [ Env.add "+" (num_fun ( + )) ; Env.add "-" (num_fun ( - )) ; Env.add "*" (num_fun ( * )) ; Env.add "/" (num_fun ( / )) ]) ;; let rec eval_ast ast env = match ast with | T.Symbol { T.value = s } -> (try Env.find s !env with | Not_found -> raise (Invalid_argument ("Symbol '" ^ s ^ "' not found"))) | T.List { T.value = xs; T.meta } -> T.List { T.value = List.map (fun x -> eval x env) xs; T.meta } | T.Vector { T.value = xs; T.meta } -> T.Vector { T.value = List.map (fun x -> eval x env) xs; T.meta } | _ -> ast and eval ast env = let result = eval_ast ast env in match result with | T.List { T.value = T.Proc { T.value = f } :: args } -> f args | _ -> result ;; let nameplate = "Martian9 Scheme v0.1" let read str = Reader.read_str str let print exp = Printer.print exp true let rep str env = print (eval (read str) env) let rec main = try print_endline nameplate; while true do print_string "m9> "; let line = read_line () in try print_endline (rep line repl_env) with | End_of_file -> () | Invalid_argument x -> output_string stderr ("Invalid argument: " ^ x ^ "\n"); flush stderr done with | End_of_file -> () ;;