pub mod machine_state;
pub mod machine_state_impl;
pub mod mock_wam;
+pub mod parsed_results;
pub mod partial_string;
pub mod preprocessor;
pub mod stack;
use ordered_float::OrderedFloat;
use std::cmp::Ordering;
-use std::collections::BTreeMap;
use std::env;
use std::io::Read;
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
use tokio::runtime::Runtime;
+use self::parsed_results::*;
+
lazy_static! {
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
}
None
}
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum QueryResult {
- True,
- False,
- Matches(Vec<QueryResultLine>),
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum QueryResultLine {
- True,
- False,
- Match(BTreeMap<String, Value>),
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Value {
- Integer(Integer),
- Rational(Rational),
- Float(OrderedFloat<f64>),
- Atom(Atom),
- String(String),
- List(Vec<Value>),
- Structure(Atom, Vec<Value>),
- Var,
-}
-
impl Machine {
#[inline]
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
pub fn parse_output(&self) -> QueryResult {
let output = self.get_user_output();
- let parsed_lines = output.split(";")
+ output.split(";")
.map(|s| s.trim())
.map(|s| s.replace(".", ""))
.filter(|s| !s.is_empty())
- .map(|s| {
- match s.as_str() {
- "true" => QueryResultLine::True,
- "false" => QueryResultLine::False,
- _ => QueryResultLine::Match(
- s.split(",")
- .map(|s| s.trim())
- .filter(|s| !s.is_empty())
- .map(|s| {
- let mut iter = s.split(" = ");
-
- let key = iter.next().unwrap().to_string();
- let value = iter.next().unwrap().to_string();
-
- (key, Machine::parse_value(value))
- })
- .collect::<BTreeMap<_, _>>()
- )
- }
- })
- .collect::<Vec<QueryResultLine>>();
-
- // If there is only one line, and it is true or false, return that.
- if parsed_lines.len() == 1 {
- match parsed_lines[0].clone() {
- QueryResultLine::True => return QueryResult::True,
- QueryResultLine::False => return QueryResult::False,
- _ => {}
- }
- }
-
- // If there is at least one line with true and no matches, return true.
- if parsed_lines.iter().any(|l| l == &QueryResultLine::True)
- && !parsed_lines.iter().any(|l| {
- if let &QueryResultLine::Match(_) = l { true } else { false }
- }) {
- return QueryResult::True;
- }
-
- // If there is at least one match, return all matches.
- if parsed_lines.iter().any(|l| {
- if let &QueryResultLine::Match(_) = l { true } else { false }
- }) {
- let all_matches = parsed_lines.into_iter()
- .filter(|l| {
- if let &QueryResultLine::Match(_) = l { true } else { false }
- })
- .collect::<Vec<_>>();
- return QueryResult::Matches(all_matches);
- }
-
- QueryResult::False
+ .map(QueryResultLine::try_from)
+ .filter_map(Result::ok)
+ .collect::<Vec<QueryResultLine>>()
+ .into()
}
- pub fn parse_value(string: String) -> Value {
- let trimmed = string.trim();
-
- if trimmed.starts_with("'") && trimmed.ends_with("'") {
- Value::String(trimmed[1..trimmed.len() - 1].into())
- } else
- if trimmed.starts_with("\"") && trimmed.ends_with("\"") {
- Value::String(trimmed[1..trimmed.len() - 1].into())
- } else if trimmed.starts_with("[") && trimmed.ends_with("]") {
- let mut iter = trimmed[1..trimmed.len() - 1].split(",");
-
- let mut values = vec![];
-
- while let Some(value) = iter.next() {
- values.push(Machine::parse_value(value.to_string()));
- }
-
- Value::List(values)
- } else if trimmed.starts_with("{") && trimmed.ends_with("}") {
- let mut iter = trimmed[1..trimmed.len() - 1].split(",");
-
- let mut values = vec![];
-
- while let Some(value) = iter.next() {
- let mut iter = value.split(":");
-
- let key = iter.next().unwrap().to_string();
- let value = iter.next().unwrap().to_string();
-
- values.push(Machine::parse_value(value));
- }
-
- Value::Structure(atom!("{}"), values)
- } else if trimmed.starts_with("<<") && trimmed.ends_with(">>") {
- let mut iter = trimmed[2..trimmed.len() - 2].split(",");
-
- let mut values = vec![];
-
- while let Some(value) = iter.next() {
- let mut iter = value.split(":");
-
- let key = iter.next().unwrap().to_string();
- let value = iter.next().unwrap().to_string();
-
- values.push(Machine::parse_value(value));
- }
-
- Value::Structure(atom!("<<>>"), values)
- } else {
- Value::String(string)
- }
- }
-
-
pub(crate) fn configure_modules(&mut self) {
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir, arena: &mut Arena) {
for arity in 1..66 {
--- /dev/null
+use ordered_float::OrderedFloat;
+use rug::*;
+use std::{collections::BTreeMap};
+use crate::atom_table::*;
+
+use super::Machine;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum QueryResult {
+ True,
+ False,
+ Matches(Vec<QueryResultLine>),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum QueryResultLine {
+ True,
+ False,
+ Match(BTreeMap<String, Value>),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Value {
+ Integer(Integer),
+ Rational(Rational),
+ Float(OrderedFloat<f64>),
+ Atom(Atom),
+ String(String),
+ List(Vec<Value>),
+ Structure(Atom, Vec<Value>),
+ Var,
+}
+
+impl From<Vec<QueryResultLine>> for QueryResult {
+ fn from(query_result_lines: Vec<QueryResultLine>) -> Self {
+ // If there is only one line, and it is true or false, return that.
+ if query_result_lines.len() == 1 {
+ match query_result_lines[0].clone() {
+ QueryResultLine::True => return QueryResult::True,
+ QueryResultLine::False => return QueryResult::False,
+ _ => {}
+ }
+ }
+
+ // If there is at least one line with true and no matches, return true.
+ if query_result_lines.iter().any(|l| l == &QueryResultLine::True)
+ && !query_result_lines.iter().any(|l| {
+ if let &QueryResultLine::Match(_) = l { true } else { false }
+ }) {
+ return QueryResult::True;
+ }
+
+ // If there is at least one match, return all matches.
+ if query_result_lines.iter().any(|l| {
+ if let &QueryResultLine::Match(_) = l { true } else { false }
+ }) {
+ let all_matches = query_result_lines.into_iter()
+ .filter(|l| {
+ if let &QueryResultLine::Match(_) = l { true } else { false }
+ })
+ .collect::<Vec<_>>();
+ return QueryResult::Matches(all_matches);
+ }
+
+ QueryResult::False
+ }
+}
+
+
+impl TryFrom<String> for QueryResultLine {
+ type Error = ();
+ fn try_from(string: String) -> Result<Self, Self::Error> {
+ match string.as_str() {
+ "true" => Ok(QueryResultLine::True),
+ "false" => Ok(QueryResultLine::False),
+ _ => Ok(QueryResultLine::Match(
+ string.split(",")
+ .map(|s| s.trim())
+ .filter(|s| !s.is_empty())
+ .map(|s| -> Result<(String, Value), ()>{
+ let mut iter = s.split(" = ");
+
+ let key = iter.next().unwrap().to_string();
+ let value = iter.next().unwrap().to_string();
+
+ Ok((key, Value::try_from(value)?))
+ })
+ .filter_map(Result::ok)
+ .collect::<BTreeMap<_, _>>()
+ ))
+ }
+ }
+}
+
+impl TryFrom<String> for Value {
+ type Error = ();
+ fn try_from(string: String) -> Result<Self, Self::Error> {
+ let trimmed = string.trim();
+
+ if trimmed.starts_with("'") && trimmed.ends_with("'") {
+ Ok(Value::String(trimmed[1..trimmed.len() - 1].into()))
+ } else
+ if trimmed.starts_with("\"") && trimmed.ends_with("\"") {
+ Ok(Value::String(trimmed[1..trimmed.len() - 1].into()))
+ } else if trimmed.starts_with("[") && trimmed.ends_with("]") {
+ let mut iter = trimmed[1..trimmed.len() - 1].split(",");
+
+ let mut values = vec![];
+
+ while let Some(s) = iter.next() {
+ values.push(Value::try_from(s.to_string())?);
+ }
+
+ Ok(Value::List(values))
+ } else if trimmed.starts_with("{") && trimmed.ends_with("}") {
+ let mut iter = trimmed[1..trimmed.len() - 1].split(",");
+
+ let mut values = vec![];
+
+ while let Some(value) = iter.next() {
+ let mut iter = value.split(":");
+
+ let key = iter.next().unwrap().to_string();
+ let value = iter.next().unwrap().to_string();
+
+ values.push(Value::try_from(value)?);
+ }
+
+ Ok(Value::Structure(atom!("{}"), values))
+ } else if trimmed.starts_with("<<") && trimmed.ends_with(">>") {
+ let mut iter = trimmed[2..trimmed.len() - 2].split(",");
+
+ let mut values = vec![];
+
+ while let Some(value) = iter.next() {
+ let mut iter = value.split(":");
+
+ let key = iter.next().unwrap().to_string();
+ let value = iter.next().unwrap().to_string();
+
+ values.push(Value::try_from(value)?);
+ }
+
+ Ok(Value::Structure(atom!("<<>>"), values))
+ } else {
+ Err(())
+ }
+ }
+}
\ No newline at end of file