Implement structures

This commit is contained in:
Jeff 2024-01-04 20:54:22 -05:00
parent de98c58587
commit 84cb17e75c
5 changed files with 181 additions and 142 deletions

View File

@ -1,9 +1,14 @@
data = json:parse(fs:read('examples/assets/jq_data.json')) data = json:parse(fs:read('examples/assets/jq_data.json'))
new_data = [] MyData = struct {
message <str>
name <str>
}
data_list = []
for commit_data in data { for commit_data in data {
new_data += { new_data += new MyData {
message = commit_data:commit:message message = commit_data:commit:message
name = commit_data:commit:committer:name name = commit_data:commit:committer:name
} }

View File

@ -1,5 +1,6 @@
use std::{env::args, sync::OnceLock}; use std::{env::args, sync::OnceLock};
use enum_iterator::{all, Sequence};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
@ -14,7 +15,11 @@ static JSON: OnceLock<Value> = OnceLock::new();
static RANDOM: OnceLock<Value> = OnceLock::new(); static RANDOM: OnceLock<Value> = OnceLock::new();
static STRING: OnceLock<Value> = OnceLock::new(); static STRING: OnceLock<Value> = OnceLock::new();
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub fn built_in_values() -> impl Iterator<Item = BuiltInValue> {
all()
}
#[derive(Sequence, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInValue { pub enum BuiltInValue {
Args, Args,
AssertEqual, AssertEqual,
@ -27,98 +32,121 @@ pub enum BuiltInValue {
} }
impl 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 { fn r#type(&self) -> Type {
match self { match self {
BuiltInValue::Args => Type::list(Type::String), BuiltInValue::Args => Type::list(Type::String),
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
BuiltInValue::Fs => Type::Structure(Identifier::from("fs")), BuiltInValue::Fs => Type::Structure(Identifier::from(self.name())),
BuiltInValue::Json => Type::Structure(Identifier::from("json")), BuiltInValue::Json => Type::Structure(Identifier::from(self.name())),
BuiltInValue::Length => BuiltInFunction::Length.r#type(), BuiltInValue::Length => BuiltInFunction::Length.r#type(),
BuiltInValue::Output => BuiltInFunction::Output.r#type(), BuiltInValue::Output => BuiltInFunction::Output.r#type(),
BuiltInValue::Random => Type::Structure(Identifier::from("random")), BuiltInValue::Random => Type::Structure(Identifier::from(self.name())),
BuiltInValue::String => Type::Structure(Identifier::from("string")), BuiltInValue::String => Type::Structure(Identifier::from(self.name())),
}
}
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)
}),
} }
} }
} }

View File

@ -45,10 +45,27 @@ impl AbstractTree for FunctionCall {
} }
fn check_type(&self, context: &Structure) -> Result<()> { 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 { let parameter_types = if let Type::Function {
parameter_types, .. parameter_types, ..
} = &function_expression_type } = &function_type
{ {
parameter_types parameter_types
} else { } else {

View File

@ -51,7 +51,7 @@ impl AbstractTree for Identifier {
Ok(r#type.clone()) Ok(r#type.clone())
} else { } else {
Ok(Type::None) Err(Error::VariableIdentifierNotFound(self.0.clone()))
} }
} }
} }

View File

@ -1,7 +1,9 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of an index expression.
/// ///
@ -94,8 +96,9 @@ impl AbstractTree for Index {
fn expected_type(&self, context: &Structure) -> Result<Type> { fn expected_type(&self, context: &Structure) -> Result<Type> {
match self.collection.expected_type(context)? { match self.collection.expected_type(context)? {
Type::List(item_type) => Ok(*item_type.clone()), Type::List(item_type) => Ok(*item_type.clone()),
Type::StructureDefinition(instantiator) => { Type::StructureDefinition(instantiator) => match &self.index {
if let IndexExpression::Identifier(identifier) = &self.index { IndexExpression::Value(_) => todo!(),
IndexExpression::Identifier(identifier) => {
if let Some((statement_option, type_option)) = if let Some((statement_option, type_option)) =
instantiator.get(identifier.inner()) instantiator.get(identifier.inner())
{ {
@ -107,64 +110,50 @@ impl AbstractTree for Index {
Ok(Type::None) Ok(Type::None)
} }
} else { } else {
todo!() Err(Error::VariableIdentifierNotFound(
identifier.inner().clone(),
))
} }
} else {
todo!()
} }
} IndexExpression::Index(_) => todo!(),
IndexExpression::FunctionCall(_) => todo!(),
},
Type::Structure(definition_identifier) => { Type::Structure(definition_identifier) => {
let (r#type, key) = if let IndexExpression::Identifier(identifier) = &self.index { let key = definition_identifier.inner();
let get_type = context let variables = context.variables()?;
.variables()? let get_structure = variables.get(key);
.get(definition_identifier.inner()) let value = if let Some((value, _)) = get_structure {
.map(|(_, r#type)| r#type.clone()); value.clone()
if let Some(r#type) = get_type {
(r#type, identifier.inner())
} else {
return Err(Error::VariableIdentifierNotFound(
definition_identifier.inner().clone(),
));
}
} else { } else {
return Err(Error::ExpectedIndexIdentifier { let find_built_in_value =
actual: self.index.clone(), 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 { match &self.index {
let variables = context.variables()?; IndexExpression::Identifier(identifier) => {
let get_type = variables.get(identifier.inner()); let inner_variables = structure.variables()?;
let get_type = inner_variables.get(identifier.inner());
if let Some((_, r#type)) = get_type { if let Some((_, r#type)) = get_type {
Ok(r#type.clone()) 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()
} else { } else {
if let Some(statement) = statement_option { Err(Error::VariableIdentifierNotFound(
statement.expected_type(context)? identifier.inner().clone(),
} else { ))
Type::None }
}
};
Ok(r#type)
} else {
Err(Error::VariableIdentifierNotFound(key.clone()))
} }
} else { IndexExpression::Value(_) => todo!(),
Err(Error::ExpectedStructureDefinition { actual: r#type }) IndexExpression::Index(_) => todo!(),
IndexExpression::FunctionCall(_) => todo!(),
} }
} }
Type::None => Ok(Type::None),
r#type => Ok(r#type), r#type => Ok(r#type),
} }
} }