From 3d197d55fd36fbc9c2bf4b5aa3dc80a0745f6851 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 5 Sep 2026 10:47:49 +0000 Subject: [PATCH] fix: reject uncallable objects at runtime not parse time parse_call_expression bailed unless the callee was an identifier or an inlined function literal. Since the Pratt loop feeds the already parsed Expression::Call back in when it meets the next opening round bracket, this made curried calls such as f(1)(2) a syntax error. Callability is a property of the evaluated object, not of the syntax, and evaluate_call_expression already rejects it. Drop the parse time check so any expression can be called, and let the evaluator report the error. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_013zZALDKNGa3m1LZRNmvCVV --- .../pratt_parsing/call_expression/mod.rs | 16 +---- src/tests/call_expression/mod.rs | 9 +++ ...st_call_expression_case_6_environment.snap | 10 +++ ...est_call_expression_case_6_evaluation.snap | 7 ++ ...ll_expression_case_6_lexical_analysis.snap | 36 ++++++++++ ...all_expression_case_6_syntax_analysis.snap | 47 ++++++++++++ ...st_call_expression_case_7_environment.snap | 36 ++++++++++ ...est_call_expression_case_7_evaluation.snap | 7 ++ ...ll_expression_case_7_lexical_analysis.snap | 45 ++++++++++++ ...all_expression_case_7_syntax_analysis.snap | 55 ++++++++++++++ ...st_call_expression_case_8_environment.snap | 10 +++ ...est_call_expression_case_8_evaluation.snap | 7 ++ ...ll_expression_case_8_lexical_analysis.snap | 53 ++++++++++++++ ...all_expression_case_8_syntax_analysis.snap | 71 +++++++++++++++++++ src/tests/evaluation_error/mod.rs | 1 + .../evaluation_error/uncallable_object/mod.rs | 30 ++++++++ ...llable_object_case_1_evaluation_error.snap | 7 ++ ...llable_object_case_1_lexical_analysis.snap | 15 ++++ ...allable_object_case_1_syntax_analysis.snap | 18 +++++ ...llable_object_case_2_evaluation_error.snap | 7 ++ ...llable_object_case_2_lexical_analysis.snap | 12 ++++ ...allable_object_case_2_syntax_analysis.snap | 14 ++++ ...llable_object_case_3_evaluation_error.snap | 7 ++ ...llable_object_case_3_lexical_analysis.snap | 13 ++++ ...allable_object_case_3_syntax_analysis.snap | 18 +++++ ...llable_object_case_4_evaluation_error.snap | 7 ++ ...llable_object_case_4_lexical_analysis.snap | 21 ++++++ ...allable_object_case_4_syntax_analysis.snap | 24 +++++++ ...llable_object_case_5_evaluation_error.snap | 7 ++ ...llable_object_case_5_lexical_analysis.snap | 24 +++++++ ...allable_object_case_5_syntax_analysis.snap | 26 +++++++ ...llable_object_case_6_evaluation_error.snap | 7 ++ ...llable_object_case_6_lexical_analysis.snap | 28 ++++++++ ...allable_object_case_6_syntax_analysis.snap | 36 ++++++++++ ...llable_object_case_7_evaluation_error.snap | 7 ++ ...llable_object_case_7_lexical_analysis.snap | 27 +++++++ ...allable_object_case_7_syntax_analysis.snap | 40 +++++++++++ 37 files changed, 790 insertions(+), 15 deletions(-) create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_environment.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_evaluation.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_lexical_analysis.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_syntax_analysis.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_environment.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_evaluation.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_lexical_analysis.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_syntax_analysis.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_environment.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_evaluation.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_lexical_analysis.snap create mode 100644 src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/mod.rs create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_evaluation_error.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_syntax_analysis.snap diff --git a/src/syntax_analysis/expression/pratt_parsing/call_expression/mod.rs b/src/syntax_analysis/expression/pratt_parsing/call_expression/mod.rs index c54c8459..cdae47e4 100644 --- a/src/syntax_analysis/expression/pratt_parsing/call_expression/mod.rs +++ b/src/syntax_analysis/expression/pratt_parsing/call_expression/mod.rs @@ -10,21 +10,7 @@ impl SyntaxAnalysis<'_> { ) -> anyhow::Result { debug!("Parsing a call expression."); - // check call expression was correctly called by an identifier on inlined function. - match &function { - Expression::Identifier { identifier: _ } => {} - Expression::Function { - parameters: _, - block: _, - } => {} - _ => { - anyhow::bail!( - "A call expression is not calling either an identifier or an inlined function." - ); - } - } - - // parse call expression + // Callability is a runtime concern, the evaluator rejects uncallable objects. let arguments = self.parse_comma_separated_list("call expression's arguments", Ok)?; Ok(Expression::Call { diff --git a/src/tests/call_expression/mod.rs b/src/tests/call_expression/mod.rs index 172e537f..a4acb216 100644 --- a/src/tests/call_expression/mod.rs +++ b/src/tests/call_expression/mod.rs @@ -11,6 +11,15 @@ use super::*; case( "let add = fn(x, y) { x + y }; add(1, add(2, 3));", "call_expression_case_5" + ), + case("fn(x) { fn(y) { y } }(1)(2);", "call_expression_case_6"), + case( + "let curried = fn(x) { fn(y) { y } }; curried(1)(2);", + "call_expression_case_7" + ), + case( + "fn(x) { fn(y) { fn(z) { z * 2 } } }(1)(2)(3);", + "call_expression_case_8" ) )] fn call_expression_cases(code: &str, snapshot_name: &str) {} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_environment.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_environment.snap new file mode 100644 index 00000000..1a334a01 --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_environment.snap @@ -0,0 +1,10 @@ +--- +source: src/tests/call_expression/mod.rs +expression: evaluator +--- +Evaluator { + environment: Environment { + variables: {}, + sub_environment: None, + }, +} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_evaluation.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_evaluation.snap new file mode 100644 index 00000000..69b8de98 --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_evaluation.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/call_expression/mod.rs +expression: evaluation +--- +Integer { + value: 2, +} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_lexical_analysis.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_lexical_analysis.snap new file mode 100644 index 00000000..0e78601a --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_lexical_analysis.snap @@ -0,0 +1,36 @@ +--- +source: src/tests/call_expression/mod.rs +expression: tokens +--- +[ + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Function, + OpeningRoundBracket, + Identifier { + literal: "y", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "y", + }, + ClosingCurlyBracket, + ClosingCurlyBracket, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + OpeningRoundBracket, + Integer { + literal: 2, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_syntax_analysis.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_syntax_analysis.snap new file mode 100644 index 00000000..6a5d5f6b --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_6_syntax_analysis.snap @@ -0,0 +1,47 @@ +--- +source: src/tests/call_expression/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: Call { + function: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Function { + parameters: [ + "y", + ], + block: Block { + nodes: [ + Expression { + expression: Identifier { + identifier: "y", + }, + }, + ], + }, + }, + }, + ], + }, + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + arguments: [ + Integer { + literal: 2, + }, + ], + }, + }, +] diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_environment.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_environment.snap new file mode 100644 index 00000000..53e3940b --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_environment.snap @@ -0,0 +1,36 @@ +--- +source: src/tests/call_expression/mod.rs +expression: evaluator +--- +Evaluator { + environment: Environment { + variables: { + "curried": Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Function { + parameters: [ + "y", + ], + block: Block { + nodes: [ + Expression { + expression: Identifier { + identifier: "y", + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + sub_environment: None, + }, +} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_evaluation.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_evaluation.snap new file mode 100644 index 00000000..69b8de98 --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_evaluation.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/call_expression/mod.rs +expression: evaluation +--- +Integer { + value: 2, +} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_lexical_analysis.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_lexical_analysis.snap new file mode 100644 index 00000000..995708ce --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_lexical_analysis.snap @@ -0,0 +1,45 @@ +--- +source: src/tests/call_expression/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "curried", + }, + Assign, + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Function, + OpeningRoundBracket, + Identifier { + literal: "y", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "y", + }, + ClosingCurlyBracket, + ClosingCurlyBracket, + SemiColon, + Identifier { + literal: "curried", + }, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + OpeningRoundBracket, + Integer { + literal: 2, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_syntax_analysis.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_syntax_analysis.snap new file mode 100644 index 00000000..9291ccbd --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_7_syntax_analysis.snap @@ -0,0 +1,55 @@ +--- +source: src/tests/call_expression/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "curried", + expression: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Function { + parameters: [ + "y", + ], + block: Block { + nodes: [ + Expression { + expression: Identifier { + identifier: "y", + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + }, + Expression { + expression: Call { + function: Call { + function: Identifier { + identifier: "curried", + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + arguments: [ + Integer { + literal: 2, + }, + ], + }, + }, +] diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_environment.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_environment.snap new file mode 100644 index 00000000..1a334a01 --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_environment.snap @@ -0,0 +1,10 @@ +--- +source: src/tests/call_expression/mod.rs +expression: evaluator +--- +Evaluator { + environment: Environment { + variables: {}, + sub_environment: None, + }, +} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_evaluation.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_evaluation.snap new file mode 100644 index 00000000..91956cad --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_evaluation.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/call_expression/mod.rs +expression: evaluation +--- +Integer { + value: 6, +} diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_lexical_analysis.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_lexical_analysis.snap new file mode 100644 index 00000000..20a1bc4f --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_lexical_analysis.snap @@ -0,0 +1,53 @@ +--- +source: src/tests/call_expression/mod.rs +expression: tokens +--- +[ + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Function, + OpeningRoundBracket, + Identifier { + literal: "y", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Function, + OpeningRoundBracket, + Identifier { + literal: "z", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "z", + }, + Multiply, + Integer { + literal: 2, + }, + ClosingCurlyBracket, + ClosingCurlyBracket, + ClosingCurlyBracket, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + OpeningRoundBracket, + Integer { + literal: 2, + }, + ClosingRoundBracket, + OpeningRoundBracket, + Integer { + literal: 3, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_syntax_analysis.snap b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_syntax_analysis.snap new file mode 100644 index 00000000..ac80d9b4 --- /dev/null +++ b/src/tests/call_expression/snapshots/monkey_interpreter__tests__call_expression__test_call_expression_case_8_syntax_analysis.snap @@ -0,0 +1,71 @@ +--- +source: src/tests/call_expression/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: Call { + function: Call { + function: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Function { + parameters: [ + "y", + ], + block: Block { + nodes: [ + Expression { + expression: Function { + parameters: [ + "z", + ], + block: Block { + nodes: [ + Expression { + expression: Infix { + left_hand: Identifier { + identifier: "z", + }, + operator: Multiply, + right_hand: Integer { + literal: 2, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + arguments: [ + Integer { + literal: 2, + }, + ], + }, + arguments: [ + Integer { + literal: 3, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/mod.rs b/src/tests/evaluation_error/mod.rs index 5add2623..fea6cf28 100644 --- a/src/tests/evaluation_error/mod.rs +++ b/src/tests/evaluation_error/mod.rs @@ -7,4 +7,5 @@ mod type_mismatch_boolean_infix_expression; mod type_mismatch_boolean_prefix_expression; mod type_mismatch_integer_infix_expression; mod type_mismatch_integer_prefix_expression; +mod uncallable_object; mod unknown_operator_integer_infix_expression; diff --git a/src/tests/evaluation_error/uncallable_object/mod.rs b/src/tests/evaluation_error/uncallable_object/mod.rs new file mode 100644 index 00000000..afb7adab --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/mod.rs @@ -0,0 +1,30 @@ +use super::*; + +#[template] +#[rstest( + code, + snapshot_name, + case("5(1);", "uncallable_object_case_1"), + case("\"this is a string\"();", "uncallable_object_case_2"), + case("true(1);", "uncallable_object_case_3"), + case("(1 + 2)(3);", "uncallable_object_case_4"), + case("let five = 5; five(1);", "uncallable_object_case_5"), + case("fn(x) { x }(1)(2);", "uncallable_object_case_6"), + case("if (true) { 1 } else { 2 }(3);", "uncallable_object_case_7") +)] +fn uncallable_object_cases(code: &str, snapshot_name: &str) {} + +#[apply(uncallable_object_cases)] +fn test_uncallable_object_lexical_analysis(code: &str, snapshot_name: &str) { + assert_lexical_analysis!(code, snapshot_name); +} + +#[apply(uncallable_object_cases)] +fn test_uncallable_object_syntax_analysis(code: &str, snapshot_name: &str) { + assert_syntax_analysis!(code, snapshot_name); +} + +#[apply(uncallable_object_cases)] +fn test_uncallable_object_evaluation_error(code: &str, snapshot_name: &str) { + assert_evaluation_error!(code, snapshot_name); +} diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_evaluation_error.snap new file mode 100644 index 00000000..1ab8a27a --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type INTEGER, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_lexical_analysis.snap new file mode 100644 index 00000000..888cb3aa --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_lexical_analysis.snap @@ -0,0 +1,15 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + Integer { + literal: 5, + }, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_syntax_analysis.snap new file mode 100644 index 00000000..170e23da --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_1_syntax_analysis.snap @@ -0,0 +1,18 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: Integer { + literal: 5, + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_evaluation_error.snap new file mode 100644 index 00000000..55d4601a --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type STRING, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_lexical_analysis.snap new file mode 100644 index 00000000..88db6c24 --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_lexical_analysis.snap @@ -0,0 +1,12 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + String { + literal: "this is a string", + }, + OpeningRoundBracket, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_syntax_analysis.snap new file mode 100644 index 00000000..c65935b6 --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_2_syntax_analysis.snap @@ -0,0 +1,14 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: String { + literal: "this is a string", + }, + arguments: [], + }, + }, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_evaluation_error.snap new file mode 100644 index 00000000..46c396f8 --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type BOOLEAN, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_lexical_analysis.snap new file mode 100644 index 00000000..5cd82c7e --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_lexical_analysis.snap @@ -0,0 +1,13 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + True, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_syntax_analysis.snap new file mode 100644 index 00000000..efbdfd4d --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_3_syntax_analysis.snap @@ -0,0 +1,18 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: Boolean { + literal: true, + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_evaluation_error.snap new file mode 100644 index 00000000..1ab8a27a --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type INTEGER, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_lexical_analysis.snap new file mode 100644 index 00000000..6da582ed --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_lexical_analysis.snap @@ -0,0 +1,21 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + OpeningRoundBracket, + Integer { + literal: 1, + }, + Plus, + Integer { + literal: 2, + }, + ClosingRoundBracket, + OpeningRoundBracket, + Integer { + literal: 3, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_syntax_analysis.snap new file mode 100644 index 00000000..62b5f33b --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_4_syntax_analysis.snap @@ -0,0 +1,24 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: Infix { + left_hand: Integer { + literal: 1, + }, + operator: Plus, + right_hand: Integer { + literal: 2, + }, + }, + arguments: [ + Integer { + literal: 3, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_evaluation_error.snap new file mode 100644 index 00000000..1ab8a27a --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type INTEGER, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_lexical_analysis.snap new file mode 100644 index 00000000..b94ac8bb --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_lexical_analysis.snap @@ -0,0 +1,24 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "five", + }, + Assign, + Integer { + literal: 5, + }, + SemiColon, + Identifier { + literal: "five", + }, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_syntax_analysis.snap new file mode 100644 index 00000000..043ef51e --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_5_syntax_analysis.snap @@ -0,0 +1,26 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "five", + expression: Integer { + literal: 5, + }, + }, + }, + Expression { + expression: Call { + function: Identifier { + identifier: "five", + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_evaluation_error.snap new file mode 100644 index 00000000..1ab8a27a --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type INTEGER, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_lexical_analysis.snap new file mode 100644 index 00000000..679768a5 --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_lexical_analysis.snap @@ -0,0 +1,28 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "x", + }, + ClosingCurlyBracket, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + OpeningRoundBracket, + Integer { + literal: 2, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_syntax_analysis.snap new file mode 100644 index 00000000..a4b94c26 --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_6_syntax_analysis.snap @@ -0,0 +1,36 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: Call { + function: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Identifier { + identifier: "x", + }, + }, + ], + }, + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + arguments: [ + Integer { + literal: 2, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_evaluation_error.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_evaluation_error.snap new file mode 100644 index 00000000..1ab8a27a --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: error +--- +Err( + "Cannot call an object of type INTEGER, only functions are callable.", +) diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_lexical_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_lexical_analysis.snap new file mode 100644 index 00000000..7bfebc4d --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_lexical_analysis.snap @@ -0,0 +1,27 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: tokens +--- +[ + If, + OpeningRoundBracket, + True, + ClosingRoundBracket, + OpeningCurlyBracket, + Integer { + literal: 1, + }, + ClosingCurlyBracket, + Else, + OpeningCurlyBracket, + Integer { + literal: 2, + }, + ClosingCurlyBracket, + OpeningRoundBracket, + Integer { + literal: 3, + }, + ClosingRoundBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_syntax_analysis.snap b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_syntax_analysis.snap new file mode 100644 index 00000000..d694dabd --- /dev/null +++ b/src/tests/evaluation_error/uncallable_object/snapshots/monkey_interpreter__tests__evaluation_error__uncallable_object__test_uncallable_object_case_7_syntax_analysis.snap @@ -0,0 +1,40 @@ +--- +source: src/tests/evaluation_error/uncallable_object/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Call { + function: If { + condition: Boolean { + literal: true, + }, + consequence: Block { + nodes: [ + Expression { + expression: Integer { + literal: 1, + }, + }, + ], + }, + alternative: Some( + Block { + nodes: [ + Expression { + expression: Integer { + literal: 2, + }, + }, + ], + }, + ), + }, + arguments: [ + Integer { + literal: 3, + }, + ], + }, + }, +]