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
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
open Lambda_lib

let expect_ok src =
  match Parser.parse src with
  | Ok _ -> ()
  | Error e ->
    failwith (Format.asprintf "expected to parse: %s, got %a" src Parser.pp_error e)
;;

let expect_error src =
  match Parser.parse src with
  | Ok _ -> failwith (Printf.sprintf "expected parse failure: %s" src)
  | Error _ -> ()
;;

let base_success =
  [ "42"
  ; "x"
  ; "1 + 2"
  ; "1 + 2 * 3"
  ; "(1 + 2) * 3"
  ; "let x = 5 in x + 1"
  ; "let rec fact n = if n = 0 then 1 else n * fact (n - 1) in fact 4"
  ; "fun x -> x + 1"
  ; "fun x y -> x * y"
  ; "if 1 then 2 else 3"
  ; "let f x = x in f 3"
  ; "let x = fun y -> y in x 2"
  ; "let a = 1 in let b = 2 in a + b"
  ; "let rec f x = if x = 0 then 0 else f (x - 1) in f 3"
  ; "fix (fun self -> fun n -> if n = 0 then 1 else n * self (n - 1)) 3"
  ; "true"
  ; "false"
  ; "if true then 1 else 0"
  ; "if false then 1 else 0"
  ; "let x = -5 in x"
  ]
;;

let generated_success =
  let open Printf in
  List.init 120 (fun i ->
    let n = i + 1 in
    [ sprintf "%d + %d" n (n + 1)
    ; sprintf "%d - %d" (n * 2) n
    ; sprintf "%d * %d" n (n + 2)
    ; sprintf "%d / %d" (n * (n + 1)) (n + 1)
    ])
  |> List.flatten
;;

let function_success =
  let open Printf in
  List.init 30 (fun i ->
    let n = i + 1 in
    [ sprintf "fun x -> x + %d" n
    ; sprintf "fun a b -> a * %d + b" n
    ; sprintf "let f x = x + %d in f %d" n (n * 2)
    ; sprintf "let rec f n = if n = 0 then %d else f (n - 1) in f %d" n n
    ; sprintf
        "let rec g x y = if x = 0 then y else g (x - 1) (y + %d) in g %d %d"
        n
        n
        (n * 2)
    ])
  |> List.flatten
;;

let let_chains =
  let open Printf in
  List.init 40 (fun i ->
    let n = i + 1 in
    [ sprintf "let x = %d in x + %d" n n
    ; sprintf "let x = %d in let y = %d in x * y" n (n + 1)
    ; sprintf "let x = %d in let y = x + %d in y * x" n (n + 2)
    ])
  |> List.flatten
;;

let error_cases =
  [ ""
  ; "let"
  ; "1 +"
  ; "(1 + 2"
  ; "1 + 2)"
  ; "if false thenn elsen"
  ; "if then else"
  ; "fun -> 1"
  ; "let 5 = 3"
  ; "let rec = 1"
  ; "let x = in x"
  ; "fun x y"
  ; "if x"
  ; "let x = 1 in"
  ; "let x = 1 in in"
  ; "let rec f = fun -> 1"
  ]
;;

let () =
  List.iter expect_ok base_success;
  List.iter expect_ok generated_success;
  List.iter expect_ok function_success;
  List.iter expect_ok let_chains;
  List.iter expect_error error_cases
;;