Refactor result parsing to idiomatic Rust and extract into parsed_results.rs
This commit is contained in:
@@ -15,6 +15,7 @@ pub mod machine_indices;
|
|||||||
pub mod machine_state;
|
pub mod machine_state;
|
||||||
pub mod machine_state_impl;
|
pub mod machine_state_impl;
|
||||||
pub mod mock_wam;
|
pub mod mock_wam;
|
||||||
|
pub mod parsed_results;
|
||||||
pub mod partial_string;
|
pub mod partial_string;
|
||||||
pub mod preprocessor;
|
pub mod preprocessor;
|
||||||
pub mod stack;
|
pub mod stack;
|
||||||
@@ -46,13 +47,14 @@ use lazy_static::lazy_static;
|
|||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
|
use self::parsed_results::*;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
||||||
}
|
}
|
||||||
@@ -181,32 +183,6 @@ pub(crate) fn get_structure_index(value: HeapCellValue) -> Option<CodeIndex> {
|
|||||||
None
|
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 {
|
impl Machine {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
|
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
|
||||||
@@ -360,117 +336,15 @@ impl Machine {
|
|||||||
|
|
||||||
pub fn parse_output(&self) -> QueryResult {
|
pub fn parse_output(&self) -> QueryResult {
|
||||||
let output = self.get_user_output();
|
let output = self.get_user_output();
|
||||||
let parsed_lines = output.split(";")
|
output.split(";")
|
||||||
.map(|s| s.trim())
|
.map(|s| s.trim())
|
||||||
.map(|s| s.replace(".", ""))
|
.map(|s| s.replace(".", ""))
|
||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
.map(|s| {
|
.map(QueryResultLine::try_from)
|
||||||
match s.as_str() {
|
.filter_map(Result::ok)
|
||||||
"true" => QueryResultLine::True,
|
.collect::<Vec<QueryResultLine>>()
|
||||||
"false" => QueryResultLine::False,
|
.into()
|
||||||
_ => 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
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
pub(crate) fn configure_modules(&mut self) {
|
||||||
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir, arena: &mut Arena) {
|
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir, arena: &mut Arena) {
|
||||||
|
|||||||
149
src/machine/parsed_results.rs
Normal file
149
src/machine/parsed_results.rs
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user