diff options
| author | Marcos Magueta <maguetamarcos@gmail.com> | 2026-07-12 18:52:52 -0300 |
|---|---|---|
| committer | Marcos Magueta <maguetamarcos@gmail.com> | 2026-07-12 18:52:52 -0300 |
| commit | 90cb51a907a0f78b83cb66f497f6dc0f24f01706 (patch) | |
| tree | 379e7e79a3e7c6d0e1520ab153a581689060bb4b /bin | |
| parent | 19ba625e0345a88da6c29ab91a3ba2d7a8462065 (diff) | |
| download | SOL-90cb51a907a0f78b83cb66f497f6dc0f24f01706.tar.gz SOL-90cb51a907a0f78b83cb66f497f6dc0f24f01706.zip | |
repl session commands: load, reset, quit; emacs load-file binding
Diffstat (limited to '')
| -rw-r--r-- | bin/main.ml | 80 |
1 files changed, 64 insertions, 16 deletions
diff --git a/bin/main.ml b/bin/main.ml index eb212d2..26375da 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -44,30 +44,78 @@ let run_file path = | Ok statements -> ( match run_statements statements with Ok () -> () | Error () -> exit 1) +let declarations statements = + List.filter + (function Sol.Ast.Directive ("Query", _) -> false | _ -> true) + statements + +(* Feeding statements into the session: declarations accumulate, + queries answer immediately, and a failure changes nothing, so the + session only ever holds an admitted program. *) +let feed history statements = + match run_statements (history @ statements) with + | Ok () -> history @ declarations statements + | Error () -> history + +let strip_quotes s = + let n = String.length s in + if n >= 2 && s.[0] = '"' && s.[n - 1] = '"' then String.sub s 1 (n - 2) + else s + +let load_file history argument = + let path = strip_quotes argument in + match In_channel.with_open_text path In_channel.input_all with + | exception Sys_error message -> + prerr_endline message; + history + | contents -> ( + match Sol.Front.parse_string contents with + | Error message -> + prerr_endline (path ^ ": " ^ message); + history + | Ok statements -> + let next = feed history statements in + if next != history then + Printf.printf "loaded %s: %d declarations, %d queries run.\n" path + (List.length (declarations statements)) + (List.length statements - List.length (declarations statements)); + next) + let repl () = - print_endline "Sol. Statements accumulate; Query expression: ... runs."; + print_endline + "Sol. Statements accumulate; Query expression: ... runs; :help for commands."; let rec loop history = print_string "sol> "; flush stdout; match In_channel.input_line stdin with | None -> () - | Some line when String.trim line = "" -> loop history | Some line -> ( - match Sol.Front.parse_string line with - | Error message -> - prerr_endline message; + let line = String.trim line in + match String.index_opt line ' ' with + | _ when line = "" -> loop history + | _ when line = ":quit" -> () + | _ when line = ":reset" -> + print_endline "session cleared."; + loop [] + | _ when line = ":help" -> + print_endline + ":load FILE bring a program into the session (atomic: a rejected file changes nothing)\n\ + :reset clear the session\n\ + :quit leave"; + loop history + | Some i when String.sub line 0 i = ":load" -> + loop + (load_file history + (String.trim (String.sub line i (String.length line - i)))) + | _ when String.length line > 0 && line.[0] = ':' -> + prerr_endline "unknown command; :help lists them."; loop history - | Ok statements -> ( - let declarations = - List.filter - (function - | Sol.Ast.Directive ("Query", _) -> false - | _ -> true) - statements - in - match run_statements (history @ statements) with - | Ok () -> loop (history @ declarations) - | Error () -> loop history)) + | _ -> ( + match Sol.Front.parse_string line with + | Error message -> + prerr_endline message; + loop history + | Ok statements -> loop (feed history statements))) in loop [] |
