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 (Return 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.")
}
(Return
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)
(Return (OS.die "Compilation failed."))
})
}
Let packages
Begin Match (PACKAGE.sort packages) {
| 'succeed.packages (Return packages)
| 'fail.component
(STDIO.print "Cyclic package dependencies: ")
(STDIO.print (STRING.join ", " component))
(STDIO.print_line ".")
(Return (OS.die "Compilation failed."))
}
Let paths (LIST.map packages [Func package package.path])
Let program
(Reduce -> (COMPILE.link packages)
COMPILE.macroexpand
COMPILE.elaborate_operators
COMPILE.elaborate_recursion
COMPILE.collect_free_variables
COMPILE.lift_functions
COMPILE.collect_constants
COMPILE.elaborate_patterns)
Begin {
Define (output file_name emitter)
(FILE.with_output_file file_name
Func fd (BUFIO.with_writer fd 1024 emitter))
(output (STRING.append root_path ".c")
Func w (C.emit w program))
(output (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`)
})
}
}
Where
Open Z
{
:Infix >=
:Infix !=
:Infix +
:Infix -
}
Open LIST {:Infix &}
Open FUNC
{
:Infix >>
:Infix ->
}
Where
Let BUFIO Package "bufio"
Let C Package "c"
Let COMPILE Package "compile"
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 SCAN Package "scan"
Let STDIO Package "stdio"
Let STRING Package "string"
Let SYNTAX_ERROR Package "syntax_error"
Let Z Package "z"