Skip to content

Commit

Permalink
Fixed functions scoping (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdoucy authored Aug 24, 2024
1 parent f11ef76 commit 94e4d84
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 11 deletions.
1 change: 0 additions & 1 deletion inc/ast/visitors/EvalVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ namespace ast
private:
std::ostream &_output;
runtime::Object _expressionResult;
runtime::State::ptr _globalState;
runtime::State::ptr _localState;

const runtime::Object &evaluate(const ast::ExpressionNode::ptr &expr);
Expand Down
20 changes: 17 additions & 3 deletions input.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,29 @@ else if (i == 0)
else
print("i is smaller than 0");

for (int i = 0; i < 5 && i < 10; i = i + 1)
for (int i = 0; i < 5 && i < 10; i = i + 1) {
print(i);
}

fnc print_str(s string) {
fnc print_str(str s) {
print(s);
}

fnc div(int n, int m) int {
fnc print_int() {
print(42);
}
print_int();
return n / m;
}

int r = div(4, 2);
int r = div(4, 2);

print_str("yo");

{
fnc foo() {
print("foo");
}
foo();
}
8 changes: 3 additions & 5 deletions src/ast/visitors/EvalVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,7 @@ void ast::EvalVisitor::clearState() noexcept
ast::EvalVisitor::EvalVisitor(std::ostream &output)
: _output(output),
_expressionResult(),
_globalState(runtime::State::create()),
_localState(runtime::State::create(this->_globalState))
_localState(runtime::State::create())
{}

void ast::EvalVisitor::visit(ast::WhileNode &node)
Expand Down Expand Up @@ -283,8 +282,7 @@ void ast::EvalVisitor::visit(ast::FunctionNode &node)
{
runtime::Object object(node);

// Add function object to global state, so it can be called from anywhere, including functions
this->_globalState->set(node.getIdentifier(), object);
this->_localState->set(node.getIdentifier(), object);
}

void ast::EvalVisitor::visit(ast::CallNode &node)
Expand All @@ -305,7 +303,7 @@ void ast::EvalVisitor::visit(ast::CallNode &node)
// Create a new state for the function.
// function's state takes global state as parent state, so declared functions can be called from the current function
// but variables of the current state cannot be references from current function.
auto state = runtime::State::create(this->_globalState);
auto state = runtime::State::create(this->_localState);

for (std::size_t i = 0; i < params.size(); i++) {
auto evaluatedParam = this->evaluate(params[i]);
Expand Down
60 changes: 58 additions & 2 deletions tst/evaluator/statements_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,15 +374,15 @@ TEST(StatementTest, Functions)
.expectedOutput = "8\n"
},
StatementTest{
.description = "3. Declared function scope should not have access to outer variables",
.description = "3. Declared function scope should have access to outer variables",
.program = "{ "
" int n = 0; "
" fnc f() { "
" print(n); "
" } "
" f(); "
"} ",
.shouldThrow = true
.expectedOutput = "0\n"
},
StatementTest{
.description = "4. Calling a function from a function",
Expand Down Expand Up @@ -526,6 +526,62 @@ TEST(StatementTest, Functions)
"2\n"
"4\n"
"256\n"
},
StatementTest{
.description = "17. Function defined in function",
.program =
"{ "
" fnc div(int n, int m) int { "
" fnc print_int() { "
" print(42); "
" } "
" print_int(); "
" return n / m; "
" } "
" div(4, 2); "
"} ",
.expectedOutput = "42\n"
},
StatementTest{
.description = "18. Function in block",
.program =
"{ "
" { "
" fnc foo() { "
" print(\"foo\"); "
" } "
" foo(); "
" } "
"} ",
.expectedOutput = "foo\n"
},
StatementTest{
.description = "19. Function called outside of scope #1",
.program =
"{ "
" fnc div(int n, int m) int { "
" fnc print_int() { "
" print(42); "
" } "
" return n / m; "
" } "
" div(4, 2); "
" print_int(); "
"} ",
.shouldThrow = true
},
StatementTest{
.description = "20. Function called outside of scope #2",
.program =
"{ "
" { "
" fnc foo() { "
" print(\"foo\"); "
" } "
" } "
" foo(); "
"} ",
.shouldThrow = true
}
};

Expand Down

0 comments on commit 94e4d84

Please sign in to comment.