Simplifiy syntax for function calls

This commit is contained in:
Jeff 2023-11-30 11:05:09 -05:00
parent 99dd189328
commit a0c648b33a
20 changed files with 8208 additions and 7868 deletions

View File

@ -5,9 +5,9 @@ all_cards = {
} }
is_ready_to_solve <fn map -> bool> |cards| { is_ready_to_solve <fn map -> bool> |cards| {
((length cards:suspects) == 1) (length cards:suspects) == 1
&& ((length cards:rooms) == 1) && (length cards:rooms) == 1
&& ((length cards:weapons) == 1) && (length cards:weapons) == 1
} }
take_turn <fn str str map -> map> |opponent_card current_room cards| { take_turn <fn str str map -> map> |opponent_card current_room cards| {

View File

@ -8,9 +8,6 @@ stuff = [
(random_boolean) (random_boolean)
(random_boolean) (random_boolean)
(random_boolean) (random_boolean)
"foobar_1"
"foobar_2"
"foobar_3"
] ]
(random stuff) (random stuff)

View File

@ -1,20 +1,22 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, TypeDefinition, Value, BUILT_IN_FUNCTIONS}; use crate::{
AbstractTree, Error, Identifier, Map, Result, TypeDefinition, Value, BUILT_IN_FUNCTIONS,
};
use super::expression::Expression; use super::expression::Expression;
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionCall { pub struct FunctionCall {
function: Expression, function_name: Identifier,
arguments: Vec<Expression>, arguments: Vec<Expression>,
} }
impl FunctionCall { impl FunctionCall {
pub fn new(function: Expression, arguments: Vec<Expression>) -> Self { pub fn new(function_name: Identifier, arguments: Vec<Expression>) -> Self {
Self { Self {
function, function_name,
arguments, arguments,
} }
} }
@ -24,8 +26,8 @@ impl AbstractTree for FunctionCall {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
debug_assert_eq!("function_call", node.kind()); debug_assert_eq!("function_call", node.kind());
let expression_node = node.child(1).unwrap(); let identifier_node = node.child(1).unwrap();
let function = Expression::from_syntax_node(source, expression_node, context)?; let function_name = Identifier::from_syntax_node(source, identifier_node, context)?;
let mut arguments = Vec::new(); let mut arguments = Vec::new();
@ -40,14 +42,13 @@ impl AbstractTree for FunctionCall {
} }
Ok(FunctionCall { Ok(FunctionCall {
function, function_name,
arguments, arguments,
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let function = if let Expression::Identifier(identifier) = &self.function { let key = self.function_name.inner();
let key = identifier.inner();
for built_in_function in BUILT_IN_FUNCTIONS { for built_in_function in BUILT_IN_FUNCTIONS {
if key == built_in_function.name() { if key == built_in_function.name() {
@ -63,17 +64,14 @@ impl AbstractTree for FunctionCall {
} }
} }
if let Some(value) = context.variables()?.get(key) { let variables = context.variables()?;
value.as_function().cloned() let function = if let Some(value) = variables.get(key) {
value.as_function()?
} else { } else {
return Err(Error::FunctionIdentifierNotFound(identifier.clone())); return Err(Error::FunctionIdentifierNotFound(
} self.function_name.clone(),
} else { ));
let expression_run = self.function.run(source, context)?; };
expression_run.as_function().cloned()
}?;
let mut function_context = Map::clone_from(context)?; let mut function_context = Map::clone_from(context)?;
let parameter_expression_pairs = function.parameters().iter().zip(self.arguments.iter()); let parameter_expression_pairs = function.parameters().iter().zip(self.arguments.iter());
@ -88,7 +86,7 @@ impl AbstractTree for FunctionCall {
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> { fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.function.expected_type(context) self.function_name.expected_type(context)
} }
} }

View File

@ -108,7 +108,7 @@ mod tests {
" "
x = [1 2 3] x = [1 2 3]
y <fn -> int> || { 0 } y <fn -> int> || { 0 }
x:((y)) x:(y)
", ",
) )
.unwrap(); .unwrap();

View File

@ -1,7 +1,9 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Expression, FunctionCall, Map, Result, TypeDefinition, Value}; use crate::{
AbstractTree, Expression, FunctionCall, Identifier, Map, Result, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Yield { pub struct Yield {
@ -14,7 +16,7 @@ impl AbstractTree for Yield {
let input = Expression::from_syntax_node(source, input_node, context)?; let input = Expression::from_syntax_node(source, input_node, context)?;
let function_node = node.child(3).unwrap(); let function_node = node.child(3).unwrap();
let function = Expression::from_syntax_node(source, function_node, context)?; let function = Identifier::from_syntax_node(source, function_node, context)?;
let mut arguments = Vec::new(); let mut arguments = Vec::new();

View File

@ -26,7 +26,7 @@ impl BuiltInFunction for AssertEqual {
} }
fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> { fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> {
Error::expect_built_in_function_argument_amount(self, 2, arguments.len())?; Error::expect_argument_amount(self, 2, arguments.len())?;
let left = arguments.get(0).unwrap(); let left = arguments.get(0).unwrap();
let right = arguments.get(1).unwrap(); let right = arguments.get(1).unwrap();

View File

@ -8,7 +8,7 @@ impl BuiltInFunction for FromJson {
} }
fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> { fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> {
Error::expect_built_in_function_argument_amount(self, 1, arguments.len())?; Error::expect_argument_amount(self, 1, arguments.len())?;
let json_string = arguments.first().unwrap().as_string()?; let json_string = arguments.first().unwrap().as_string()?;
let value = serde_json::from_str(&json_string)?; let value = serde_json::from_str(&json_string)?;
@ -25,7 +25,7 @@ impl BuiltInFunction for ToJson {
} }
fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> { fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> {
Error::expect_built_in_function_argument_amount(self, 1, arguments.len())?; Error::expect_argument_amount(self, 1, arguments.len())?;
let value = arguments.first().unwrap(); let value = arguments.first().unwrap();
let json_string = serde_json::to_string(&value)?; let json_string = serde_json::to_string(&value)?;

View File

@ -4,9 +4,10 @@ mod assert;
mod data_formats; mod data_formats;
mod fs; mod fs;
mod output; mod output;
mod random;
mod r#type; mod r#type;
pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 9] = [ pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 11] = [
&assert::Assert, &assert::Assert,
&assert::AssertEqual, &assert::AssertEqual,
&data_formats::FromJson, &data_formats::FromJson,
@ -15,6 +16,8 @@ pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 9] = [
&fs::Write, &fs::Write,
&fs::Append, &fs::Append,
&output::Output, &output::Output,
&random::Random,
&random::RandomInteger,
&r#type::Type, &r#type::Type,
]; ];

View File

@ -0,0 +1,34 @@
use rand::{random, thread_rng, Rng};
use crate::{BuiltInFunction, Error, Map, Result, Value};
pub struct Random;
impl BuiltInFunction for Random {
fn name(&self) -> &'static str {
"random"
}
fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> {
Error::expect_argument_minimum(self, 2, arguments.len())?;
let random_index = thread_rng().gen_range(0..arguments.len());
let random_argument = arguments.get(random_index).unwrap();
Ok(random_argument.clone())
}
}
pub struct RandomInteger;
impl BuiltInFunction for RandomInteger {
fn name(&self) -> &'static str {
"random_integer"
}
fn run(&self, arguments: &[Value], _context: &Map) -> Result<Value> {
Error::expect_argument_amount(self, 0, arguments.len())?;
Ok(Value::Integer(random()))
}
}

View File

@ -8,7 +8,7 @@ impl BuiltInFunction for Type {
} }
fn run(&self, arguments: &[Value], context: &Map) -> Result<Value> { fn run(&self, arguments: &[Value], context: &Map) -> Result<Value> {
Error::expect_built_in_function_argument_amount(self, 1, arguments.len())?; Error::expect_argument_amount(self, 1, arguments.len())?;
if arguments.len() == 1 { if arguments.len() == 1 {
let type_definition = arguments.first().unwrap().r#type(context)?; let type_definition = arguments.first().unwrap().r#type(context)?;

View File

@ -54,15 +54,15 @@ pub enum Error {
}, },
/// A function was called with the wrong amount of arguments. /// A function was called with the wrong amount of arguments.
ExpectedToolArgumentAmount { ExpectedArgumentAmount {
tool_name: &'static str, function_name: &'static str,
expected: usize, expected: usize,
actual: usize, actual: usize,
}, },
/// A function was called with the wrong amount of arguments. /// A function was called with the wrong amount of arguments.
ExpectedAtLeastFunctionArgumentAmount { ExpectedArgumentMinimum {
identifier: String, function_name: &'static str,
minimum: usize, minimum: usize,
actual: usize, actual: usize,
}, },
@ -166,7 +166,7 @@ impl Error {
} }
} }
pub fn expect_built_in_function_argument_amount<F: BuiltInFunction>( pub fn expect_argument_amount<F: BuiltInFunction>(
function: &F, function: &F,
expected: usize, expected: usize,
actual: usize, actual: usize,
@ -174,13 +174,29 @@ impl Error {
if expected == actual { if expected == actual {
Ok(()) Ok(())
} else { } else {
Err(Error::ExpectedToolArgumentAmount { Err(Error::ExpectedArgumentAmount {
tool_name: function.name(), function_name: function.name(),
expected, expected,
actual, actual,
}) })
} }
} }
pub fn expect_argument_minimum<F: BuiltInFunction>(
function: &F,
minimum: usize,
actual: usize,
) -> Result<()> {
if actual < minimum {
Ok(())
} else {
Err(Error::ExpectedArgumentMinimum {
function_name: function.name(),
minimum,
actual,
})
}
}
} }
impl<T> From<PoisonError<T>> for Error { impl<T> From<PoisonError<T>> for Error {
@ -276,21 +292,21 @@ impl fmt::Display for Error {
"An operator expected {} arguments, but got {}.", "An operator expected {} arguments, but got {}.",
expected, actual expected, actual
), ),
ExpectedToolArgumentAmount { ExpectedArgumentAmount {
tool_name, function_name: tool_name,
expected, expected,
actual, actual,
} => write!( } => write!(
f, f,
"{tool_name} expected {expected} arguments, but got {actual}.", "{tool_name} expected {expected} arguments, but got {actual}.",
), ),
ExpectedAtLeastFunctionArgumentAmount { ExpectedArgumentMinimum {
function_name,
minimum, minimum,
actual, actual,
identifier,
} => write!( } => write!(
f, f,
"{identifier} expected a minimum of {minimum} arguments, but got {actual}.", "{function_name} expected a minimum of {minimum} arguments, but got {actual}.",
), ),
ExpectedString { actual } => { ExpectedString { actual } => {
write!(f, "Expected a string but got {:?}.", actual) write!(f, "Expected a string but got {:?}.", actual)

View File

@ -12,8 +12,7 @@ async { (output 'Whaddup') }
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(value (value
(string))))))))) (string)))))))))

View File

@ -28,8 +28,7 @@ for i in [1, 2, 3] {
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(identifier))))))))) (identifier)))))))))
@ -61,7 +60,6 @@ for list in list_of_lists {
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(identifier)))))))))))) (identifier))))))))))))

View File

@ -32,8 +32,7 @@ Function Call
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(value (value
(string))))))) (string)))))))
@ -64,15 +63,13 @@ foobar <fn str num> |message number| {
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(identifier))))) (identifier)))))
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(identifier)))))))))) (identifier))))))))))
@ -95,8 +92,7 @@ Complex Function Call
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(value (value
(string))) (string)))

View File

@ -108,7 +108,8 @@ x:(y):0
(expression (expression
(identifier)) (identifier))
(expression (expression
(identifier)))) (function_call
(identifier)))))
(expression (expression
(value (value
(integer))))))) (integer)))))))

View File

@ -18,8 +18,7 @@ while true {
(statement (statement
(expression (expression
(function_call (function_call
(expression (identifier)
(identifier))
(expression (expression
(value (value
(string)))))))))) (string))))))))))
@ -28,8 +27,8 @@ while true {
Nested While Loop Nested While Loop
================================================================================ ================================================================================
while (true) { while true {
while (x > 0) { while x > 0 {
x -= 1 x -= 1
} }
} }

View File

@ -40,18 +40,6 @@ module.exports = grammar({
), ),
expression: $ => expression: $ =>
prec.right(
choice(
$._expression_kind,
seq(
'(',
$._expression_kind,
')',
),
),
),
_expression_kind: $ =>
prec.right( prec.right(
choice( choice(
$.function_call, $.function_call,
@ -197,11 +185,20 @@ module.exports = grammar({
math: $ => math: $ =>
prec.left( prec.left(
choice(
seq( seq(
$.expression, $.expression,
$.math_operator, $.math_operator,
$.expression, $.expression,
), ),
seq(
'(',
$.expression,
$.math_operator,
$.expression,
')',
),
),
), ),
math_operator: $ => math_operator: $ =>
@ -209,11 +206,20 @@ module.exports = grammar({
logic: $ => logic: $ =>
prec.right( prec.right(
choice(
seq( seq(
$.expression, $.expression,
$.logic_operator, $.logic_operator,
$.expression, $.expression,
), ),
seq(
'(',
$.expression,
$.logic_operator,
$.expression,
')',
),
),
), ),
logic_operator: $ => logic_operator: $ =>
@ -370,10 +376,9 @@ module.exports = grammar({
function_call: $ => function_call: $ =>
prec.right( prec.right(
1,
seq( seq(
'(', '(',
$.expression, $.identifier,
optional($._expression_list), optional($._expression_list),
')', ')',
), ),
@ -385,7 +390,7 @@ module.exports = grammar({
$.expression, $.expression,
'->', '->',
'(', '(',
$.expression, $.identifier,
optional($._expression_list), optional($._expression_list),
')', ')',
), ),

View File

@ -120,36 +120,6 @@
} }
}, },
"expression": { "expression": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_expression_kind"
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "SYMBOL",
"name": "_expression_kind"
},
{
"type": "STRING",
"value": ")"
}
]
}
]
}
},
"_expression_kind": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
"content": { "content": {
@ -592,6 +562,9 @@
"type": "PREC_LEFT", "type": "PREC_LEFT",
"value": 0, "value": 0,
"content": { "content": {
"type": "CHOICE",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
@ -607,6 +580,33 @@
"name": "expression" "name": "expression"
} }
] ]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "SYMBOL",
"name": "math_operator"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": ")"
}
]
}
]
} }
}, },
"math_operator": { "math_operator": {
@ -638,6 +638,9 @@
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
"content": { "content": {
"type": "CHOICE",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
@ -653,6 +656,33 @@
"name": "expression" "name": "expression"
} }
] ]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "SYMBOL",
"name": "logic_operator"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": ")"
}
]
}
]
} }
}, },
"logic_operator": { "logic_operator": {
@ -1183,7 +1213,7 @@
}, },
"function_call": { "function_call": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 1, "value": 0,
"content": { "content": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -1193,7 +1223,7 @@
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "expression" "name": "identifier"
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -1234,7 +1264,7 @@
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "expression" "name": "identifier"
}, },
{ {
"type": "CHOICE", "type": "CHOICE",

View File

@ -177,6 +177,10 @@
{ {
"type": "expression", "type": "expression",
"named": true "named": true
},
{
"type": "identifier",
"named": true
} }
] ]
} }
@ -580,6 +584,10 @@
{ {
"type": "expression", "type": "expression",
"named": true "named": true
},
{
"type": "identifier",
"named": true
} }
] ]
} }

File diff suppressed because it is too large Load Diff