;; Build the stage3 version of Menhir, based on a parser generated by the
;; stage2 version of Menhir.

;; One might think that one could save time by building only the stage3
;; parser.ml and parser.mli, as opposed to a full stage3 executable. However,
;; because Menhir is used in --infer mode, building these files in a correct
;; manner actually requires type-checking a large part of Menhir's source
;; code. It's simpler to just build everything than to be smart.

;; -----------------------------------------------------------------------------

;; As dune cannot use the same OCaml module in two different libraries or
;; executables, we must copy the source files to the present directory.

(copy_files# ../*.{ml,mli})

;; The following files are copied from stage 2.

(copy_files ../stage2/menhir_flags.sexp)
(copy_files ../stage2/parser.mly)
(copy_files ../stage2/Driver.ml)
(copy_files ../stage2/parserMessages.ml)

;; -----------------------------------------------------------------------------

;; Bind the name "menhir" to "../stage2/main.exe" within the present scope.

(env
  (_ (binaries ../stage2/main.exe (../stage2/main.exe as menhir)))
)

;; Menhir's parser is generated by Menhir.

;; We include the flags found in the file "menhir_flags" plus extra flags
;; specified here.

(menhir
  (flags
    (:include menhir_flags.sexp)
  )
  (modules parser)
)

;; -----------------------------------------------------------------------------

;; The stage3 version of Menhir.

;; The link_deps field below is an artificial way of requiring the @bootstrap
;; target to be automatically built.

(executable
  (name main)
  (libraries unix fix menhirLib menhirSdk)
  (flags :standard -open MenhirSdk)
  (link_deps (alias bootstrap))
)

;; ----------------------------------------------------------------------------

;; The bootstrap check verifies that stage1-Menhir and stage2-Menhir produce
;; the same result when applied to Menhir's stage2 grammar. If this check
;; fails, then the ocamlyacc parser in stage1/parser.mly and the Menhir parser
;; in stage2/parser.mly have different semantics, a mistake that must be
;; fixed.

;; This check compares the [Parser] modules generated by the stage1 and stage2
;; executables, and fails if they are not identical.

;; These parsers contain line directives that are necessarily different
;; because they were generated in different directories. A helper script is
;; used to remove the "filename" part of the line directives.

;; This check is run as part of [dune test].

(rule
  (with-stdout-to parser.stage2.ml
    (run anonymize/anonymize.exe %{dep:../stage2/parser.ml})
  )
)

(rule
  (with-stdout-to parser.stage3.ml
    (run anonymize/anonymize.exe %{dep:parser.ml})
  )
)

(rule
  (alias bootstrap)
  (action (progn
    (echo "Bootstrap check: comparing the stage 2 and stage 3 parsers...\n")
    (progn
      (diff parser.stage2.ml parser.stage3.ml)
      (diff ../stage2/parser.mli parser.mli)
    )
    (echo "Bootstrap check: done.\n")
  ))
)

(rule
  (alias test)
  (deps (alias bootstrap))
  (action (progn))
)
