From 568abef5b8af9e961d3c7a95a896e8071de83962 Mon Sep 17 00:00:00 2001 From: Nicolas Luck Date: Wed, 12 Jul 2023 01:24:39 +0200 Subject: [PATCH] Parsed QueryResult --- src/machine/mod.rs | 150 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 3 deletions(-) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 2d5cff2e..b3e5b2e3 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -46,6 +46,7 @@ use lazy_static::lazy_static; use ordered_float::OrderedFloat; use std::cmp::Ordering; +use std::collections::BTreeMap; use std::env; use std::io::Read; use std::path::PathBuf; @@ -180,6 +181,32 @@ pub(crate) fn get_structure_index(value: HeapCellValue) -> Option { None } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum QueryResult { + True, + False, + Matches(Vec), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum QueryResultLine { + True, + False, + Match(BTreeMap), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Value { + Integer(Integer), + Rational(Rational), + Float(OrderedFloat), + Atom(Atom), + String(String), + List(Vec), + Structure(Atom, Vec), + Var, +} + impl Machine { #[inline] pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) { @@ -315,7 +342,7 @@ impl Machine { self.user_input = Stream::from_owned_string(input, &mut self.machine_st.arena); } - pub fn get_user_output(&mut self) -> String { + pub fn get_user_output(&self) -> String { let output_bytes: Vec<_> = self.user_output.bytes().map(|b| b.unwrap()).collect(); String::from_utf8(output_bytes).unwrap() } @@ -325,12 +352,129 @@ impl Machine { self.load_file(module_name, stream); } - pub fn run_query(&mut self, query: String) -> String{ + pub fn run_query(&mut self, query: String) -> QueryResult{ self.set_user_input(query); self.run_input_once(); - self.get_user_output() + self.parse_output() + } + + pub fn parse_output(&self) -> QueryResult { + let output = self.get_user_output(); + println!("parse_output output: {:?}", output); + let parsed_lines = 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::>() + ) + } + }) + .collect::>(); + + println!("parsed_lines: {:?}", parsed_lines); + + // 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::>(); + 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) { fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir, arena: &mut Arena) { for arity in 1..66 { -- 2.54.0