Add block statements
This commit is contained in:
		@@ -1,8 +1,10 @@
 | 
				
			|||||||
#include "ast_interpreter.hh"
 | 
					#include "ast_interpreter.hh"
 | 
				
			||||||
 | 
					#include "environment.hh"
 | 
				
			||||||
#include "expr.hh"
 | 
					#include "expr.hh"
 | 
				
			||||||
#include "stmt.hh"
 | 
					#include "stmt.hh"
 | 
				
			||||||
#include "../error_handler.hh"
 | 
					#include "../error_handler.hh"
 | 
				
			||||||
#include "../tokenizer.hh"
 | 
					#include "../tokenizer.hh"
 | 
				
			||||||
 | 
					#include <exception>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
@@ -26,6 +28,11 @@ void AstInterpreter::execute(const Stmt &stmt) {
 | 
				
			|||||||
    case StmtType::EXPRESSION: return execute_expression_statement(stmt);
 | 
					    case StmtType::EXPRESSION: return execute_expression_statement(stmt);
 | 
				
			||||||
    case StmtType::PRINT:      return execute_print_statement(stmt);
 | 
					    case StmtType::PRINT:      return execute_print_statement(stmt);
 | 
				
			||||||
    case StmtType::VAR:        return execute_var_statement(stmt);
 | 
					    case StmtType::VAR:        return execute_var_statement(stmt);
 | 
				
			||||||
 | 
					    case StmtType::BLOCK: {
 | 
				
			||||||
 | 
					      std::shared_ptr<_Block> ptr = std::get<std::shared_ptr<_Block>>(stmt.value);
 | 
				
			||||||
 | 
					      assert(ptr != nullptr);
 | 
				
			||||||
 | 
					      return execute_block_statement(ptr->statements, Environment{std::make_shared<Environment>(environment)});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,6 +67,19 @@ void AstInterpreter::execute_var_statement(const Stmt &stmt) {
 | 
				
			|||||||
  environment.define(ptr->name.lexeme, value);
 | 
					  environment.define(ptr->name.lexeme, value);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AstInterpreter::execute_block_statement(const std::vector<Stmt> &statements, Environment environment) {
 | 
				
			||||||
 | 
					  Environment previous = this->environment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    this->environment = environment;
 | 
				
			||||||
 | 
					    for (const auto &stmt : statements) {
 | 
				
			||||||
 | 
					      execute(stmt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } catch (std::exception) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  this->environment = previous;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Object AstInterpreter::evaluate(const Expr &expr) {
 | 
					Object AstInterpreter::evaluate(const Expr &expr) {
 | 
				
			||||||
  switch (expr.type) {
 | 
					  switch (expr.type) {
 | 
				
			||||||
    case ExprType::BINARY:   return evaluate_binary_expression(expr);
 | 
					    case ExprType::BINARY:   return evaluate_binary_expression(expr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,7 @@ private:
 | 
				
			|||||||
  void execute_expression_statement(const Stmt &stmt);
 | 
					  void execute_expression_statement(const Stmt &stmt);
 | 
				
			||||||
  void execute_print_statement(const Stmt &stmt);
 | 
					  void execute_print_statement(const Stmt &stmt);
 | 
				
			||||||
  void execute_var_statement(const Stmt &stmt);
 | 
					  void execute_var_statement(const Stmt &stmt);
 | 
				
			||||||
 | 
					  void execute_block_statement(const std::vector<Stmt> &statements, Environment environment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Object evaluate(const Expr &expr);
 | 
					  Object evaluate(const Expr &expr);
 | 
				
			||||||
  Object evaluate_binary_expression(const Expr &expr);
 | 
					  Object evaluate_binary_expression(const Expr &expr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,6 +43,11 @@ void Environment::assign(const Token &name, const Object &value) {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (enclosing != nullptr) {
 | 
				
			||||||
 | 
					    enclosing->assign(name, value);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  throw RuntimeException(name, "Undefined variable '" + name.lexeme + "'.");
 | 
					  throw RuntimeException(name, "Undefined variable '" + name.lexeme + "'.");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,5 +56,9 @@ Object Environment::get(const Token &name) {
 | 
				
			|||||||
    return values.at(name.lexeme);
 | 
					    return values.at(name.lexeme);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (enclosing != nullptr) {
 | 
				
			||||||
 | 
					    return enclosing->get(name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  throw RuntimeException(name, "Undefined variable '" + name.lexeme + "'.");
 | 
					  throw RuntimeException(name, "Undefined variable '" + name.lexeme + "'.");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,9 +46,24 @@ Stmt Parser::statement() {
 | 
				
			|||||||
    return print_statement();
 | 
					    return print_statement();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (match({TokenType::LEFT_BRACE})) {
 | 
				
			||||||
 | 
					    return Block(block_statement());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return expression_statement();
 | 
					  return expression_statement();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<Stmt> Parser::block_statement() {
 | 
				
			||||||
 | 
					  std::vector<Stmt> statements{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (!check(TokenType::RIGHT_BRACE) && !is_at_end()) {
 | 
				
			||||||
 | 
					    statements.push_back(declaration());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  consume(TokenType::RIGHT_BRACE, "Expect '}' after block.");
 | 
				
			||||||
 | 
					  return statements;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Stmt Parser::print_statement() {
 | 
					Stmt Parser::print_statement() {
 | 
				
			||||||
  Expr value{expression()};
 | 
					  Expr value{expression()};
 | 
				
			||||||
  consume(TokenType::SEMICOLON, "Expect ';' after value.");
 | 
					  consume(TokenType::SEMICOLON, "Expect ';' after value.");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ struct Parser {
 | 
				
			|||||||
  Stmt declaration();
 | 
					  Stmt declaration();
 | 
				
			||||||
  Stmt var_declaration();
 | 
					  Stmt var_declaration();
 | 
				
			||||||
  Stmt statement();
 | 
					  Stmt statement();
 | 
				
			||||||
 | 
					  std::vector<Stmt> block_statement();
 | 
				
			||||||
  Stmt print_statement();
 | 
					  Stmt print_statement();
 | 
				
			||||||
  Stmt expression_statement();
 | 
					  Stmt expression_statement();
 | 
				
			||||||
  Expr expression();
 | 
					  Expr expression();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,27 +4,32 @@
 | 
				
			|||||||
#include "expr.hh"
 | 
					#include "expr.hh"
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <variant>
 | 
					#include <variant>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Stmt;
 | 
					struct Stmt;
 | 
				
			||||||
struct _Expression;
 | 
					struct _Expression;
 | 
				
			||||||
struct _Print;
 | 
					struct _Print;
 | 
				
			||||||
struct _Var;
 | 
					struct _Var;
 | 
				
			||||||
 | 
					struct _Block;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class StmtType {
 | 
					enum class StmtType {
 | 
				
			||||||
  EXPRESSION,
 | 
					  EXPRESSION,
 | 
				
			||||||
  PRINT,
 | 
					  PRINT,
 | 
				
			||||||
  VAR,
 | 
					  VAR,
 | 
				
			||||||
 | 
					  BLOCK,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using StmtVariant = std::variant<
 | 
					using StmtVariant = std::variant<
 | 
				
			||||||
  std::shared_ptr<_Expression>,
 | 
					  std::shared_ptr<_Expression>,
 | 
				
			||||||
  std::shared_ptr<_Print>,
 | 
					  std::shared_ptr<_Print>,
 | 
				
			||||||
  std::shared_ptr<_Var>
 | 
					  std::shared_ptr<_Var>,
 | 
				
			||||||
 | 
					  std::shared_ptr<_Block>
 | 
				
			||||||
>;
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define Expression(EXPR) (Stmt{StmtType::EXPRESSION, std::make_shared<_Expression>(EXPR)})
 | 
					#define Expression(EXPR) (Stmt{StmtType::EXPRESSION, std::make_shared<_Expression>(EXPR)})
 | 
				
			||||||
#define Print(EXPR) (Stmt{StmtType::PRINT, std::make_shared<_Print>(EXPR)})
 | 
					#define Print(EXPR) (Stmt{StmtType::PRINT, std::make_shared<_Print>(EXPR)})
 | 
				
			||||||
#define Var(NAME, EXPR) (Stmt{StmtType::VAR, std::make_shared<_Var>(NAME, EXPR)})
 | 
					#define Var(NAME, EXPR) (Stmt{StmtType::VAR, std::make_shared<_Var>(NAME, EXPR)})
 | 
				
			||||||
 | 
					#define Block(STATEMENTS) (Stmt{StmtType::BLOCK, std::make_shared<_Block>(STATEMENTS)})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Stmt {
 | 
					struct Stmt {
 | 
				
			||||||
  Stmt(StmtType type, StmtVariant value);
 | 
					  Stmt(StmtType type, StmtVariant value);
 | 
				
			||||||
@@ -63,4 +68,9 @@ struct _Var {
 | 
				
			|||||||
  Expr expr;
 | 
					  Expr expr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct _Block {
 | 
				
			||||||
 | 
					  _Block(const std::vector<Stmt> &statements) : statements{statements} {}
 | 
				
			||||||
 | 
					  std::vector<Stmt> statements;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user