-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b645ca6
commit b60cbda
Showing
7 changed files
with
220 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
|
||
#ifndef CRUX_RESOLVER_H | ||
#define CRUX_RESOLVER_H | ||
|
||
#include "Interpreter.h" | ||
#include <stack> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
struct varFlags { | ||
bool isInitilised; | ||
bool isReferenced; | ||
}; | ||
|
||
class Resolver { | ||
|
||
private: | ||
std::vector<std::unordered_map<std::string, varFlags> *> scopes; | ||
Interpreter *interpreter; | ||
Resolver(Interpreter *interpreter); | ||
|
||
public: | ||
void resolve(std::vector<Statement *> stmnts); | ||
void resolve(Expr *expr); | ||
void resolve(Statement *stmnt); | ||
|
||
void beginScope(); | ||
void endScope(); | ||
|
||
void declare(Token *name); | ||
void define(Token *name); | ||
|
||
void resolveLocal(Expr *expr, Token *name); | ||
|
||
Object excecuteBlock(std::vector<Statement *> stmnts, Environment *env); | ||
|
||
void interpret(std::vector<Statement *> &statements); | ||
|
||
void visitPrintStmnt(Print *stmnt); | ||
|
||
void visitBlockStmnt(Block *stmnt); | ||
|
||
void visitExprStmnt(Expression *stmnt); | ||
|
||
void visitVarStmnt(Var *stmnt); | ||
|
||
void visitIfStmnt(If *stmnt); | ||
|
||
void visitWhileStmnt(While *stmnt); | ||
|
||
void visitFuncStmnt(Function *stmnt); | ||
|
||
void visitReturnStmnt(Return *stmnt); | ||
|
||
void visitAssignment(Assignment *expr); | ||
|
||
void visitLogicalExp(Logical *expr); | ||
|
||
void visitLiteral(Literal *expr); | ||
|
||
void visitGroupExp(Grouping *expr); | ||
|
||
void visitCall(Call *stmnt); | ||
|
||
void visitUnaryExp(Unary *expr); | ||
|
||
void visitBinaryExp(Binary *expr); | ||
|
||
void visitTernaryExp(Ternary *expr); | ||
|
||
void visitVariableExp(Variable *expr); | ||
}; | ||
|
||
#endif // CRUX_RESOLVER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// | ||
// | ||
// | ||
#include "Resolver.h" | ||
#include "Error.h" | ||
#include "Expr.h" | ||
#include "Statement.h" | ||
#include <string> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
Resolver::Resolver(Interpreter *interpreter) : interpreter(interpreter) {} | ||
|
||
void Resolver::resolve(std::vector<Statement *> stmnts) { | ||
for (Statement *stmnt : stmnts) { | ||
resolve(stmnt); | ||
} | ||
} | ||
|
||
void Resolver::resolve(Statement *stmnt) { | ||
switch (stmnt->type) { | ||
case StmntPrint_type: | ||
visitPrintStmnt((Print *)stmnt); | ||
break; | ||
case StmntExpr_type: | ||
visitExprStmnt((Expression *)stmnt); | ||
break; | ||
case StmntVar_type: | ||
visitVarStmnt((Var *)stmnt); | ||
break; | ||
case StmntBlock_type: | ||
visitBlockStmnt((Block *)stmnt); | ||
break; | ||
case StmntIf_type: | ||
visitIfStmnt((If *)stmnt); | ||
break; | ||
case StmntWhile_type: | ||
visitWhileStmnt((While *)stmnt); | ||
break; | ||
case StmntFunc_type: | ||
visitFuncStmnt((Function *)stmnt); | ||
break; | ||
case StmntReturn_type: | ||
visitReturnStmnt((Return *)stmnt); | ||
break; | ||
case StmntBreak_type: | ||
break; | ||
} | ||
} | ||
|
||
void Resolver::resolve(Expr *expr) { | ||
switch (expr->type) { | ||
case ExprType_Binary: | ||
return visitBinaryExp((Binary *)expr); | ||
case ExprType_Unary: | ||
return visitUnaryExp((Unary *)expr); | ||
case ExprType_Literal: | ||
return visitLiteral((Literal *)expr); | ||
case ExprType_Grouping: | ||
return visitGroupExp((Grouping *)expr); | ||
case ExprType_Ternary: | ||
return visitTernaryExp((Ternary *)expr); | ||
case ExprType_Variable: | ||
return visitVariableExp((Variable *)expr); | ||
case ExprType_Assignment: | ||
return visitAssignment((Assignment *)expr); | ||
case ExprType_Logical: | ||
return visitLogicalExp((Logical *)expr); | ||
case ExprType_Call: | ||
return visitCall((Call *)expr); | ||
} | ||
} | ||
|
||
void Resolver::beginScope() { | ||
scopes.push_back(new std::unordered_map<std::string, varFlags>()); | ||
} | ||
|
||
void Resolver::endScope() { | ||
auto scope = scopes.back(); | ||
delete scope; | ||
scopes.pop_back(); | ||
} | ||
|
||
void Resolver::declare(Token *name) { | ||
if (scopes.empty()) | ||
return; | ||
std::unordered_map<std::string, varFlags> *scope = scopes.back(); | ||
(*scope)[name->lexeme].isReferenced = false; | ||
(*scope)[name->lexeme].isInitilised = false; | ||
} | ||
|
||
void Resolver::define(Token *name) { | ||
if (scopes.empty()) | ||
return; | ||
std::unordered_map<std::string, varFlags> *scope = scopes.back(); | ||
(*scope)[name->lexeme].isInitilised = true; | ||
} | ||
|
||
void Resolver::resolveLocal(Expr *expr, Token *name) { | ||
for (int i = scopes.size(); i >= 0; i--) { | ||
if (scopes[i]->find(name->lexeme) != scopes[i]->end()) | ||
interpreter.resolve(expr, scopes.size() - i - 1); | ||
return; | ||
} | ||
} | ||
|
||
void Resolver::visitBlockStmnt(Block *block) { | ||
beginScope(); | ||
resolve(block->stmnt); | ||
endScope(); | ||
} | ||
|
||
void Resolver::visitVarStmnt(Var *stmnt) { | ||
declare(stmnt->name); | ||
if (stmnt->expression != nullptr) { | ||
resolve(stmnt->expression); | ||
} | ||
define(stmnt->name); | ||
} | ||
|
||
void Resolver::visitVariableExp(Variable *expr) { | ||
if (!scopes.empty()) { | ||
auto scope = scopes.back(); | ||
auto it = scope->find(expr->name->lexeme); | ||
if (it != scope->end() && !it->second.isInitilised == true) | ||
crux::error(*expr->name, | ||
"Can't read local variable in its own initializer."); | ||
} | ||
resolveLocal(expr, expr->name); | ||
} | ||
|
||
void Resolver::visitAssignment(Assignment *expr) { | ||
resolve(expr->value); | ||
resolveLocal(expr, expr->name); | ||
} |