Skip to content

Commit a8890f0

Browse files
committed
evaluator: Optimize rvalue access
Accessing elements of an rvalue array previously required creating a temporary shallow copy of the array or struct entries, which could be unnecessarily slow. This commit eliminates the unnecessary copy by iterating over the elements directly.
1 parent 2f188e7 commit a8890f0

1 file changed

Lines changed: 32 additions & 31 deletions

File tree

lib/source/pl/core/ast/ast_node_rvalue.cpp

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -153,34 +153,18 @@ namespace pl::core::ast {
153153
void ASTNodeRValue::createPatterns(Evaluator *evaluator, std::vector<std::shared_ptr<ptrn::Pattern>> &resultPatterns) const {
154154
[[maybe_unused]] auto context = evaluator->updateRuntime(this);
155155

156-
std::vector<std::shared_ptr<ptrn::Pattern>> searchScope;
157156
std::shared_ptr<ptrn::Pattern> currPattern;
158157
i32 scopeIndex = 0;
159158
bool iterable = true;
160159

161-
if (!evaluator->isGlobalScope()) {
162-
const auto &globalScope = evaluator->getGlobalScope().scope;
163-
std::copy(globalScope->begin(), globalScope->end(), std::back_inserter(searchScope));
164-
}
165-
166-
{
167-
const auto &templateParameters = evaluator->getTemplateParameters();
168-
std::copy(templateParameters.begin(), templateParameters.end(), std::back_inserter(searchScope));
169-
}
170-
171-
{
172-
const auto &currScope = evaluator->getScope(0);
173-
std::copy(currScope.scope->begin(), currScope.scope->end(), std::back_inserter(searchScope));
174-
}
175-
176160
for (const auto &part : this->getPath()) {
177161

178162
if (!iterable)
179163
err::E0001.throwError("Member access of a non-iterable type.", "Try using a struct-like object or an array instead.", this->getLocation());
180164

181165
if (part.index() == 0) {
182166
// Variable access
183-
auto name = std::get<std::string>(part);
167+
const auto &name = std::get<std::string>(part);
184168

185169
if (name == "parent") {
186170
do {
@@ -190,7 +174,6 @@ namespace pl::core::ast {
190174
err::E0003.throwError("Cannot access parent of global scope.", {}, this->getLocation());
191175
} while (evaluator->getScope(scopeIndex).parent == nullptr);
192176

193-
searchScope = *evaluator->getScope(scopeIndex).scope;
194177
auto currParent = evaluator->getScope(scopeIndex).parent;
195178

196179
if (currParent == nullptr) {
@@ -201,8 +184,6 @@ namespace pl::core::ast {
201184

202185
continue;
203186
} else if (name == "this") {
204-
searchScope = *evaluator->getScope(scopeIndex).scope;
205-
206187
auto currParent = evaluator->getScope(0).parent;
207188

208189
if (currParent == nullptr)
@@ -211,22 +192,44 @@ namespace pl::core::ast {
211192
currPattern = currParent;
212193
continue;
213194
} else {
214-
bool found = false;
215-
for (auto iter = searchScope.crbegin(); iter != searchScope.crend(); ++iter) {
216-
if ((*iter)->getVariableName() == name) {
217-
currPattern = *iter;
218-
found = true;
219-
break;
220-
}
195+
using namespace std::views;
196+
using std::ranges::find;
197+
std::shared_ptr<ptrn::Pattern> pattern;
198+
199+
if (currPattern == nullptr) {
200+
auto currScope = *evaluator->getScope(0).scope | all;
201+
auto templateParameters = evaluator->getTemplateParameters() | all;
202+
auto globalScope = *evaluator->getGlobalScope().scope | all;
203+
auto allScopes = {globalScope, templateParameters, currScope};
204+
auto searchScopes = allScopes | drop(evaluator->isGlobalScope() ? 1 : 0);
205+
auto view = searchScopes | join | reverse;
206+
if (auto result = find(view, name, &ptrn::Pattern::getVariableName); result != view.end())
207+
pattern = *result;
208+
} else if (auto currParent = evaluator->getScope(scopeIndex).parent; currParent == currPattern) {
209+
auto view = *evaluator->getScope(scopeIndex).scope | reverse;
210+
if (auto result = find(view, name, &ptrn::Pattern::getVariableName); result != view.end())
211+
pattern = *result;
212+
} else if (auto indexablePattern = dynamic_cast<ptrn::IIndexable *>(currPattern.get()); indexablePattern != nullptr) {
213+
auto iota_view = iota((size_t)0, indexablePattern->getEntryCount());
214+
auto view = iota_view | transform(std::bind_front(&ptrn::IIndexable::getEntry, indexablePattern)) | reverse;
215+
if (auto result = find(view, name, &ptrn::Pattern::getVariableName); result != view.end())
216+
pattern = *result;
217+
} else if (auto iterablePattern = dynamic_cast<ptrn::IIterable *>(currPattern.get()); iterablePattern != nullptr) {
218+
auto scope = iterablePattern->getEntries();
219+
auto view = scope | reverse;
220+
if (auto result = find(view, name, &ptrn::Pattern::getVariableName); result != view.end())
221+
pattern = *result;
221222
}
222223

223224
if (name == "$")
224225
err::E0003.throwError("Invalid use of '$' operator in rvalue.", {}, this->getLocation());
225226
else if (name == "null")
226227
err::E0003.throwError("Invalid use of 'null' keyword in rvalue.", {}, this->getLocation());
227228

228-
if (!found)
229+
if (pattern == nullptr)
229230
err::E0003.throwError(fmt::format("No variable named '{}' found.", name), {}, this->getLocation());
231+
232+
currPattern = std::move(pattern);
230233
}
231234
} else {
232235
// Array indexing
@@ -262,9 +265,7 @@ namespace pl::core::ast {
262265

263266
auto indexPattern = currPattern.get();
264267

265-
if (auto iterablePattern = dynamic_cast<ptrn::IIterable *>(indexPattern); iterablePattern != nullptr)
266-
searchScope = iterablePattern->getEntries();
267-
else
268+
if (auto iterablePattern = dynamic_cast<ptrn::IIterable *>(indexPattern); iterablePattern == nullptr)
268269
iterable = false;
269270

270271
}

0 commit comments

Comments
 (0)