]> Repositorios git - scryer-prolog.git/commitdiff
MachineBuilder
authorbakaq <[email protected]>
Sat, 12 Oct 2024 19:07:13 +0000 (16:07 -0300)
committerbakaq <[email protected]>
Sun, 8 Dec 2024 23:18:06 +0000 (20:18 -0300)
src/lib.rs
src/machine/config.rs
src/machine/lib_machine.rs
src/machine/mock_wam.rs
src/machine/mod.rs

index dc8693eccd5a71dffed1d25e6ffd956f07b31c66..6148ef5c705cec555a366ea84a9c2d2b1b5d7784 100644 (file)
@@ -66,7 +66,7 @@ pub fn eval_code(s: &str) -> String {
 /// The entry point for the Scryer Prolog CLI.
 pub fn run_binary() -> std::process::ExitCode {
     use crate::atom_table::Atom;
-    use crate::machine::{Machine, INTERRUPT};
+    use crate::machine::INTERRUPT;
 
     #[cfg(feature = "repl")]
     ctrlc::set_handler(move || {
@@ -87,7 +87,9 @@ pub fn run_binary() -> std::process::ExitCode {
         .unwrap();
 
     runtime.block_on(async move {
-        let mut wam = Machine::new(Default::default());
+        let mut wam = MachineBuilder::default()
+            .with_streams(StreamConfig::stdio())
+            .build();
         wam.run_module_predicate(atom!("$toplevel"), (atom!("$repl"), 0))
     })
 }
index ec930464f251457ccd365b4d800f27b59e4adc51..039cf2f454b4520ae3d83f9465e5de00ea5134fd 100644 (file)
@@ -1,13 +1,21 @@
+use rand::{rngs::StdRng, SeedableRng};
+
+use crate::Machine;
+
+use super::{
+    bootstrapping_compile, current_dir, import_builtin_impls, libraries, load_module, Atom,
+    CompilationTarget, IndexStore, ListingSource, MachineArgs, MachineState, Stream, StreamOptions,
+};
+
 /// Describes how the streams of a [`Machine`](crate::Machine) will be handled.
-///
-/// Defaults to using standard IO.
 pub struct StreamConfig {
-    pub(crate) inner: StreamConfigInner,
+    inner: StreamConfigInner,
 }
 
 impl Default for StreamConfig {
+    /// Defaults to using in-memory streams.
     fn default() -> Self {
-        Self::stdio()
+        Self::in_memory()
     }
 }
 
@@ -29,27 +37,28 @@ impl StreamConfig {
     }
 }
 
-pub(crate) enum StreamConfigInner {
+enum StreamConfigInner {
     Stdio,
     Memory,
 }
 
 /// Describes how a [`Machine`](crate::Machine) will be configured.
-pub struct MachineConfig {
+pub struct MachineBuilder {
     pub(crate) streams: StreamConfig,
     pub(crate) toplevel: &'static str,
 }
 
-impl Default for MachineConfig {
+impl Default for MachineBuilder {
+    /// Defaults to using in-memory streams.
     fn default() -> Self {
-        MachineConfig {
+        MachineBuilder {
             streams: Default::default(),
             toplevel: default_toplevel(),
         }
     }
 }
 
-impl MachineConfig {
+impl MachineBuilder {
     /// Creates a default configuration.
     pub fn new() -> Self {
         Default::default()
@@ -66,6 +75,114 @@ impl MachineConfig {
         self.toplevel = toplevel;
         self
     }
+
+    /// Builds the [`Machine`](crate::Machine) from this configuration.
+    pub fn build(self) -> Machine {
+        let args = MachineArgs::new();
+        let mut machine_st = MachineState::new();
+
+        let (user_input, user_output, user_error) = match self.streams.inner {
+            StreamConfigInner::Stdio => (
+                Stream::stdin(&mut machine_st.arena, args.add_history),
+                Stream::stdout(&mut machine_st.arena),
+                Stream::stderr(&mut machine_st.arena),
+            ),
+            StreamConfigInner::Memory => (
+                Stream::Null(StreamOptions::default()),
+                Stream::from_owned_string("".to_owned(), &mut machine_st.arena),
+                Stream::stderr(&mut machine_st.arena),
+            ),
+        };
+
+        let mut wam = Machine {
+            machine_st,
+            indices: IndexStore::new(),
+            code: vec![],
+            user_input,
+            user_output,
+            user_error,
+            load_contexts: vec![],
+            #[cfg(feature = "ffi")]
+            foreign_function_table: Default::default(),
+            rng: StdRng::from_entropy(),
+        };
+
+        let mut lib_path = current_dir();
+
+        lib_path.pop();
+        lib_path.push("lib");
+
+        wam.add_impls_to_indices();
+
+        bootstrapping_compile(
+            Stream::from_static_string(
+                libraries::get("ops_and_meta_predicates")
+                    .expect("library ops_and_meta_predicates should exist"),
+                &mut wam.machine_st.arena,
+            ),
+            &mut wam,
+            ListingSource::from_file_and_path(
+                atom!("ops_and_meta_predicates.pl"),
+                lib_path.clone(),
+            ),
+        )
+        .unwrap();
+
+        bootstrapping_compile(
+            Stream::from_static_string(
+                libraries::get("builtins").expect("library builtins should exist"),
+                &mut wam.machine_st.arena,
+            ),
+            &mut wam,
+            ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
+        )
+        .unwrap();
+
+        if let Some(builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
+            load_module(
+                &mut wam.machine_st,
+                &mut wam.indices.code_dir,
+                &mut wam.indices.op_dir,
+                &mut wam.indices.meta_predicates,
+                &CompilationTarget::User,
+                builtins,
+            );
+
+            import_builtin_impls(&wam.indices.code_dir, builtins);
+        } else {
+            unreachable!()
+        }
+
+        lib_path.pop(); // remove the "lib" at the end
+
+        bootstrapping_compile(
+            Stream::from_static_string(include_str!("../loader.pl"), &mut wam.machine_st.arena),
+            &mut wam,
+            ListingSource::from_file_and_path(atom!("loader.pl"), lib_path.clone()),
+        )
+        .unwrap();
+
+        wam.configure_modules();
+
+        if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
+            load_module(
+                &mut wam.machine_st,
+                &mut wam.indices.code_dir,
+                &mut wam.indices.op_dir,
+                &mut wam.indices.meta_predicates,
+                &CompilationTarget::User,
+                loader,
+            );
+        } else {
+            unreachable!()
+        }
+
+        wam.load_special_forms();
+        wam.load_top_level(self.toplevel);
+        wam.configure_streams();
+
+        wam
+    }
 }
 
 /// Returns a static string slice to the default toplevel
index 04cfb55c2b5bcae8a34946543f2b29d4fb49c9bb..c4f168b6e06a88d7db737d795da583c1640afbb6 100644 (file)
@@ -1,17 +1,17 @@
 use std::collections::BTreeMap;
 
+use crate::atom_table;
 use crate::machine::machine_indices::VarKey;
 use crate::machine::mock_wam::CompositeOpDir;
 use crate::machine::{BREAK_FROM_DISPATCH_LOOP_LOC, LIB_QUERY_SUCCESS};
 use crate::parser::ast::{Var, VarPtr};
 use crate::parser::parser::{Parser, Tokens};
 use crate::read::{write_term_to_heap, TermWriteResult};
-use crate::{atom_table, StreamConfig};
 use indexmap::IndexMap;
 
 use super::{
     streams::Stream, Atom, AtomCell, HeapCellValue, HeapCellValueTag, LeafAnswer, Machine,
-    MachineConfig, PrologTerm,
+    PrologTerm,
 };
 
 /// An iterator though the leaf answers of a query.
@@ -166,11 +166,6 @@ impl Iterator for QueryState<'_> {
 }
 
 impl Machine {
-    /// Creates a new [`Machine`] configured for use as a library.
-    pub fn new_lib() -> Self {
-        Machine::new(MachineConfig::default().with_streams(StreamConfig::in_memory()))
-    }
-
     /// Loads a module into the [`Machine`] from a string.
     pub fn load_module_string(&mut self, module_name: &str, program: impl Into<String>) {
         let stream = Stream::from_owned_string(program.into(), &mut self.machine_st.arena);
index a4aba11281741df65af8b42f92a6b04077c6e050..457afacfdcf836d92fef5a9152630b7e5231c9c9 100644 (file)
@@ -6,7 +6,6 @@ pub use crate::machine::*;
 pub use crate::parser::ast::*;
 use crate::read::*;
 pub use crate::types::*;
-use crate::StreamConfig;
 
 use std::sync::Arc;
 
@@ -232,11 +231,6 @@ pub(crate) fn parse_and_write_parsed_term_to_heap(
 }
 
 impl Machine {
-    /// For use in tests.
-    pub fn with_test_streams() -> Self {
-        Machine::new(MachineConfig::default().with_streams(StreamConfig::in_memory()))
-    }
-
     /// For use in tests.
     pub fn test_load_file(&mut self, file: &str) -> Vec<u8> {
         let stream = Stream::from_owned_string(
index 448734e4080e1115fc6294f07a6b47a03e165ef6..7da191467544ef15d492a2eb2a5a00014378b39b 100644 (file)
@@ -55,7 +55,6 @@ use lazy_static::lazy_static;
 use ordered_float::OrderedFloat;
 
 use rand::rngs::StdRng;
-use rand::SeedableRng;
 use std::cmp::Ordering;
 use std::env;
 use std::io::Read;
@@ -63,7 +62,6 @@ use std::path::PathBuf;
 use std::sync::atomic::AtomicBool;
 use std::sync::OnceLock;
 
-use self::config::MachineConfig;
 use self::parsed_results::*;
 
 lazy_static! {
@@ -71,6 +69,8 @@ lazy_static! {
 }
 
 /// An instance of Scryer Prolog.
+///
+/// Created with [`MachineBuilder::build`](crate::machine::config::MachineBuilder::build).
 #[derive(Debug)]
 pub struct Machine {
     pub(super) machine_st: MachineState,
@@ -482,115 +482,6 @@ impl Machine {
         }
     }
 
-    /// Creates a new [`Machine`] from a [`MachineConfig`].
-    #[allow(clippy::new_without_default)]
-    pub fn new(config: MachineConfig) -> Self {
-        let args = MachineArgs::new();
-        let mut machine_st = MachineState::new();
-
-        let (user_input, user_output, user_error) = match config.streams.inner {
-            config::StreamConfigInner::Stdio => (
-                Stream::stdin(&mut machine_st.arena, args.add_history),
-                Stream::stdout(&mut machine_st.arena),
-                Stream::stderr(&mut machine_st.arena),
-            ),
-            config::StreamConfigInner::Memory => (
-                Stream::Null(StreamOptions::default()),
-                Stream::from_owned_string("".to_owned(), &mut machine_st.arena),
-                Stream::stderr(&mut machine_st.arena),
-            ),
-        };
-
-        let mut wam = Machine {
-            machine_st,
-            indices: IndexStore::new(),
-            code: vec![],
-            user_input,
-            user_output,
-            user_error,
-            load_contexts: vec![],
-            #[cfg(feature = "ffi")]
-            foreign_function_table: Default::default(),
-            rng: StdRng::from_entropy(),
-        };
-
-        let mut lib_path = current_dir();
-
-        lib_path.pop();
-        lib_path.push("lib");
-
-        wam.add_impls_to_indices();
-
-        bootstrapping_compile(
-            Stream::from_static_string(
-                libraries::get("ops_and_meta_predicates")
-                    .expect("library ops_and_meta_predicates should exist"),
-                &mut wam.machine_st.arena,
-            ),
-            &mut wam,
-            ListingSource::from_file_and_path(
-                atom!("ops_and_meta_predicates.pl"),
-                lib_path.clone(),
-            ),
-        )
-        .unwrap();
-
-        bootstrapping_compile(
-            Stream::from_static_string(
-                libraries::get("builtins").expect("library builtins should exist"),
-                &mut wam.machine_st.arena,
-            ),
-            &mut wam,
-            ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
-        )
-        .unwrap();
-
-        if let Some(builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
-            load_module(
-                &mut wam.machine_st,
-                &mut wam.indices.code_dir,
-                &mut wam.indices.op_dir,
-                &mut wam.indices.meta_predicates,
-                &CompilationTarget::User,
-                builtins,
-            );
-
-            import_builtin_impls(&wam.indices.code_dir, builtins);
-        } else {
-            unreachable!()
-        }
-
-        lib_path.pop(); // remove the "lib" at the end
-
-        bootstrapping_compile(
-            Stream::from_static_string(include_str!("../loader.pl"), &mut wam.machine_st.arena),
-            &mut wam,
-            ListingSource::from_file_and_path(atom!("loader.pl"), lib_path.clone()),
-        )
-        .unwrap();
-
-        wam.configure_modules();
-
-        if let Some(loader) = wam.indices.modules.get(&atom!("loader")) {
-            load_module(
-                &mut wam.machine_st,
-                &mut wam.indices.code_dir,
-                &mut wam.indices.op_dir,
-                &mut wam.indices.meta_predicates,
-                &CompilationTarget::User,
-                loader,
-            );
-        } else {
-            unreachable!()
-        }
-
-        wam.load_special_forms();
-        wam.load_top_level(config.toplevel);
-        wam.configure_streams();
-
-        wam
-    }
-
     pub(crate) fn configure_streams(&mut self) {
         self.user_input
             .options_mut()