Skip to content

Commit 23a58f8

Browse files
committed
implement range based for over iterables
1 parent a252990 commit 23a58f8

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

src/pscript/context.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,20 @@ ps::value context::execute(peg::Ast const* node, block_scope* scope, std::string
494494
}
495495
// using for (let i : iterable) syntax
496496
else if (iterable) {
497+
ps::value iterable_val = evaluate_expression(iterable, scope);
498+
if (iterable_val.get_type() != ps::type::list) {
499+
report_error(iterable, fmt::format("In range-for expression: Iterated variable '{}' 'has type '{}', which is not iterable.",
500+
iterable->token_to_string(), type_str(iterable_val.get_type())));
501+
PLIB_UNREACHABLE();
502+
}
497503

504+
ps::list& list = static_cast<ps::list&>(iterable_val);
505+
for (std::size_t i = 0; i < list->size(); ++i) {
506+
block_scope local_scope {};
507+
local_scope.parent = scope;
508+
ps::variable& it = create_variable(identifier->token_to_string(), ps::value::ref(list->get(i)), &local_scope);
509+
execute(compound, &local_scope, namespace_prefix);
510+
}
498511
}
499512
} else { // regular for loop
500513
peg::Ast const* initializer = find_child_with_type(content, "declaration");

tests/main.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,4 +1032,18 @@ TEST_CASE("range-for") {
10321032
ps::script script(source, ctx);
10331033
ctx.execute(script);
10341034
}
1035+
1036+
SECTION("list iteration") {
1037+
std::string source = R"(
1038+
import std.io;
1039+
1040+
let l = [1, 2, 3, 4, 5];
1041+
for (let i : l) {
1042+
std.io.print(i);
1043+
}
1044+
)";
1045+
1046+
ps::script script(source, ctx);
1047+
ctx.execute(script);
1048+
}
10351049
}

0 commit comments

Comments
 (0)