2023-11-18 01:10:07 +00:00
|
|
|
use std::collections::BTreeMap;
|
2023-10-10 18:12:07 +00:00
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use tree_sitter::Node;
|
|
|
|
|
2023-10-10 21:12:38 +00:00
|
|
|
use crate::{
|
2023-12-05 21:42:11 +00:00
|
|
|
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
|
2023-12-12 23:21:16 +00:00
|
|
|
Type, TypeDefinition, Value,
|
2023-10-10 21:12:38 +00:00
|
|
|
};
|
2023-10-10 18:12:07 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
2023-11-27 22:53:12 +00:00
|
|
|
pub enum ValueNode {
|
|
|
|
Boolean(String),
|
|
|
|
Float(String),
|
2023-12-02 03:54:25 +00:00
|
|
|
Function(Function),
|
2023-11-27 22:53:12 +00:00
|
|
|
Integer(String),
|
|
|
|
String(String),
|
|
|
|
List(Vec<Expression>),
|
2023-12-22 20:02:22 +00:00
|
|
|
Option(Option<Box<Expression>>),
|
2023-12-20 23:29:18 +00:00
|
|
|
Map(BTreeMap<String, (Statement, Option<Type>)>),
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AbstractTree for ValueNode {
|
2023-11-30 03:54:46 +00:00
|
|
|
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
2023-11-30 14:30:25 +00:00
|
|
|
Error::expect_syntax_node(source, "value", node)?;
|
2023-10-10 18:12:07 +00:00
|
|
|
|
|
|
|
let child = node.child(0).unwrap();
|
2023-11-27 22:53:12 +00:00
|
|
|
let value_node = match child.kind() {
|
|
|
|
"boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()),
|
|
|
|
"float" => ValueNode::Float(source[child.byte_range()].to_string()),
|
2023-12-05 21:42:11 +00:00
|
|
|
"function" => {
|
|
|
|
let child_count = child.child_count();
|
|
|
|
let mut parameters = Vec::new();
|
2023-12-12 23:21:16 +00:00
|
|
|
let mut parameter_types = Vec::new();
|
2023-12-05 21:42:11 +00:00
|
|
|
|
2023-12-17 01:42:19 +00:00
|
|
|
for index in 2..child_count - 2 {
|
2023-12-05 21:42:11 +00:00
|
|
|
let child = child.child(index).unwrap();
|
|
|
|
|
2023-12-12 23:21:16 +00:00
|
|
|
if child.kind() == "identifier" {
|
2023-12-05 21:42:11 +00:00
|
|
|
let identifier = Identifier::from_syntax_node(source, child, context)?;
|
|
|
|
|
|
|
|
parameters.push(identifier);
|
|
|
|
}
|
2023-12-12 23:21:16 +00:00
|
|
|
|
|
|
|
if child.kind() == "type_definition" {
|
|
|
|
let type_definition =
|
|
|
|
TypeDefinition::from_syntax_node(source, child, context)?;
|
|
|
|
|
|
|
|
parameter_types.push(type_definition.take_inner());
|
|
|
|
}
|
2023-12-05 21:42:11 +00:00
|
|
|
}
|
|
|
|
|
2023-12-22 21:12:41 +00:00
|
|
|
let function_context = Map::clone_from(context)?;
|
2023-12-18 00:06:36 +00:00
|
|
|
|
|
|
|
for (parameter_name, parameter_type) in
|
|
|
|
parameters.iter().zip(parameter_types.iter())
|
|
|
|
{
|
2023-12-22 21:12:41 +00:00
|
|
|
function_context.set(
|
2023-12-18 00:06:36 +00:00
|
|
|
parameter_name.inner().clone(),
|
2023-12-22 20:02:22 +00:00
|
|
|
Value::Option(None),
|
2023-12-18 00:06:36 +00:00
|
|
|
Some(parameter_type.clone()),
|
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
2023-12-12 23:21:16 +00:00
|
|
|
let return_type_node = child.child(child_count - 2).unwrap();
|
|
|
|
let return_type =
|
|
|
|
TypeDefinition::from_syntax_node(source, return_type_node, context)?;
|
|
|
|
|
2023-12-05 21:42:11 +00:00
|
|
|
let body_node = child.child(child_count - 1).unwrap();
|
2023-12-22 21:12:41 +00:00
|
|
|
let body = Block::from_syntax_node(source, body_node, &function_context)?;
|
2023-12-05 21:42:11 +00:00
|
|
|
|
2023-12-12 23:21:16 +00:00
|
|
|
let r#type = Type::Function {
|
|
|
|
parameter_types,
|
|
|
|
return_type: Box::new(return_type.take_inner()),
|
|
|
|
};
|
|
|
|
|
2023-12-22 20:02:22 +00:00
|
|
|
ValueNode::Function(Function::new(parameters, body, Some(r#type)))
|
2023-12-05 21:42:11 +00:00
|
|
|
}
|
2023-11-27 22:53:12 +00:00
|
|
|
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
|
|
|
"string" => {
|
|
|
|
let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
|
|
|
|
|
|
|
|
ValueNode::String(source[without_quotes].to_string())
|
|
|
|
}
|
2023-10-10 18:12:07 +00:00
|
|
|
"list" => {
|
2023-10-28 14:28:43 +00:00
|
|
|
let mut expressions = Vec::new();
|
2023-10-10 18:12:07 +00:00
|
|
|
|
|
|
|
for index in 1..child.child_count() - 1 {
|
2023-10-28 14:28:43 +00:00
|
|
|
let current_node = child.child(index).unwrap();
|
2023-10-10 18:12:07 +00:00
|
|
|
|
2023-10-28 14:28:43 +00:00
|
|
|
if current_node.is_named() {
|
2023-11-30 03:54:46 +00:00
|
|
|
let expression =
|
|
|
|
Expression::from_syntax_node(source, current_node, context)?;
|
2023-10-28 14:28:43 +00:00
|
|
|
expressions.push(expression);
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-27 22:53:12 +00:00
|
|
|
ValueNode::List(expressions)
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
"map" => {
|
|
|
|
let mut child_nodes = BTreeMap::new();
|
|
|
|
let mut current_key = "".to_string();
|
2023-12-20 23:29:18 +00:00
|
|
|
let mut current_type = None;
|
2023-10-10 18:12:07 +00:00
|
|
|
|
|
|
|
for index in 0..child.child_count() - 1 {
|
|
|
|
let child_syntax_node = child.child(index).unwrap();
|
|
|
|
|
|
|
|
if child_syntax_node.kind() == "identifier" {
|
|
|
|
current_key =
|
2023-11-30 03:54:46 +00:00
|
|
|
Identifier::from_syntax_node(source, child_syntax_node, context)?
|
|
|
|
.take_inner();
|
2023-12-20 23:29:18 +00:00
|
|
|
current_type = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
if child_syntax_node.kind() == "type_definition" {
|
|
|
|
current_type = Some(
|
|
|
|
TypeDefinition::from_syntax_node(source, child_syntax_node, context)?
|
|
|
|
.take_inner(),
|
|
|
|
);
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-31 19:21:13 +00:00
|
|
|
if child_syntax_node.kind() == "statement" {
|
2023-11-30 03:54:46 +00:00
|
|
|
let statement =
|
|
|
|
Statement::from_syntax_node(source, child_syntax_node, context)?;
|
2023-10-10 18:12:07 +00:00
|
|
|
|
2023-12-20 23:36:42 +00:00
|
|
|
if let Some(type_definition) = ¤t_type {
|
|
|
|
type_definition.check(&statement.expected_type(context)?)?;
|
|
|
|
}
|
|
|
|
|
2023-12-20 23:29:18 +00:00
|
|
|
child_nodes.insert(current_key.clone(), (statement, current_type.clone()));
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-27 22:53:12 +00:00
|
|
|
ValueNode::Map(child_nodes)
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
2023-12-22 20:02:22 +00:00
|
|
|
"option" => {
|
|
|
|
let first_grandchild = child.child(0).unwrap();
|
|
|
|
|
|
|
|
if first_grandchild.kind() == "none" {
|
|
|
|
ValueNode::Option(None)
|
|
|
|
} else {
|
|
|
|
let expression_node = child.child(2).unwrap();
|
|
|
|
let expression =
|
|
|
|
Expression::from_syntax_node(source, expression_node, context)?;
|
|
|
|
|
|
|
|
ValueNode::Option(Some(Box::new(expression)))
|
|
|
|
}
|
|
|
|
}
|
2023-10-10 18:12:07 +00:00
|
|
|
_ => {
|
|
|
|
return Err(Error::UnexpectedSyntaxNode {
|
2023-12-22 20:02:22 +00:00
|
|
|
expected: "string, integer, float, boolean, list, map, or option",
|
2023-10-10 18:12:07 +00:00
|
|
|
actual: child.kind(),
|
|
|
|
location: child.start_position(),
|
|
|
|
relevant_source: source[child.byte_range()].to_string(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-11-27 22:53:12 +00:00
|
|
|
Ok(value_node)
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 00:23:42 +00:00
|
|
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
2023-11-27 22:53:12 +00:00
|
|
|
let value = match self {
|
|
|
|
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
|
|
|
|
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
|
2023-12-02 03:54:25 +00:00
|
|
|
ValueNode::Function(function) => Value::Function(function.clone()),
|
2023-11-27 22:53:12 +00:00
|
|
|
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());
|
|
|
|
|
|
|
|
for node in expressions {
|
2023-10-10 18:12:07 +00:00
|
|
|
let value = node.run(source, context)?;
|
|
|
|
|
|
|
|
values.push(value);
|
|
|
|
}
|
|
|
|
|
2023-10-26 22:03:59 +00:00
|
|
|
Value::List(List::with_items(values))
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
2023-12-22 20:02:22 +00:00
|
|
|
ValueNode::Option(option) => {
|
|
|
|
let option_value = if let Some(expression) = option {
|
|
|
|
Some(Box::new(expression.run(source, context)?))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
Value::Option(option_value)
|
|
|
|
}
|
2023-11-27 22:53:12 +00:00
|
|
|
ValueNode::Map(key_statement_pairs) => {
|
2023-10-29 23:31:06 +00:00
|
|
|
let map = Map::new();
|
2023-10-10 18:12:07 +00:00
|
|
|
|
2023-11-05 18:54:29 +00:00
|
|
|
{
|
2023-12-20 23:29:18 +00:00
|
|
|
for (key, (statement, r#type)) in key_statement_pairs {
|
2023-11-27 22:53:12 +00:00
|
|
|
let value = statement.run(source, context)?;
|
2023-10-10 18:12:07 +00:00
|
|
|
|
2023-12-20 23:29:18 +00:00
|
|
|
map.set(key.clone(), value, r#type.clone())?;
|
2023-11-05 18:54:29 +00:00
|
|
|
}
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 23:31:06 +00:00
|
|
|
Value::Map(map)
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(value)
|
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
|
2023-12-05 22:08:22 +00:00
|
|
|
fn expected_type(&self, context: &Map) -> Result<Type> {
|
2023-11-30 05:57:15 +00:00
|
|
|
let type_definition = match self {
|
2023-12-05 22:08:22 +00:00
|
|
|
ValueNode::Boolean(_) => Type::Boolean,
|
|
|
|
ValueNode::Float(_) => Type::Float,
|
|
|
|
ValueNode::Function(function) => function.r#type().clone(),
|
|
|
|
ValueNode::Integer(_) => Type::Integer,
|
|
|
|
ValueNode::String(_) => Type::String,
|
2023-11-30 00:23:42 +00:00
|
|
|
ValueNode::List(expressions) => {
|
2023-11-30 05:57:15 +00:00
|
|
|
let mut previous_type = None;
|
|
|
|
|
|
|
|
for expression in expressions {
|
|
|
|
let expression_type = expression.expected_type(context)?;
|
|
|
|
|
|
|
|
if let Some(previous) = previous_type {
|
|
|
|
if expression_type != previous {
|
2023-12-05 22:08:22 +00:00
|
|
|
return Ok(Type::List(Box::new(Type::Any)));
|
2023-11-30 05:57:15 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
|
2023-11-30 05:57:15 +00:00
|
|
|
previous_type = Some(expression_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(previous) = previous_type {
|
2023-12-05 22:08:22 +00:00
|
|
|
Type::List(Box::new(previous))
|
2023-11-30 05:57:15 +00:00
|
|
|
} else {
|
2023-12-05 22:08:22 +00:00
|
|
|
Type::List(Box::new(Type::Any))
|
2023-11-30 05:57:15 +00:00
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
}
|
2023-12-22 20:02:22 +00:00
|
|
|
ValueNode::Option(option) => {
|
|
|
|
if let Some(expression) = option {
|
2023-12-26 22:19:12 +00:00
|
|
|
Type::Option(Box::new(expression.expected_type(context)?))
|
2023-12-22 20:02:22 +00:00
|
|
|
} else {
|
2023-12-26 22:19:12 +00:00
|
|
|
Type::None
|
2023-12-22 20:02:22 +00:00
|
|
|
}
|
|
|
|
}
|
2023-12-05 22:08:22 +00:00
|
|
|
ValueNode::Map(_) => Type::Map,
|
2023-11-30 00:23:42 +00:00
|
|
|
};
|
|
|
|
|
2023-11-30 05:57:15 +00:00
|
|
|
Ok(type_definition)
|
2023-11-30 00:23:42 +00:00
|
|
|
}
|
2023-10-10 18:12:07 +00:00
|
|
|
}
|
2023-11-30 14:48:56 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::{evaluate, List};
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_empty() {
|
2023-12-22 20:02:22 +00:00
|
|
|
assert_eq!(evaluate("x = 9"), Ok(Value::Option(None)));
|
|
|
|
assert_eq!(evaluate("x = 1 + 1"), Ok(Value::Option(None)));
|
2023-11-30 14:48:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_integer() {
|
|
|
|
assert_eq!(evaluate("1"), Ok(Value::Integer(1)));
|
|
|
|
assert_eq!(evaluate("123"), Ok(Value::Integer(123)));
|
|
|
|
assert_eq!(evaluate("-666"), Ok(Value::Integer(-666)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_float() {
|
|
|
|
assert_eq!(evaluate("0.1"), Ok(Value::Float(0.1)));
|
|
|
|
assert_eq!(evaluate("12.3"), Ok(Value::Float(12.3)));
|
|
|
|
assert_eq!(evaluate("-6.66"), Ok(Value::Float(-6.66)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_string() {
|
|
|
|
assert_eq!(evaluate("\"one\""), Ok(Value::String("one".to_string())));
|
|
|
|
assert_eq!(evaluate("'one'"), Ok(Value::String("one".to_string())));
|
|
|
|
assert_eq!(evaluate("`one`"), Ok(Value::String("one".to_string())));
|
|
|
|
assert_eq!(evaluate("`'one'`"), Ok(Value::String("'one'".to_string())));
|
|
|
|
assert_eq!(evaluate("'`one`'"), Ok(Value::String("`one`".to_string())));
|
|
|
|
assert_eq!(
|
|
|
|
evaluate("\"'one'\""),
|
|
|
|
Ok(Value::String("'one'".to_string()))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_list() {
|
|
|
|
assert_eq!(
|
|
|
|
evaluate("[1, 2, 'foobar']"),
|
|
|
|
Ok(Value::List(List::with_items(vec![
|
|
|
|
Value::Integer(1),
|
|
|
|
Value::Integer(2),
|
|
|
|
Value::String("foobar".to_string()),
|
|
|
|
])))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_map() {
|
|
|
|
let map = Map::new();
|
|
|
|
|
2023-12-13 20:47:41 +00:00
|
|
|
map.set("x".to_string(), Value::Integer(1), None).unwrap();
|
|
|
|
map.set("foo".to_string(), Value::String("bar".to_string()), None)
|
|
|
|
.unwrap();
|
2023-11-30 14:48:56 +00:00
|
|
|
|
|
|
|
assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
|
|
|
}
|
2023-12-17 01:17:38 +00:00
|
|
|
|
2023-12-20 23:29:18 +00:00
|
|
|
#[test]
|
|
|
|
fn evaluate_map_types() {
|
|
|
|
let map = Map::new();
|
|
|
|
|
|
|
|
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
|
|
|
|
.unwrap();
|
|
|
|
map.set(
|
|
|
|
"foo".to_string(),
|
|
|
|
Value::String("bar".to_string()),
|
|
|
|
Some(Type::String),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
evaluate("{ x <int> = 1, foo <str> = 'bar' }"),
|
|
|
|
Ok(Value::Map(map))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-12-20 23:36:42 +00:00
|
|
|
#[test]
|
|
|
|
fn evaluate_map_type_errors() {
|
|
|
|
assert!(evaluate("{ foo <bool> = 'bar' }")
|
|
|
|
.unwrap_err()
|
|
|
|
.is_type_check_error(&Error::TypeCheck {
|
|
|
|
expected: Type::Boolean,
|
|
|
|
actual: Type::String
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2023-12-17 01:17:38 +00:00
|
|
|
#[test]
|
|
|
|
fn evaluate_function() {
|
2023-12-17 01:42:19 +00:00
|
|
|
let result = evaluate("(fn) <int> { 1 }");
|
2023-12-17 01:17:38 +00:00
|
|
|
let value = result.unwrap();
|
|
|
|
let function = value.as_function().unwrap();
|
|
|
|
|
|
|
|
assert_eq!(&Vec::<Identifier>::with_capacity(0), function.parameters());
|
2023-12-17 01:42:19 +00:00
|
|
|
assert_eq!(Ok(&Type::Integer), function.return_type());
|
2023-12-17 01:17:38 +00:00
|
|
|
|
|
|
|
let result = evaluate("(fn x <bool>) <bool> {true}");
|
|
|
|
let value = result.unwrap();
|
|
|
|
let function = value.as_function().unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
&vec![Identifier::new("x".to_string())],
|
|
|
|
function.parameters()
|
|
|
|
);
|
|
|
|
assert_eq!(Ok(&Type::Boolean), function.return_type());
|
|
|
|
}
|
2023-12-22 20:02:22 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn evaluate_option() {
|
|
|
|
let result = evaluate("x <option(int)> = some(1); x").unwrap();
|
|
|
|
|
|
|
|
assert_eq!(Value::Option(Some(Box::new(Value::Integer(1)))), result);
|
|
|
|
}
|
2023-11-30 14:48:56 +00:00
|
|
|
}
|