diff --git a/gleam.toml b/gleam.toml index 0d10db8..203162a 100644 --- a/gleam.toml +++ b/gleam.toml @@ -24,3 +24,4 @@ glexer = ">= 1.0.1 and < 2.0.0" gleescript = ">= 1.4.0 and < 2.0.0" pprint = ">= 1.0.3 and < 2.0.0" gleeunit = ">= 1.2.0 and < 2.0.0" +temporary = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index 9835223..8d94dbd 100644 --- a/manifest.toml +++ b/manifest.toml @@ -3,9 +3,12 @@ packages = [ { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, + { name = "envoy", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "CFAACCCFC47654F7E8B75E614746ED924C65BD08B1DE21101548AC314A8B6A41" }, + { name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" }, { name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" }, { name = "glam", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "66EC3BCD632E51EED029678F8DF419659C1E57B1A93D874C5131FE220DFAD2B2" }, { name = "glance", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "8F3314D27773B7C3B9FB58D8C02C634290422CE531988C0394FA0DF8676B964D" }, + { name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" }, { name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" }, { name = "gleam_stdlib", version = "0.39.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "2D7DE885A6EA7F1D5015D1698920C9BAF7241102836CE0C3837A4F160128A9C4" }, { name = "gleescript", version = "1.4.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "gleam_erlang", "gleam_stdlib", "simplifile", "snag", "tom"], otp_app = "gleescript", source = "hex", outer_checksum = "8CDDD29F91064E69950A91A40061785F10275ADB70A0520075591F61A724C455" }, @@ -14,6 +17,7 @@ packages = [ { name = "pprint", version = "1.0.3", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "76BBB92E23D12D954BD452686543F29EDE8EBEBB7FC0ACCBCA66EEF276EC3A06" }, { name = "simplifile", version = "2.0.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "5FFEBD0CAB39BDD343C3E1CCA6438B2848847DC170BA2386DF9D7064F34DF000" }, { name = "snag", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "54D32E16E33655346AA3E66CBA7E191DE0A8793D2C05284E3EFB90AD2CE92BCC" }, + { name = "temporary", version = "1.0.0", build_tools = ["gleam"], requirements = ["envoy", "exception", "filepath", "gleam_crypto", "gleam_stdlib", "simplifile"], otp_app = "temporary", source = "hex", outer_checksum = "51C0FEF4D72CE7CA507BD188B21C1F00695B3D5B09D7DFE38240BFD3A8E1E9B3" }, { name = "tom", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "9EECB60150E834A07238BD5C7DF1FF07F7D4C5862BB8A773923D1981C7875FB0" }, ] @@ -27,3 +31,4 @@ gleeunit = { version = ">= 1.2.0 and < 2.0.0" } glexer = { version = ">= 1.0.1 and < 2.0.0" } pprint = { version = ">= 1.0.3 and < 2.0.0" } simplifile = { version = ">= 2.0.1 and < 3.0.0" } +temporary = { version = ">= 1.0.0 and < 2.0.0" } diff --git a/src/macabre.gleam b/src/macabre.gleam index 13dfc49..dcc4c20 100644 --- a/src/macabre.gleam +++ b/src/macabre.gleam @@ -28,7 +28,9 @@ pub fn usage(message: String) -> Nil { io.println("Usage: macabre \n\n" <> message) } -fn write_program(program: program.CompiledProgram) -> Result(Nil, errors.Error) { +pub fn write_program( + program: program.CompiledProgram, +) -> Result(Nil, errors.Error) { let build_directory = program.build_directory(program.base_directory) let source_directory = program.source_directory(program.base_directory) output.delete(build_directory) diff --git a/test/compiler/directory_structure_tests.gleam b/test/compiler/directory_structure_tests.gleam new file mode 100644 index 0000000..79ad123 --- /dev/null +++ b/test/compiler/directory_structure_tests.gleam @@ -0,0 +1,146 @@ +import compiler +import compiler/program +import filepath +import gleam/dict +import gleam/list +import gleam/option +import gleam/set +import gleam/string +import gleeunit/should +import macabre +import simplifile +import temporary + +// These tests have to touch the filesystem, so +// they add measurably to the compile time. +// Tests in other files are pure and require no IO. +// This file should *only* test that stuff is being placed +// in the right directories. +// +// I tried to bulk all the situations in just one test, but +// it may have to be split out if it becomes too hard to +// maintain. + +pub type ProjectFiles { + ProjectFiles( + base_dir: String, + src_dir: String, + build_dir: String, + main_path: String, + ) +} + +fn init_folders( + use_function: fn(ProjectFiles) -> a, +) -> Result(a, simplifile.FileError) { + use dir <- temporary.create(temporary.directory()) + let project_name = filepath.base_name(dir) + let src = filepath.join(dir, "src") + let build = filepath.join(dir, "build") + let main_path = filepath.join(src, project_name <> ".gleam") + + simplifile.create_directory_all(src) + |> should.be_ok + let project_files = + ProjectFiles( + base_dir: dir, + src_dir: src, + build_dir: build, + main_path: main_path, + ) + use_function(project_files) +} + +pub fn program_compile_test_with_nested_folders_test() { + // src/ + // src/baz.py + // src/foo/bar.gleam + // src/foo/bindings.py + use project_files <- init_folders() + simplifile.write( + to: project_files.main_path, + contents: "import foo/bar + + @external(python, \"baz\", \"baz\") + fn baz() -> Nil + + + pub fn main() {}", + ) + |> should.be_ok + + simplifile.write( + to: filepath.join(project_files.src_dir, "baz.py"), + contents: " + fn baz(): + print('baz')", + ) + |> should.be_ok + + let foo_dir = filepath.join(project_files.src_dir, "foo") + simplifile.create_directory_all(foo_dir) + |> should.be_ok + simplifile.write( + to: filepath.join(foo_dir, "bar.gleam"), + contents: "@external(python, \"foo.bindings\", \"bar\") + fn bar() -> Nil", + ) + |> should.be_ok + + simplifile.write( + to: filepath.join(foo_dir, "bindings.py"), + contents: "def bar(): + pass", + ) + |> should.be_ok + + let gleam_program = + program.load_program(project_files.base_dir) + |> should.be_ok + + // load + + should.equal(gleam_program.base_directory, project_files.base_dir) + should.equal( + gleam_program.main_module, + filepath.base_name(project_files.main_path), + ) + gleam_program.modules + |> dict.size + |> should.equal(2) + gleam_program.external_import_files |> set.size |> should.equal(2) + + // --- compile + let compiled_program = compiler.compile_program(gleam_program) + should.equal(compiled_program.base_directory, project_files.base_dir) + should.equal( + compiled_program.main_module, + option.Some( + filepath.base_name(project_files.main_path) |> string.drop_right(6), + ), + ) + compiled_program.modules + |> dict.size + |> should.equal(2) + compiled_program.external_import_files |> set.size |> should.equal(2) + + // --- write output + macabre.write_program(compiled_program) |> should.be_ok + + simplifile.read_directory(project_files.build_dir) + |> should.be_ok + |> list.sort(string.compare) + |> should.equal([ + filepath.base_name(project_files.main_path) |> string.drop_right(6) <> ".py", + "__main__.py", + "baz.py", + "foo", + "gleam_builtins.py", + ]) + + project_files.build_dir + |> filepath.join("foo") + |> simplifile.read_directory + |> should.be_ok + |> should.equal(["bindings.py", "bar.py"]) +}