Skip to content

Commit

Permalink
support function declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
rapiz1 committed Oct 30, 2021
1 parent 5da6cec commit 7caa750
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 14 deletions.
10 changes: 9 additions & 1 deletion ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void EvalVisitor::visit(Binary* expr) {
Boolean* b1 = dynamic_cast<Boolean*>(v1.value);
Boolean* b2 = dynamic_cast<Boolean*>(v2.value);
Variable* lv = dynamic_cast<Variable*>(expr->left);
Expr* rv = v2.value;
Literal* rv = v2.value;
switch (expr->op.tokenType) {
case PLUS:
if (n1 && n2) {
Expand Down Expand Up @@ -182,6 +182,14 @@ void ExecVisitor::visit(VarDecl* s) {
context.define(s->identifier, v.getValue());
}

void ExecVisitor::visit(FunDecl* s) {
if (context.count(s->identifier)) {
std::cerr << "redefine function " << s->identifier;
exit(-1);
}
context.define(s->identifier, new Function(s));
}

void ExecVisitor::visit(BlockStmt* s) {
ExecVisitor v = wrap();
for (auto d : s->decls) {
Expand Down
34 changes: 34 additions & 0 deletions ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Variable;

class Declaration;
class VarDecl;
class FunDecl;

class Statement;
class PrintStmt;
Expand All @@ -31,6 +32,7 @@ class DeclVisitor {
virtual void visit(ExprStmt* st) = 0;
virtual void visit(PrintStmt* st) = 0;
virtual void visit(VarDecl* d) = 0;
virtual void visit(FunDecl* d) = 0;
virtual void visit(BlockStmt* d) = 0;
virtual void visit(IfStmt* d) = 0;
virtual void visit(WhileStmt* d) = 0;
Expand All @@ -50,6 +52,7 @@ class ExecVisitor : public DeclVisitor {
virtual void visit(ExprStmt* st) override;
virtual void visit(PrintStmt* st) override;
virtual void visit(VarDecl* d) override;
virtual void visit(FunDecl* d) override;
virtual void visit(BlockStmt* d) override;
virtual void visit(IfStmt* d) override;
virtual void visit(WhileStmt* d) override;
Expand Down Expand Up @@ -197,6 +200,22 @@ class VarDecl : public Declaration {
friend class ExecVisitor;
};

typedef std::vector<Token> Args;
class FunDecl : public Declaration {
protected:
std::string identifier;
Args args;
BlockStmt* body;

public:
FunDecl(std::string id, Args args, BlockStmt* body)
: identifier(id), args(args), body(body){};
operator std::string() override { return "function " + identifier; };

void accept(DeclVisitor* v) { v->visit(this); }
friend class ExecVisitor;
};

class Binary : public Expr {
protected:
Expr* left;
Expand Down Expand Up @@ -277,6 +296,21 @@ class Boolean : public Literal {
void accept(ExprVisitor* v) { v->visit(this); }
friend class EvalVisitor;
};

class Function : public Literal {
protected:
FunDecl* fun;

public:
Function(FunDecl* fun) : fun(fun){};
operator std::string() { return std::string(*fun); };

bool isTruthy() { return fun != nullptr; }

void accept(ExprVisitor* v) { v->visit(this); }
friend class EvalVisitor;
};

class Variable : public Expr {
protected:
std::string name;
Expand Down
16 changes: 8 additions & 8 deletions context.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@
#include <memory>
#include <string>

class Expr;
class Literal;
enum class ReturnReason { NORMAL, RETURN, BREAK, CONTINUE };
class ExecContext {
ExecContext* parent;
typedef std::map<std::string, Expr*> Rec;
std::shared_ptr<Rec> rec;
typedef std::map<std::string, Literal*> VarRec;
std::shared_ptr<VarRec> varRec;
ReturnReason* reason;

bool localCount(std::string);
void setOrCreateVar(std::string, Expr* expr);
void setOrCreateVar(std::string, Literal* expr);

public:
ExecContext(ExecContext* parent = nullptr, ReturnReason* reason = nullptr)
: parent(parent), reason(reason) {
rec = std::make_shared<Rec>();
varRec = std::make_shared<VarRec>();
}

bool count(std::string);

void define(std::string, Expr* expr);
void set(std::string, Expr* expr);
Expr* get(std::string);
void define(std::string, Literal* expr);
void set(std::string, Literal* expr);
Literal* get(std::string);

void setReason(ReturnReason r);
ReturnReason getReason();
Expand Down
33 changes: 33 additions & 0 deletions parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Declaration* Parser::decl() {
d = varDecl();
break;

case FUNCTION:
d = funDecl();
break;

default:
d = stmt();
break;
Expand Down Expand Up @@ -229,6 +233,35 @@ VarDecl* Parser::varDecl() {
return s;
}

Args Parser::args() {
Args args;

args.push_back(consume(IDENTIFIER, "Expect an identifier"));
while (match(1, COMMA)) {
advance();
args.push_back(consume(IDENTIFIER, "Expect an identifier"));
}

return args;
}

FunDecl* Parser::funDecl() {
consume(FUNCTION, "Expect a `function` declaration");
Token id = consume(IDENTIFIER, "Expect an identifier for function name");
consume(LEFT_PAREN, "Expect `(` as argument list begins");

Args a;
if (!match(1, RIGHT_PAREN)) {
a = args();
}

consume(RIGHT_PAREN, "Expect `)` as argument list ends");

BlockStmt* b = blockStmt();

return new FunDecl(id.lexeme, a, b);
}

Expr* Parser::expression() { return assignment(); }

Expr* Parser::assignment() {
Expand Down
2 changes: 2 additions & 0 deletions parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class Parser {
BlockStmt* forStmt(); // FOR '(' VAR_DECL EXPRESSION; EXPRESSION ')'
WhileStmt* whileStmt(); // WHILE '(' EXPRESSION ')' STMT
VarDecl* varDecl(); // VAR IDENTIFIER (EQUAL EXPRESSION)? ;
FunDecl* funDecl(); // FUN IDENTIFIER '(' ARGS? ')' BLOCK
Args args(); // ID (, ID)*

Expr* expression();
Expr* assignment();
Expand Down
9 changes: 5 additions & 4 deletions testfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
function printOne() {
print 1;
}
print "loop begins!";
for (var i = 0; i != 3; i = i + 1)
print i;
for (var i = 0; i < 10; i = i + 1) {
print i*i;
if (i*i > 10) {
print "wow big";
{
if (i*i>50) break;
}
}
2 changes: 1 addition & 1 deletion token.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enum TokenType {
CLASS,
ELSE,
FALSE,
FUN,
FUNCTION,
FOR,
IF,
NIL,
Expand Down

0 comments on commit 7caa750

Please sign in to comment.