1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
[@@@ocaml.text "/*"]

(** Copyright 2021-2024, Kakadu and contributors *)

(** SPDX-License-Identifier: LGPL-3.0-or-later *)

[@@@ocaml.text "/*"]

open Base
open Stdio
open Lambda_lib
open Lambda_lib.Interpret

(** Parse command line arguments*)
let parse_args args =
  let rec parse max_steps = function
    | [] -> Some max_steps
    | "-max-steps" :: n :: rest ->
      (match Stdlib.int_of_string_opt n with
       | Some steps -> parse steps rest
       | None ->
         eprintf "Error: Invalid value for -max-steps: %s\n" n;
         None)
    | arg :: _ ->
      eprintf "Error: Unknown argument: %s\n" arg;
      None
  in
  match parse 10000 args with
  | Some max_steps -> max_steps
  | None -> Stdlib.exit 1
;;

let () =
  let max_steps = parse_args (List.tl_exn (Array.to_list (Sys.get_argv ()))) in
  let input = In_channel.input_all In_channel.stdin |> String.strip in
  match Parser.parse input with
  | Error e ->
    let msg = Stdlib.Format.asprintf "%a" Parser.pp_error e in
    eprintf "Error: %s\n" msg;
    Stdlib.exit 1
  | Result.Ok ast ->
    (match eval_expr ~max_steps ast with
     | Result.Ok (VInt n) -> printf "%d\n" n
     | Result.Ok (VClosure _) -> printf "<fun>\n"
     | Result.Ok (VBuiltin (name, _)) -> printf "<builtin:%s>\n" name
     | Result.Ok VUnit -> printf "()\n"
     | Result.Error (UnknownVariable name) ->
       eprintf "Unbound variable: %s\n" name;
       Stdlib.exit 1
     | Result.Error DivisionByZero ->
       eprintf "Division by zero\n";
       Stdlib.exit 1
     | Result.Error TypeMismatch ->
       eprintf "Type error\n";
       Stdlib.exit 1
     | Result.Error StepLimitExceeded ->
       eprintf "Step limit exceeded\n";
       Stdlib.exit 1)
;;