From 2768beec4c49660a0636b93e585790efd62dbe6a Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Sun, 19 Jul 2020 11:07:03 +0200 Subject: [PATCH] ADDED: path_segments/2 for portable reasoning about path components. The platform-specific directory separator is taken into account. The clean representation of segments as a list simplifies reasoning. --- src/clause_types.rs | 3 ++ src/lib/files.pl | 55 +++++++++++++++++++++++++++++++++++++ src/machine/system_calls.rs | 4 +++ 3 files changed, 62 insertions(+) diff --git a/src/clause_types.rs b/src/clause_types.rs index f43b30fd..ab555630 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -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), diff --git a/src/lib/files.pl b/src/lib/files.pl index da511d06..bdc38b90 100644 --- a/src/lib/files.pl +++ b/src/lib/files.pl @@ -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] + ). diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 3d150107..31024167 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -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(); -- 2.54.0