From 84cb17e75c6d80964d831d51eabb5021492b8055 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 4 Jan 2024 20:54:22 -0500 Subject: [PATCH] Implement structures --- examples/jq_data.ds | 9 +- src/abstract_tree/built_in_value.rs | 202 ++++++++++++++++------------ src/abstract_tree/function_call.rs | 21 ++- src/abstract_tree/identifier.rs | 2 +- src/abstract_tree/index.rs | 89 ++++++------ 5 files changed, 181 insertions(+), 142 deletions(-) diff --git a/examples/jq_data.ds b/examples/jq_data.ds index 3673a51..b24b183 100644 --- a/examples/jq_data.ds +++ b/examples/jq_data.ds @@ -1,9 +1,14 @@ data = json:parse(fs:read('examples/assets/jq_data.json')) -new_data = [] +MyData = struct { + message + name +} + +data_list = [] for commit_data in data { - new_data += { + new_data += new MyData { message = commit_data:commit:message name = commit_data:commit:committer:name } diff --git a/src/abstract_tree/built_in_value.rs b/src/abstract_tree/built_in_value.rs index ac3a11c..ff367ce 100644 --- a/src/abstract_tree/built_in_value.rs +++ b/src/abstract_tree/built_in_value.rs @@ -1,5 +1,6 @@ use std::{env::args, sync::OnceLock}; +use enum_iterator::{all, Sequence}; use serde::{Deserialize, Serialize}; use tree_sitter::Node; @@ -14,7 +15,11 @@ static JSON: OnceLock = OnceLock::new(); static RANDOM: OnceLock = OnceLock::new(); static STRING: OnceLock = OnceLock::new(); -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub fn built_in_values() -> impl Iterator { + all() +} + +#[derive(Sequence, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum BuiltInValue { Args, AssertEqual, @@ -27,98 +32,121 @@ pub enum BuiltInValue { } impl BuiltInValue { + pub fn name(&self) -> &'static str { + match self { + BuiltInValue::Args => "args", + BuiltInValue::AssertEqual => "assert_equal", + BuiltInValue::Fs => "fs", + BuiltInValue::Json => "json", + BuiltInValue::Length => "length", + BuiltInValue::Output => "output", + BuiltInValue::Random => "random", + BuiltInValue::String => "string", + } + } + + pub fn get(self) -> Value { + match self { + BuiltInValue::Args => ARGS + .get_or_init(|| { + let args = args().map(|arg| Value::string(arg.to_string())).collect(); + + Value::List(List::with_items(args)) + }) + .clone(), + BuiltInValue::AssertEqual => { + Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) + } + BuiltInValue::Fs => FS + .get_or_init(|| { + let fs_context = Structure::default(); + + fs_context + .set( + "read".to_string(), + Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)), + None, + ) + .unwrap(); + + Value::Structure(fs_context) + }) + .clone(), + BuiltInValue::Json => JSON + .get_or_init(|| { + let json_context = Structure::default(); + + json_context + .set( + "parse".to_string(), + Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)), + None, + ) + .unwrap(); + + Value::Structure(json_context) + }) + .clone(), + BuiltInValue::Length => Value::Function(Function::BuiltIn(BuiltInFunction::Length)), + BuiltInValue::Output => Value::Function(Function::BuiltIn(BuiltInFunction::Output)), + BuiltInValue::Random => RANDOM + .get_or_init(|| { + let random_context = Structure::default(); + + { + let mut variables = random_context.variables_mut().unwrap(); + + for built_in_function in [ + BuiltInFunction::RandomBoolean, + BuiltInFunction::RandomFloat, + BuiltInFunction::RandomFrom, + BuiltInFunction::RandomInteger, + ] { + let key = built_in_function.name().to_string(); + let value = Value::Function(Function::BuiltIn(built_in_function)); + let r#type = built_in_function.r#type(); + + variables.insert(key, (value, r#type)); + } + } + + Value::Structure(random_context) + }) + .clone(), + BuiltInValue::String => STRING + .get_or_init(|| { + let string_context = Structure::default(); + + { + let mut variables = string_context.variables_mut().unwrap(); + + for string_function in string_functions() { + let key = string_function.name().to_string(); + let value = Value::Function(Function::BuiltIn( + BuiltInFunction::String(string_function), + )); + let r#type = string_function.r#type(); + + variables.insert(key, (value, r#type)); + } + } + + Value::Structure(string_context) + }) + .clone(), + } + } + fn r#type(&self) -> Type { match self { BuiltInValue::Args => Type::list(Type::String), BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), - BuiltInValue::Fs => Type::Structure(Identifier::from("fs")), - BuiltInValue::Json => Type::Structure(Identifier::from("json")), + BuiltInValue::Fs => Type::Structure(Identifier::from(self.name())), + BuiltInValue::Json => Type::Structure(Identifier::from(self.name())), BuiltInValue::Length => BuiltInFunction::Length.r#type(), BuiltInValue::Output => BuiltInFunction::Output.r#type(), - BuiltInValue::Random => Type::Structure(Identifier::from("random")), - BuiltInValue::String => Type::Structure(Identifier::from("string")), - } - } - - fn get(&self) -> &Value { - match self { - BuiltInValue::Args => ARGS.get_or_init(|| { - let args = args().map(|arg| Value::string(arg.to_string())).collect(); - - Value::List(List::with_items(args)) - }), - BuiltInValue::AssertEqual => { - &Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) - } - BuiltInValue::Fs => FS.get_or_init(|| { - let fs_context = Structure::default(); - - fs_context - .set( - "read".to_string(), - Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)), - None, - ) - .unwrap(); - - Value::Structure(fs_context) - }), - BuiltInValue::Json => JSON.get_or_init(|| { - let json_context = Structure::default(); - - json_context - .set( - "parse".to_string(), - Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)), - None, - ) - .unwrap(); - - Value::Structure(json_context) - }), - BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), - BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)), - BuiltInValue::Random => RANDOM.get_or_init(|| { - let random_context = Structure::default(); - - { - let mut variables = random_context.variables_mut().unwrap(); - - for built_in_function in [ - BuiltInFunction::RandomBoolean, - BuiltInFunction::RandomFloat, - BuiltInFunction::RandomFrom, - BuiltInFunction::RandomInteger, - ] { - let key = built_in_function.name().to_string(); - let value = Value::Function(Function::BuiltIn(built_in_function)); - let r#type = built_in_function.r#type(); - - variables.insert(key, (value, r#type)); - } - } - - Value::Structure(random_context) - }), - BuiltInValue::String => STRING.get_or_init(|| { - let string_context = Structure::default(); - - { - let mut variables = string_context.variables_mut().unwrap(); - - for string_function in string_functions() { - let key = string_function.name().to_string(); - let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( - string_function, - ))); - let r#type = string_function.r#type(); - - variables.insert(key, (value, r#type)); - } - } - - Value::Structure(string_context) - }), + BuiltInValue::Random => Type::Structure(Identifier::from(self.name())), + BuiltInValue::String => Type::Structure(Identifier::from(self.name())), } } } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index f88680c..31b5748 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -45,10 +45,27 @@ impl AbstractTree for FunctionCall { } fn check_type(&self, context: &Structure) -> Result<()> { - let function_expression_type = self.function_expression.expected_type(context)?; + let variables = context.variables()?; + let function_type = match &self.function_expression { + FunctionExpression::Identifier(identifier) => { + let get_type = variables.get(identifier.inner()); + + if let Some((_, r#type)) = get_type { + r#type + } else { + return Err(Error::FunctionIdentifierNotFound( + identifier.inner().clone(), + )); + } + } + FunctionExpression::FunctionCall(_) => todo!(), + FunctionExpression::Value(_) => todo!(), + FunctionExpression::Index(_) => todo!(), + FunctionExpression::Yield(_) => todo!(), + }; let parameter_types = if let Type::Function { parameter_types, .. - } = &function_expression_type + } = &function_type { parameter_types } else { diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index a08db72..8072c08 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -51,7 +51,7 @@ impl AbstractTree for Identifier { Ok(r#type.clone()) } else { - Ok(Type::None) + Err(Error::VariableIdentifierNotFound(self.0.clone())) } } } diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index aa3ebda..dd1220e 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, IndexExpression, List, Result, Structure, Type, Value}; +use crate::{ + built_in_values, AbstractTree, Error, IndexExpression, List, Result, Structure, Type, Value, +}; /// Abstract representation of an index expression. /// @@ -94,8 +96,9 @@ impl AbstractTree for Index { fn expected_type(&self, context: &Structure) -> Result { match self.collection.expected_type(context)? { Type::List(item_type) => Ok(*item_type.clone()), - Type::StructureDefinition(instantiator) => { - if let IndexExpression::Identifier(identifier) = &self.index { + Type::StructureDefinition(instantiator) => match &self.index { + IndexExpression::Value(_) => todo!(), + IndexExpression::Identifier(identifier) => { if let Some((statement_option, type_option)) = instantiator.get(identifier.inner()) { @@ -107,64 +110,50 @@ impl AbstractTree for Index { Ok(Type::None) } } else { - todo!() + Err(Error::VariableIdentifierNotFound( + identifier.inner().clone(), + )) } - } else { - todo!() } - } + IndexExpression::Index(_) => todo!(), + IndexExpression::FunctionCall(_) => todo!(), + }, Type::Structure(definition_identifier) => { - let (r#type, key) = if let IndexExpression::Identifier(identifier) = &self.index { - let get_type = context - .variables()? - .get(definition_identifier.inner()) - .map(|(_, r#type)| r#type.clone()); - - if let Some(r#type) = get_type { - (r#type, identifier.inner()) - } else { - return Err(Error::VariableIdentifierNotFound( - definition_identifier.inner().clone(), - )); - } + let key = definition_identifier.inner(); + let variables = context.variables()?; + let get_structure = variables.get(key); + let value = if let Some((value, _)) = get_structure { + value.clone() } else { - return Err(Error::ExpectedIndexIdentifier { - actual: self.index.clone(), - }); + let find_built_in_value = + built_in_values().find(|built_in_value| built_in_value.name() == key); + + if let Some(built_in_value) = find_built_in_value { + built_in_value.get() + } else { + return Err(Error::VariableIdentifierNotFound(key.to_string())); + } }; + let structure = value.as_structure()?; - if let Type::Structure(identifier) = r#type { - let variables = context.variables()?; - let get_type = variables.get(identifier.inner()); + match &self.index { + IndexExpression::Identifier(identifier) => { + let inner_variables = structure.variables()?; + let get_type = inner_variables.get(identifier.inner()); - if let Some((_, r#type)) = get_type { - Ok(r#type.clone()) - } else { - Ok(Type::None) - } - } else if let Type::StructureDefinition(instantiator) = &r#type { - let get_type = instantiator.get(key); - - if let Some((statement_option, type_option)) = get_type { - let r#type = if let Some(r#type) = type_option { - r#type.inner().clone() + if let Some((_, r#type)) = get_type { + Ok(r#type.clone()) } else { - if let Some(statement) = statement_option { - statement.expected_type(context)? - } else { - Type::None - } - }; - - Ok(r#type) - } else { - Err(Error::VariableIdentifierNotFound(key.clone())) + Err(Error::VariableIdentifierNotFound( + identifier.inner().clone(), + )) + } } - } else { - Err(Error::ExpectedStructureDefinition { actual: r#type }) + IndexExpression::Value(_) => todo!(), + IndexExpression::Index(_) => todo!(), + IndexExpression::FunctionCall(_) => todo!(), } } - Type::None => Ok(Type::None), r#type => Ok(r#type), } }