Skip to content

Commit

Permalink
add class this feature
Browse files Browse the repository at this point in the history
  • Loading branch information
flyingalex committed Feb 24, 2020
1 parent 793e0f8 commit 02bf7d2
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 24 deletions.
30 changes: 18 additions & 12 deletions Expr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class Get;
template<class R>
class Set;

template<class R>
class This;

template <class R>
class Visitor {
public:
Expand All @@ -58,8 +61,8 @@ class Visitor {
virtual R visitCallExpr(shared_ptr<Call<R>> expr) = 0;
virtual R visitGetExpr(shared_ptr<Get<R>> expr) = 0;
virtual R visitSetExpr(shared_ptr<Set<R>> expr) = 0;
virtual R visitThisExpr(shared_ptr<This<R>> expr) = 0;
// virtual string visitSuperExpr(Super& expr) = 0;
// virtual string visitThisExpr(This& expr) = 0;
};

template<class R>
Expand Down Expand Up @@ -225,12 +228,25 @@ class Set:
object(object_), name(name_), value(value_) { }
R accept(shared_ptr<Visitor<R>> visitor) override {
return visitor->visitSetExpr(this->shared_from_this());
};
}
shared_ptr<Expr<R>> object;
Token name;
shared_ptr<Expr<R>> value;
};

template <class R>
class This :
public Expr<R>,
public std::enable_shared_from_this<This<R>>
{
public:
explicit This(Token keyword_): keyword(keyword_) { }
R accept(shared_ptr<Visitor<R>> visitor) override {
return visitor->visitThisExpr(this->shared_from_this());
}
Token keyword;
};

// template <class R>
// class Super: public Expr<R> {
// public:
Expand All @@ -241,14 +257,4 @@ class Set:
// Token keyword;
// Token method;
// };

// template <class R>
// class This : public Expr<R>{
// public:
// explicit This(Token keyword);
// R accept(shared_ptr<Visitor<R>> visitor) override {
// return visitor->visitThisExpr(*this);
// };
// Token keyword;
// };
#endif // EXPR_HPP_
7 changes: 5 additions & 2 deletions Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Object Interpreter::visitVariableExpr(shared_ptr<Variable<Object>> expr) {
}

Object Interpreter::lookUpVariable(
Token name, shared_ptr<Variable<Object>> expr) {
Token name, shared_ptr<Expr<Object>> expr) {
auto distance = locals.find(expr);
if (distance != locals.end()) {
return environment->getAt(distance->second, name.lexeme);
Expand Down Expand Up @@ -226,10 +226,13 @@ Object Interpreter::visitSetExpr(shared_ptr<Set<Object>> expr) {
}

Object value = evaluate(expr->value);
value.instance->set(expr->name, value);
object.instance->set(expr->name, value);
return value;
}

Object Interpreter::visitThisExpr(shared_ptr<This<Object>> expr) {
return lookUpVariable(expr->keyword, expr);
}

void Interpreter::visitExpressionStmt(const Expression& stmt) {
evaluate(stmt.expression);
Expand Down
3 changes: 2 additions & 1 deletion Interpreter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Interpreter:
Object visitCallExpr(shared_ptr<Call<Object>> expr);
Object visitGetExpr(shared_ptr<Get<Object>> expr);
Object visitSetExpr(shared_ptr<Set<Object>> expr);
Object visitThisExpr(shared_ptr<This<Object>> expr);
void visitExpressionStmt(const Expression& stmt);
void visitPrintStmt(const Print& stmt);
void visitVarStmt(const Var& stmt);
Expand All @@ -62,7 +63,7 @@ class Interpreter:
void checkNumberOperand(Token operation, Object operand);
void checkNumberOperands(Token operation, Object left, Object right);
string stringify(Object object);
Object lookUpVariable(Token name, shared_ptr<Variable<Object>> expr);
Object lookUpVariable(Token name, shared_ptr<Expr<Object>> expr);
};

#endif // INTERPRETER_HPP_
7 changes: 7 additions & 0 deletions LoxFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "./Token.hpp"
#include "./ReturnError.hpp"
#include "./LoxFunction.hpp"
#include "./LoxInstance.hpp"

using std::shared_ptr;
using std::vector;
Expand Down Expand Up @@ -47,3 +48,9 @@ Object LoxFunction::call(
string LoxFunction::toString() {
return "<fn " + declaration->name.lexeme + ">";
}

shared_ptr<LoxFunction> LoxFunction::bind(shared_ptr<LoxInstance> instance) {
shared_ptr<Environment> environment(new Environment(closure));
environment->define("this", Object::make_instance_obj(instance));
return shared_ptr<LoxFunction> (new LoxFunction(declaration, environment));
}
1 change: 1 addition & 0 deletions LoxFunction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class LoxFunction: public LoxCallable {
vector<Object> arguments
);

shared_ptr<LoxFunction> bind(shared_ptr<LoxInstance> instance);
string toString();
};

Expand Down
2 changes: 1 addition & 1 deletion LoxInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Object LoxInstance::get(Token name) {

shared_ptr<LoxFunction> method = klass.findMethod(name.lexeme);
if (method != nullptr) {
return Object::make_fun_obj(method);
return Object::make_fun_obj(method->bind(shared_from_this()));
}

throw RuntimeError(name,
Expand Down
3 changes: 2 additions & 1 deletion LoxInstance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
#define LOXINSTANCE_HPP_

#include <string>
#include <memory>
#include <map>
#include "./LoxClass.hpp"
#include "./Token.hpp"

using std::string;
using std::map;

class LoxInstance {
class LoxInstance: public std::enable_shared_from_this<LoxInstance> {
public:
LoxClass klass;
map<string, Object> fields;
Expand Down
4 changes: 4 additions & 0 deletions Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ shared_ptr<Expr<Object>> Parser::primary() {
new Literal<Object>(Object::make_str_obj(previous().literal.str)));
}

if (match({ THIS })) {
return shared_ptr<Expr<Object>>(new This<Object>(previous()));
}

if (match({ IDENTIFIER })) {
return shared_ptr<Expr<Object>>(
new Variable<Object>(previous()));
Expand Down
25 changes: 24 additions & 1 deletion Resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ Object Resolver::visitSetExpr(shared_ptr<Set<Object>> expr) {
return Object::make_nil_obj();
}

Object Resolver::visitThisExpr(shared_ptr<This<Object>> expr) {
if (currentClass == CLASS_NONE) {
lox::error(expr->keyword.line,
"Cannot use 'this' outside of a class.");
return Object::make_nil_obj();
}
resolveLocal(expr, expr->keyword);
return Object::make_nil_obj();
}

void Resolver::visitExpressionStmt(const Expression& stmt) {
resolve(stmt.expression);
}
Expand All @@ -106,13 +116,26 @@ void Resolver::visitBlockStmt(const Block& stmt) {
}

void Resolver::visitClassStmt(const Class& stmt) {
ClassType enclosingClass = currentClass;
currentClass = CLASS;

declare(stmt.name);
define(stmt.name);

beginScope();
auto back = scopes.back();
back["this"] = true;
scopes.pop_back();
scopes.emplace_back(back);

for (auto method : stmt.methods) {
FunctionType declaration = METHOD;
resolveFunction(method, declaration);
}

endScope();

currentClass = enclosingClass;
}

void Resolver::visitIfStmt(const If& stmt) {
Expand All @@ -135,7 +158,7 @@ void Resolver::visitFunctionStmt(shared_ptr<Function> stmt) {
}

void Resolver::visitReturnStmt(const Return& stmt) {
if (currentFunction == NONE) {
if (currentFunction == FUNCTION_NONE) {
lox::error(stmt.name.line, "Cannot return from top-level code.");
}

Expand Down
10 changes: 8 additions & 2 deletions Resolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Resolver:
Object visitCallExpr(shared_ptr<Call<Object>> expr);
Object visitGetExpr(shared_ptr<Get<Object>> expr);
Object visitSetExpr(shared_ptr<Set<Object>> expr);
Object visitThisExpr(shared_ptr<This<Object>> expr);
void visitExpressionStmt(const Expression& stmt);
void visitPrintStmt(const Print& stmt);
void visitVarStmt(const Var& stmt);
Expand All @@ -49,11 +50,16 @@ class Resolver:
void resolve(shared_ptr<Expr<Object>> expr);
private:
enum FunctionType {
NONE,
FUNCTION_NONE,
FUNCTION,
METHOD
};
FunctionType currentFunction = NONE;
enum ClassType {
CLASS_NONE,
CLASS
};
ClassType currentClass = CLASS_NONE;
FunctionType currentFunction = FUNCTION_NONE;
void beginScope();
void endScope();
void declare(Token name);
Expand Down
11 changes: 7 additions & 4 deletions test.lox
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
class Bacon {
eat() {
print "Crunch crunch crunch!";
class Cake {
taste() {
var adjective = "delicious";
print "The " + this.flavor + " cake is " + adjective + "!";
}
}

Bacon().eat();
var cake = Cake();
cake.flavor = "German chocolate";
cake.taste();

0 comments on commit 02bf7d2

Please sign in to comment.