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 () = print_endline "--- Tokens ---"; let f token = Printf.printf "%s " (Lexer.show_token token) in Printf.printf "Got %d tokens\n" (List.length tokens); List.iter f tokens; print_newline (); print_endline "--------------"; print_newline () in print_tokens () else () in let* stmts = Parser.parse tokens |> Error.of_parser_error in let () = if debug then let print_statements () = print_endline "--- Statements ---"; let f (stmt : Stmt.stmt_node) = print_endline (Stmt.show_stmt stmt.stmt) in List.iter f stmts; print_endline "------------------"; print_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 -> ()