patterns: Added continue and break statements to arrays of structs

This commit is contained in:
WerWolv 2021-12-30 18:31:24 +01:00
parent 3ce0f8f4a8
commit 0884025b82
2 changed files with 77 additions and 21 deletions

View File

@ -561,7 +561,10 @@ namespace hex::pl {
for (auto &statement : other.m_body) for (auto &statement : other.m_body)
this->m_body.push_back(statement->clone()); this->m_body.push_back(statement->clone());
if (other.m_postExpression != nullptr)
this->m_postExpression = other.m_postExpression->clone(); this->m_postExpression = other.m_postExpression->clone();
else
this->m_postExpression = nullptr;
} }
[[nodiscard]] ASTNode* clone() const override { [[nodiscard]] ASTNode* clone() const override {
@ -974,6 +977,13 @@ namespace hex::pl {
evaluator->handleAbort(); evaluator->handleAbort();
}; };
auto discardEntry = [&] {
delete entries.back();
entries.pop_back();
entryIndex--;
};
if (this->m_size != nullptr) { if (this->m_size != nullptr) {
auto sizeNode = this->m_size->evaluate(evaluator); auto sizeNode = this->m_size->evaluate(evaluator);
ON_SCOPE_EXIT { delete sizeNode; }; ON_SCOPE_EXIT { delete sizeNode; };
@ -990,9 +1000,18 @@ namespace hex::pl {
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
for (u64 i = 0; i < entryCount; i++) { for (u64 i = 0; i < entryCount; i++) {
auto pattern = this->m_type->createPatterns(evaluator).front(); auto patterns = this->m_type->createPatterns(evaluator);
addEntry(pattern); if (!patterns.empty())
addEntry(patterns.front());
auto ctrlFlow = evaluator->getCurrentControlFlowStatement();
if (ctrlFlow == ControlFlowStatement::Break)
break;
else if (ctrlFlow == ControlFlowStatement::Continue) {
discardEntry();
continue;
}
} }
} else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(sizeNode)) { } else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(sizeNode)) {
while (whileStatement->evaluateCondition(evaluator)) { while (whileStatement->evaluateCondition(evaluator)) {
@ -1000,9 +1019,18 @@ namespace hex::pl {
if (entryIndex > limit) if (entryIndex > limit)
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
auto pattern = this->m_type->createPatterns(evaluator).front(); auto patterns = this->m_type->createPatterns(evaluator);
addEntry(pattern); if (!patterns.empty())
addEntry(patterns.front());
auto ctrlFlow = evaluator->getCurrentControlFlowStatement();
if (ctrlFlow == ControlFlowStatement::Break)
break;
else if (ctrlFlow == ControlFlowStatement::Continue) {
discardEntry();
continue;
}
} }
} }
} else { } else {
@ -1011,7 +1039,11 @@ namespace hex::pl {
if (entryIndex > limit) if (entryIndex > limit)
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
auto pattern = this->m_type->createPatterns(evaluator).front(); auto patterns = this->m_type->createPatterns(evaluator);
if (!patterns.empty()) {
auto pattern = patterns.front();
std::vector<u8> buffer(pattern->getSize()); std::vector<u8> buffer(pattern->getSize());
if (evaluator->dataOffset() >= evaluator->getProvider()->getActualSize() - buffer.size()) { if (evaluator->dataOffset() >= evaluator->getProvider()->getActualSize() - buffer.size()) {
@ -1021,6 +1053,14 @@ namespace hex::pl {
addEntry(pattern); addEntry(pattern);
auto ctrlFlow = evaluator->getCurrentControlFlowStatement();
if (ctrlFlow == ControlFlowStatement::Break)
break;
else if (ctrlFlow == ControlFlowStatement::Continue) {
discardEntry();
continue;
}
evaluator->getProvider()->read(evaluator->dataOffset() - pattern->getSize(), buffer.data(), buffer.size()); evaluator->getProvider()->read(evaluator->dataOffset() - pattern->getSize(), buffer.data(), buffer.size());
bool reachedEnd = true; bool reachedEnd = true;
for (u8 &byte : buffer) { for (u8 &byte : buffer) {
@ -1033,6 +1073,7 @@ namespace hex::pl {
if (reachedEnd) break; if (reachedEnd) break;
} }
} }
}
arrayPattern->setEntries(entries); arrayPattern->setEntries(entries);
arrayPattern->setSize(size); arrayPattern->setSize(size);
@ -2044,7 +2085,11 @@ namespace hex::pl {
ASTNodeControlFlowStatement(const ASTNodeControlFlowStatement &other) : ASTNode(other) { ASTNodeControlFlowStatement(const ASTNodeControlFlowStatement &other) : ASTNode(other) {
this->m_type = other.m_type; this->m_type = other.m_type;
if (other.m_rvalue != nullptr)
this->m_rvalue = other.m_rvalue->clone(); this->m_rvalue = other.m_rvalue->clone();
else
this->m_rvalue = nullptr;
} }
[[nodiscard]] ASTNode* clone() const override { [[nodiscard]] ASTNode* clone() const override {
@ -2059,6 +2104,13 @@ namespace hex::pl {
return this->m_rvalue; return this->m_rvalue;
} }
[[nodiscard]] std::vector<PatternData*> createPatterns(Evaluator *evaluator) const override {
this->execute(evaluator);
return { };
}
FunctionResult execute(Evaluator *evaluator) const override { FunctionResult execute(Evaluator *evaluator) const override {
auto returnValue = this->getReturnValue(); auto returnValue = this->getReturnValue();

View File

@ -880,6 +880,10 @@ namespace hex::pl {
return parseConditional(); return parseConditional();
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM))) else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
throwParseError("unexpected end of program", -2); throwParseError("unexpected end of program", -2);
else if (MATCHES(sequence(KEYWORD_BREAK)))
member = new ASTNodeControlFlowStatement(ControlFlowStatement::Break, nullptr);
else if (MATCHES(sequence(KEYWORD_CONTINUE)))
member = new ASTNodeControlFlowStatement(ControlFlowStatement::Continue, nullptr);
else else
throwParseError("invalid struct member", 0); throwParseError("invalid struct member", 0);