Add block statements

This commit is contained in:
Abdelrahman Said 2025-06-29 22:03:03 +01:00
parent fb06f6f483
commit f094fcb376
6 changed files with 57 additions and 1 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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 + "'.");
} }

View File

@ -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.");

View File

@ -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();

View File

@ -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