diff --git a/bin/main.ml b/bin/main.ml index f13d098..11c1eb3 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,6 +1,7 @@ open Conkeldurr open Cmdliner +let version = "1.0a" let conkeldurr_process_file file = file |> Entry.entry_point let input_file_arg = @@ -10,7 +11,7 @@ let input_file_arg = let main_cmd = let term = Term.(const conkeldurr_process_file $ input_file_arg) in - Cmd.v (Cmd.info "conkeldurr" ~version:"%%VERSION%%") term + Cmd.v (Cmd.info "conkeldurr" ~version) term ;; let main () = Cmd.eval main_cmd diff --git a/lib/ast.ml b/lib/ast.ml index 2ef75ae..74a9601 100644 --- a/lib/ast.ml +++ b/lib/ast.ml @@ -76,6 +76,12 @@ module Export = struct ;; end +module Chdir = struct + type t = string [@@deriving sexp] + + let to_string node = Printf.sprintf "Chdir to %s" node +end + module Node = struct type t = | ReadConstant of ReadConstant.t @@ -83,6 +89,7 @@ module Node = struct | ReadSpreadsheet of ReadSpreadsheet.t | Import of Import.t | Export of Export.t + | Chdir of Chdir.t [@@deriving sexp] let to_string node = @@ -92,5 +99,6 @@ module Node = struct | ReadSpreadsheet n -> ReadSpreadsheet.to_string n | Import n -> Import.to_string n | Export n -> Export.to_string n + | Chdir n -> Chdir.to_string n ;; end diff --git a/lib/ast.mli b/lib/ast.mli index d3c626b..92a6c80 100644 --- a/lib/ast.mli +++ b/lib/ast.mli @@ -58,6 +58,14 @@ module Export : sig val to_string : t -> string end +module Chdir : sig + type t = string [@@deriving sexp] + + val t_of_sexp : Sexplib0.Sexp.t -> t + val sexp_of_t : t -> Sexplib0.Sexp.t + val to_string : t -> string +end + (* Node is a node in the AST tree *) module Node : sig type t = @@ -66,6 +74,7 @@ module Node : sig | ReadSpreadsheet of ReadSpreadsheet.t | Import of Import.t | Export of Export.t + | Chdir of Chdir.t val t_of_sexp : Sexplib0.Sexp.t -> t val sexp_of_t : t -> Sexplib0.Sexp.t diff --git a/lib/interpreter.ml b/lib/interpreter.ml index 725ce9f..b81133c 100644 --- a/lib/interpreter.ml +++ b/lib/interpreter.ml @@ -4,6 +4,7 @@ module T = struct ; spreadsheet_store : Spreadsheet.t Store.T.t ; interface_set : Variable.T.t Store.T.t ; import_store : Variable.T.t Store.T.t + ; root_directory : string } let interpret_read_constant state (node : Ast.ReadConstant.t) = @@ -76,6 +77,17 @@ module T = struct Store.T.clear state.import_store ;; + let interpret_chdir state (node : Ast.Chdir.t) = + let cwd = Sys.getcwd () in + try + Io.Files.cd state.root_directory; + Io.Files.cd node + with + | Io.Files.Io_exception msg -> + Io.Files.cd cwd; + failwith msg + ;; + let interpret_node state node = match node with | Ast.Node.ReadConstant n -> interpret_read_constant state n @@ -85,6 +97,7 @@ module T = struct | Ast.Node.Export n -> interpret_export state n; reset_state state + | Ast.Node.Chdir n -> interpret_chdir state n ;; let[@inline] create_blank_state () = @@ -92,6 +105,7 @@ module T = struct ; spreadsheet_store = Store.T.create () ; interface_set = Store.T.create () ; import_store = Store.T.create () + ; root_directory = Sys.getcwd () } ;; diff --git a/lib/interpreter.mli b/lib/interpreter.mli index 207c9b4..41c59ee 100644 --- a/lib/interpreter.mli +++ b/lib/interpreter.mli @@ -5,6 +5,7 @@ module T : sig ; spreadsheet_store : Spreadsheet.t Store.T.t ; interface_set : Variable.T.t Store.T.t ; import_store : Variable.T.t Store.T.t + ; root_directory : string } val interpret_node : state -> Ast.Node.t -> unit diff --git a/lib/io.ml b/lib/io.ml index 9abf334..bf08d63 100644 --- a/lib/io.ml +++ b/lib/io.ml @@ -1,13 +1,20 @@ module Files = struct + exception Io_exception of string + let[@inline] get_absolute_file_path file = file |> Util.T.unquote |> Filename_unix.realpath ;; let[@inline] is_valid_path path = path |> get_absolute_file_path |> Sys.file_exists + let[@inline] cd dir = + try Sys.chdir dir with + | Sys_error msg -> raise (Io_exception msg) + ;; + let set_working_directory input = let full_path = input |> get_absolute_file_path in - full_path |> Filename.dirname |> Sys.chdir; + full_path |> Filename.dirname |> cd; full_path ;; end diff --git a/lib/io.mli b/lib/io.mli index 734452a..6c8e5e6 100644 --- a/lib/io.mli +++ b/lib/io.mli @@ -1,7 +1,10 @@ (* Some useful file system utils *) module Files : sig + exception Io_exception of string + val get_absolute_file_path : string -> string val is_valid_path : string -> bool + val cd : string -> unit val set_working_directory : string -> string end diff --git a/test/expect_tests/ast_tests.ml b/test/expect_tests/ast_tests.ml index e570381..4bbf4b7 100644 --- a/test/expect_tests/ast_tests.ml +++ b/test/expect_tests/ast_tests.ml @@ -45,6 +45,16 @@ let%expect_test "parses ReadSpreadsheet correctly" = |}] ;; +let%expect_test "parses Import correctly" = + let sample_sexp = + {| + ((Import ((var SomeEnum) (from some-file.ts)))) + |} + in + sample_sexp |> Program.T.of_string |> Program.T.to_readable_string |> print_endline; + [%expect {| Import SomeEnum from some-file.ts |}] +;; + let%expect_test "parses Export correctly" = let sample_sexp = {| @@ -59,3 +69,20 @@ let%expect_test "parses Export correctly" = Export to stdout |}] ;; + +let%expect_test "parses Chdir correctly" = + let sample_sexp = + {|( + (Chdir "some_folder1") + (Chdir "some_folder2") + (Chdir "some_folder3") + )|} + in + sample_sexp |> Program.T.of_string |> Program.T.to_readable_string |> print_endline; + [%expect + {| + Chdir to some_folder1 + Chdir to some_folder2 + Chdir to some_folder3 + |}] +;; diff --git a/test/expect_tests/cases/chdir_program_test.sexp b/test/expect_tests/cases/chdir_program_test.sexp new file mode 100644 index 0000000..fcb32e2 --- /dev/null +++ b/test/expect_tests/cases/chdir_program_test.sexp @@ -0,0 +1,12 @@ +( + (Chdir "./data/a") + (ReadSpreadsheet ((var "sheet1") (interface "interface1") (path (Csv "data.csv")))) + + (Chdir "./data/b") + (ReadSpreadsheet ((var "sheet2") (interface "interface2") (path (Csv "data.csv")))) + + (Chdir "./data/c") + (ReadSpreadsheet ((var "sheet3") (interface "interface3") (path (Csv "data.csv")))) + + (Export Stdout) +) diff --git a/test/expect_tests/cases/data/a/data.csv b/test/expect_tests/cases/data/a/data.csv new file mode 100644 index 0000000..df80f0c --- /dev/null +++ b/test/expect_tests/cases/data/a/data.csv @@ -0,0 +1,2 @@ +(String col) +"A" diff --git a/test/expect_tests/cases/data/b/data.csv b/test/expect_tests/cases/data/b/data.csv new file mode 100644 index 0000000..9d03cf3 --- /dev/null +++ b/test/expect_tests/cases/data/b/data.csv @@ -0,0 +1,2 @@ +(String col) +"B" diff --git a/test/expect_tests/cases/data/c/data.csv b/test/expect_tests/cases/data/c/data.csv new file mode 100644 index 0000000..33b51a3 --- /dev/null +++ b/test/expect_tests/cases/data/c/data.csv @@ -0,0 +1,2 @@ +(String col) +"C" diff --git a/test/expect_tests/end_to_end_program_tests.ml b/test/expect_tests/end_to_end_program_tests.ml index f870f0f..e3612ed 100644 --- a/test/expect_tests/end_to_end_program_tests.ml +++ b/test/expect_tests/end_to_end_program_tests.ml @@ -290,3 +290,35 @@ let%expect_test "fails on duplicate imported modules" = print_endline msg; [%expect {| variable SomeEnum already set |}] ;; + +let%expect_test "passes chdir end to end test" = + Entry.entry_point "chdir_program_test.sexp"; + [%expect + {| + export interface interface1 { + col: string; + }; + + export const sheet1: Array = [ + { col: "A" } + ]; + + + export interface interface2 { + col: string; + }; + + export const sheet2: Array = [ + { col: "B" } + ]; + + + export interface interface3 { + col: string; + }; + + export const sheet3: Array = [ + { col: "C" } + ]; + |}] +;;