let ( let* ) = Result.bind module Error = Error module Expr = Expr module Interpreter = Interpreter module Lexer = Lexer module Parser = Parser module Stmt = Stmt type lox_error = Error.lox_error let run ?(env : Environment.environment option) ?(debug = false) (source : string) : (unit, lox_error) result = let env = Option.value env ~default:(Environment.Env.make ()) in let* tokens = Error.of_lexer_error (Lexer.tokenize source) in let () = if debug then let print_tokens () = prerr_endline "--- Tokens ---"; let f token = Printf.eprintf "%s %!" (Lexer.show_token token) in Printf.eprintf "Got %d tokens\n%!" (List.length tokens); List.iter f tokens; prerr_newline (); prerr_endline "--------------"; prerr_newline () in print_tokens () else () in let* stmts = Parser.parse tokens |> Error.of_parser_error in let () = if debug then let print_statements () = prerr_endline "--- Statements ---"; let f (stmt : Stmt.stmt_node) = prerr_endline (Stmt.show_stmt stmt.stmt) in List.iter f stmts; prerr_endline "------------------"; prerr_newline () in print_statements () else () in let rec interpret_stmts (stmts : Stmt.stmt_node list) = match stmts with | [] -> Ok () | stmt :: tail -> let* () = Interpreter.interpret_stmt env stmt in interpret_stmts tail in interpret_stmts stmts |> Error.of_runtimer_error let runRepl ?(debug = false) () : unit = let env = Environment.Env.make () in try while true do print_string "> "; let line = read_line () in let result = run ~env ~debug line in Result.iter_error Error.print_error result done with End_of_file -> ()