Begin adding index assignment
This commit is contained in:
parent
0b14ab5832
commit
a804a85b1f
@ -19,6 +19,8 @@ pub enum AssignmentOperator {
|
||||
|
||||
impl AbstractTree for Assignment {
|
||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||
Error::expect_syntax_node(source, "assignment", node)?;
|
||||
|
||||
let identifier_node = node.child(0).unwrap();
|
||||
let identifier = Identifier::from_syntax_node(source, identifier_node)?;
|
||||
|
||||
|
@ -5,9 +5,9 @@ use crate::{AbstractTree, Error, Expression, List, Map, Result, Value};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Index {
|
||||
collection: Expression,
|
||||
index: Expression,
|
||||
index_end: Option<Expression>,
|
||||
pub collection: Expression,
|
||||
pub index: Expression,
|
||||
pub index_end: Option<Expression>,
|
||||
}
|
||||
|
||||
impl AbstractTree for Index {
|
||||
@ -50,7 +50,7 @@ impl AbstractTree for Index {
|
||||
|
||||
Ok(item)
|
||||
}
|
||||
Value::Map(mut map) => {
|
||||
Value::Map(map) => {
|
||||
let value = if let Expression::Identifier(identifier) = &self.index {
|
||||
let key = identifier.inner();
|
||||
|
||||
|
@ -19,6 +19,8 @@ pub enum AssignmentOperator {
|
||||
|
||||
impl AbstractTree for IndexAssignment {
|
||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||
Error::expect_syntax_node(source, "index_assignment", node)?;
|
||||
|
||||
let index_node = node.child(0).unwrap();
|
||||
let index = Index::from_syntax_node(source, index_node)?;
|
||||
|
||||
@ -48,14 +50,43 @@ impl AbstractTree for IndexAssignment {
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||
let mut left = self.index.run(source, context)?;
|
||||
let right = self.statement.run(source, context)?;
|
||||
let index_collection = self.index.collection.run(source, context)?;
|
||||
let index_context = index_collection.as_map().unwrap_or(&context);
|
||||
let index_key = if let crate::Expression::Identifier(identifier) = &self.index.index {
|
||||
identifier.inner()
|
||||
} else {
|
||||
return Err(Error::VariableIdentifierNotFound(
|
||||
self.index.index.run(source, context)?.to_string(),
|
||||
));
|
||||
};
|
||||
|
||||
match self.operator {
|
||||
AssignmentOperator::PlusEqual => left += right,
|
||||
AssignmentOperator::MinusEqual => left -= right,
|
||||
AssignmentOperator::Equal => left = right,
|
||||
let value = self.statement.run(source, &mut context.clone())?;
|
||||
|
||||
let new_value = match self.operator {
|
||||
AssignmentOperator::PlusEqual => {
|
||||
if let Some(mut previous_value) = index_context.variables()?.get(index_key).cloned()
|
||||
{
|
||||
previous_value += value;
|
||||
previous_value
|
||||
} else {
|
||||
Value::Empty
|
||||
}
|
||||
}
|
||||
AssignmentOperator::MinusEqual => {
|
||||
if let Some(mut previous_value) = index_context.variables()?.get(index_key).cloned()
|
||||
{
|
||||
previous_value -= value;
|
||||
previous_value
|
||||
} else {
|
||||
Value::Empty
|
||||
}
|
||||
}
|
||||
AssignmentOperator::Equal => value,
|
||||
};
|
||||
|
||||
context
|
||||
.variables_mut()?
|
||||
.insert(index_key.clone(), new_value);
|
||||
|
||||
Ok(Value::Empty)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ pub mod function_call;
|
||||
pub mod identifier;
|
||||
pub mod if_else;
|
||||
pub mod index;
|
||||
pub mod index_assignment;
|
||||
pub mod insert;
|
||||
pub mod logic;
|
||||
pub mod r#match;
|
||||
@ -30,8 +31,9 @@ pub mod r#while;
|
||||
|
||||
pub use {
|
||||
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
|
||||
function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*, r#for::*,
|
||||
r#match::*, r#while::*, remove::*, select::*, statement::*, transform::*, value_node::*,
|
||||
function_call::*, identifier::*, if_else::*, index::*, index_assignment::*, insert::*,
|
||||
logic::*, math::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*,
|
||||
transform::*, value_node::*,
|
||||
};
|
||||
|
||||
use tree_sitter::Node;
|
||||
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
|
||||
use crate::{
|
||||
AbstractTree, Assignment, Block, Error, Expression, Filter, Find, For, IfElse, Insert, Map,
|
||||
Match, Remove, Result, Select, Transform, Value, While,
|
||||
AbstractTree, Assignment, Block, Error, Expression, Filter, Find, For, IfElse, IndexAssignment,
|
||||
Insert, Map, Match, Remove, Result, Select, Transform, Value, While,
|
||||
};
|
||||
|
||||
/// Abstract representation of a statement.
|
||||
@ -25,12 +25,11 @@ pub enum Statement {
|
||||
Remove(Box<Remove>),
|
||||
Select(Box<Select>),
|
||||
Insert(Box<Insert>),
|
||||
IndexAssignment(Box<IndexAssignment>),
|
||||
}
|
||||
|
||||
impl AbstractTree for Statement {
|
||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||
debug_assert_eq!("statement", node.kind());
|
||||
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
match child.kind() {
|
||||
@ -73,12 +72,14 @@ impl AbstractTree for Statement {
|
||||
"insert" => Ok(Statement::Insert(Box::new(Insert::from_syntax_node(
|
||||
source, child,
|
||||
)?))),
|
||||
_ => Err(Error::UnexpectedSyntaxNode {
|
||||
expected: "assignment, expression, if...else, while, for, transform, filter, tool, async, find, remove, select or insert",
|
||||
actual: child.kind(),
|
||||
location: child.start_position(),
|
||||
relevant_source: source[child.byte_range()].to_string(),
|
||||
}),
|
||||
"index_assignment" => Ok(Statement::IndexAssignment(Box::new(IndexAssignment::from_syntax_node(
|
||||
source, child,
|
||||
)?))),
|
||||
_ => Err(Error::expect_syntax_node(
|
||||
source,
|
||||
"assignment, expression, if...else, while, for, transform, filter, tool, async, find, remove, select, insert or index_assignment",
|
||||
child
|
||||
).unwrap_err())
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,6 +98,7 @@ impl AbstractTree for Statement {
|
||||
Statement::Remove(remove) => remove.run(source, context),
|
||||
Statement::Select(select) => select.run(source, context),
|
||||
Statement::Insert(insert) => insert.run(source, context),
|
||||
Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ x:y = 1
|
||||
|
||||
(root
|
||||
(statement
|
||||
(assignment
|
||||
(index_assignment
|
||||
(index
|
||||
(expression
|
||||
(identifier))
|
||||
@ -47,7 +47,7 @@ x:9 = 'foobar'
|
||||
|
||||
(root
|
||||
(statement
|
||||
(assignment
|
||||
(index_assignment
|
||||
(index
|
||||
(expression
|
||||
(identifier))
|
||||
|
@ -21,7 +21,7 @@ module.exports = grammar({
|
||||
'}',
|
||||
),
|
||||
|
||||
statement: $ => prec.right(seq(
|
||||
statement: $ => prec.left(seq(
|
||||
choice(
|
||||
$.assignment,
|
||||
$.block,
|
||||
@ -30,6 +30,7 @@ module.exports = grammar({
|
||||
$.find,
|
||||
$.for,
|
||||
$.if_else,
|
||||
$.index_assignment,
|
||||
$.insert,
|
||||
$.match,
|
||||
$.reduce,
|
||||
@ -153,10 +154,13 @@ module.exports = grammar({
|
||||
),
|
||||
|
||||
assignment: $ => seq(
|
||||
choice(
|
||||
$.identifier,
|
||||
$.index,
|
||||
$.assignment_operator,
|
||||
$.statement,
|
||||
),
|
||||
|
||||
index_assignment: $ => seq(
|
||||
$.index,
|
||||
$.assignment_operator,
|
||||
$.statement,
|
||||
),
|
||||
|
@ -50,7 +50,7 @@
|
||||
]
|
||||
},
|
||||
"statement": {
|
||||
"type": "PREC_RIGHT",
|
||||
"type": "PREC_LEFT",
|
||||
"value": 0,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
@ -86,6 +86,10 @@
|
||||
"type": "SYMBOL",
|
||||
"name": "if_else"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "index_assignment"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "insert"
|
||||
@ -706,9 +710,6 @@
|
||||
},
|
||||
"assignment": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
@ -716,10 +717,21 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "index"
|
||||
"name": "assignment_operator"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"index_assignment": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "index"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "assignment_operator"
|
||||
|
@ -15,10 +15,6 @@
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "index",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "statement",
|
||||
"named": true
|
||||
@ -348,6 +344,29 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "index_assignment",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "assignment_operator",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "index",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "statement",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "insert",
|
||||
"named": true,
|
||||
@ -588,6 +607,10 @@
|
||||
"type": "if_else",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "index_assignment",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "insert",
|
||||
"named": true
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user