Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,6 @@ set_property(TEST unresolved_field.frank PROPERTY WILL_FAIL true)
set_property(TEST unresolved_global.frank PROPERTY WILL_FAIL true)
set_property(TEST unresolved_name.frank PROPERTY WILL_FAIL true)
set_property(TEST func_no_return.frank PROPERTY WILL_FAIL true)
set_property(TEST assert_lrc_bad_1.frank PROPERTY WILL_FAIL true)
set_property(TEST assert_lrc_bad_2.frank PROPERTY WILL_FAIL true)
set_property(TEST assert_lrc_bad_3.frank PROPERTY WILL_FAIL true)
80 changes: 80 additions & 0 deletions src/rt/core/builtin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,91 @@ namespace rt::core
});
}

void assert_rc__function_impl(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void assert_rc__function_impl(
void assert_rc_function_impl(

verona::interpreter::FrameObj* frame, size_t args, bool assert_lrc)
{
std::string option;
if (assert_lrc)
{
option = "lrc";
}
else
{
option = "sbrc";
}


if (args != 2)
{
std::stringstream ss;
ss << "assert_" << option << " expected 2 arguments";
ui::error(ss.str());
}

auto count_str = frame->stack_pop("count_str");
auto bridge = frame->stack_pop("bridge");
// Make sure we're comparing the correct LRC value
rt::remove_reference(frame->object(), bridge);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can cause undefined behaviour of the RC hits 0.

if (count_str->get_prototype() != stringPrototypeObject())
{
ui::error("given count is not a string", count_str);
}
auto region = objects::get_region(bridge);
if (region->bridge != bridge)
{
std::stringstream ss;
ss << bridge << " is not the bridge object of the region";
ui::error(ss.str(), bridge);
}
// Remove string object whitespace
auto s = count_str->get_name();
if (s[0] == '\"')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be undefined behaviour, if the string is empty

{
s.erase(0, 1);
s.erase(s.size() - 1);
}
auto count = std::stoi(s);
size_t actual;
if (assert_lrc)
{
actual = rt::objects::get_region(bridge)->local_reference_count;
}
else
{
actual = rt::objects::get_region(bridge)->sub_region_reference_count;
}
if (actual != count)
{
std::stringstream ss;
ss << "count: " << count << " did not match " << option << ": " << actual;
auto msg = ss.str();
ui::error(msg, bridge);
}

rt::remove_reference(frame->object(), count_str);
};

void test_builtins()
{
// Onus is on caller to provide a string object representing an actual integer
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Onus?

// Fixme:
// Refactor once integers are implemented
add_builtin("assert_lrc", [](auto frame, auto args) {
assert_rc__function_impl(frame, args, true);
return std::nullopt;
});
add_builtin("assert_sbrc", [](auto frame, auto args) {
assert_rc__function_impl(frame, args, false);
return std::nullopt;
});
}

void init_builtins(ui::UI* ui)
{
mermaid_builtins(ui);
ctor_builtins();
action_builtins();
pragma_builtins();
test_builtins();
}
}
11 changes: 11 additions & 0 deletions tests/builtin_test/assert_lrc_1.frank
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Feels incorrect to utilize frank-tests for builtins
# that are meant to be utilized for frank-tests...
r1 = Region()
# Give r1 a LRC of 2
a = {}
r1.a = a
# Using string object
expected = "2"
assert_lrc(r1, expected)
# Using string directly
assert_lrc(r1, "2")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert_lrc(r1, "2")
assert_lrc(r1, "2")

Some in the other files

3 changes: 3 additions & 0 deletions tests/builtin_test/assert_lrc_bad_1.frank
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Not a bridge
a = {}
assert_lrc(a, "2")
3 changes: 3 additions & 0 deletions tests/builtin_test/assert_lrc_bad_2.frank
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Not a string
a = {}
assert_lrc(a, a)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first argument should be a bridge

4 changes: 4 additions & 0 deletions tests/builtin_test/assert_lrc_bad_3.frank
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
r1 = Region()
expected = "2"
# LRC is only 1
assert_lrc(r1, expected)
15 changes: 15 additions & 0 deletions tests/regions/merge5.frank
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

r1 = Region()
r2 = Region()
r1.r2 = r2

assert_sbrc(r1, "1")
r2 = None
assert_sbrc(r1, "0")
assert_lrc(r1.r2, "0")

# Edge case where r2 does not contribute to sbrc of r1
# Assure that lrc is unchanged
assert_lrc(r1, "1")
merge(r1.r2, r1)
assert_lrc(r1, "1")
Loading