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| {
((length cards:suspects) == 1)
&& ((length cards:rooms) == 1)
&& ((length cards:weapons) == 1)
(length cards:suspects) == 1
&& (length cards:rooms) == 1
&& (length cards:weapons) == 1
}
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)
"foobar_1"
"foobar_2"
"foobar_3"
]
(random stuff)

View File

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

View File

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

View File

@ -1,7 +1,9 @@
use serde::{Deserialize, Serialize};
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)]
pub struct Yield {
@ -14,7 +16,7 @@ impl AbstractTree for Yield {
let input = Expression::from_syntax_node(source, input_node, context)?;
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();

View File

@ -26,7 +26,7 @@ impl BuiltInFunction for AssertEqual {
}
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 right = arguments.get(1).unwrap();

View File

@ -8,7 +8,7 @@ impl BuiltInFunction for FromJson {
}
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 value = serde_json::from_str(&json_string)?;
@ -25,7 +25,7 @@ impl BuiltInFunction for ToJson {
}
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 json_string = serde_json::to_string(&value)?;

View File

@ -4,9 +4,10 @@ mod assert;
mod data_formats;
mod fs;
mod output;
mod random;
mod r#type;
pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 9] = [
pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 11] = [
&assert::Assert,
&assert::AssertEqual,
&data_formats::FromJson,
@ -15,6 +16,8 @@ pub const BUILT_IN_FUNCTIONS: [&dyn BuiltInFunction; 9] = [
&fs::Write,
&fs::Append,
&output::Output,
&random::Random,
&random::RandomInteger,
&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> {
Error::expect_built_in_function_argument_amount(self, 1, arguments.len())?;
Error::expect_argument_amount(self, 1, arguments.len())?;
if arguments.len() == 1 {
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.
ExpectedToolArgumentAmount {
tool_name: &'static str,
ExpectedArgumentAmount {
function_name: &'static str,
expected: usize,
actual: usize,
},
/// A function was called with the wrong amount of arguments.
ExpectedAtLeastFunctionArgumentAmount {
identifier: String,
ExpectedArgumentMinimum {
function_name: &'static str,
minimum: 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,
expected: usize,
actual: usize,
@ -174,13 +174,29 @@ impl Error {
if expected == actual {
Ok(())
} else {
Err(Error::ExpectedToolArgumentAmount {
tool_name: function.name(),
Err(Error::ExpectedArgumentAmount {
function_name: function.name(),
expected,
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 {
@ -276,21 +292,21 @@ impl fmt::Display for Error {
"An operator expected {} arguments, but got {}.",
expected, actual
),
ExpectedToolArgumentAmount {
tool_name,
ExpectedArgumentAmount {
function_name: tool_name,
expected,
actual,
} => write!(
f,
"{tool_name} expected {expected} arguments, but got {actual}.",
),
ExpectedAtLeastFunctionArgumentAmount {
ExpectedArgumentMinimum {
function_name,
minimum,
actual,
identifier,
} => write!(
f,
"{identifier} expected a minimum of {minimum} arguments, but got {actual}.",
"{function_name} expected a minimum of {minimum} arguments, but got {actual}.",
),
ExpectedString { actual } => {
write!(f, "Expected a string but got {:?}.", actual)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -120,36 +120,6 @@
}
},
"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",
"value": 0,
"content": {
@ -592,19 +562,49 @@
"type": "PREC_LEFT",
"value": 0,
"content": {
"type": "SEQ",
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "expression"
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "SYMBOL",
"name": "math_operator"
},
{
"type": "SYMBOL",
"name": "expression"
}
]
},
{
"type": "SYMBOL",
"name": "math_operator"
},
{
"type": "SYMBOL",
"name": "expression"
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "SYMBOL",
"name": "math_operator"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": ")"
}
]
}
]
}
@ -638,19 +638,49 @@
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "expression"
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "SYMBOL",
"name": "logic_operator"
},
{
"type": "SYMBOL",
"name": "expression"
}
]
},
{
"type": "SYMBOL",
"name": "logic_operator"
},
{
"type": "SYMBOL",
"name": "expression"
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "SYMBOL",
"name": "logic_operator"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": ")"
}
]
}
]
}
@ -1183,7 +1213,7 @@
},
"function_call": {
"type": "PREC_RIGHT",
"value": 1,
"value": 0,
"content": {
"type": "SEQ",
"members": [
@ -1193,7 +1223,7 @@
},
{
"type": "SYMBOL",
"name": "expression"
"name": "identifier"
},
{
"type": "CHOICE",
@ -1234,7 +1264,7 @@
},
{
"type": "SYMBOL",
"name": "expression"
"name": "identifier"
},
{
"type": "CHOICE",

View File

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

File diff suppressed because it is too large Load Diff