1
0

Revise language syntax

This commit is contained in:
Jeff 2023-10-31 15:21:13 -04:00
parent 42f0834d80
commit df7cd0e972
20 changed files with 44985 additions and 45163 deletions

View File

@ -1,17 +1,18 @@
count = 1 count = 1
while count <= 15 while count <= 15 {
divides_by_3 = count % 3 == 0 divides_by_3 = count % 3 == 0
divides_by_5 = count % 5 == 0 divides_by_5 = count % 5 == 0
if divides_by_3 && divides_by_5 if divides_by_3 && divides_by_5 {
output 'fizzbuzz' output 'fizzbuzz'
else if divides_by_3 } else if divides_by_3 {
output 'fizz' output 'fizz'
else if divides_by_5 } else if divides_by_5 {
output 'buzz' output 'buzz'
else } else {
output count output count
}
count += 1 count += 1
}

View File

@ -14,7 +14,7 @@ use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, List, Map, Result, Table, Value, ValueType}; use crate::{AbstractTree, Error, Expression, List, Map, Result, Table, Value, ValueType};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Tool { pub enum BuiltInFunction {
// General // General
Assert(Vec<Expression>), Assert(Vec<Expression>),
AssertEqual(Vec<Expression>), AssertEqual(Vec<Expression>),
@ -61,14 +61,14 @@ pub enum Tool {
Reverse(Expression, Option<(Expression, Expression)>), Reverse(Expression, Option<(Expression, Expression)>),
} }
impl AbstractTree for Tool { impl AbstractTree for BuiltInFunction {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
debug_assert_eq!("tool", node.kind()); debug_assert_eq!("built_in_function", node.kind());
fn parse_expressions(source: &str, node: Node) -> Result<Vec<Expression>> { fn parse_expressions(source: &str, node: Node) -> Result<Vec<Expression>> {
let mut expressions = Vec::new(); let mut expressions = Vec::new();
for index in 2..node.child_count() - 1 { for index in 1..node.child_count() {
let child_node = node.child(index).unwrap(); let child_node = node.child(index).unwrap();
if child_node.kind() == "expression" { if child_node.kind() == "expression" {
@ -81,23 +81,23 @@ impl AbstractTree for Tool {
Ok(expressions) Ok(expressions)
} }
let tool_node = node.child(1).unwrap(); let tool_node = node.child(0).unwrap();
let tool = match tool_node.kind() { let tool = match tool_node.kind() {
"assert" => { "assert" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Assert(expressions) BuiltInFunction::Assert(expressions)
} }
"assert_equal" => { "assert_equal" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::AssertEqual(expressions) BuiltInFunction::AssertEqual(expressions)
} }
"download" => { "download" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Download(expression) BuiltInFunction::Download(expression)
} }
"help" => { "help" => {
let child_node = node.child(2).unwrap(); let child_node = node.child(2).unwrap();
@ -107,138 +107,138 @@ impl AbstractTree for Tool {
None None
}; };
Tool::Help(expression) BuiltInFunction::Help(expression)
} }
"length" => { "length" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Length(expression) BuiltInFunction::Length(expression)
} }
"output" => { "output" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Output(expressions) BuiltInFunction::Output(expressions)
} }
"output_error" => { "output_error" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions) BuiltInFunction::OutputError(expressions)
} }
"type" => { "type" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Type(expression) BuiltInFunction::Type(expression)
} }
"workdir" => Tool::Workdir, "workdir" => BuiltInFunction::Workdir,
"append" => { "append" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Error::expect_tool_argument_amount("append", 2, expressions.len())?; Error::expect_tool_argument_amount("append", 2, expressions.len())?;
Tool::Append(expressions) BuiltInFunction::Append(expressions)
} }
"metadata" => { "metadata" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Metadata(expression) BuiltInFunction::Metadata(expression)
} }
"move" => { "move" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Error::expect_tool_argument_amount("move", 2, expressions.len())?; Error::expect_tool_argument_amount("move", 2, expressions.len())?;
Tool::Move(expressions) BuiltInFunction::Move(expressions)
} }
"read" => { "read" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Read(expression) BuiltInFunction::Read(expression)
} }
"remove" => { "remove" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Remove(expression) BuiltInFunction::Remove(expression)
} }
"write" => { "write" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Error::expect_tool_argument_amount("write", 2, expressions.len())?; Error::expect_tool_argument_amount("write", 2, expressions.len())?;
Tool::Write(expressions) BuiltInFunction::Write(expressions)
} }
"from_json" => { "from_json" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::FromJson(expression) BuiltInFunction::FromJson(expression)
} }
"to_json" => { "to_json" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::ToJson(expression) BuiltInFunction::ToJson(expression)
} }
"to_string" => { "to_string" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::ToString(expression) BuiltInFunction::ToString(expression)
} }
"to_float" => { "to_float" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::ToFloat(expression) BuiltInFunction::ToFloat(expression)
} }
"bash" => { "bash" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Bash(expressions) BuiltInFunction::Bash(expressions)
} }
"fish" => { "fish" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Fish(expressions) BuiltInFunction::Fish(expressions)
} }
"raw" => { "raw" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Raw(expressions) BuiltInFunction::Raw(expressions)
} }
"sh" => { "sh" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Sh(expressions) BuiltInFunction::Sh(expressions)
} }
"zsh" => { "zsh" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Zsh(expressions) BuiltInFunction::Zsh(expressions)
} }
"random" => { "random" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
Tool::Random(expressions) BuiltInFunction::Random(expressions)
} }
"random_boolean" => Tool::RandomBoolean, "random_boolean" => BuiltInFunction::RandomBoolean,
"random_float" => Tool::RandomFloat, "random_float" => BuiltInFunction::RandomFloat,
"random_integer" => Tool::RandomInteger, "random_integer" => BuiltInFunction::RandomInteger,
"columns" => { "columns" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Columns(expression) BuiltInFunction::Columns(expression)
} }
"rows" => { "rows" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Rows(expression) BuiltInFunction::Rows(expression)
} }
"reverse" => { "reverse" => {
let list_node = node.child(2).unwrap(); let list_node = node.child(2).unwrap();
@ -254,11 +254,11 @@ impl AbstractTree for Tool {
None None
}; };
Tool::Reverse(list_expression, slice_range_nodes) BuiltInFunction::Reverse(list_expression, slice_range_nodes)
} }
_ => { _ => {
return Err(Error::UnexpectedSyntaxNode { return Err(Error::UnexpectedSyntaxNode {
expected: "built-in tool", expected: "built-in function",
actual: tool_node.kind(), actual: tool_node.kind(),
location: tool_node.start_position(), location: tool_node.start_position(),
relevant_source: source[tool_node.byte_range()].to_string(), relevant_source: source[tool_node.byte_range()].to_string(),
@ -271,7 +271,7 @@ impl AbstractTree for Tool {
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
match self { match self {
Tool::Assert(expressions) => { BuiltInFunction::Assert(expressions) => {
for expression in expressions { for expression in expressions {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
@ -284,7 +284,7 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::AssertEqual(expressions) => { BuiltInFunction::AssertEqual(expressions) => {
let mut prev_value = None; let mut prev_value = None;
for expression in expressions { for expression in expressions {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
@ -305,14 +305,14 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::Download(expression) => { BuiltInFunction::Download(expression) => {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
let url = value.as_string()?; let url = value.as_string()?;
let data = get(url)?.text()?; let data = get(url)?.text()?;
Ok(Value::String(data)) Ok(Value::String(data))
} }
Tool::Length(expression) => { BuiltInFunction::Length(expression) => {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
let length = match value { let length = match value {
Value::List(list) => list.items().len(), Value::List(list) => list.items().len(),
@ -328,7 +328,7 @@ impl AbstractTree for Tool {
Ok(Value::Integer(length as i64)) Ok(Value::Integer(length as i64))
} }
Tool::Help(_expression) => { BuiltInFunction::Help(_expression) => {
let mut help_table = let mut help_table =
Table::new(vec!["tool".to_string(), "description".to_string()]); Table::new(vec!["tool".to_string(), "description".to_string()]);
@ -339,7 +339,7 @@ impl AbstractTree for Tool {
Ok(Value::Table(help_table)) Ok(Value::Table(help_table))
} }
Tool::Output(expressions) => { BuiltInFunction::Output(expressions) => {
for expression in expressions { for expression in expressions {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
@ -348,7 +348,7 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::OutputError(expressions) => { BuiltInFunction::OutputError(expressions) => {
for expression in expressions { for expression in expressions {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
@ -357,7 +357,7 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::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.value_type()
@ -369,12 +369,12 @@ impl AbstractTree for Tool {
Ok(Value::String(value_type.to_string())) Ok(Value::String(value_type.to_string()))
} }
Tool::Workdir => { BuiltInFunction::Workdir => {
let workdir = current_dir()?.to_string_lossy().to_string(); let workdir = current_dir()?.to_string_lossy().to_string();
Ok(Value::String(workdir)) Ok(Value::String(workdir))
} }
Tool::Append(expressions) => { BuiltInFunction::Append(expressions) => {
let path_value = expressions[0].run(source, context)?; let path_value = expressions[0].run(source, context)?;
let path = path_value.as_string()?; let path = path_value.as_string()?;
let data = expressions[1].run(source, context)?.to_string(); let data = expressions[1].run(source, context)?.to_string();
@ -384,7 +384,7 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::Metadata(expression) => { BuiltInFunction::Metadata(expression) => {
let path_value = expression.run(source, context)?; let path_value = expression.run(source, context)?;
let path = path_value.as_string()?; let path = path_value.as_string()?;
let metadata = metadata(path)?; let metadata = metadata(path)?;
@ -415,7 +415,7 @@ impl AbstractTree for Tool {
Ok(Value::Map(metadata_output)) Ok(Value::Map(metadata_output))
} }
Tool::Move(expressions) => { BuiltInFunction::Move(expressions) => {
let from_value = expressions[0].run(source, context)?; let from_value = expressions[0].run(source, context)?;
let from = from_value.as_string()?; let from = from_value.as_string()?;
let to_value = expressions[1].run(source, context)?; let to_value = expressions[1].run(source, context)?;
@ -426,7 +426,7 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::Read(expression) => { BuiltInFunction::Read(expression) => {
let path_value = expression.run(source, context)?; let path_value = expression.run(source, context)?;
let path = PathBuf::from(path_value.as_string()?); let path = PathBuf::from(path_value.as_string()?);
let content = if path.is_dir() { let content = if path.is_dir() {
@ -447,7 +447,7 @@ impl AbstractTree for Tool {
Ok(content) Ok(content)
} }
Tool::Remove(expression) => { BuiltInFunction::Remove(expression) => {
let path_value = expression.run(source, context)?; let path_value = expression.run(source, context)?;
let path = PathBuf::from(path_value.as_string()?); let path = PathBuf::from(path_value.as_string()?);
@ -455,7 +455,7 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::Write(expressions) => { BuiltInFunction::Write(expressions) => {
let path_value = expressions[0].run(source, context)?; let path_value = expressions[0].run(source, context)?;
let path = path_value.as_string()?; let path = path_value.as_string()?;
let data_value = expressions[1].run(source, context)?; let data_value = expressions[1].run(source, context)?;
@ -465,26 +465,26 @@ impl AbstractTree for Tool {
Ok(Value::Empty) Ok(Value::Empty)
} }
Tool::FromJson(expression) => { BuiltInFunction::FromJson(expression) => {
let json_value = expression.run(source, context)?; let json_value = expression.run(source, context)?;
let json = json_value.as_string()?; let json = json_value.as_string()?;
let value = serde_json::from_str(json)?; let value = serde_json::from_str(json)?;
Ok(value) Ok(value)
} }
Tool::ToJson(expression) => { BuiltInFunction::ToJson(expression) => {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
let json = serde_json::to_string(&value)?; let json = serde_json::to_string(&value)?;
Ok(Value::String(json)) Ok(Value::String(json))
} }
Tool::ToString(expression) => { BuiltInFunction::ToString(expression) => {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
let string = value.to_string(); let string = value.to_string();
Ok(Value::String(string)) Ok(Value::String(string))
} }
Tool::ToFloat(expression) => { BuiltInFunction::ToFloat(expression) => {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
let float = match value { let float = match value {
Value::String(string) => string.parse()?, Value::String(string) => string.parse()?,
@ -495,7 +495,7 @@ impl AbstractTree for Tool {
Ok(Value::Float(float)) Ok(Value::Float(float))
} }
Tool::Bash(expressions) => { BuiltInFunction::Bash(expressions) => {
let mut command = Command::new("bash"); let mut command = Command::new("bash");
for expression in expressions { for expression in expressions {
@ -509,7 +509,7 @@ impl AbstractTree for Tool {
Ok(Value::String(String::from_utf8(output)?)) Ok(Value::String(String::from_utf8(output)?))
} }
Tool::Fish(expressions) => { BuiltInFunction::Fish(expressions) => {
let mut command = Command::new("fish"); let mut command = Command::new("fish");
for expression in expressions { for expression in expressions {
@ -523,7 +523,7 @@ impl AbstractTree for Tool {
Ok(Value::String(String::from_utf8(output)?)) Ok(Value::String(String::from_utf8(output)?))
} }
Tool::Raw(expressions) => { BuiltInFunction::Raw(expressions) => {
let raw_command = expressions[0].run(source, context)?; let raw_command = expressions[0].run(source, context)?;
let mut command = Command::new(raw_command.as_string()?); let mut command = Command::new(raw_command.as_string()?);
@ -538,7 +538,7 @@ impl AbstractTree for Tool {
Ok(Value::String(String::from_utf8(output)?)) Ok(Value::String(String::from_utf8(output)?))
} }
Tool::Sh(expressions) => { BuiltInFunction::Sh(expressions) => {
let mut command = Command::new("sh"); let mut command = Command::new("sh");
for expression in expressions { for expression in expressions {
@ -552,7 +552,7 @@ impl AbstractTree for Tool {
Ok(Value::String(String::from_utf8(output)?)) Ok(Value::String(String::from_utf8(output)?))
} }
Tool::Zsh(expressions) => { BuiltInFunction::Zsh(expressions) => {
let mut command = Command::new("zsh"); let mut command = Command::new("zsh");
for expression in expressions { for expression in expressions {
@ -566,7 +566,7 @@ impl AbstractTree for Tool {
Ok(Value::String(String::from_utf8(output)?)) Ok(Value::String(String::from_utf8(output)?))
} }
Tool::Random(expressions) => { BuiltInFunction::Random(expressions) => {
if expressions.len() == 1 { if expressions.len() == 1 {
let value = expressions[0].run(source, context)?; let value = expressions[0].run(source, context)?;
let list = value.as_list()?.items(); let list = value.as_list()?.items();
@ -594,10 +594,10 @@ impl AbstractTree for Tool {
Ok(value) Ok(value)
} }
Tool::RandomBoolean => Ok(Value::Boolean(random())), BuiltInFunction::RandomBoolean => Ok(Value::Boolean(random())),
Tool::RandomFloat => Ok(Value::Float(random())), BuiltInFunction::RandomFloat => Ok(Value::Float(random())),
Tool::RandomInteger => Ok(Value::Integer(random())), BuiltInFunction::RandomInteger => Ok(Value::Integer(random())),
Tool::Columns(expression) => { BuiltInFunction::Columns(expression) => {
let column_names = expression let column_names = expression
.run(source, context)? .run(source, context)?
.as_table()? .as_table()?
@ -609,7 +609,7 @@ impl AbstractTree for Tool {
Ok(Value::List(List::with_items(column_names))) Ok(Value::List(List::with_items(column_names)))
} }
Tool::Rows(expression) => { BuiltInFunction::Rows(expression) => {
let rows = expression let rows = expression
.run(source, context)? .run(source, context)?
.as_table()? .as_table()?
@ -621,7 +621,7 @@ impl AbstractTree for Tool {
Ok(Value::List(List::with_items(rows))) Ok(Value::List(List::with_items(rows)))
} }
Tool::Reverse(list_expression, slice_range) => { BuiltInFunction::Reverse(list_expression, slice_range) => {
let expression_run = list_expression.run(source, context)?; let expression_run = list_expression.run(source, context)?;
let list = expression_run.as_list()?; let list = expression_run.as_list()?;

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, Sublist, Tool, value_node::ValueNode, AbstractTree, BuiltInFunction, Error, Identifier, Index, Map, Result,
Value, Sublist, Value,
}; };
use super::{function_call::FunctionCall, logic::Logic, math::Math}; use super::{function_call::FunctionCall, logic::Logic, math::Math};
@ -17,7 +17,7 @@ pub enum Expression {
Math(Box<Math>), Math(Box<Math>),
Logic(Box<Logic>), Logic(Box<Logic>),
FunctionCall(FunctionCall), FunctionCall(FunctionCall),
Tool(Box<Tool>), Tool(Box<BuiltInFunction>),
} }
impl AbstractTree for Expression { impl AbstractTree for Expression {
@ -40,7 +40,9 @@ impl AbstractTree for Expression {
"function_call" => { "function_call" => {
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?) Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
} }
"tool" => Expression::Tool(Box::new(Tool::from_syntax_node(source, child)?)), "tool" => {
Expression::Tool(Box::new(BuiltInFunction::from_syntax_node(source, child)?))
}
_ => continue, _ => continue,
}; };

View File

@ -1,49 +1,67 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Value}; use crate::{AbstractTree, BuiltInFunction, Error, Map, Result, Value};
use super::{expression::Expression, identifier::Identifier}; use super::{expression::Expression, identifier::Identifier};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionCall { pub enum FunctionCall {
name: Identifier, BuiltIn(Box<BuiltInFunction>),
arguments: Vec<Expression>, ContextDefined {
name: Identifier,
arguments: Vec<Expression>,
},
} }
impl AbstractTree for FunctionCall { impl AbstractTree for FunctionCall {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
debug_assert_eq!("function_call", node.kind()); debug_assert_eq!("function_call", node.kind());
let name_node = node.child(1).unwrap(); let function_node = node.child(0).unwrap();
let name = Identifier::from_syntax_node(source, name_node)?;
let mut arguments = Vec::new(); let mut arguments = Vec::new();
for index in 2..node.child_count() - 1 { for index in 1..node.child_count() {
let child = node.child(index).unwrap(); let child = node.child(index).unwrap();
if child.is_named() { if child.kind() == "expression" {
let expression = Expression::from_syntax_node(source, child)?; let expression = Expression::from_syntax_node(source, child)?;
arguments.push(expression); arguments.push(expression);
} }
} }
Ok(FunctionCall { name, arguments }) let function_call = if function_node.kind() == "built_in_function" {
let function = BuiltInFunction::from_syntax_node(source, function_node)?;
FunctionCall::BuiltIn(Box::new(function))
} else {
let identifier = Identifier::from_syntax_node(source, function_node)?;
FunctionCall::ContextDefined {
name: identifier,
arguments,
}
};
Ok(function_call)
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let key = self.name.inner(); let (name, arguments) = match self {
let definition = if let Some(value) = context.variables().get(key) { FunctionCall::BuiltIn(function) => return function.run(source, context),
FunctionCall::ContextDefined { name, arguments } => (name, arguments),
};
let definition = if let Some(value) = context.variables().get(name.inner()) {
value.as_function().cloned()? value.as_function().cloned()?
} else { } else {
return Err(Error::FunctionIdentifierNotFound(self.name.clone())); return Err(Error::FunctionIdentifierNotFound(name.clone()));
}; };
let id_expr_pairs = definition.identifiers().iter().zip(self.arguments.iter());
let mut function_context = Map::clone_from(context); let mut function_context = Map::clone_from(context);
let identifier_expression_pairs = definition.identifiers().iter().zip(arguments.iter());
for (identifier, expression) in id_expr_pairs { for (identifier, expression) in identifier_expression_pairs {
let key = identifier.inner().clone(); let key = identifier.inner().clone();
let value = expression.run(source, context)?; let value = expression.run(source, context)?;

View File

@ -9,6 +9,7 @@
pub mod assignment; pub mod assignment;
pub mod r#async; pub mod r#async;
pub mod block; pub mod block;
pub mod built_in_function;
pub mod expression; pub mod expression;
pub mod filter; pub mod filter;
pub mod find; pub mod find;
@ -25,16 +26,15 @@ pub mod remove;
pub mod select; pub mod select;
pub mod statement; pub mod statement;
pub mod sublist; pub mod sublist;
pub mod tool;
pub mod transform; pub mod transform;
pub mod value_node; pub mod value_node;
pub mod r#while; pub mod r#while;
pub use { pub use {
assignment::*, block::*, expression::*, filter::*, find::*, function_call::*, identifier::*, assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
if_else::*, index::*, insert::*, logic::*, math::*, r#async::*, r#for::*, r#match::*, function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*,
r#while::*, remove::*, select::*, statement::*, sublist::*, tool::*, transform::*, r#async::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*, sublist::*,
value_node::*, transform::*, value_node::*,
}; };
use tree_sitter::Node; use tree_sitter::Node;

View File

@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Table, Value, AbstractTree, Block, Error, Expression, Function, Identifier, List, Map, Result, Statement,
ValueType, Table, Value, ValueType,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -88,11 +88,11 @@ impl AbstractTree for ValueNode {
Identifier::from_syntax_node(source, child_syntax_node)?.take_inner(); Identifier::from_syntax_node(source, child_syntax_node)?.take_inner();
} }
if child_syntax_node.kind() == "expression" { if child_syntax_node.kind() == "statement" {
let key = current_key.clone(); let key = current_key.clone();
let expression = Expression::from_syntax_node(source, child_syntax_node)?; let statement = Statement::from_syntax_node(source, child_syntax_node)?;
child_nodes.insert(key, expression); child_nodes.insert(key, statement);
} }
} }

View File

@ -154,7 +154,7 @@ mod tests {
map.variables_mut() map.variables_mut()
.insert("foo".to_string(), Value::String("bar".to_string())); .insert("foo".to_string(), Value::String("bar".to_string()));
assert_eq!(evaluate("{ x = 1 foo = 'bar' }"), Ok(Value::Map(map))); assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
} }
#[test] #[test]
@ -256,7 +256,7 @@ mod tests {
} }
#[test] #[test]
fn evaluate_tool_call() { fn evaluate_built_in_function_call() {
assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty)); assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty));
} }
} }

View File

@ -5,7 +5,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{value_node::ValueNode, Expression, Function, Identifier, Value}; use crate::{value_node::ValueNode, Expression, Function, Identifier, Statement, Value};
/// The type of a `Value`. /// The type of a `Value`.
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)] #[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
@ -17,7 +17,7 @@ pub enum ValueType {
Boolean, Boolean,
List(Vec<Expression>), List(Vec<Expression>),
Empty, Empty,
Map(BTreeMap<String, Expression>), Map(BTreeMap<String, Statement>),
Table { Table {
column_names: Vec<Identifier>, column_names: Vec<Identifier>,
rows: Box<Expression>, rows: Box<Expression>,
@ -117,9 +117,9 @@ impl From<&Value> for ValueType {
for (key, value) in map.variables().iter() { for (key, value) in map.variables().iter() {
let value_type = value.value_type(); let value_type = value.value_type();
let value_node = ValueNode::new(value_type, 0, 0); let value_node = ValueNode::new(value_type, 0, 0);
let expression = Expression::Value(value_node); let statement = Statement::Expression(Expression::Value(value_node));
value_nodes.insert(key.to_string(), expression); value_nodes.insert(key.to_string(), statement);
} }
ValueType::Map(value_nodes) ValueType::Map(value_nodes)

View File

@ -14,10 +14,10 @@ async { (output 'Whaddup') }
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(value (value
(string))))))))))) (string))))))))))))
================== ==================
Complex Async Statements Complex Async Statements

View File

@ -0,0 +1,49 @@
==================
Simple Function Call
==================
(output 'hi')
---
(root
(block
(statement
(expression
(function_call
(built_in_function
(expression
(value
(string)))))))))
==================
Nested Function Call
==================
(assert_equal (random_integer) 4)
assert_equal random_integer 4
---
(root
(block
(statement
(expression
(function_call
(built_in_function
(expression
(function_call
(built_in_function)))
(expression
(value
(integer)))))))
(statement
(expression
(function_call
(built_in_function
(expression
(function_call
(built_in_function
(expression
(value
(integer))))))))))))

View File

@ -1,12 +1,12 @@
================== ================================================================================
Simple Find Loop Simple Find Loop
================== ================================================================================
find i in [1, 2, 3] { find i in [1, 2, 3] {
i <= 3 i <= 3
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -36,9 +36,9 @@ find i in [1, 2, 3] {
(value (value
(integer))))))))))) (integer)))))))))))
================== ================================================================================
Nested Find Loop Nested Find Loop
================== ================================================================================
find i in ["one", "two", "three"] { find i in ["one", "two", "three"] {
found = find j in i { found = find j in i {
@ -53,7 +53,7 @@ find i in ["one", "two", "three"] {
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -99,9 +99,9 @@ find i in ["one", "two", "three"] {
(logic (logic
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(identifier)))) (identifier)))))
(logic_operator) (logic_operator)
(expression (expression
(value (value

View File

@ -1,12 +1,10 @@
================== ================================================================================
Simple For Loop Simple For Loop
================== ================================================================================
for i in [1, 2, 3] { for i in [1, 2, 3] output i
(output i)
}
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -29,21 +27,17 @@ for i in [1, 2, 3] {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(identifier)))))))))) (identifier)))))))))))
================== ================================================================================
Nested For Loop Nested For Loop
================== ================================================================================
for list in list_of_lists { for list in list_of_lists for item in list output item
for item in list {
(output item)
}
}
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -62,6 +56,6 @@ for list in list_of_lists {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(identifier))))))))))))) (identifier))))))))))))))

View File

@ -1,10 +1,10 @@
================== ================================================================================
Simple Function Simple Function
================== ================================================================================
function { "Hiya" } function { "Hiya" }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -17,14 +17,14 @@ function { "Hiya" }
(expression (expression
(value (value
(string))))))))))) (string)))))))))))
================== ================================================================================
Function Call Function Call
================== ================================================================================
(foobar "Hiya") (foobar "Hiya")
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -36,16 +36,16 @@ Function Call
(value (value
(string)))))))) (string))))))))
================== ================================================================================
Complex Function Complex Function
================== ================================================================================
function <message number> { function <message number> {
(output message) (output message)
(output number) (output number)
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -59,19 +59,19 @@ function <message number> {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(identifier))))) (identifier))))))
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(identifier)))))))))))) (identifier)))))))))))))
================== ================================================================================
Complex Function Call Complex Function Call
================== ================================================================================
(foobar (foobar
"hi" "hi"
@ -82,7 +82,7 @@ Complex Function Call
} }
) )
--- --------------------------------------------------------------------------------
(root (root
(block (block

View File

@ -1,49 +0,0 @@
==================
Simple Tool Call
==================
(output 'hi')
---
(root
(block
(statement
(expression
(function_call
(built_in_function)
(expression
(value
(string))))))))
==================
Nested Tool Call
==================
(assert_equal (random_integer) 4)
assert_equal random_integer 4
---
(root
(block
(statement
(expression
(function_call
(built_in_function)
(expression
(function_call
(built_in_function)))
(expression
(value
(integer))))))
(statement
(expression
(function_call
(built_in_function)
(expression
(function_call
(built_in_function)
(expression
(value
(integer))))))))))

View File

@ -1,12 +1,12 @@
================== ================================================================================
Transform Loop Transform Loop
================== ================================================================================
transform i in [1, 2, 3] { transform i in [1, 2, 3] {
(output i) (output i)
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -29,13 +29,13 @@ transform i in [1, 2, 3] {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(identifier)))))))))) (identifier)))))))))))
================== ================================================================================
Nested Transform Loop Nested Transform Loop
================== ================================================================================
transform i in [['one'] ['two'] ['three']] { transform i in [['one'] ['two'] ['three']] {
transform j in i { transform j in i {
@ -43,7 +43,7 @@ transform i in [['one'] ['two'] ['three']] {
} }
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block

View File

@ -1,12 +1,12 @@
================== ================================================================================
While Loop While Loop
================== ================================================================================
while true { while true {
(output "This is a bad idea...") (output "This is a bad idea...")
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -19,14 +19,14 @@ while true {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function) (built_in_function
(expression (expression
(value (value
(string))))))))))) (string))))))))))))
================== ================================================================================
Nested While Loop Nested While Loop
================== ================================================================================
while (true) { while (true) {
while (x > 0) { while (x > 0) {
@ -34,7 +34,7 @@ while (true) {
} }
} }
--- --------------------------------------------------------------------------------
(root (root
(block (block
@ -62,4 +62,4 @@ while (true) {
(statement (statement
(expression (expression
(value (value
(integer)))))))))))))) (integer))))))))))))))

View File

@ -19,12 +19,7 @@ module.exports = grammar({
seq('{', repeat1($.statement), '}'), seq('{', repeat1($.statement), '}'),
)), )),
statement: $ => prec.right(seq( statement: $ => prec.right(choice(
$._statement_kind,
optional(';'),
)),
_statement_kind: $ => prec.right(choice(
$.assignment, $.assignment,
$.async, $.async,
$.expression, $.expression,
@ -68,14 +63,14 @@ module.exports = grammar({
$.map, $.map,
), ),
integer: $ => prec.left(token(seq( integer: $ => token(prec.left(seq(
optional('-'), optional('-'),
repeat1( repeat1(
choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')
), ),
))), ))),
float: $ => prec.left(token(seq( float: $ => token(prec.left(seq(
optional('-'), optional('-'),
repeat1(choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')), repeat1(choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')),
'.', '.',
@ -115,12 +110,6 @@ module.exports = grammar({
$.expression, $.expression,
)), )),
)), )),
function: $ => seq(
'function',
optional(seq('<', repeat(seq($.identifier, optional(','))), '>')),
$.block,
),
table: $ => prec.left(seq( table: $ => prec.left(seq(
'table', 'table',
@ -194,11 +183,6 @@ module.exports = grammar({
$.block, $.block,
)), )),
function_call: $ => prec.right(seq(
choice($.identifier, $.built_in_function),
repeat(prec.right(seq($.expression, optional(',')))),
)),
match: $ => prec.right(seq( match: $ => prec.right(seq(
'match', 'match',
$.expression, $.expression,
@ -287,8 +271,29 @@ module.exports = grammar({
'async', 'async',
$.block, $.block,
), ),
function: $ => seq(
'function',
optional(seq('<', repeat(seq($.identifier, optional(','))), '>')),
$.block,
),
built_in_function: $ => choice( function_call: $ => choice(
$.built_in_function,
$._context_defined_function,
),
_context_defined_function: $ => prec.right(seq(
$.identifier,
repeat(prec.right(seq($.expression, optional(',')))),
)),
built_in_function: $ => prec.right(seq(
$._built_in_function_name,
repeat(prec.right(seq($.expression, optional(',')))),
)),
_built_in_function_name: $ => choice(
// General // General
'assert', 'assert',
'assert_equal', 'assert_equal',
@ -298,13 +303,13 @@ module.exports = grammar({
'output', 'output',
'output_error', 'output_error',
'type', 'type',
'workdir',
// Filesystem // Filesystem
'append', 'append',
'metadata', 'metadata',
'move', 'move',
'read', 'read',
'workdir',
'write', 'write',
// Format conversion // Format conversion

View File

@ -50,31 +50,6 @@
} }
}, },
"statement": { "statement": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_statement_kind"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ";"
},
{
"type": "BLANK"
}
]
}
]
}
},
"_statement_kind": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
"content": { "content": {
@ -244,10 +219,10 @@
] ]
}, },
"integer": { "integer": {
"type": "PREC_LEFT", "type": "TOKEN",
"value": 0,
"content": { "content": {
"type": "TOKEN", "type": "PREC_LEFT",
"value": 0,
"content": { "content": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -316,10 +291,10 @@
} }
}, },
"float": { "float": {
"type": "PREC_LEFT", "type": "TOKEN",
"value": 0,
"content": { "content": {
"type": "TOKEN", "type": "PREC_LEFT",
"value": 0,
"content": { "content": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -584,64 +559,6 @@
] ]
} }
}, },
"function": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "function"
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
},
{
"type": "STRING",
"value": ">"
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "block"
}
]
},
"table": { "table": {
"type": "PREC_LEFT", "type": "PREC_LEFT",
"value": 0, "value": 0,
@ -925,56 +842,6 @@
] ]
} }
}, },
"function_call": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "built_in_function"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
}
}
]
}
},
"match": { "match": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
@ -1318,7 +1185,160 @@
} }
] ]
}, },
"function": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "function"
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
},
{
"type": "STRING",
"value": ">"
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "block"
}
]
},
"function_call": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "built_in_function"
},
{
"type": "SYMBOL",
"name": "_context_defined_function"
}
]
},
"_context_defined_function": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "REPEAT",
"content": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
}
}
]
}
},
"built_in_function": { "built_in_function": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_built_in_function_name"
},
{
"type": "REPEAT",
"content": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
}
}
]
}
},
"_built_in_function_name": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{ {
@ -1353,10 +1373,6 @@
"type": "STRING", "type": "STRING",
"value": "type" "value": "type"
}, },
{
"type": "STRING",
"value": "workdir"
},
{ {
"type": "STRING", "type": "STRING",
"value": "append" "value": "append"
@ -1373,6 +1389,10 @@
"type": "STRING", "type": "STRING",
"value": "read" "value": "read"
}, },
{
"type": "STRING",
"value": "workdir"
},
{ {
"type": "STRING", "type": "STRING",
"value": "write" "value": "write"

View File

@ -65,7 +65,17 @@
{ {
"type": "built_in_function", "type": "built_in_function",
"named": true, "named": true,
"fields": {} "fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "expression",
"named": true
}
]
}
}, },
{ {
"type": "else", "type": "else",
@ -205,11 +215,6 @@
] ]
} }
}, },
{
"type": "float",
"named": true,
"fields": {}
},
{ {
"type": "for", "type": "for",
"named": true, "named": true,
@ -351,11 +356,6 @@
] ]
} }
}, },
{
"type": "integer",
"named": true,
"fields": {}
},
{ {
"type": "list", "type": "list",
"named": true, "named": true,
@ -768,10 +768,6 @@
"type": ":", "type": ":",
"named": false "named": false
}, },
{
"type": ";",
"named": false
},
{ {
"type": "<", "type": "<",
"named": false "named": false
@ -864,6 +860,10 @@
"type": "fish", "type": "fish",
"named": false "named": false
}, },
{
"type": "float",
"named": true
},
{ {
"type": "for", "type": "for",
"named": false "named": false
@ -900,6 +900,10 @@
"type": "insert", "type": "insert",
"named": false "named": false
}, },
{
"type": "integer",
"named": true
},
{ {
"type": "into", "type": "into",
"named": false "named": false

File diff suppressed because it is too large Load Diff