Skip to content

Commit

Permalink
Add return, continue, and break types
Browse files Browse the repository at this point in the history
Add return, continue, and break types
  • Loading branch information
sriharivishnu committed Oct 9, 2020
2 parents e19d097 + 95f1006 commit f2debe6
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 39 deletions.
10 changes: 7 additions & 3 deletions include/Result.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ class TypeException;
struct object;
class identifier {
public:
identifier() = default;;
identifier() = default;
};
using type = std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier>;
struct null {
null() = default;
};
using type = std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier, null>;
struct Result {
public:
explicit Result(type a) : mResult(std::move(a)) {};
Expand Down Expand Up @@ -73,7 +76,8 @@ struct Result {
else if constexpr(std::is_same_v<T, identifier>) return "function";
else if constexpr(std::is_same_v<T, std::shared_ptr<object>>) return "object";
else if constexpr(std::is_same_v<T,std::vector<std::shared_ptr<object>>>) return "list";
else return "null";
else if constexpr(std::is_same_v<T, null>) return "null";
else return "unknown";
}
};
#endif
51 changes: 44 additions & 7 deletions include/Statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,36 @@ class Expression;
struct Context;
using expression_ptr = std::shared_ptr<Expression>;
using shared_obj = std::shared_ptr<object>;

class flow {
public:
enum class type {
SIMPLE,
RETURN,
CONTINUE,
BREAK,
NONE
};
type flow_type;
std::optional<shared_obj> value;
bool isType(type a);
flow(type, shared_obj obj);
flow(type);
};

class statement {
public:
statement() = default;
virtual std::optional<shared_obj> execute(Context& context) {
return {};
virtual flow execute(Context& context) {
return flow(flow::type::NONE);
};
virtual ~statement() = default;
};
using statement_ptr = std::shared_ptr<statement>;

class simple_statement : public statement {
public:
std::optional<shared_obj> execute(Context& context) override;
flow execute(Context& context) override;
simple_statement(expression_ptr expr);
private:
expression_ptr expr;
Expand All @@ -39,7 +56,7 @@ class if_statement : public statement {
std::vector<statement_ptr> elifBlocks,
statement_ptr elseBlock);

std::optional<shared_obj> execute(Context& context) override;
flow execute(Context& context) override;
private:
expression_ptr if_condition;
statement_ptr if_block;
Expand All @@ -54,7 +71,7 @@ class while_statement : public statement {
expression_ptr condition_,
statement_ptr statement_
);
std::optional<shared_obj> execute(Context& context) override;
flow execute(Context& context) override;
private:
expression_ptr condition;
statement_ptr statement;
Expand All @@ -76,9 +93,29 @@ class while_statement : public statement {
class block_statement : public statement {
public:
block_statement(std::vector<statement_ptr> statements);
std::optional<shared_obj> execute(Context& context) override;
flow execute(Context& context) override;
private:
std::vector<statement_ptr> statements;
};


class return_statement : public statement {
public:
return_statement(expression_ptr toReturn);
return_statement();
flow execute(Context& context) override;
private:
std::optional<expression_ptr> toReturn;
};

class break_statement : public statement {
public:
break_statement();
flow execute(Context& context) override;
};

class continue_statement : public statement {
public:
continue_statement();
flow execute(Context& context) override;
};
#endif
5 changes: 3 additions & 2 deletions include/SymbolTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
// class function_statement;
struct object;
struct Result;
struct identifier;
class identifier;
struct null;
using shared_obj = std::shared_ptr<object>;
using natFun = std::function<std::optional<std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier>>(std::vector<shared_obj>)>;
using natFun = std::function<std::optional<std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier, null>>(std::vector<shared_obj>)>;
class SymbolTable {
public:
SymbolTable() {}
Expand Down
1 change: 1 addition & 0 deletions include/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Token {
FUNCTION,
RETURN,
CONTINUE,
BREAK,
ARROW, //->
COMMA, //,
NOT, //!
Expand Down
14 changes: 13 additions & 1 deletion include/nova.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,19 @@ namespace nova {
}
if (!stmt) continue;
try {
std::optional<shared_obj> res = stmt->execute(context);
flow res = stmt->execute(context);
if (res.isType(flow::type::RETURN)) {
throw SyntaxError("No matching function for return");
}
else if (res.isType(flow::type::BREAK)) {
throw SyntaxError("Break called outside of loops or structures");
}
else if (res.isType(flow::type::CONTINUE)) {
throw SyntaxError("Continue called outside of loops or structures");
}
else if (res.isType(flow::type::SIMPLE)) {
std::cout << res.value->get()->toString() << std::endl;
}
// if (res) std::cout << res->get()->toString() << std::endl;
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ struct func_type : object {
std::shared_ptr<statement> toRun;
};

using type = std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier>;
using type = std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier, null>;

struct native_func : object {
native_func(std::string name_, std::function<std::optional<type>(std::vector<shared_obj>)> func_, int numParams);
Expand Down
2 changes: 2 additions & 0 deletions src/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Token Lexer::makeIdentifier() {
else if (value == "fun") return Token(Token::Type::FUNCTION, value, position);
else if (value == "true" || value == "false") return Token(Token::Type::BOOL, value, position);
else if (value == "return") return Token(Token::Type::RETURN, value, position);
else if (value == "break") return Token(Token::Type::BREAK, value, position);
else if (value == "continue") return Token(Token::Type::CONTINUE, value, position);
else if (value == "exit") return Token(Token::Type::EXIT, value, position);
else return Token(Token::Type::IDENTIFIER, value, position);
}
Expand Down
22 changes: 22 additions & 0 deletions src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,28 @@ shared_ptr<statement> Parser::parseStatement() {
stmt = make_shared<block_statement>(statements);
break;
}
case Token::Type::RETURN: {
consume();
if (lookAhead(0).is(Token::Type::STMT_END)) {
stmt = make_shared<return_statement>();
consume();
}
else {
shared_ptr<Expression> toReturn = parseExpression();
stmt = make_shared<return_statement>(toReturn);
}
break;
}
case Token::Type::CONTINUE: {
consume();
stmt = make_shared<continue_statement>();
break;
}
case Token::Type::BREAK: {
consume();
stmt = make_shared<break_statement>();
break;
}
case Token::Type::WHILE: {
consume(Token::Type::WHILE);
consume(Token::Type::LPAREN, ", expected a '('");
Expand Down
60 changes: 47 additions & 13 deletions src/Statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@

#include <utility>
#include "Result.h"
bool flow::isType(type a) {
return flow_type == a;
}
flow::flow(type t, shared_obj obj) : flow_type(t), value(obj) {};
flow::flow(type t) : flow_type(t) {}

std::optional<shared_obj> simple_statement::execute(Context& context) {
flow simple_statement::execute(Context& context) {
Visitor v;
return expr->accept(context, v);
return flow(flow::type::SIMPLE, expr->accept(context, v));
};
simple_statement::simple_statement(std::shared_ptr<Expression> expr_) : expr(std::move(expr_)) {}

Expand All @@ -14,20 +19,30 @@ while_statement::while_statement(
statement_ptr statement_
) : condition(std::move(condition_)), statement(std::move(statement_)) {}

std::optional<shared_obj> while_statement::execute(Context& context) {
flow while_statement::execute(Context& context) {
Visitor v;
while (condition->accept(context, v)->value) {
statement->execute(context);
flow ret = statement->execute(context);
if (ret.isType(flow::type::BREAK)) break;
else if (ret.isType(flow::type::RETURN)) return ret;
}
return {};
return flow(flow::type::NONE);
};

block_statement::block_statement(vector<statement_ptr> statements) : statements(std::move(statements)) {}
std::optional<shared_obj> block_statement::execute(Context& context) {
flow block_statement::execute(Context& context) {
for (auto & statement : statements) {
statement->execute(context);
flow ret = statement->execute(context);
switch(ret.flow_type) {
case flow::type::RETURN:
case flow::type::BREAK:
case flow::type::CONTINUE:
return ret;
default:
continue;
}
}
return {};
return flow(flow::type::NONE);
}

if_statement::if_statement(
Expand All @@ -37,11 +52,9 @@ if_statement::if_statement(
std::vector<statement_ptr> elifBlocks,
statement_ptr elseBlock) : if_condition(std::move(ifCondition)), if_block(std::move(ifBlock)), elif_conditions(std::move(elifConditions)),
elif_blocks(std::move(elifBlocks)), else_block(std::move(elseBlock))
{

}
{}

std::optional<shared_obj> if_statement::execute(Context& context) {
flow if_statement::execute(Context& context) {
Visitor v;
if (if_condition->accept(context, v)->value) {
return if_block->execute(context);
Expand All @@ -54,5 +67,26 @@ std::optional<shared_obj> if_statement::execute(Context& context) {
if (else_block) {
return else_block->execute(context);
}
return {};
return flow(flow::type::NONE);
}
return_statement::return_statement() = default;
return_statement::return_statement(expression_ptr toReturn) : toReturn(toReturn) {}
flow return_statement::execute(Context& context) {
Visitor v;
if (toReturn) {
return flow(flow::type::RETURN, toReturn->get()->accept(context, v));
}
else {
return flow(flow::type::RETURN, std::make_shared<null_type>());
}
}

break_statement::break_statement() = default;
flow break_statement::execute(Context& context) {
return flow(flow::type::BREAK);
}

continue_statement::continue_statement() = default;
flow continue_statement::execute(Context& context) {
return flow(flow::type::CONTINUE);
}
2 changes: 1 addition & 1 deletion src/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ bool SymbolTable::update(const std::string& name, const shared_obj& value) {
void SymbolTable::remove(const std::string& name) {
symbols.erase(name);
}
using type = std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier>;
using type = std::variant<std::string, int, double, std::vector<std::shared_ptr<object>>, identifier, null>;

void SymbolTable::addFunction(const std::string& name, const natFun& func, int numParams) {
shared_obj t = make_shared<native_func>(name, func, numParams);
Expand Down
2 changes: 1 addition & 1 deletion src/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <functional>
#include "nova.h"
#include "stdfuncs.h"
using natFun = std::function<std::optional<std::variant<std::string, int, double, std::vector<shared_obj>, identifier>>(std::vector<shared_obj>)>;
using natFun = std::function<std::optional<std::variant<std::string, int, double, std::vector<shared_obj>, identifier, null>>(std::vector<shared_obj>)>;
int main(int arg_count, char * arg_list[]) {
std::string toRun;
std::string command;
Expand Down
2 changes: 1 addition & 1 deletion src/stdfuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void addStdFunctions(const Context& context) {
res += i->toString();
}
std::cout << std::endl;
return res;
return null();
}, -1);
context.symbols->addFunction("str", [&](std::vector<shared_obj> arg) {
return arg[0]->toString();
Expand Down
23 changes: 14 additions & 9 deletions src/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,16 +493,14 @@ shared_obj func_type::call(Context& parent, vector<shared_obj> args) {
symbols->set(params[i], args[i]);
}
Context child(name, symbols);
std::optional<shared_obj> temp = toRun->execute(child);
if (temp) return *temp;
else return {};
flow temp = toRun->execute(child);
if (temp.value) return *temp.value;
else return std::make_shared<null_type>();
}
std::string func_type::toString() {
return "function <" + name + ">";
}

#undef MAKE_OBJ

std::string null_type::toString() {
return "null";
}
Expand All @@ -524,20 +522,27 @@ shared_obj native_func::call(Context &context, std::vector<shared_obj> args) {
shared_obj ret;
std::visit(overloaded{
[&](std::vector<shared_obj> arg) {
ret = make_shared<list_type>(arg);
ret = MAKE_OBJ(arg, list_type);
},
[&](int arg) {
ret = make_shared<integer_type>(arg);
ret = MAKE_OBJ(arg, integer_type);
},
[&](double arg) {
ret = make_shared<double_type>(arg);
ret = MAKE_OBJ(arg, double_type);
},
[&](std::string arg) {
ret = make_shared<string_type>(arg);
ret = MAKE_OBJ(arg, string_type);
},
[&](null arg) {
ret = std::make_shared<null_type>();
},
[&](auto arg) {
throw Error("Unknown Error", "Unknown return type when running: " + name);
}
}, *got);
return ret;
}


#undef MAKE_OBJ

0 comments on commit f2debe6

Please sign in to comment.