Skip to content

Commit

Permalink
Merge pull request #23 from sriharivishnu/for-loops
Browse files Browse the repository at this point in the history
For loops + bug fixes + v0.3.0
  • Loading branch information
sriharivishnu committed Oct 10, 2020
2 parents 113accd + 295386e commit 92098ce
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 44 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
AC_PREREQ(2.50)

AC_INIT(nova, 0.2.0, srihari.vishnu@gmail.com)
AC_INIT(nova, 0.3.0, srihari.vishnu@gmail.com)

# Define where autogenerated build files such as 'missing'
# should be located. This is also the location of any additional
Expand Down
18 changes: 18 additions & 0 deletions examples/test.nov
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@


fun getFibonacci(n) {
var arr = [];
if (n < 0) {
return [];
}
for i in (0,n) {
if (i == 0 || i == 1) arr.add(i);
else {
arr.add(arr[i-1] + arr[i-2]);
}
}
return arr;
};

print (getFibonacci(10));

1 change: 1 addition & 0 deletions include/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ using symbol_table = std::shared_ptr<SymbolTable>;
struct Context {
Context() {};
Context(std::string _name, symbol_table _symbols) : name(_name), parent(nullptr), symbols(_symbols) {}
Context(std::string _name, std::shared_ptr<Context> _parent, symbol_table _symbols) : name(_name), parent(_parent), symbols(_symbols) {}
Context(std::string _name, std::shared_ptr<Context> _parent, Position& _entry_pos, symbol_table _symbols)
: name(_name), entry_pos(_entry_pos), parent(_parent), symbols(_symbols) {}
std::string name;
Expand Down
12 changes: 10 additions & 2 deletions include/Result.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,22 @@ struct Result {
using T = std::decay_t<decltype(arg)>;
if constexpr(std::is_same_v<T, int>) return std::get<int>(mResult);
else if constexpr(std::is_same_v<T, std::string>) {
if (std::get<std::string>(mResult).empty()) {
if (!std::get<std::string>(mResult).empty()) {
return 1;
} else return 0;
}
else if (std::is_same_v<T, std::vector<std::shared_ptr<object>>>) {
if (!std::get<std::vector<std::shared_ptr<object>>>(mResult).empty()) return 1;
else return 0;
}
else if constexpr(std::is_same_v<T, double>) {
if (std::get<double>(mResult) != 0) return 1; else return 0;
}
return 0;
else if constexpr(std::is_same_v<T, null>) {
return 0;
}

return 1;
}, mResult);
}

Expand Down
28 changes: 17 additions & 11 deletions include/Statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,24 @@ class while_statement : public statement {
statement_ptr statement;
};

// class for_statement : public statement {
// public:
// for_statement(

// );
// std::optional<Result> execute(Context& context) override;
// private:
// Token identifier;
// expression_ptr start;
// expression_ptr end;
class for_statement : public statement {
public:
for_statement(
Token identifier,
expression_ptr start,
expression_ptr end,
statement_ptr toRun,
expression_ptr step = nullptr
);
flow execute(Context& context) override;
private:
Token identifier;
expression_ptr start;
expression_ptr end;
expression_ptr step;
statement_ptr toRun;

// };
};

class block_statement : public statement {
public:
Expand Down
1 change: 1 addition & 0 deletions include/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Token {
ELSE,
WHILE,
FOR,
IN,
COLON,//:
VAR,
STMT_END,
Expand Down
4 changes: 2 additions & 2 deletions include/nova.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#include "Token.h"
#include "Context.h"
namespace nova {
int run(const std::string& command, Context& context, bool shell = false) {
Lexer lex("main", command.c_str());
int run(const std::string& command, Context& context, bool shell = false, std::string fileName = "main") {
Lexer lex(fileName, command.c_str());
std::vector<Token> a;
try {
a = lex.getTokens();
Expand Down
1 change: 1 addition & 0 deletions include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct object {
virtual shared_obj preNot();
virtual shared_obj dot(const std::string& name, const std::vector<shared_obj>& args);
virtual shared_obj call(Context& context, std::vector<shared_obj> args);
// virtual shared_obj iterate(statement_ptr toRun);
virtual std::string toString();

template <typename T>
Expand Down
Binary file removed nova-0.2.0.tar.gz
Binary file not shown.
Binary file added nova-0.3.0.tar.gz
Binary file not shown.
1 change: 1 addition & 0 deletions src/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Token Lexer::makeIdentifier() {
else if (value == "else") return Token(Token::Type::ELSE, value, position);
else if (value == "while") return Token(Token::Type::WHILE, value, position);
else if (value == "for") return Token(Token::Type::FOR, value, position);
else if (value == "in") return Token(Token::Type::IN, value, position);
else if (value == "var") return Token(Token::Type::VAR, value, position);
else if (value == "fun") return Token(Token::Type::FUNCTION, value, position);
else if (value == "true" || value == "false") return Token(Token::Type::BOOL, value, position);
Expand Down
25 changes: 24 additions & 1 deletion src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,34 @@ shared_ptr<statement> Parser::parseStatement() {
stmt = make_shared<while_statement>(condition, statement);
break;
}

case Token::Type::FOR: {
consume(Token::Type::FOR);
Token identifier = consume(Token::Type::IDENTIFIER, ", expected an identifier");
consume(Token::Type::IN, ", expected 'in'");
if (lookAhead(0).is(Token::Type::LPAREN)) {
consume();
shared_ptr<Expression> start = parseExpression();
consume(Token::Type::COMMA, ", expected ','");
shared_ptr<Expression> end = parseExpression();
shared_ptr<Expression> step = nullptr;
if (lookAhead(0).is(Token::Type::COMMA)) {
consume();
step = parseExpression();
}
consume(Token::Type::RPAREN, ", expected ')'");
shared_ptr<statement> toRun = parseStatement();
stmt = make_shared<for_statement>(identifier, start, end, toRun, step);
}
else {
throw SyntaxError(lookAhead(0).startPos, "Unexpected token in for loop");
}
break;
}
default: {
shared_ptr<Expression> expression = parseExpression();
stmt = make_shared<simple_statement>(expression);
ENSURE_END
if (lookAhead(0).is(Token::Type::STMT_END)) consume();
break;
}

Expand Down
44 changes: 44 additions & 0 deletions src/Statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,50 @@ flow while_statement::execute(Context& context) {
return flow(flow::type::NONE);
};

for_statement::for_statement(
Token identifier_,
expression_ptr start_,
expression_ptr end_,
statement_ptr toRun_,
expression_ptr step_
) : identifier(identifier_), start(start_), end(end_), toRun(toRun_), step(step_)
{}
flow for_statement::execute(Context& parent) {
Visitor v;
std::shared_ptr<SymbolTable> symbols = make_shared<SymbolTable>(parent.symbols);
Context context(parent.name, symbols);
shared_obj start_obj = start->accept(parent, v);
shared_obj end_obj = end->accept(parent, v);
if (!start_obj->value.isType<int>() || !end_obj->value.isType<int>()) {
throw Error("Type Exception", "Expected an integer type in for loop iterator");
}
int inc = 1;
if (step) {
shared_obj step_obj = step->accept(context, v);
if (!step_obj->value.isType<int>()) {
throw Error("Type Exception", "Expected an integer type in for loop iterator");
}
inc = step_obj->getValue<int>();
}
if (start_obj->getValue<int>() <= end_obj->getValue<int>()) {
for (int i = start_obj->getValue<int>(); i >= start_obj->getValue<int>() && i < end_obj->getValue<int>(); i += inc) {
symbols->set(identifier.getValue(), make_shared<integer_type>(i));
flow ret = toRun->execute(context);
if (ret.isType(flow::type::BREAK)) break;
else if (ret.isType(flow::type::RETURN)) return ret;
}
}
else {
for (int i = start_obj->getValue<int>(); i <= start_obj->getValue<int>() && i > end_obj->getValue<int>(); i += inc) {
symbols->set(identifier.getValue(), make_shared<integer_type>(i));
flow ret = toRun->execute(context);
if (ret.isType(flow::type::BREAK)) break;
else if (ret.isType(flow::type::RETURN)) return ret;
}
}
return flow(flow::type::NONE);
}

block_statement::block_statement(vector<statement_ptr> statements) : statements(std::move(statements)) {}
flow block_statement::execute(Context& context) {
for (auto & statement : statements) {
Expand Down
2 changes: 1 addition & 1 deletion src/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int main(int arg_count, char * arg_list[]) {
}
myfile.close();
} else {
std::cout << "Could not open file";
std::cout << "Could not open file " << arg_list[1] << std::endl;
}
nova::run(toRun, global, false);
}
Expand Down
26 changes: 0 additions & 26 deletions test.nov

This file was deleted.

0 comments on commit 92098ce

Please sign in to comment.