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'))
new_data = []
MyData = struct {
message <str>
name <str>
}
data_list = []
for commit_data in data {
new_data += {
new_data += new MyData {
message = commit_data:commit:message
name = commit_data:commit:committer:name
}

View File

@ -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<Value> = OnceLock::new();
static RANDOM: 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 {
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())),
}
}
}

View File

@ -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 {

View File

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

View File

@ -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<Type> {
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),
}
}