1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 05:48:12 +00:00

Shell: Implement for_each_entry() for syntactic list nodes

This allows correct iteration over nested lists.
Also store values to variables without resolving them, to delay the
resolution step as much as possible (this helps with storing nested
lists in variables).
This commit is contained in:
AnotherTest 2021-01-18 04:36:19 +03:30 committed by Andreas Kling
parent fc7a06af9d
commit 1c78d12f1c
2 changed files with 24 additions and 10 deletions

View file

@ -390,6 +390,17 @@ RefPtr<Value> ListConcatenate::run(RefPtr<Shell> shell)
return result;
}
void ListConcatenate::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(NonnullRefPtr<Value>)> callback)
{
for (auto& entry : m_list) {
auto value = entry->run(shell);
if (!value)
continue;
if (callback(value.release_nonnull()) == IterationDecision::Break)
break;
}
}
void ListConcatenate::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
{
auto first = metadata.is_first_in_list;
@ -694,6 +705,12 @@ RefPtr<Value> CastToList::run(RefPtr<Shell> shell)
return create<ListValue>(cast_values);
}
void CastToList::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(NonnullRefPtr<Value>)> callback)
{
if (m_inner)
m_inner->for_each_entry(shell, move(callback));
}
void CastToList::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
{
if (m_inner)
@ -1046,7 +1063,7 @@ FunctionDeclaration::~FunctionDeclaration()
void ForLoop::dump(int level) const
{
Node::dump(level);
print_indented(String::format("%s in\n", m_variable_name.characters()), level + 1);
print_indented(String::format("%s in", m_variable_name.characters()), level + 1);
if (m_iterated_expression)
m_iterated_expression->dump(level + 2);
else
@ -1075,6 +1092,9 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell)
return IterationDecision::Continue;
}
if (!shell->has_error(Shell::ShellError::None))
return IterationDecision::Break;
if (block_value->is_job()) {
auto job = static_cast<JobValue*>(block_value.ptr())->job();
if (!job || job->is_running_in_background())
@ -2855,15 +2875,7 @@ RefPtr<Value> VariableDeclarations::run(RefPtr<Shell> shell)
ASSERT(name_value.size() == 1);
auto name = name_value[0];
auto value = var.value->run(shell);
if (value->is_list()) {
auto parts = value->resolve_as_list(shell);
shell->set_local_variable(name, adopt(*new ListValue(move(parts))));
} else if (value->is_command()) {
shell->set_local_variable(name, value);
} else {
auto part = value->resolve_as_list(shell);
shell->set_local_variable(name, adopt(*new StringValue(part[0])));
}
shell->set_local_variable(name, value.release_nonnull());
}
return create<ListValue>({});