Add block statements
This commit is contained in:
parent
fb06f6f483
commit
f094fcb376
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user