Implement type checking
This commit is contained in:
parent
25852efcd6
commit
2bd4ccb40d
@ -1,6 +1,6 @@
|
|||||||
(output "This will print first.")
|
(output "This will print first.")
|
||||||
|
|
||||||
create_random_numbers = |count| => {
|
create_random_numbers = |count <int>| {
|
||||||
numbers = [];
|
numbers = [];
|
||||||
|
|
||||||
while (length numbers) < count {
|
while (length numbers) < count {
|
||||||
|
@ -4,7 +4,7 @@ add_one = |numbers <list>| <list> {
|
|||||||
new_numbers = []
|
new_numbers = []
|
||||||
|
|
||||||
for number in numbers {
|
for number in numbers {
|
||||||
new_list += number + 1
|
new_numbers += number + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
new_numbers
|
new_numbers
|
||||||
@ -13,4 +13,3 @@ add_one = |numbers <list>| <list> {
|
|||||||
foo = [1, 2, 3] -> (add_one)
|
foo = [1, 2, 3] -> (add_one)
|
||||||
|
|
||||||
(assert_equal [2 3 4] foo)
|
(assert_equal [2 3 4] foo)
|
||||||
|
|
||||||
|
@ -63,24 +63,24 @@ impl AbstractTree for Assignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||||
let key = self.identifier.inner().clone();
|
let key = self.identifier.inner();
|
||||||
let value = self.statement.run(source, context)?;
|
let value = self.statement.run(source, context)?;
|
||||||
|
|
||||||
let new_value = match self.operator {
|
let new_value = match self.operator {
|
||||||
AssignmentOperator::PlusEqual => {
|
AssignmentOperator::PlusEqual => {
|
||||||
if let Some(mut previous_value) = context.variables()?.get(&key).cloned() {
|
if let Some(mut previous_value) = context.variables()?.get(key).cloned() {
|
||||||
previous_value += value;
|
previous_value += value;
|
||||||
previous_value
|
previous_value
|
||||||
} else {
|
} else {
|
||||||
Value::Empty
|
return Err(Error::VariableIdentifierNotFound(key.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssignmentOperator::MinusEqual => {
|
AssignmentOperator::MinusEqual => {
|
||||||
if let Some(mut previous_value) = context.variables()?.get(&key).cloned() {
|
if let Some(mut previous_value) = context.variables()?.get(key).cloned() {
|
||||||
previous_value -= value;
|
previous_value -= value;
|
||||||
previous_value
|
previous_value
|
||||||
} else {
|
} else {
|
||||||
Value::Empty
|
return Err(Error::VariableIdentifierNotFound(key.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssignmentOperator::Equal => value,
|
AssignmentOperator::Equal => value,
|
||||||
@ -90,7 +90,7 @@ impl AbstractTree for Assignment {
|
|||||||
r#type.check(&new_value)?;
|
r#type.check(&new_value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.variables_mut()?.insert(key, new_value);
|
context.variables_mut()?.insert(key.clone(), new_value);
|
||||||
|
|
||||||
Ok(Value::Empty)
|
Ok(Value::Empty)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use rayon::prelude::*;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Map, Result, Statement, Value};
|
use crate::{AbstractTree, Error, Map, Result, Statement, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
@ -14,7 +14,7 @@ pub struct Block {
|
|||||||
|
|
||||||
impl AbstractTree for Block {
|
impl AbstractTree for Block {
|
||||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
debug_assert_eq!("block", node.kind());
|
Error::expect_syntax_node(source, "block", node)?;
|
||||||
|
|
||||||
let first_child = node.child(0).unwrap();
|
let first_child = node.child(0).unwrap();
|
||||||
let is_async = first_child.kind() == "async";
|
let is_async = first_child.kind() == "async";
|
||||||
|
@ -11,7 +11,7 @@ use reqwest::blocking::get;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Expression, List, Map, Result, Table, Value, ValueType};
|
use crate::{AbstractTree, Error, Expression, List, Map, Result, Table, Type, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum BuiltInFunction {
|
pub enum BuiltInFunction {
|
||||||
@ -367,9 +367,9 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::Type(expression) => {
|
BuiltInFunction::Type(expression) => {
|
||||||
let run_expression = expression.run(source, context);
|
let run_expression = expression.run(source, context);
|
||||||
let value_type = if let Ok(value) = run_expression {
|
let value_type = if let Ok(value) = run_expression {
|
||||||
value.value_type()
|
value.r#type()
|
||||||
} else if let Err(Error::VariableIdentifierNotFound(_)) = run_expression {
|
} else if let Err(Error::VariableIdentifierNotFound(_)) = run_expression {
|
||||||
ValueType::Empty
|
Type::Any
|
||||||
} else {
|
} else {
|
||||||
return run_expression;
|
return run_expression;
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,8 @@ pub struct For {
|
|||||||
|
|
||||||
impl AbstractTree for For {
|
impl AbstractTree for For {
|
||||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "for", node)?;
|
||||||
|
|
||||||
let for_node = node.child(0).unwrap();
|
let for_node = node.child(0).unwrap();
|
||||||
let is_async = match for_node.kind() {
|
let is_async = match for_node.kind() {
|
||||||
"for" => false,
|
"for" => false,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
@ -89,3 +91,19 @@ impl AbstractTree for Type {
|
|||||||
Ok(Value::Empty)
|
Ok(Value::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Type {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Type::Any => write!(f, "any"),
|
||||||
|
Type::Boolean => write!(f, "bool"),
|
||||||
|
Type::Float => write!(f, "float"),
|
||||||
|
Type::Function => write!(f, "function"),
|
||||||
|
Type::Integer => write!(f, "integer"),
|
||||||
|
Type::List => write!(f, "list"),
|
||||||
|
Type::Map => write!(f, "map"),
|
||||||
|
Type::String => write!(f, "string"),
|
||||||
|
Type::Table => write!(f, "table"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,19 +5,23 @@ use tree_sitter::Node;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table,
|
AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table,
|
||||||
Value, ValueType,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct ValueNode {
|
pub enum ValueNode {
|
||||||
value_type: ValueType,
|
Boolean(String),
|
||||||
source: String,
|
Float(String),
|
||||||
}
|
Integer(String),
|
||||||
|
String(String),
|
||||||
impl ValueNode {
|
List(Vec<Expression>),
|
||||||
pub fn new(value_type: ValueType, source: String) -> Self {
|
Empty,
|
||||||
Self { value_type, source }
|
Map(BTreeMap<String, Statement>),
|
||||||
}
|
Table {
|
||||||
|
column_names: Vec<Identifier>,
|
||||||
|
rows: Box<Expression>,
|
||||||
|
},
|
||||||
|
Function(Function),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for ValueNode {
|
impl AbstractTree for ValueNode {
|
||||||
@ -25,12 +29,15 @@ impl AbstractTree for ValueNode {
|
|||||||
debug_assert_eq!("value", node.kind());
|
debug_assert_eq!("value", node.kind());
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
let value_type = match child.kind() {
|
let value_node = match child.kind() {
|
||||||
"integer" => ValueType::Integer,
|
"boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()),
|
||||||
"float" => ValueType::Float,
|
"float" => ValueNode::Float(source[child.byte_range()].to_string()),
|
||||||
"string" => ValueType::String,
|
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
||||||
"boolean" => ValueType::Boolean,
|
"string" => {
|
||||||
"empty" => ValueType::Empty,
|
let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
|
||||||
|
|
||||||
|
ValueNode::String(source[without_quotes].to_string())
|
||||||
|
}
|
||||||
"list" => {
|
"list" => {
|
||||||
let mut expressions = Vec::new();
|
let mut expressions = Vec::new();
|
||||||
|
|
||||||
@ -43,7 +50,7 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType::List(expressions)
|
ValueNode::List(expressions)
|
||||||
}
|
}
|
||||||
"table" => {
|
"table" => {
|
||||||
let identifier_list_node = child.child(1).unwrap();
|
let identifier_list_node = child.child(1).unwrap();
|
||||||
@ -63,7 +70,7 @@ impl AbstractTree for ValueNode {
|
|||||||
let expression_node = child.child(2).unwrap();
|
let expression_node = child.child(2).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
ValueType::Table {
|
ValueNode::Table {
|
||||||
column_names,
|
column_names,
|
||||||
rows: Box::new(expression),
|
rows: Box::new(expression),
|
||||||
}
|
}
|
||||||
@ -88,9 +95,9 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType::Map(child_nodes)
|
ValueNode::Map(child_nodes)
|
||||||
}
|
}
|
||||||
"function" => ValueType::Function(Function::from_syntax_node(source, child)?),
|
"function" => ValueNode::Function(Function::from_syntax_node(source, child)?),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected:
|
expected:
|
||||||
@ -102,27 +109,19 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ValueNode {
|
Ok(value_node)
|
||||||
value_type,
|
|
||||||
source: source[child.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||||
let value = match &self.value_type {
|
let value = match self {
|
||||||
ValueType::Any => todo!(),
|
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
|
||||||
ValueType::String => {
|
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
|
||||||
let without_quotes = &self.source[1..self.source.len() - 1];
|
ValueNode::Integer(value_source) => Value::Integer(value_source.parse().unwrap()),
|
||||||
|
ValueNode::String(value_source) => Value::String(value_source.parse().unwrap()),
|
||||||
|
ValueNode::List(expressions) => {
|
||||||
|
let mut values = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
Value::String(without_quotes.to_string())
|
for node in expressions {
|
||||||
}
|
|
||||||
ValueType::Float => Value::Float(self.source.parse().unwrap()),
|
|
||||||
ValueType::Integer => Value::Integer(self.source.parse().unwrap()),
|
|
||||||
ValueType::Boolean => Value::Boolean(self.source.parse().unwrap()),
|
|
||||||
ValueType::List(nodes) => {
|
|
||||||
let mut values = Vec::with_capacity(nodes.len());
|
|
||||||
|
|
||||||
for node in nodes {
|
|
||||||
let value = node.run(source, context)?;
|
let value = node.run(source, context)?;
|
||||||
|
|
||||||
values.push(value);
|
values.push(value);
|
||||||
@ -130,15 +129,15 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
Value::List(List::with_items(values))
|
Value::List(List::with_items(values))
|
||||||
}
|
}
|
||||||
ValueType::Empty => Value::Empty,
|
ValueNode::Empty => Value::Empty,
|
||||||
ValueType::Map(nodes) => {
|
ValueNode::Map(key_statement_pairs) => {
|
||||||
let map = Map::new();
|
let map = Map::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut variables = map.variables_mut()?;
|
let mut variables = map.variables_mut()?;
|
||||||
|
|
||||||
for (key, node) in nodes {
|
for (key, statement) in key_statement_pairs {
|
||||||
let value = node.run(source, context)?;
|
let value = statement.run(source, context)?;
|
||||||
|
|
||||||
variables.insert(key.clone(), value);
|
variables.insert(key.clone(), value);
|
||||||
}
|
}
|
||||||
@ -146,7 +145,7 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
Value::Map(map)
|
Value::Map(map)
|
||||||
}
|
}
|
||||||
ValueType::Table {
|
ValueNode::Table {
|
||||||
column_names,
|
column_names,
|
||||||
rows: row_expression,
|
rows: row_expression,
|
||||||
} => {
|
} => {
|
||||||
@ -172,7 +171,7 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
Value::Table(table)
|
Value::Table(table)
|
||||||
}
|
}
|
||||||
ValueType::Function(function) => Value::Function(function.clone()),
|
ValueNode::Function(function) => Value::Function(function.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
18
src/error.rs
18
src/error.rs
@ -3,7 +3,7 @@
|
|||||||
//! To deal with errors from dependencies, either create a new error variant
|
//! To deal with errors from dependencies, either create a new error variant
|
||||||
//! or use the ToolFailure variant if the error can only occur inside a tool.
|
//! or use the ToolFailure variant if the error can only occur inside a tool.
|
||||||
|
|
||||||
use tree_sitter::Node;
|
use tree_sitter::{Node, Point};
|
||||||
|
|
||||||
use crate::{value::Value, Identifier};
|
use crate::{value::Value, Identifier};
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ pub enum Error {
|
|||||||
UnexpectedSyntaxNode {
|
UnexpectedSyntaxNode {
|
||||||
expected: &'static str,
|
expected: &'static str,
|
||||||
actual: &'static str,
|
actual: &'static str,
|
||||||
location: tree_sitter::Point,
|
location: Point,
|
||||||
relevant_source: String,
|
relevant_source: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -127,12 +127,23 @@ pub enum Error {
|
|||||||
|
|
||||||
/// A custom error explained by its message.
|
/// A custom error explained by its message.
|
||||||
CustomMessage(String),
|
CustomMessage(String),
|
||||||
|
|
||||||
|
/// Invalid user input.
|
||||||
|
Syntax {
|
||||||
|
source: String,
|
||||||
|
location: Point,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn expect_syntax_node(source: &str, expected: &'static str, actual: Node) -> Result<()> {
|
pub fn expect_syntax_node(source: &str, expected: &'static str, actual: Node) -> Result<()> {
|
||||||
if expected == actual.kind() {
|
if expected == actual.kind() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else if actual.is_error() {
|
||||||
|
Err(Error::Syntax {
|
||||||
|
source: source[actual.byte_range()].to_string(),
|
||||||
|
location: actual.start_position(),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnexpectedSyntaxNode {
|
Err(Error::UnexpectedSyntaxNode {
|
||||||
expected,
|
expected,
|
||||||
@ -337,6 +348,9 @@ impl fmt::Display for Error {
|
|||||||
),
|
),
|
||||||
ToolFailure(message) => write!(f, "{message}"),
|
ToolFailure(message) => write!(f, "{message}"),
|
||||||
CustomMessage(message) => write!(f, "{message}"),
|
CustomMessage(message) => write!(f, "{message}"),
|
||||||
|
Syntax { source, location } => {
|
||||||
|
write!(f, "Syntax error at {location}, this is not valid: {source}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,16 +85,18 @@ impl<'c, 's> Evaluator<'c, 's> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self) -> Result<Value> {
|
pub fn run(self) -> Result<Value> {
|
||||||
let mut cursor = self.syntax_tree.walk();
|
let root_node = self.syntax_tree.root_node();
|
||||||
let root_node = cursor.node();
|
|
||||||
let mut prev_result = Ok(Value::Empty);
|
|
||||||
|
|
||||||
for statement_node in root_node.children(&mut cursor) {
|
let mut prev_result = Value::Empty;
|
||||||
|
|
||||||
|
for index in 0..root_node.child_count() {
|
||||||
|
let statement_node = root_node.child(index).unwrap();
|
||||||
let statement = Statement::from_syntax_node(self.source, statement_node)?;
|
let statement = Statement::from_syntax_node(self.source, statement_node)?;
|
||||||
prev_result = statement.run(self.source, self.context);
|
|
||||||
|
prev_result = statement.run(self.source, self.context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_result
|
Ok(prev_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn syntax_tree(&self) -> String {
|
pub fn syntax_tree(&self) -> String {
|
||||||
|
@ -8,7 +8,7 @@ pub use crate::{
|
|||||||
abstract_tree::*,
|
abstract_tree::*,
|
||||||
error::*,
|
error::*,
|
||||||
evaluator::*,
|
evaluator::*,
|
||||||
value::{function::Function, list::List, map::Map, table::Table, value_type::ValueType, Value},
|
value::{function::Function, list::List, map::Map, table::Table, Value},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod abstract_tree;
|
mod abstract_tree;
|
||||||
|
@ -56,8 +56,6 @@ impl AbstractTree for Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||||
println!("{self}");
|
|
||||||
|
|
||||||
let return_value = self.body.run(source, context)?;
|
let return_value = self.body.run(source, context)?;
|
||||||
|
|
||||||
if let Some(r#type) = &self.return_type {
|
if let Some(r#type) = &self.return_type {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Types that represent runtime values.
|
//! Types that represent runtime values.
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
Function, List, Map, Table, Type, ValueType,
|
Function, List, Map, Table, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
@ -22,7 +22,6 @@ pub mod function;
|
|||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod value_type;
|
|
||||||
|
|
||||||
/// Dust value representation.
|
/// Dust value representation.
|
||||||
///
|
///
|
||||||
@ -58,10 +57,6 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
|
||||||
ValueType::from(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_table(&self) -> bool {
|
pub fn is_table(&self) -> bool {
|
||||||
matches!(self, Value::Table(_))
|
matches!(self, Value::Table(_))
|
||||||
}
|
}
|
||||||
@ -348,6 +343,17 @@ impl SubAssign for Value {
|
|||||||
(Value::Integer(left), Value::Integer(right)) => *left -= right,
|
(Value::Integer(left), Value::Integer(right)) => *left -= right,
|
||||||
(Value::Float(left), Value::Float(right)) => *left -= right,
|
(Value::Float(left), Value::Float(right)) => *left -= right,
|
||||||
(Value::Float(left), Value::Integer(right)) => *left -= right as f64,
|
(Value::Float(left), Value::Integer(right)) => *left -= right as f64,
|
||||||
|
(Value::List(list), value) => {
|
||||||
|
let index_to_remove = list
|
||||||
|
.items()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(i, list_value)| if list_value == &value { Some(i) } else { None });
|
||||||
|
|
||||||
|
if let Some(index) = index_to_remove {
|
||||||
|
list.items_mut().remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,152 +0,0 @@
|
|||||||
use std::{
|
|
||||||
collections::BTreeMap,
|
|
||||||
fmt::{self, Debug, Display, Formatter},
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{value_node::ValueNode, Expression, Function, Identifier, Statement, Value};
|
|
||||||
|
|
||||||
/// The type of a `Value`.
|
|
||||||
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
|
|
||||||
pub enum ValueType {
|
|
||||||
Any,
|
|
||||||
String,
|
|
||||||
Float,
|
|
||||||
Integer,
|
|
||||||
Boolean,
|
|
||||||
List(Vec<Expression>),
|
|
||||||
Empty,
|
|
||||||
Map(BTreeMap<String, Statement>),
|
|
||||||
Table {
|
|
||||||
column_names: Vec<Identifier>,
|
|
||||||
rows: Box<Expression>,
|
|
||||||
},
|
|
||||||
Function(Function),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for ValueType {}
|
|
||||||
|
|
||||||
impl PartialEq for ValueType {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
match (self, other) {
|
|
||||||
(ValueType::Any, _) => true,
|
|
||||||
(_, ValueType::Any) => true,
|
|
||||||
(ValueType::String, ValueType::String) => true,
|
|
||||||
(ValueType::Float, ValueType::Float) => true,
|
|
||||||
(ValueType::Integer, ValueType::Integer) => true,
|
|
||||||
(ValueType::Boolean, ValueType::Boolean) => true,
|
|
||||||
(ValueType::List(left), ValueType::List(right)) => left == right,
|
|
||||||
(ValueType::Empty, ValueType::Empty) => true,
|
|
||||||
(ValueType::Map(left), ValueType::Map(right)) => left == right,
|
|
||||||
(
|
|
||||||
ValueType::Table {
|
|
||||||
column_names: left_columns,
|
|
||||||
rows: left_rows,
|
|
||||||
},
|
|
||||||
ValueType::Table {
|
|
||||||
column_names: right_columns,
|
|
||||||
rows: right_rows,
|
|
||||||
},
|
|
||||||
) => left_columns == right_columns && left_rows == right_rows,
|
|
||||||
(ValueType::Function(left), ValueType::Function(right)) => left == right,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for ValueType {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
match &self {
|
|
||||||
ValueType::Any => write!(f, "any"),
|
|
||||||
ValueType::String => write!(f, "string"),
|
|
||||||
ValueType::Float => write!(f, "float"),
|
|
||||||
ValueType::Integer => write!(f, "integer"),
|
|
||||||
ValueType::Boolean => write!(f, "boolean"),
|
|
||||||
ValueType::List(list) => {
|
|
||||||
write!(f, "(")?;
|
|
||||||
for (index, item) in list.iter().enumerate() {
|
|
||||||
if index > 0 {
|
|
||||||
write!(f, ", ")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "{item:?}")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, ")")
|
|
||||||
}
|
|
||||||
ValueType::Empty => write!(f, "empty"),
|
|
||||||
ValueType::Map(_map) => write!(f, "map"),
|
|
||||||
ValueType::Table {
|
|
||||||
column_names: _,
|
|
||||||
rows: _,
|
|
||||||
} => {
|
|
||||||
write!(f, "table")
|
|
||||||
}
|
|
||||||
ValueType::Function(function) => write!(f, "{function}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for ValueType {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{self}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Value> for ValueType {
|
|
||||||
fn from(value: &Value) -> Self {
|
|
||||||
match value {
|
|
||||||
Value::String(_) => ValueType::String,
|
|
||||||
Value::Float(_) => ValueType::Float,
|
|
||||||
Value::Integer(_) => ValueType::Integer,
|
|
||||||
Value::Boolean(_) => ValueType::Boolean,
|
|
||||||
Value::Empty => ValueType::Empty,
|
|
||||||
Value::List(list) => {
|
|
||||||
let value_nodes = list
|
|
||||||
.items()
|
|
||||||
.iter()
|
|
||||||
.map(|value| {
|
|
||||||
Expression::Value(ValueNode::new(
|
|
||||||
value.value_type(),
|
|
||||||
String::with_capacity(0),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
ValueType::List(value_nodes)
|
|
||||||
}
|
|
||||||
Value::Map(map) => {
|
|
||||||
let mut value_nodes = BTreeMap::new();
|
|
||||||
|
|
||||||
for (key, value) in map.variables().unwrap().iter() {
|
|
||||||
let value_type = value.value_type();
|
|
||||||
let value_node = ValueNode::new(value_type, String::with_capacity(0));
|
|
||||||
let statement = Statement::Expression(Expression::Value(value_node));
|
|
||||||
|
|
||||||
value_nodes.insert(key.to_string(), statement);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType::Map(value_nodes)
|
|
||||||
}
|
|
||||||
Value::Table(table) => ValueType::Table {
|
|
||||||
column_names: table
|
|
||||||
.headers()
|
|
||||||
.iter()
|
|
||||||
.map(|column_name| Identifier::new(column_name.clone()))
|
|
||||||
.collect(),
|
|
||||||
rows: Box::new(Expression::Value(ValueNode::new(
|
|
||||||
ValueType::List(Vec::with_capacity(0)),
|
|
||||||
String::with_capacity(0),
|
|
||||||
))),
|
|
||||||
},
|
|
||||||
Value::Function(function) => ValueType::Function(function.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&mut Value> for ValueType {
|
|
||||||
fn from(value: &mut Value) -> Self {
|
|
||||||
From::<&Value>::from(value)
|
|
||||||
}
|
|
||||||
}
|
|
@ -276,7 +276,7 @@ module.exports = grammar({
|
|||||||
|
|
||||||
function: $ => seq(
|
function: $ => seq(
|
||||||
'|',
|
'|',
|
||||||
repeat($._function_parameters),
|
field('parameters', repeat($._function_parameters)),
|
||||||
'|',
|
'|',
|
||||||
optional(field('return_type', $.type)),
|
optional(field('return_type', $.type)),
|
||||||
field('body', $.block),
|
field('body', $.block),
|
||||||
|
Loading…
Reference in New Issue
Block a user