]> Repositorios git - scryer-prolog.git/commitdiff
ADDED: path_segments/2 for portable reasoning about path components.
authorMarkus Triska <[email protected]>
Sun, 19 Jul 2020 09:07:03 +0000 (11:07 +0200)
committerMarkus Triska <[email protected]>
Sun, 19 Jul 2020 10:32:01 +0000 (12:32 +0200)
The platform-specific directory separator is taken into account.
The clean representation of segments as a list simplifies reasoning.

src/clause_types.rs
src/lib/files.pl
src/machine/system_calls.rs

index f43b30fdccada6011eb3264e4053906c66398ae6..ab55563078e6c69ff6595a6ef65dbe2b3a19c173 100644 (file)
@@ -175,6 +175,7 @@ pub enum SystemClauseType {
     FileSize,
     FileExists,
     DirectoryExists,
+    DirectorySeparator,
     MakeDirectory,
     DeleteFile,
     WorkingDirectory,
@@ -344,6 +345,7 @@ impl SystemClauseType {
             &SystemClauseType::FileSize => clause_name!("$file_size"),
             &SystemClauseType::FileExists => clause_name!("$file_exists"),
             &SystemClauseType::DirectoryExists => clause_name!("$directory_exists"),
+            &SystemClauseType::DirectorySeparator => clause_name!("$directory_separator"),
             &SystemClauseType::MakeDirectory => clause_name!("$make_directory"),
             &SystemClauseType::DeleteFile => clause_name!("$delete_file"),
             &SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
@@ -682,6 +684,7 @@ impl SystemClauseType {
             ("$file_size", 2) => Some(SystemClauseType::FileSize),
             ("$file_exists", 1) => Some(SystemClauseType::FileExists),
             ("$directory_exists", 1) => Some(SystemClauseType::DirectoryExists),
+            ("$directory_separator", 1) => Some(SystemClauseType::DirectorySeparator),
             ("$make_directory", 1) => Some(SystemClauseType::MakeDirectory),
             ("$delete_file", 1) => Some(SystemClauseType::DeleteFile),
             ("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory),
index da511d06be389e4253c34797e11445e45a3d1ea5..bdc38b90d0b5871ca0677d2a73b3777a5089eaa7 100644 (file)
@@ -54,6 +54,7 @@
                   make_directory/1,
                   working_directory/2,
                   path_canonical/2,
+                  path_segments/2,
                   file_modification_time/2,
                   file_creation_time/2,
                   file_access_time/2]).
@@ -143,3 +144,57 @@ file_creation_time(File, T) :-
 file_time_(File, Which, T) :-
         '$file_time'(File, Which, T0),
         read_term_from_chars(T0, T).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   path_segments(Ps, Segments): True iff Segments are the segments of Ps.
+
+   Segments is the list of components of the path Ps that are
+   separated by the platform-specific directory separator. Each
+   segment is a list of characters.
+
+   At least one of the arguments must be instantiated.
+
+   Examples:
+
+      ?- path_segments("/hello/there", Segments).
+         Segments = [[],"hello","there"]
+      ;  false.
+
+      ?- path_segments(Path, ["hello","there"]).
+         Path = "hello/there"
+      ;  false.
+
+
+   To obtain the platform-specific directory separator, you can use:
+
+      ?- path_segments(Separator, ["",""]).
+         Separator = "/"
+      ;  false.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+path_segments(Path, Segments) :-
+        '$directory_separator'(Sep),
+        (   var(Path) ->
+            must_be(list, Segments),
+            maplist(list_of_chars, Segments),
+            append_with_separator(Segments, Sep, Path)
+        ;   list_of_chars(Path),
+            path_to_segments(Path, Sep, Segments)
+        ).
+
+append_with_separator([], _, []).
+append_with_separator([Segment|Segments], Sep, Path) :-
+        append_with_separator_(Segments, Segment, Sep, Path).
+
+append_with_separator_([], Segment, _, Segment).
+append_with_separator_([Segment|Segments], Prev, Sep, Path) :-
+        append(Prev, [Sep|Rest], Path),
+        append_with_separator_(Segments, Segment, Sep, Rest).
+
+path_to_segments(Path, Sep, Segments) :-
+        (   append(Front, [Sep|Ps], Path) ->
+            Segments = [Front|Rest],
+            path_to_segments(Ps, Sep, Rest)
+        ;   Segments = [Path]
+        ).
index 3d1501070b00fe733b2e3c4096735b62d5f1d338..31024167b8dc921e8e313959e633c878067dd7d2 100644 (file)
@@ -870,6 +870,10 @@ impl MachineState {
                     return Ok(());
                 }
             }
+            &SystemClauseType::DirectorySeparator => {
+                let addr = self.heap.put_constant(Constant::Char(std::path::MAIN_SEPARATOR));
+                self.unify(self[temp_v!(1)], addr);
+            }
             &SystemClauseType::MakeDirectory => {
                 let directory = self.heap_pstr_iter(self[temp_v!(1)]).to_string();