From: bakaq Date: Sat, 12 Oct 2024 19:07:13 +0000 (-0300) Subject: MachineBuilder X-Git-Tag: v0.10.0~92^2~13 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=d336cbc86a17105f1cfb7b21ec42605fbcb11ec9;p=scryer-prolog.git MachineBuilder --- diff --git a/src/lib.rs b/src/lib.rs index dc8693ec..6148ef5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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)) }) } diff --git a/src/machine/config.rs b/src/machine/config.rs index ec930464..039cf2f4 100644 --- a/src/machine/config.rs +++ b/src/machine/config.rs @@ -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 diff --git a/src/machine/lib_machine.rs b/src/machine/lib_machine.rs index 04cfb55c..c4f168b6 100644 --- a/src/machine/lib_machine.rs +++ b/src/machine/lib_machine.rs @@ -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) { let stream = Stream::from_owned_string(program.into(), &mut self.machine_st.arena); diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index a4aba112..457afacf 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -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 { let stream = Stream::from_owned_string( diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 448734e4..7da19146 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -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()