Skip to content

Commit

Permalink
update: add closure and resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohith-Raju committed May 22, 2024
1 parent b645ca6 commit b60cbda
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 4 deletions.
4 changes: 3 additions & 1 deletion include/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

#include "CruxCallable.h"
#include "Statement.h"
#include "env/Env.h"

class CruxFunction : public CruxCallable {
public:
Function *declaration;
CruxFunction(Function *declaration);
Environment *closure;
CruxFunction(Function *declaration, Environment *closure);
virtual int arity() override;
virtual Object call(Interpreter *interpreter, std::vector<Object>) override;
virtual std::string str() override;
Expand Down
2 changes: 2 additions & 0 deletions include/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class Interpreter {

void interpret(std::vector<Statement *> &statements);

void resolve();

void visitPrintStmnt(Print *stmnt);

void visitBlockStmnt(Block *stmnt);
Expand Down
74 changes: 74 additions & 0 deletions include/Resolver.h
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
5 changes: 3 additions & 2 deletions src/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
#include "utls/Object.h"
#include <string>

CruxFunction::CruxFunction(Function *declaration) : declaration(declaration) {}
CruxFunction::CruxFunction(Function *declaration, Environment *closure)
: declaration(declaration), closure(closure) {}

int CruxFunction::arity() { return declaration->params.size(); }

Object CruxFunction::call(Interpreter *interpreter, std::vector<Object> args) {
Environment *env = new Environment(interpreter->globals);
Environment *env = new Environment(closure);
for (int i = 0; i < declaration->params.size(); i++) {
env->define(declaration->params[i], args[i]);
}
Expand Down
4 changes: 3 additions & 1 deletion src/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ Object Interpreter::evaluate(Expr *expr) {
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);
}
Expand Down Expand Up @@ -165,7 +167,7 @@ void Interpreter::visitWhileStmnt(While *stmnt) {
}

void Interpreter::visitFuncStmnt(Function *stmnt) {
Object declaration(new CruxFunction(stmnt));
Object declaration(new CruxFunction(stmnt, environment));
environment->define(stmnt->name, declaration);
}

Expand Down
135 changes: 135 additions & 0 deletions src/Resolver.cpp
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);
}
Empty file added test.crux
Empty file.

0 comments on commit b60cbda

Please sign in to comment.