Skip to content

Commit

Permalink
♻️ upate AstNode with boxed values
Browse files Browse the repository at this point in the history
  • Loading branch information
KPMGE committed Apr 25, 2024
1 parent 8129519 commit b543a6f
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 37 deletions.
9 changes: 6 additions & 3 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@ pub struct BlockStatement {
#[derive(Debug, Eq, Clone, PartialEq)]
pub enum Statement {
ReturnStatement(Box<Expression>),
LetStatement { name: Box<Expression>, value: Box<Expression> },
LetStatement {
name: Box<Expression>,
value: Box<Expression>,
},
}

#[derive(Debug, Eq, Clone, PartialEq)]
pub enum AstNode {
Statement(Statement),
Expression(Expression),
Statement(Box<Statement>),
Expression(Box<Expression>),
Program { statements: Vec<AstNode> },
}
22 changes: 11 additions & 11 deletions src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ impl Evaluator {
pub fn eval(&mut self, node: AstNode) -> Object {
match node {
AstNode::Program { statements } => self.eval_program(statements),
AstNode::Statement(statement) => self.eval_statement(statement),
AstNode::Expression(expression) => self.eval_expression(expression),
AstNode::Statement(statement) => self.eval_statement(*statement),
AstNode::Expression(expression) => self.eval_expression(*expression),
}
}

Expand All @@ -50,16 +50,16 @@ impl Evaluator {
Expression::Boolean(value) => Object::Boolean(value),
Expression::String(value) => Object::String(value),
Expression::Prefix { operator, right } => {
let right = self.eval(AstNode::Expression(*right));
let right = self.eval(AstNode::Expression(right));
self.eval_prefix_expression(operator, right)
}
Expression::Infix {
operator,
left,
right,
} => {
let left = self.eval(AstNode::Expression(*left));
let right = self.eval(AstNode::Expression(*right));
let left = self.eval(AstNode::Expression(left));
let right = self.eval(AstNode::Expression(right));
self.eval_infix_expression(left, right, operator)
}
Expression::IfExpression {
Expand All @@ -68,7 +68,7 @@ impl Evaluator {
alternative,
..
} => {
let condition = self.eval(AstNode::Expression(*condition));
let condition = self.eval(AstNode::Expression(condition));

if condition.is_truthy() {
return self.eval_block_statement(consequence.statements);
Expand All @@ -93,7 +93,7 @@ impl Evaluator {
arguments,
..
} => {
let function = self.eval(AstNode::Expression(*function));
let function = self.eval(AstNode::Expression(function));

match function {
Object::Builtin(builtin_fn) => {
Expand Down Expand Up @@ -153,7 +153,7 @@ impl Evaluator {
fn eval_statement(&mut self, statement: Statement) -> Object {
match statement {
Statement::ReturnStatement(value) => {
let result_object = self.eval(AstNode::Expression(*value));
let result_object = self.eval(AstNode::Expression(value));
Object::Return(Box::new(result_object))
}
Statement::LetStatement { name, value } => {
Expand All @@ -162,7 +162,7 @@ impl Evaluator {
_ => panic!(),
};

let result_object = self.eval(AstNode::Expression(*value));
let result_object = self.eval(AstNode::Expression(value));
self.context.insert(let_name.clone(), result_object.clone());
result_object
}
Expand All @@ -172,7 +172,7 @@ impl Evaluator {
fn eval_expressions(&mut self, expressions: Vec<Expression>) -> Vec<Object> {
expressions
.iter()
.map(|expression| self.eval(AstNode::Expression(expression.clone())))
.map(|expression| self.eval(AstNode::Expression(Box::new(expression.clone()))))
.collect()
}

Expand Down Expand Up @@ -261,7 +261,7 @@ impl Object {
Object::Null => "null".to_string(),
Object::Array(elems) => {
let elements_str = elems
.into_iter()
.iter()
.map(|e| e.inspect())
.collect::<Vec<String>>()
.join(", ");
Expand Down
11 changes: 8 additions & 3 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ impl Parser {
return None;
}

Some(AstNode::Statement(Statement::LetStatement { name, value }))
Some(AstNode::Statement(Box::new(Statement::LetStatement {
name,
value,
})))
}

fn parse_expression_statement(&mut self) -> Option<AstNode> {
let expression = self.parse_expression(Precedence::Lowest)?;
let expression = Box::new(self.parse_expression(Precedence::Lowest)?);

if self.current_token == Token::Semicolon {
self.advance_tokens();
Expand All @@ -126,7 +129,9 @@ impl Parser {

let expression = Box::new(self.parse_expression(Precedence::Lowest)?);

Some(AstNode::Statement(Statement::ReturnStatement(expression)))
Some(AstNode::Statement(Box::new(Statement::ReturnStatement(
expression,
))))
}

fn parse_expression(&mut self, precedence: Precedence) -> Option<Expression> {
Expand Down
47 changes: 27 additions & 20 deletions tests/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ fn given_let_statements_with_single_integers_shold_parse_correctly() {
let expected_identifier = expected_identifiers.get(idx).unwrap();
let expected_int = expected_ints.get(idx).unwrap();

let expected_statement = AstNode::Statement(Statement::LetStatement {
let expected_statement = AstNode::Statement(Box::new(Statement::LetStatement {
name: Box::new(Expression::Identifier(expected_identifier.to_string())),
value: Box::new(Expression::Int(expected_int.to_string().parse().unwrap())),
});
}));

assert_eq!(*statement, expected_statement);
})
Expand Down Expand Up @@ -67,8 +67,9 @@ fn given_return_statements_with_single_integers_shold_parse_correctly() {
let expected_expression =
Expression::Int(expected_int.to_string().parse().unwrap());

let expected_statement =
AstNode::Statement(Statement::ReturnStatement(Box::new(expected_expression)));
let expected_statement = AstNode::Statement(Box::new(Statement::ReturnStatement(
Box::new(expected_expression),
)));

assert_eq!(*statement, expected_statement);
})
Expand All @@ -94,7 +95,7 @@ fn given_a_variable_name_it_should_parse_correctly() {

match statements.first().unwrap() {
AstNode::Expression(expression) => {
assert_eq!(*expression, Expression::Identifier("foo".to_string()));
assert_eq!(**expression, Expression::Identifier("foo".to_string()));
}
_ => panic!("wrong statement!"),
}
Expand Down Expand Up @@ -122,7 +123,7 @@ fn given_a_number_expression_it_should_parse_correctly() {
match statement {
AstNode::Expression(expression) => {
assert_eq!(
*expression,
**expression,
Expression::Int("5".to_string().parse().unwrap())
);
}
Expand Down Expand Up @@ -163,7 +164,7 @@ fn given_a_prefix_expression_it_should_parse_correctly() {
let expected_right_expression =
Expression::Int(expected_values.get(idx).unwrap().parse().unwrap());

match expression {
match &**expression {
Expression::Prefix { operator, right } => {
assert_eq!(operator, expected_operator);
assert_eq!(*right, Box::new(expected_right_expression));
Expand Down Expand Up @@ -291,7 +292,9 @@ fn given_an_if_expression_it_should_parse_correctly() {
right: Box::new(Expression::Identifier("y".to_string())),
}),
consequence: Box::new(BlockStatement {
statements: vec![AstNode::Expression(Expression::Identifier("x".to_string()))],
statements: vec![AstNode::Expression(Box::new(Expression::Identifier(
"x".to_string(),
)))],
}),
alternative: None,
};
Expand All @@ -305,7 +308,7 @@ fn given_an_if_expression_it_should_parse_correctly() {

let statement = statements.first().unwrap();
match statement {
AstNode::Expression(expression) => assert_eq!(*expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(**expression, expected_expression),
_ => panic!("Unexpected statement!"),
}
}
Expand All @@ -326,10 +329,14 @@ fn given_an_if_else_expression_it_should_parse_correctly() {
right: Box::new(Expression::Identifier("y".to_string())),
}),
consequence: Box::new(BlockStatement {
statements: vec![AstNode::Expression(Expression::Identifier("x".to_string()))],
statements: vec![AstNode::Expression(Box::new(Expression::Identifier(
"x".to_string(),
)))],
}),
alternative: Some(BlockStatement {
statements: vec![AstNode::Expression(Expression::Identifier("y".to_string()))],
statements: vec![AstNode::Expression(Box::new(Expression::Identifier(
"y".to_string(),
)))],
}),
};

Expand All @@ -343,7 +350,7 @@ fn given_an_if_else_expression_it_should_parse_correctly() {

let statement = statements.first().unwrap();
match statement {
AstNode::Expression(expression) => assert_eq!(*expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(**expression, expected_expression),
_ => panic!("Unexpected statement!"),
}
}
Expand All @@ -360,11 +367,11 @@ fn given_a_function_expression_it_should_parse_correctly() {
Token::Identifier("b".to_string()),
],
body: Box::new(BlockStatement {
statements: vec![AstNode::Expression(Expression::Infix {
statements: vec![AstNode::Expression(Box::new(Expression::Infix {
operator: Token::Plus,
left: Box::new(Expression::Identifier("a".to_string())),
right: Box::new(Expression::Identifier("b".to_string())),
})],
}))],
}),
};

Expand All @@ -381,7 +388,7 @@ fn given_a_function_expression_it_should_parse_correctly() {
let statement = statements.first().unwrap();

match statement {
AstNode::Expression(expression) => assert_eq!(*expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(**expression, expected_expression),
_ => panic!("Unexpected expression!"),
}
}
Expand Down Expand Up @@ -422,7 +429,7 @@ fn given_a_call_expression_it_should_parse_correctly() {

let statement = statements.first().unwrap();
match statement {
AstNode::Expression(expression) => assert_eq!(*expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(**expression, expected_expression),
_ => panic!("Unexpected statement!"),
}
}
Expand All @@ -448,7 +455,7 @@ fn given_a_string_expression_it_should_parse_correctly() {
let statement = statements.first().unwrap();

match statement {
AstNode::Expression(expression) => assert_eq!(*expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(**expression, expected_expression),
_ => panic!("Unexpected expression!"),
}
}
Expand Down Expand Up @@ -482,7 +489,7 @@ fn given_an_array_expression_it_should_parse_correctly() {
let statement = statements.first().unwrap();

match statement {
AstNode::Expression(expression) => assert_eq!(*expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(**expression, expected_expression),
_ => panic!("Unexpected expression!"),
}
}
Expand All @@ -505,7 +512,7 @@ fn assert_boolean_expression(code: &str, expected_expression: &Expression) {
let statement = statements.first().unwrap();

match statement {
AstNode::Expression(expression) => assert_eq!(expression, expected_expression),
AstNode::Expression(expression) => assert_eq!(&**expression, expected_expression),
_ => panic!("Unexpected statement!"),
}
}
Expand Down Expand Up @@ -539,7 +546,7 @@ fn assert_infix_expression(code: &str, expected_operator: Token, expected_litera
right: Box::new(expected_right_exp),
};

assert_eq!(*expression, expected_expression);
assert_eq!(&**expression, &expected_expression);
}
_ => panic!(),
}
Expand Down

0 comments on commit b543a6f

Please sign in to comment.