]> Repositorios git - scryer-prolog.git/commitdiff
Implemented phrase_from_file/2 and /2
authornotoria <[email protected]>
Sat, 25 Apr 2020 16:00:16 +0000 (18:00 +0200)
committernotoria <[email protected]>
Sat, 25 Apr 2020 16:04:13 +0000 (18:04 +0200)
src/prolog/clause_types.rs
src/prolog/lib/pio.pl [new file with mode: 0644]
src/prolog/machine/system_calls.rs

index 53d0f8e1da6aacb26735270cee33802f1a1c96f1..756080ca82c5a8f34baa544737ae7f1cb3f5ed28 100644 (file)
@@ -178,6 +178,7 @@ pub enum SystemClauseType {
     ExpandTerm,
     FetchGlobalVar,
     FetchGlobalVarWithOffset,
+    FileToChars,
     GetChar,
     GetSingleChar,
     ResetAttrVarState,
@@ -312,6 +313,7 @@ impl SystemClauseType {
             &SystemClauseType::FetchGlobalVarWithOffset => {
                 clause_name!("$fetch_global_var_with_offset")
             }
+            &SystemClauseType::FileToChars => clause_name!("$file_to_chars"),
             &SystemClauseType::GetChar => clause_name!("$get_char"),
             &SystemClauseType::GetSingleChar => clause_name!("$get_single_char"),
             &SystemClauseType::ResetAttrVarState => clause_name!("$reset_attr_var_state"),
@@ -461,6 +463,7 @@ impl SystemClauseType {
             ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
             ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
             ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
+            ("$file_to_chars", 2) => Some(SystemClauseType::FileToChars),
             ("$get_char", 1) => Some(SystemClauseType::GetChar),
             ("$get_single_char", 1) => Some(SystemClauseType::GetSingleChar),
             ("$points_to_cont_reset_marker", 1) => {
diff --git a/src/prolog/lib/pio.pl b/src/prolog/lib/pio.pl
new file mode 100644 (file)
index 0000000..c4ee0a2
--- /dev/null
@@ -0,0 +1,7 @@
+:- module(pio, [phrase_from_file/2]).
+
+:- use_module(library(dcgs)).
+
+phrase_from_file(NT, File) :-
+    '$file_to_chars'(File, Chars),
+    phrase(NT, Chars).
index fe88f0622d8e6578c7e03234910131432cacedee..eec6fc89b7250874bda88a1b0006550335b3f6ac 100644 (file)
@@ -24,8 +24,9 @@ use indexmap::IndexSet;
 
 use std::cmp;
 use std::convert::TryFrom;
-use std::io::{stdout, Write};
+use std::io::{stdout, Read, Write};
 use std::iter::once;
+use std::fs::File;
 use std::rc::Rc;
 
 use std::time::Duration;
@@ -1519,6 +1520,74 @@ impl MachineState {
                     }
                 };
             }
+            &SystemClauseType::FileToChars => {
+                let a1 = self.store(self.deref(self[temp_v!(1)]));
+                let a2 = self.store(self.deref(self[temp_v!(2)]));
+
+                let file_name = match a1 {
+                    Addr::Con(h) if self.heap.atom_at(h) => {
+                        if let HeapCellValue::Atom(name, _) = &self.heap[h] {
+                            name.as_str().to_string()
+                        }
+                        else {
+                            unreachable!()
+                        }
+                    }
+                    Addr::Char(c) => {
+                        c.to_string()
+                    }
+                    _ => unreachable!()
+                };
+                let name = clause_name!("$file_to_chars");
+                let mut file = match File::open(&file_name) {
+                    Ok(f) => f,
+                    Err(_e) => {
+                        let file_name_ = clause_name!(file_name.clone(),
+                            indices.atom_tbl.clone());
+                        let arity = 2;
+                        let stub = MachineError::functor_stub(name.clone(), arity);
+                        let h = self.heap.h();
+
+                        let err = MachineError::existence_error(
+                            h,
+                            ExistenceError::SourceSink(
+                                ModuleSource::File(file_name_)
+                            ),
+                        );
+                        let err = self.error_form(err, stub);
+
+                        self.throw_exception(err);
+                        return Ok(());
+                    }
+                };
+                let mut buffer = String::new();
+                let _ = match file.read_to_string(&mut buffer) {
+                    Ok(size) => size,
+                    Err(_e) => {
+                        // TODO: Distinguish the case/error.
+                        let file_name_ = clause_name!(file_name.clone(),
+                            indices.atom_tbl.clone());
+                        let arity = 2;
+                        let stub = MachineError::functor_stub(name.clone(), arity);
+                        let h = self.heap.h();
+
+                        let err = MachineError::existence_error(
+                            h,
+                            ExistenceError::SourceSink(
+                                ModuleSource::File(file_name_)
+                            ),
+                        );
+                        let err = self.error_form(err, stub);
+
+                        self.throw_exception(err);
+                        return Ok(());
+                    }
+                };
+                let chars = buffer.trim().chars().map(|c| Addr::Char(c));
+                let char_list = Addr::HeapCell(self.heap.to_list(chars));
+
+                self.unify(char_list, a2);
+            }
             &SystemClauseType::GetChar => {
                 let mut iter = parsing_stream(current_input_stream.clone());
                 let result = iter.next();