1
0

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,30 +32,33 @@ pub enum BuiltInValue {
} }
impl BuiltInValue { impl BuiltInValue {
fn r#type(&self) -> Type { pub fn name(&self) -> &'static str {
match self { match self {
BuiltInValue::Args => Type::list(Type::String), BuiltInValue::Args => "args",
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), BuiltInValue::AssertEqual => "assert_equal",
BuiltInValue::Fs => Type::Structure(Identifier::from("fs")), BuiltInValue::Fs => "fs",
BuiltInValue::Json => Type::Structure(Identifier::from("json")), BuiltInValue::Json => "json",
BuiltInValue::Length => BuiltInFunction::Length.r#type(), BuiltInValue::Length => "length",
BuiltInValue::Output => BuiltInFunction::Output.r#type(), BuiltInValue::Output => "output",
BuiltInValue::Random => Type::Structure(Identifier::from("random")), BuiltInValue::Random => "random",
BuiltInValue::String => Type::Structure(Identifier::from("string")), BuiltInValue::String => "string",
} }
} }
fn get(&self) -> &Value { pub fn get(self) -> Value {
match self { match self {
BuiltInValue::Args => ARGS.get_or_init(|| { BuiltInValue::Args => ARGS
.get_or_init(|| {
let args = args().map(|arg| Value::string(arg.to_string())).collect(); let args = args().map(|arg| Value::string(arg.to_string())).collect();
Value::List(List::with_items(args)) Value::List(List::with_items(args))
}), })
.clone(),
BuiltInValue::AssertEqual => { BuiltInValue::AssertEqual => {
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
} }
BuiltInValue::Fs => FS.get_or_init(|| { BuiltInValue::Fs => FS
.get_or_init(|| {
let fs_context = Structure::default(); let fs_context = Structure::default();
fs_context fs_context
@ -62,8 +70,10 @@ impl BuiltInValue {
.unwrap(); .unwrap();
Value::Structure(fs_context) Value::Structure(fs_context)
}), })
BuiltInValue::Json => JSON.get_or_init(|| { .clone(),
BuiltInValue::Json => JSON
.get_or_init(|| {
let json_context = Structure::default(); let json_context = Structure::default();
json_context json_context
@ -75,10 +85,12 @@ impl BuiltInValue {
.unwrap(); .unwrap();
Value::Structure(json_context) Value::Structure(json_context)
}), })
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), .clone(),
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)), BuiltInValue::Length => Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::Random => RANDOM.get_or_init(|| { BuiltInValue::Output => Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
BuiltInValue::Random => RANDOM
.get_or_init(|| {
let random_context = Structure::default(); let random_context = Structure::default();
{ {
@ -99,8 +111,10 @@ impl BuiltInValue {
} }
Value::Structure(random_context) Value::Structure(random_context)
}), })
BuiltInValue::String => STRING.get_or_init(|| { .clone(),
BuiltInValue::String => STRING
.get_or_init(|| {
let string_context = Structure::default(); let string_context = Structure::default();
{ {
@ -108,9 +122,9 @@ impl BuiltInValue {
for string_function in string_functions() { for string_function in string_functions() {
let key = string_function.name().to_string(); let key = string_function.name().to_string();
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( let value = Value::Function(Function::BuiltIn(
string_function, BuiltInFunction::String(string_function),
))); ));
let r#type = string_function.r#type(); let r#type = string_function.r#type();
variables.insert(key, (value, r#type)); variables.insert(key, (value, r#type));
@ -118,7 +132,21 @@ impl BuiltInValue {
} }
Value::Structure(string_context) 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(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(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<()> { 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
.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(),
));
}
} else {
return Err(Error::ExpectedIndexIdentifier {
actual: self.index.clone(),
});
};
if let Type::Structure(identifier) = r#type {
let variables = context.variables()?; let variables = context.variables()?;
let get_type = variables.get(identifier.inner()); let get_structure = variables.get(key);
let value = if let Some((value, _)) = get_structure {
value.clone()
} else {
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()?;
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 { if let Some((_, r#type)) = get_type {
Ok(r#type.clone()) Ok(r#type.clone())
} else { } else {
Ok(Type::None) Err(Error::VariableIdentifierNotFound(
} identifier.inner().clone(),
} else if let Type::StructureDefinition(instantiator) = &r#type { ))
let get_type = instantiator.get(key); }
}
if let Some((statement_option, type_option)) = get_type { IndexExpression::Value(_) => todo!(),
let r#type = if let Some(r#type) = type_option { IndexExpression::Index(_) => todo!(),
r#type.inner().clone() IndexExpression::FunctionCall(_) => todo!(),
} else {
if let Some(statement) = statement_option {
statement.expected_type(context)?
} else {
Type::None
}
};
Ok(r#type)
} else {
Err(Error::VariableIdentifierNotFound(key.clone()))
}
} else {
Err(Error::ExpectedStructureDefinition { actual: r#type })
} }
} }
Type::None => Ok(Type::None),
r#type => Ok(r#type), r#type => Ok(r#type),
} }
} }