Block Let root_path (parse_command_line) In Let packages (parse_packages root_path) In Let paths (LIST.map packages [Func p p.path]) Let program (compile packages) In Begin (write_dependencies_file root_path paths) (emit root_path program) End Where Define (parse_command_line) Let usage "usage: 84 <program>" In Let root_path If [(OS.fetch_argc) = 2] (OS.fetch_arg 1) (OS.die usage) In root_path Define (parse_packages root_path) Let STRING_SET (SEARCH.SET STRING.compare) In Define (parse_file path) Let file_name (STRING.append path ".84") In Let text Let file (OS.file_open file_name) In Let text (OS.file_read_all file) Do (OS.file_close file) In text In Match (PARSE.file text) | 'succeed.expr expr | 'fail.{message i} Begin (SYNTAX_ERROR.show file_name text message i) (OS.die "Compilation failed.") End ; Define (push_paths stack filter paths) (LIST.reduce paths {stack filter} Func {{stack filter} path} Match (STRING_SET.search filter path) | 'just._ {stack filter} | 'nothing {[path & stack] (STRING_SET.insert filter path)} ;) In Let packages Let packages 'nil Let stack [root_path & 'nil] Let filter (STRING_SET.new [root_path & 'nil]) In Unfold {packages stack filter} Match stack | 'nil packages | 'cons.{path stack} Let expr (parse_file path) In Let imports (PACKAGE.gather_imports expr) In Let package {: path : imports : expr} Let {stack filter} (push_paths stack filter imports) In (Fold [package & packages] stack filter) ; In (PACKAGE.sort_by_dependence packages) Define (write_dependencies_file root_path paths) Let file_name (STRING.append root_path ".c.d") In Let file (OS.file_create file_name) In Begin (OS.file_write file (STRING.append root_path ".c:")) Unfold paths Match paths | 'nil Begin (OS.file_write file "\n") (OS.file_close file) End | 'cons.{path paths} Begin (OS.file_write file (STRING.concat [Right " " & path & ".84" & 'nil])) (Fold paths) End ; End Define (compile program) Let {_ program} (LIST.fold program {1 'nil} Func {package {i packages}} Let {init i functions} (COMPILE.lift_functions i (COMPILE.collect_free_variables (COMPILE.elaborate_recursion package.expr))) In Let package { : path package.path : imports package.imports : init : functions } In {i [package & packages]}) In (COMPILE.collect_constants program) Define (emit root_path program) Let file (OS.file_create (STRING.append root_path ".c")) In Define (write string) (OS.file_write file string) In Begin (C.emit (C.elaborate program) write) (OS.file_close file) End Where Let C Package "c" Let COMPILE Package "compile" Let LIST Package "list" Let OS Package "os" Let PACKAGE Package "package" Let PARSE Package "parse" Let SEARCH Package "search" Let STDIO Package "stdio" Let STRING Package "string" Let SYNTAX_ERROR Package "syntax_error"