Simplifiy syntax for function calls
This commit is contained in:
parent
99dd189328
commit
a0c648b33a
@ -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| {
|
||||
|
@ -8,9 +8,6 @@ stuff = [
|
||||
(random_boolean)
|
||||
(random_boolean)
|
||||
(random_boolean)
|
||||
"foobar_1"
|
||||
"foobar_2"
|
||||
"foobar_3"
|
||||
]
|
||||
|
||||
(random stuff)
|
||||
|
@ -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,14 +42,13 @@ 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() {
|
||||
@ -63,17 +64,14 @@ impl AbstractTree for FunctionCall {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = context.variables()?.get(key) {
|
||||
value.as_function().cloned()
|
||||
let variables = context.variables()?;
|
||||
let function = if let Some(value) = variables.get(key) {
|
||||
value.as_function()?
|
||||
} else {
|
||||
return Err(Error::FunctionIdentifierNotFound(identifier.clone()));
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ mod tests {
|
||||
"
|
||||
x = [1 2 3]
|
||||
y <fn -> int> || { 0 }
|
||||
x:((y))
|
||||
x:(y)
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)?;
|
||||
|
@ -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,
|
||||
];
|
||||
|
||||
|
34
src/built_in_functions/random.rs
Normal file
34
src/built_in_functions/random.rs
Normal 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()))
|
||||
}
|
||||
}
|
@ -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)?;
|
||||
|
40
src/error.rs
40
src/error.rs
@ -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)
|
||||
|
@ -12,8 +12,7 @@ async { (output 'Whaddup') }
|
||||
(statement
|
||||
(expression
|
||||
(function_call
|
||||
(expression
|
||||
(identifier))
|
||||
(identifier)
|
||||
(expression
|
||||
(value
|
||||
(string)))))))))
|
||||
|
@ -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))))))))))))
|
||||
|
@ -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)))
|
||||
|
@ -108,7 +108,8 @@ x:(y):0
|
||||
(expression
|
||||
(identifier))
|
||||
(expression
|
||||
(identifier))))
|
||||
(function_call
|
||||
(identifier)))))
|
||||
(expression
|
||||
(value
|
||||
(integer)))))))
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -40,18 +40,6 @@ module.exports = grammar({
|
||||
),
|
||||
|
||||
expression: $ =>
|
||||
prec.right(
|
||||
choice(
|
||||
$._expression_kind,
|
||||
seq(
|
||||
'(',
|
||||
$._expression_kind,
|
||||
')',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
_expression_kind: $ =>
|
||||
prec.right(
|
||||
choice(
|
||||
$.function_call,
|
||||
@ -197,11 +185,20 @@ module.exports = grammar({
|
||||
|
||||
math: $ =>
|
||||
prec.left(
|
||||
choice(
|
||||
seq(
|
||||
$.expression,
|
||||
$.math_operator,
|
||||
$.expression,
|
||||
),
|
||||
seq(
|
||||
'(',
|
||||
$.expression,
|
||||
$.math_operator,
|
||||
$.expression,
|
||||
')',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
math_operator: $ =>
|
||||
@ -209,11 +206,20 @@ module.exports = grammar({
|
||||
|
||||
logic: $ =>
|
||||
prec.right(
|
||||
choice(
|
||||
seq(
|
||||
$.expression,
|
||||
$.logic_operator,
|
||||
$.expression,
|
||||
),
|
||||
seq(
|
||||
'(',
|
||||
$.expression,
|
||||
$.logic_operator,
|
||||
$.expression,
|
||||
')',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
logic_operator: $ =>
|
||||
@ -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),
|
||||
')',
|
||||
),
|
||||
|
@ -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,6 +562,9 @@
|
||||
"type": "PREC_LEFT",
|
||||
"value": 0,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
@ -607,6 +580,33 @@
|
||||
"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": {
|
||||
@ -638,6 +638,9 @@
|
||||
"type": "PREC_RIGHT",
|
||||
"value": 0,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
@ -653,6 +656,33 @@
|
||||
"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": {
|
||||
@ -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",
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user