Skip to content

Commit

Permalink
update(test): add tests to interpereter
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohith-Raju committed Apr 13, 2024
1 parent f63b475 commit 4bf7d9d
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 29 deletions.
2 changes: 2 additions & 0 deletions include/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class Interpreter {
bool checkCompatibility(Token *op, Object left, Object right);

public:
bool isBreakUsed = false;

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

void visitPrintStmnt(Print *stmnt);
Expand Down
4 changes: 4 additions & 0 deletions include/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class Parser {
};
std::vector<Token> tokens;
int current = 0;
// loopCounter to determine if "break" is valid or not. (break should only
// occur in loops)
int loopCounter = 0;

// Precidence
Expr *Or();
Expand All @@ -35,6 +38,7 @@ class Parser {
Statement *ifStatement();
Statement *whileStatement();
Statement *forStatement();
Statement *breakStatement();
Statement *expressionStatement();
std::vector<Statement *> blockStatement();

Expand Down
9 changes: 8 additions & 1 deletion include/Statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ enum Statement_type {
StmntVar_type,
StmntBlock_type,
StmntIf_type,
StmntWhile_type
StmntWhile_type,
StmntBreak_type
};

class Statement {
Expand Down Expand Up @@ -69,4 +70,10 @@ class While : public Statement {
~While();
};

class Break : public Statement {
public:
bool isBreakPresent = false;
Break(bool breakSet);
};

#endif
1 change: 1 addition & 0 deletions include/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum TokenType {
TRUE,
VAR,
WHILE,
BREAK,

ENDOFFILE
};
Expand Down
12 changes: 7 additions & 5 deletions src/Interpreter.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
//
// Created by Rohith on 3/17/24
//

#include "Interpreter.h"
#include "Error.h"
Expand Down Expand Up @@ -33,6 +31,8 @@ void Interpreter::excecute(Statement *stmnt) {
case StmntWhile_type:
visitWhileStmnt((While *)stmnt);
break;
case StmntBreak_type:
isBreakUsed = true;
}
}

Expand Down Expand Up @@ -135,10 +135,12 @@ void Interpreter::visitIfStmnt(If *stmnt) {
}

void Interpreter::visitWhileStmnt(While *stmnt) {
while (isTruthy(evaluate(stmnt->condition)))
while (isTruthy(evaluate(stmnt->condition))) {
excecute(stmnt->body);
if (isBreakUsed)
break;
}
}

void Interpreter::visitBlockStmnt(Block *stmnt) {
excecuteBlock(stmnt->stmnt, new Environment(environment));
}
Expand Down Expand Up @@ -191,7 +193,7 @@ Object Interpreter::visitUnaryExp(Unary *expr) {
checkNumberOperand(expr->op, right);
return -right.num_literal;
default:
RuntimeError(*expr->op, "Invalid operator used");
throw RuntimeError(*expr->op, "Invalid operator used");
}
return Object();
}
Expand Down
19 changes: 16 additions & 3 deletions src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Statement *Parser::statement() {
return whileStatement();
if (match(FOR))
return forStatement();
if (match(BREAK))
return breakStatement();
if (match(LEFT_BRACE))
return new Block(blockStatement());
return expressionStatement();
Expand Down Expand Up @@ -83,10 +85,12 @@ Statement *Parser::ifStatement() {
}

Statement *Parser::whileStatement() {
consume(LEFT_PAREN, "expected ( after while");
consume(LEFT_PAREN, "Expected ( after while");
Expr *expr = expression();
consume(RIGHT_PAREN, "expected ) after while");
consume(RIGHT_PAREN, "Expected ) after while");
loopCounter++;
Statement *body = statement();
loopCounter--;
return new While(expr, body);
}

Expand Down Expand Up @@ -115,7 +119,7 @@ Statement *Parser::forStatement() {
else
increment = expression();

consume(RIGHT_PAREN, "expected ) after clause");
consume(RIGHT_PAREN, "Expected ) after clause");

Statement *body;
body = statement();
Expand All @@ -141,6 +145,15 @@ Statement *Parser::forStatement() {
return body;
}

Statement *Parser::breakStatement() {
if (loopCounter == 0) {
Token tkn = tokens[current];
crux::error(tkn, "break should ony occur in for/while loops");
}
consume(SEMICOLON, "Expected ';' after 'break'.");
return new Break(true);
}

Statement *Parser::printStatement() {
Expr *expr = expression();
consume(SEMICOLON, "Expected ; at the end of the statement");
Expand Down
1 change: 1 addition & 0 deletions src/Scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,5 @@ void tkn::initializeKeywords() {
keywords["true"] = TRUE;
keywords["var"] = VAR;
keywords["while"] = WHILE;
keywords["break"] = BREAK;
}
3 changes: 3 additions & 0 deletions src/Statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ While::~While() {
delete condition;
delete body;
}

Break::Break(bool isBrkPre)
: Statement(StmntBreak_type), isBreakPresent(isBrkPre) {}
57 changes: 38 additions & 19 deletions test/TestInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,70 @@
#include "Scanner.h"
#include "gtest/gtest.h"
#include <Statement.h>
#include <iostream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <vector>

TEST(InterpreterTest, TestInterpreterFlow) {
TEST(InterpreterTest, TestInterpreterExpression) {
std::string test = "10 + (40 + (20 - 30) - 10) + 50;";
Scanner scan(test);
std::vector<Token> tokens = scan.scanTokens();
Parser p(tokens);
std::vector<Statement *> statements = p.parse();
// ASSERT_EQ(Interpreter{}.interpret(statements), "80.000000");
testing::internal::CaptureStdout();
Interpreter{}.interpret(statements);
std::string result = testing::internal::GetCapturedStdout();
ASSERT_EQ(result, "80.000000\n");
}

TEST(InterpreterTest, TestInterpreterUnary) {
TEST(InterpreterTest, TestInterpreterUnaryExpression) {
std::string test = "!true;";
Scanner scan(test);
std::vector<Token> tokens = scan.scanTokens();
Parser p(tokens);
std::vector<Statement *> statements = p.parse();
// ASSERT_EQ(Interpreter{}.interpret(statements), "false");
testing::internal::CaptureStdout();
Interpreter{}.interpret(statements);
std::string result = testing::internal::GetCapturedStdout();
ASSERT_EQ(result, "false\n");
}

TEST(InterpreterTest, TestParserTernary) {
TEST(InterpreterTest, TestParserTernaryExpression) {
std::string test = "3 > 1 ? true : false;";
Scanner scan(test);
std::vector<Token> tokens = scan.scanTokens();
Parser p(tokens);
std::vector<Statement *> statements = p.parse();
// ASSERT_EQ(Interpreter{}.interpret(statements), "true");
testing::internal::CaptureStdout();
Interpreter{}.interpret(statements);
std::string result = testing::internal::GetCapturedStdout();
ASSERT_EQ(result, "true\n");
}

TEST(IntrepreterTest, TestStringNumExpressions) {
std::string test1 = "\"test\"+8;";
std::string test2 = "8+\"test\";";
TEST(InterpreterTest, TestInterpreterVarStatement) {

Scanner scan1(test1);
Scanner scan2(test2);
std::vector<Token> tokens1 = scan1.scanTokens();
std::vector<Token> tokens2 = scan2.scanTokens();
std::string test = "var a = 10; print(a);";
std::string test_f = "a = 10"; // fails

Parser p1(tokens1);
Parser p2(tokens2);
Scanner scan(test);
Scanner scan_f(test_f);

std::vector<Token> token = scan.scanTokens();
std::vector<Token> token_f = scan_f.scanTokens();

Parser parser(token);
Parser parser_f(token_f);

std::vector<Statement *> statement = parser.parse();

std::vector<Statement *> statements1 = p1.parse();
std::vector<Statement *> statements2 = p2.parse();
std::stringstream buffer;
std::streambuf *sbuf = std::cout.rdbuf();
std::cout.rdbuf(buffer.rdbuf());
Interpreter{}.interpret(statement);
std::cout.rdbuf(sbuf);
ASSERT_EQ(buffer.str(), "10.000000\n");

// ASSERT_EQ(Interpreter{}.interpret(statements1), "test8.000000");
// ASSERT_EQ(Interpreter{}.interpret(statements2), "8.000000test");
EXPECT_THROW(parser_f.parse(), std::runtime_error);
}
2 changes: 1 addition & 1 deletion test/lib
Submodule lib updated 1 files
+8 −9 docs/primer.md

0 comments on commit 4bf7d9d

Please sign in to comment.