Implement structures
This commit is contained in:
parent
de98c58587
commit
84cb17e75c
@ -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
|
||||
}
|
||||
|
@ -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())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -51,7 +51,7 @@ impl AbstractTree for Identifier {
|
||||
|
||||
Ok(r#type.clone())
|
||||
} else {
|
||||
Ok(Type::None)
|
||||
Err(Error::VariableIdentifierNotFound(self.0.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user