glowdust 0.0.1

A DBMS with a data model based on functions and pattern matching
Documentation
use crate::compiler::cursor::{FunctionCursor, VectorFunctionCursor};
use crate::compiler::value::parameters::{parameter_vectors_match, Parameter};
use crate::compiler::value::values::{
    FunctionDefinitionObject, FunctionValuesObject, TypeDefinition, Value,
};
use crate::store::{arguments_match_value, Store, NATIVE_FUNCTIONS};
use crate::{value_is_tuple, value_to_tuple};
use std::collections::HashMap;
use std::io::Error;

pub struct MemoryStore {
    function_definitions_registry: HashMap<String, Vec<FunctionDefinitionObject>>,
    function_values_registry: HashMap<String, FunctionValuesObject>,
    type_definitions: HashMap<String, TypeDefinition>,
}

impl Store for MemoryStore {
    fn is_function_name_defined(&self, name: &str) -> Result<bool, Error> {
        Ok(self.function_definitions_registry.contains_key(name))
    }

    fn get_function_value(&self, name: &str, argument: &[Value]) -> Result<Option<Value>, Error> {
        if let Some(values) = self.function_values_registry.get(name) {
            return Ok(values.values.get(argument).cloned());
        } else {
            Ok(None)
        }
    }

    fn set_function_value(
        &mut self,
        name: &str,
        argument: &[Value],
        value: Value,
    ) -> Result<(), Error> {
        if let Some(values) = self.function_values_registry.get_mut(name) {
            values.values.insert(argument.to_vec(), value);
        } else {
            let mut values = FunctionValuesObject::new();
            values.values.insert(argument.to_vec(), value);
            self.function_values_registry
                .insert(name.to_string(), values);
        }
        Ok(())
    }

    fn get_function_definition(
        &self,
        name: &str,
        argument: &[Value],
    ) -> Result<Option<FunctionDefinitionObject>, Error> {
        if let Some(definitions) = self.function_definitions_registry.get(name) {
            for definition in definitions {
                // debug!(
                //     "Checking next def, def arity is {}, arg arity is {}, defs params are {:?}",
                //     definition.formal_arguments.len(),
                //     argument.len(),
                //     definition.formal_arguments
                // );

                if arguments_match_value(&definition.formal_arguments, argument) {
                    // debug!("all good, we'll use this one");
                    return Ok(Some(definition.clone()));
                }
            }
        }
        Ok(None)
    }

    fn set_function_definition(
        &mut self,
        name: &str,
        parameters: &[Parameter],
        function: FunctionDefinitionObject,
    ) -> Result<(), Error> {
        if let Some(defs) = self.function_definitions_registry.get_mut(name) {
            // retain all definitions that do not have these parameters (i.e. remove matching definitions
            defs.retain(|definition| {
                !parameter_vectors_match(&definition.formal_arguments, parameters)
            });
            // add the new one back in
            defs.push(function);
            // we basically replaced, if it existed, the definition for this parameter vector with 2 lines. <mic drop>
        } else {
            let defs = vec![function];
            self.function_definitions_registry
                .insert(name.to_string(), defs);
        }
        Ok(())
    }

    fn function_cursor(&self, name: &str) -> FunctionCursor {
        return match self.function_values_registry.get(name) {
            None => FunctionCursor::Vector(VectorFunctionCursor::empty()),
            Some(function) => {
                let mut lhs = vec![];
                let mut rhs = vec![];
                for (key, value) in &function.values {
                    lhs.push(key.clone());
                    match value {
                        Value::PrimitiveValue(_) => {
                            rhs.push(vec![value.clone()]);
                        }
                        Value::Tuple(vec) => {
                            rhs.push(vec.clone());
                        }
                        Value::TypedValueInstance(_) => {
                            rhs.push(vec![value.clone()]);
                        }
                        Value::FunctionNameValue(name) => {
                            panic!(
                                "Function name values not supported as stored value types yet: {}",
                                name
                            );
                        }
                    }
                }
                FunctionCursor::Vector(VectorFunctionCursor::new(lhs, rhs, name))
            }
        };
    }

    fn has_values(&self, name: &str) -> bool {
        self.function_values_registry.get(name).is_some()
    }

    fn domain_arity(&self, name: &str) -> Option<u8> {
        // check values first
        match self.function_values_registry.get(name) {
            Some(function) => match function.values.keys().next() {
                None => {
                    panic!("Cannot have values and not have values at the same time, what the hell")
                }
                Some(key) => return Some(key.len() as u8),
            },
            None => {}
        };
        // then definitions
        match self.function_definitions_registry.get(name) {
            Some(defs) => {
                return Some(defs.first().unwrap().formal_arguments.len() as u8);
            }
            None => {}
        };
        // finally natives
        match NATIVE_FUNCTIONS.get(name) {
            Some(_) => Some(1),
            None => None,
        }
    }

    fn codomain_arity(&self, name: &str) -> Option<u8> {
        // check values first
        match self.function_values_registry.get(name) {
            Some(function) => match function.values.values().next() {
                None => {
                    panic!("Cannot have values and not have values at the same time, what the hell")
                }
                Some(value) => {
                    if value_is_tuple!(value) {
                        return Some(value_to_tuple!(value).len() as u8);
                    }
                    return Some(1_u8);
                }
            },
            None => {}
        };
        // then definitions
        match self.function_definitions_registry.get(name) {
            Some(_) => {
                return Some(1_u8);
            }
            None => {}
        };
        // finally natives
        match NATIVE_FUNCTIONS.get(name) {
            Some(_) => Some(1),
            None => None,
        }
    }

    fn set_type_definition(&mut self, name: &str, the_type: TypeDefinition) -> Result<(), Error> {
        self.type_definitions.insert(name.to_string(), the_type);
        Ok(())
    }

    fn type_definition_by_name(&self, name: &str) -> Result<Option<TypeDefinition>, Error> {
        Ok(self.type_definitions.get(name).cloned())
    }
}

impl MemoryStore {
    pub fn new() -> Self {
        MemoryStore {
            function_definitions_registry: HashMap::new(),
            function_values_registry: HashMap::new(),
            type_definitions: HashMap::new(),
        }
    }
}

impl Default for MemoryStore {
    fn default() -> Self {
        Self::new()
    }
}