/// 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 || {
.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))
})
}
+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()
}
}
}
}
-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()
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
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.
}
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);
pub use crate::parser::ast::*;
use crate::read::*;
pub use crate::types::*;
-use crate::StreamConfig;
use std::sync::Arc;
}
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(
use ordered_float::OrderedFloat;
use rand::rngs::StdRng;
-use rand::SeedableRng;
use std::cmp::Ordering;
use std::env;
use std::io::Read;
use std::sync::atomic::AtomicBool;
use std::sync::OnceLock;
-use self::config::MachineConfig;
use self::parsed_results::*;
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,
}
}
- /// 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()