Begin {
    When [OS.argc != 2] { (OS.die "usage: 84 <program>") }
    Let root_path (OS.argv 1)
    Let packages
        Let QUEUE PACKAGE.QUEUE
        In
        Iterate {queue packages} From {(QUEUE.new root_path) 'nil}
            Begin Match (QUEUE.pop queue) {
            | 'nothing packages
            | 'just.{path queue}
                Let file_name (STRING.append path ".84")
                Let text (FILE.read_all file_name)
                Begin Match (SCAN.validate_bytes text) {
                | 'succeed
                | 'fail.message
                    (STDIO.print_line message)
                    (OS.die "Compilation failed.")
                }
                Begin Match (PARSE.file text) {
                | 'succeed.expr
                    Let imports (PACKAGE.gather_imports expr)
                    Let package {:path :imports :expr}
                    Let queue (QUEUE.push_all queue imports)
                    (Continue queue [package & packages])
                | 'fail.{message i}
                    (SYNTAX_ERROR.show file_name text message i)
                    (OS.die "Compilation failed.")
                }
            }
    Let packages
        Begin Match (PACKAGE.sort packages) {
        | 'succeed.packages packages
        | 'fail.component
            (Reduce <- STDIO.printf
                "Cyclic package dependencies: %s.\n"
                (STRING.join ", " component))
            (OS.die "Compilation failed.")
        }
    Let paths (LIST.map packages [Func package package.path])
    Let program (PACKAGE.link packages)
    Let program
        (Reduce -> program
            PROGRAM.expand_macros
            PROGRAM.elaborate_operators
            PROGRAM.elaborate_recursion
            PROGRAM.collect_free_variables
            PROGRAM.lift_functions
            PROGRAM.collect_constants
            PROGRAM.elaborate_patterns)
    (with_output_file (STRING.append root_path ".c.d")
        Func w Begin {
            (IO.write_all w (STRING.append root_path ".c: "))
            (IO.write_all w
                (STRING.join " "
                    (LIST.map paths
                        Func path (STRING.append path ".84"))))
            (IO.write_byte w `\n`)
        })
    (with_output_file (STRING.append root_path ".c")
        Func w (C.emit w program))
}

Where

Define (with_output_file file_name generator)
    (FILE.with_output_file file_name
        Func fd (BUFIO.with_writer fd 1024 generator))

Where

Open Z {:Infix !=}

Open LIST {:Infix &}

Open FUNC
    {
    :Infix <-
    :Infix ->
    }

Where

Let BUFIO Package "bufio"
Let C Package "c"
Let FILE Package "file"
Let FUNC Package "func"
Let IO Package "io"
Let LIST Package "list"
Let OS Package "os"
Let PACKAGE Package "package"
Let PARSE Package "parse"
Let PROGRAM Package "program"
Let SCAN Package "scan"
Let STDIO Package "stdio"
Let STRING Package "string"
Let SYNTAX_ERROR Package "syntax_error"
Let Z Package "z"