From b67792038472f8094a92f989c249b906e536cc23 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 13:32:39 +0000 Subject: [PATCH] fix: error on undefined identifiers instead of evaluating to null Environment::get returned Object::Null when a name was not bound anywhere in the environment chain, so a typo silently produced a null value. The mistake then surfaced further downstream as a confusing type mismatch, pointing at the operator rather than at the undefined name. Environment::get now returns Option, and identifier evaluation moves into its own module which bails with "Identifier not found: ." when the lookup misses. identifier_expression_case_8 enshrined the old behaviour, evaluating "let is_directory = false;\nis_file" and asserting Ok(Null). It now references the identifier it binds, and the undefined-identifier code it used to cover moves to the new identifier_not_found evaluation error suite alongside nine other cases. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Htq6Br9uauDWFGr9zPxTyc --- src/evaluator/environment/mod.rs | 15 +++---- src/evaluator/expression/identifier/mod.rs | 14 ++++++ src/evaluator/expression/mod.rs | 5 ++- .../identifier_not_found/mod.rs | 42 ++++++++++++++++++ ...er_not_found_case_10_evaluation_error.snap | 7 +++ ...er_not_found_case_10_lexical_analysis.snap | 11 +++++ ...ier_not_found_case_10_syntax_analysis.snap | 13 ++++++ ...ier_not_found_case_1_evaluation_error.snap | 7 +++ ...ier_not_found_case_1_lexical_analysis.snap | 10 +++++ ...fier_not_found_case_1_syntax_analysis.snap | 11 +++++ ...ier_not_found_case_2_evaluation_error.snap | 7 +++ ...ier_not_found_case_2_lexical_analysis.snap | 16 +++++++ ...fier_not_found_case_2_syntax_analysis.snap | 19 ++++++++ ...ier_not_found_case_3_evaluation_error.snap | 7 +++ ...ier_not_found_case_3_lexical_analysis.snap | 22 ++++++++++ ...fier_not_found_case_3_syntax_analysis.snap | 25 +++++++++++ ...ier_not_found_case_4_evaluation_error.snap | 7 +++ ...ier_not_found_case_4_lexical_analysis.snap | 35 +++++++++++++++ ...fier_not_found_case_4_syntax_analysis.snap | 43 +++++++++++++++++++ ...ier_not_found_case_5_evaluation_error.snap | 7 +++ ...ier_not_found_case_5_lexical_analysis.snap | 35 +++++++++++++++ ...fier_not_found_case_5_syntax_analysis.snap | 43 +++++++++++++++++++ ...ier_not_found_case_6_evaluation_error.snap | 7 +++ ...ier_not_found_case_6_lexical_analysis.snap | 35 +++++++++++++++ ...fier_not_found_case_6_syntax_analysis.snap | 42 ++++++++++++++++++ ...ier_not_found_case_7_evaluation_error.snap | 7 +++ ...ier_not_found_case_7_lexical_analysis.snap | 24 +++++++++++ ...fier_not_found_case_7_syntax_analysis.snap | 33 ++++++++++++++ ...ier_not_found_case_8_evaluation_error.snap | 7 +++ ...ier_not_found_case_8_lexical_analysis.snap | 15 +++++++ ...fier_not_found_case_8_syntax_analysis.snap | 14 ++++++ ...ier_not_found_case_9_evaluation_error.snap | 7 +++ ...ier_not_found_case_9_lexical_analysis.snap | 11 +++++ ...fier_not_found_case_9_syntax_analysis.snap | 13 ++++++ src/tests/evaluation_error/mod.rs | 1 + src/tests/identifier_expression/mod.rs | 5 ++- ...entifier_expression_case_8_evaluation.snap | 2 +- ...er_expression_case_8_lexical_analysis.snap | 2 +- ...ier_expression_case_8_syntax_analysis.snap | 2 +- 39 files changed, 614 insertions(+), 14 deletions(-) create mode 100644 src/evaluator/expression/identifier/mod.rs create mode 100644 src/tests/evaluation_error/identifier_not_found/mod.rs create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_syntax_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_evaluation_error.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_lexical_analysis.snap create mode 100644 src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_syntax_analysis.snap diff --git a/src/evaluator/environment/mod.rs b/src/evaluator/environment/mod.rs index d14336c1..05e24b0d 100644 --- a/src/evaluator/environment/mod.rs +++ b/src/evaluator/environment/mod.rs @@ -32,16 +32,13 @@ impl Environment { self.variables.insert(identifier, value); } - pub(super) fn get>(&self, identifier: T) -> Object { + pub(super) fn get>(&self, identifier: T) -> Option { match self.variables.get(identifier.as_ref()) { - Some(value) => value.clone(), - None => { - if let Some(sub_environment) = &self.sub_environment { - return sub_environment.get(identifier); - } - - Object::Null - } + Some(value) => Some(value.clone()), + None => match &self.sub_environment { + Some(sub_environment) => sub_environment.get(identifier), + None => None, + }, } } } diff --git a/src/evaluator/expression/identifier/mod.rs b/src/evaluator/expression/identifier/mod.rs new file mode 100644 index 00000000..a43b0246 --- /dev/null +++ b/src/evaluator/expression/identifier/mod.rs @@ -0,0 +1,14 @@ +use crate::evaluator::Evaluator; +use crate::evaluator::Object; + +impl Evaluator { + pub(super) fn evaluate_identifier_expression( + &self, + identifier: String, + ) -> anyhow::Result { + match self.environment.get(&identifier) { + Some(object) => Ok(object), + None => anyhow::bail!("Identifier not found: {}.", identifier), + } + } +} diff --git a/src/evaluator/expression/mod.rs b/src/evaluator/expression/mod.rs index d5e71e39..672ccc65 100644 --- a/src/evaluator/expression/mod.rs +++ b/src/evaluator/expression/mod.rs @@ -5,6 +5,7 @@ use crate::syntax_analysis::*; mod boolean; mod call; mod function; +mod identifier; mod if_expression; mod infix; mod integer; @@ -33,7 +34,9 @@ impl Evaluator { consequence, alternative, } => self.evaluate_if_expression(*condition, *consequence, *alternative), - Expression::Identifier { identifier } => Ok(self.environment.get(identifier)), + Expression::Identifier { identifier } => { + self.evaluate_identifier_expression(identifier) + } Expression::Function { parameters, block } => { self.evaluate_function_expression(parameters, *block) } diff --git a/src/tests/evaluation_error/identifier_not_found/mod.rs b/src/tests/evaluation_error/identifier_not_found/mod.rs new file mode 100644 index 00000000..3637c407 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/mod.rs @@ -0,0 +1,42 @@ +use super::*; + +#[template] +#[rstest( + code, + snapshot_name, + case("foobar;", "identifier_not_found_case_1"), + case("let is_directory = false;\nis_file", "identifier_not_found_case_2"), + case("let a = 5;\na + b", "identifier_not_found_case_3"), + case( + "let double = fn(x) { x * 2 };\ndoubel(5)", + "identifier_not_found_case_4" + ), + case( + "let double = fn(x) { x * multiplier };\ndouble(5)", + "identifier_not_found_case_5" + ), + case( + "let identity = fn(x) { x };\nidentity(1);\nx", + "identifier_not_found_case_6" + ), + case("if (unknown) { 1 } else { 2 };", "identifier_not_found_case_7"), + case("let a = b;", "identifier_not_found_case_8"), + case("return missing;", "identifier_not_found_case_9"), + case("!undefined_boolean;", "identifier_not_found_case_10") +)] +fn identifier_not_found_cases(code: &str, snapshot_name: &str) {} + +#[apply(identifier_not_found_cases)] +fn test_identifier_not_found_lexical_analysis(code: &str, snapshot_name: &str) { + assert_lexical_analysis!(code, snapshot_name); +} + +#[apply(identifier_not_found_cases)] +fn test_identifier_not_found_syntax_analysis(code: &str, snapshot_name: &str) { + assert_syntax_analysis!(code, snapshot_name); +} + +#[apply(identifier_not_found_cases)] +fn test_identifier_not_found_evaluation_error(code: &str, snapshot_name: &str) { + assert_evaluation_error!(code, snapshot_name); +} diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_evaluation_error.snap new file mode 100644 index 00000000..b09a82b6 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: undefined_boolean.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_lexical_analysis.snap new file mode 100644 index 00000000..e86409c4 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_lexical_analysis.snap @@ -0,0 +1,11 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Not, + Identifier { + literal: "undefined_boolean", + }, + SemiColon, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_syntax_analysis.snap new file mode 100644 index 00000000..a9e37b30 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_10_syntax_analysis.snap @@ -0,0 +1,13 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: NotPrefix { + right_hand: Identifier { + identifier: "undefined_boolean", + }, + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_evaluation_error.snap new file mode 100644 index 00000000..35e86743 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: foobar.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_lexical_analysis.snap new file mode 100644 index 00000000..cf2bf6f6 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_lexical_analysis.snap @@ -0,0 +1,10 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Identifier { + literal: "foobar", + }, + SemiColon, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_syntax_analysis.snap new file mode 100644 index 00000000..b4b7bfd4 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_1_syntax_analysis.snap @@ -0,0 +1,11 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: Identifier { + identifier: "foobar", + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_evaluation_error.snap new file mode 100644 index 00000000..d226f56e --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: is_file.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_lexical_analysis.snap new file mode 100644 index 00000000..887e5852 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_lexical_analysis.snap @@ -0,0 +1,16 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "is_directory", + }, + Assign, + False, + SemiColon, + Identifier { + literal: "is_file", + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_syntax_analysis.snap new file mode 100644 index 00000000..8b24d22e --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_2_syntax_analysis.snap @@ -0,0 +1,19 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "is_directory", + expression: Boolean { + literal: false, + }, + }, + }, + Expression { + expression: Identifier { + identifier: "is_file", + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_evaluation_error.snap new file mode 100644 index 00000000..0c304305 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: b.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_lexical_analysis.snap new file mode 100644 index 00000000..3b92d2dd --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_lexical_analysis.snap @@ -0,0 +1,22 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "a", + }, + Assign, + Integer { + literal: 5, + }, + SemiColon, + Identifier { + literal: "a", + }, + Plus, + Identifier { + literal: "b", + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_syntax_analysis.snap new file mode 100644 index 00000000..ba2b137b --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_3_syntax_analysis.snap @@ -0,0 +1,25 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "a", + expression: Integer { + literal: 5, + }, + }, + }, + Expression { + expression: Infix { + left_hand: Identifier { + identifier: "a", + }, + operator: Plus, + right_hand: Identifier { + identifier: "b", + }, + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_evaluation_error.snap new file mode 100644 index 00000000..6c0c8cb6 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: doubel.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_lexical_analysis.snap new file mode 100644 index 00000000..4fc62d59 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_lexical_analysis.snap @@ -0,0 +1,35 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "double", + }, + Assign, + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "x", + }, + Multiply, + Integer { + literal: 2, + }, + ClosingCurlyBracket, + SemiColon, + Identifier { + literal: "doubel", + }, + OpeningRoundBracket, + Integer { + literal: 5, + }, + ClosingRoundBracket, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_syntax_analysis.snap new file mode 100644 index 00000000..5173177c --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_4_syntax_analysis.snap @@ -0,0 +1,43 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "double", + expression: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Infix { + left_hand: Identifier { + identifier: "x", + }, + operator: Multiply, + right_hand: Integer { + literal: 2, + }, + }, + }, + ], + }, + }, + }, + }, + Expression { + expression: Call { + function: Identifier { + identifier: "doubel", + }, + arguments: [ + Integer { + literal: 5, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_evaluation_error.snap new file mode 100644 index 00000000..869c6239 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: multiplier.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_lexical_analysis.snap new file mode 100644 index 00000000..5aaaca38 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_lexical_analysis.snap @@ -0,0 +1,35 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "double", + }, + Assign, + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "x", + }, + Multiply, + Identifier { + literal: "multiplier", + }, + ClosingCurlyBracket, + SemiColon, + Identifier { + literal: "double", + }, + OpeningRoundBracket, + Integer { + literal: 5, + }, + ClosingRoundBracket, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_syntax_analysis.snap new file mode 100644 index 00000000..ae2f01e8 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_5_syntax_analysis.snap @@ -0,0 +1,43 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "double", + expression: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Infix { + left_hand: Identifier { + identifier: "x", + }, + operator: Multiply, + right_hand: Identifier { + identifier: "multiplier", + }, + }, + }, + ], + }, + }, + }, + }, + Expression { + expression: Call { + function: Identifier { + identifier: "double", + }, + arguments: [ + Integer { + literal: 5, + }, + ], + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_evaluation_error.snap new file mode 100644 index 00000000..1505d040 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: x.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_lexical_analysis.snap new file mode 100644 index 00000000..89b71429 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_lexical_analysis.snap @@ -0,0 +1,35 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "identity", + }, + Assign, + Function, + OpeningRoundBracket, + Identifier { + literal: "x", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Identifier { + literal: "x", + }, + ClosingCurlyBracket, + SemiColon, + Identifier { + literal: "identity", + }, + OpeningRoundBracket, + Integer { + literal: 1, + }, + ClosingRoundBracket, + SemiColon, + Identifier { + literal: "x", + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_syntax_analysis.snap new file mode 100644 index 00000000..4c71e543 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_6_syntax_analysis.snap @@ -0,0 +1,42 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "identity", + expression: Function { + parameters: [ + "x", + ], + block: Block { + nodes: [ + Expression { + expression: Identifier { + identifier: "x", + }, + }, + ], + }, + }, + }, + }, + Expression { + expression: Call { + function: Identifier { + identifier: "identity", + }, + arguments: [ + Integer { + literal: 1, + }, + ], + }, + }, + Expression { + expression: Identifier { + identifier: "x", + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_evaluation_error.snap new file mode 100644 index 00000000..172484b7 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: unknown.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_lexical_analysis.snap new file mode 100644 index 00000000..0281724c --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_lexical_analysis.snap @@ -0,0 +1,24 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + If, + OpeningRoundBracket, + Identifier { + literal: "unknown", + }, + ClosingRoundBracket, + OpeningCurlyBracket, + Integer { + literal: 1, + }, + ClosingCurlyBracket, + Else, + OpeningCurlyBracket, + Integer { + literal: 2, + }, + ClosingCurlyBracket, + SemiColon, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_syntax_analysis.snap new file mode 100644 index 00000000..8dd2cee4 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_7_syntax_analysis.snap @@ -0,0 +1,33 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Expression { + expression: If { + condition: Identifier { + identifier: "unknown", + }, + consequence: Block { + nodes: [ + Expression { + expression: Integer { + literal: 1, + }, + }, + ], + }, + alternative: Some( + Block { + nodes: [ + Expression { + expression: Integer { + literal: 2, + }, + }, + ], + }, + ), + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_evaluation_error.snap new file mode 100644 index 00000000..0c304305 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: b.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_lexical_analysis.snap new file mode 100644 index 00000000..21fcfd6e --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_lexical_analysis.snap @@ -0,0 +1,15 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Let, + Identifier { + literal: "a", + }, + Assign, + Identifier { + literal: "b", + }, + SemiColon, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_syntax_analysis.snap new file mode 100644 index 00000000..d4948cc3 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_8_syntax_analysis.snap @@ -0,0 +1,14 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Let { + identifier: "a", + expression: Identifier { + identifier: "b", + }, + }, + }, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_evaluation_error.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_evaluation_error.snap new file mode 100644 index 00000000..1b345213 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_evaluation_error.snap @@ -0,0 +1,7 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: error +--- +Err( + "Identifier not found: missing.", +) diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_lexical_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_lexical_analysis.snap new file mode 100644 index 00000000..e0594849 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_lexical_analysis.snap @@ -0,0 +1,11 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: tokens +--- +[ + Return, + Identifier { + literal: "missing", + }, + SemiColon, +] diff --git a/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_syntax_analysis.snap b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_syntax_analysis.snap new file mode 100644 index 00000000..7297a2a8 --- /dev/null +++ b/src/tests/evaluation_error/identifier_not_found/snapshots/monkey_interpreter__tests__evaluation_error__identifier_not_found__test_identifier_not_found_case_9_syntax_analysis.snap @@ -0,0 +1,13 @@ +--- +source: src/tests/evaluation_error/identifier_not_found/mod.rs +expression: abstract_syntax_tree +--- +[ + Statement { + statement: Return { + expression: Identifier { + identifier: "missing", + }, + }, + }, +] diff --git a/src/tests/evaluation_error/mod.rs b/src/tests/evaluation_error/mod.rs index 355085a0..5b1009e4 100644 --- a/src/tests/evaluation_error/mod.rs +++ b/src/tests/evaluation_error/mod.rs @@ -4,6 +4,7 @@ use super::*; mod macros; mod division_by_zero_integer_infix_expression; +mod identifier_not_found; mod type_mismatch_boolean_infix_expression; mod type_mismatch_boolean_prefix_expression; mod type_mismatch_integer_infix_expression; diff --git a/src/tests/identifier_expression/mod.rs b/src/tests/identifier_expression/mod.rs index 7b34807d..c806f68a 100644 --- a/src/tests/identifier_expression/mod.rs +++ b/src/tests/identifier_expression/mod.rs @@ -20,7 +20,10 @@ use super::*; case("let a = 5;\na", "identifier_expression_case_5"), case("let a = 25;\nlet b = 91;\nb", "identifier_expression_case_6"), case("let is_file = true;\nis_file", "identifier_expression_case_7"), - case("let is_directory = false;\nis_file", "identifier_expression_case_8"), + case( + "let is_directory = false;\nis_directory", + "identifier_expression_case_8" + ), case( "\tlet file = \"/tmp/temp.txt\";\nfile", "identifier_expression_case_9" diff --git a/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_evaluation.snap b/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_evaluation.snap index 337eea3f..7ee11554 100644 --- a/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_evaluation.snap +++ b/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_evaluation.snap @@ -2,4 +2,4 @@ source: src/tests/identifier_expression/mod.rs expression: evaluation --- -Null +False diff --git a/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_lexical_analysis.snap b/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_lexical_analysis.snap index b049f05f..de741dbc 100644 --- a/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_lexical_analysis.snap +++ b/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_lexical_analysis.snap @@ -11,6 +11,6 @@ expression: tokens False, SemiColon, Identifier { - literal: "is_file", + literal: "is_directory", }, ] diff --git a/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_syntax_analysis.snap b/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_syntax_analysis.snap index 1ed25238..a788ba4c 100644 --- a/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_syntax_analysis.snap +++ b/src/tests/identifier_expression/snapshots/monkey_interpreter__tests__identifier_expression__test_identifier_expression_case_8_syntax_analysis.snap @@ -13,7 +13,7 @@ expression: abstract_syntax_tree }, Expression { expression: Identifier { - identifier: "is_file", + identifier: "is_directory", }, }, ]