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'))
|
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
|
||||||
}
|
}
|
||||||
|
@ -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())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user