patterns: Added function if statements, improved returns
This commit is contained in:
parent
7f0bdc95da
commit
c9fae32ddf
@ -68,6 +68,7 @@ namespace hex::lang {
|
|||||||
ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node);
|
ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node);
|
||||||
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
|
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
|
||||||
void evaluateFunctionDefinition(ASTNodeFunctionDefinition *node);
|
void evaluateFunctionDefinition(ASTNodeFunctionDefinition *node);
|
||||||
|
std::optional<ASTNode*> evaluateFunctionBody(const std::vector<ASTNode*> &body);
|
||||||
|
|
||||||
PatternData* findPattern(std::vector<PatternData*> currMembers, const ASTNodeRValue::Path &path);
|
PatternData* findPattern(std::vector<PatternData*> currMembers, const ASTNodeRValue::Path &path);
|
||||||
PatternData* evaluateAttributes(ASTNode *currNode, PatternData *currPattern);
|
PatternData* evaluateAttributes(ASTNode *currNode, PatternData *currPattern);
|
||||||
|
@ -73,8 +73,10 @@ namespace hex::lang {
|
|||||||
|
|
||||||
void parseAttribute(Attributable *currNode);
|
void parseAttribute(Attributable *currNode);
|
||||||
ASTNode* parseFunctionDefintion();
|
ASTNode* parseFunctionDefintion();
|
||||||
ASTNode* parseVariableAssignment();
|
ASTNode* parseFunctionStatement();
|
||||||
ASTNode* parseReturnStatement();
|
ASTNode* parseFunctionVariableAssignment();
|
||||||
|
ASTNode* parseFunctionReturnStatement();
|
||||||
|
ASTNode* parseFunctionConditional();
|
||||||
ASTNode* parseConditional();
|
ASTNode* parseConditional();
|
||||||
ASTNode* parseWhileStatement();
|
ASTNode* parseWhileStatement();
|
||||||
ASTNode* parseType(s32 startIndex);
|
ASTNode* parseType(s32 startIndex);
|
||||||
|
@ -480,47 +480,7 @@ namespace hex::lang {
|
|||||||
}
|
}
|
||||||
evaluator.m_currOffset = startOffset;
|
evaluator.m_currOffset = startOffset;
|
||||||
|
|
||||||
for (auto &statement : body) {
|
return evaluator.evaluateFunctionBody(body).value_or(nullptr);
|
||||||
ON_SCOPE_EXIT { evaluator.m_currOffset = startOffset; };
|
|
||||||
|
|
||||||
if (auto functionCallNode = dynamic_cast<ASTNodeFunctionCall*>(statement); functionCallNode != nullptr) {
|
|
||||||
auto result = evaluator.evaluateFunctionCall(functionCallNode);
|
|
||||||
delete result;
|
|
||||||
} else if (auto varDeclNode = dynamic_cast<ASTNodeVariableDecl*>(statement); varDeclNode != nullptr) {
|
|
||||||
auto pattern = evaluator.evaluateVariable(varDeclNode);
|
|
||||||
evaluator.createLocalVariable(varDeclNode->getName(), pattern);
|
|
||||||
} else if (auto assignmentNode = dynamic_cast<ASTNodeAssignment*>(statement); assignmentNode != nullptr) {
|
|
||||||
if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(assignmentNode->getRValue()); numericExpressionNode != nullptr) {
|
|
||||||
auto value = evaluator.evaluateMathematicalExpression(numericExpressionNode);
|
|
||||||
ON_SCOPE_EXIT { delete value; };
|
|
||||||
|
|
||||||
std::visit([&](auto &&value) {
|
|
||||||
evaluator.setLocalVariableValue(assignmentNode->getLValueName(), &value, sizeof(value));
|
|
||||||
}, value->getValue());
|
|
||||||
} else {
|
|
||||||
evaluator.getConsole().abortEvaluation("invalid rvalue used in assignment");
|
|
||||||
}
|
|
||||||
} else if (auto assignmentNode = dynamic_cast<ASTNodeAssignment*>(statement); assignmentNode != nullptr) {
|
|
||||||
if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(assignmentNode->getRValue()); numericExpressionNode != nullptr) {
|
|
||||||
auto value = evaluator.evaluateMathematicalExpression(numericExpressionNode);
|
|
||||||
ON_SCOPE_EXIT { delete value; };
|
|
||||||
|
|
||||||
std::visit([&](auto &&value) {
|
|
||||||
evaluator.setLocalVariableValue(assignmentNode->getLValueName(), &value, sizeof(value));
|
|
||||||
}, value->getValue());
|
|
||||||
} else {
|
|
||||||
evaluator.getConsole().abortEvaluation("invalid rvalue used in assignment");
|
|
||||||
}
|
|
||||||
} else if (auto returnNode = dynamic_cast<ASTNodeReturnStatement*>(statement); returnNode != nullptr) {
|
|
||||||
if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(returnNode->getRValue()); numericExpressionNode != nullptr) {
|
|
||||||
return evaluator.evaluateMathematicalExpression(numericExpressionNode);
|
|
||||||
} else {
|
|
||||||
evaluator.getConsole().abortEvaluation("invalid rvalue used in return statement");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -530,6 +490,68 @@ namespace hex::lang {
|
|||||||
this->m_definedFunctions.insert({ std::string(node->getName()), function });
|
this->m_definedFunctions.insert({ std::string(node->getName()), function });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<ASTNode*> Evaluator::evaluateFunctionBody(const std::vector<ASTNode*> &body) {
|
||||||
|
std::optional<ASTNode*> returnResult;
|
||||||
|
auto startOffset = this->m_currOffset;
|
||||||
|
|
||||||
|
for (auto &statement : body) {
|
||||||
|
ON_SCOPE_EXIT { this->m_currOffset = startOffset; };
|
||||||
|
|
||||||
|
if (auto functionCallNode = dynamic_cast<ASTNodeFunctionCall*>(statement); functionCallNode != nullptr) {
|
||||||
|
auto result = this->evaluateFunctionCall(functionCallNode);
|
||||||
|
delete result;
|
||||||
|
} else if (auto varDeclNode = dynamic_cast<ASTNodeVariableDecl*>(statement); varDeclNode != nullptr) {
|
||||||
|
auto pattern = this->evaluateVariable(varDeclNode);
|
||||||
|
this->createLocalVariable(varDeclNode->getName(), pattern);
|
||||||
|
} else if (auto assignmentNode = dynamic_cast<ASTNodeAssignment*>(statement); assignmentNode != nullptr) {
|
||||||
|
if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(assignmentNode->getRValue()); numericExpressionNode != nullptr) {
|
||||||
|
auto value = this->evaluateMathematicalExpression(numericExpressionNode);
|
||||||
|
ON_SCOPE_EXIT { delete value; };
|
||||||
|
|
||||||
|
std::visit([&](auto &&value) {
|
||||||
|
this->setLocalVariableValue(assignmentNode->getLValueName(), &value, sizeof(value));
|
||||||
|
}, value->getValue());
|
||||||
|
} else {
|
||||||
|
this->getConsole().abortEvaluation("invalid rvalue used in assignment");
|
||||||
|
}
|
||||||
|
} else if (auto returnNode = dynamic_cast<ASTNodeReturnStatement*>(statement); returnNode != nullptr) {
|
||||||
|
if (returnNode->getRValue() == nullptr) {
|
||||||
|
returnResult = nullptr;
|
||||||
|
} else if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(returnNode->getRValue()); numericExpressionNode != nullptr) {
|
||||||
|
returnResult = this->evaluateMathematicalExpression(numericExpressionNode);
|
||||||
|
} else {
|
||||||
|
this->getConsole().abortEvaluation("invalid rvalue used in return statement");
|
||||||
|
}
|
||||||
|
} else if (auto conditionalNode = dynamic_cast<ASTNodeConditionalStatement*>(statement); conditionalNode != nullptr) {
|
||||||
|
if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(conditionalNode->getCondition()); numericExpressionNode != nullptr) {
|
||||||
|
auto condition = this->evaluateMathematicalExpression(numericExpressionNode);
|
||||||
|
|
||||||
|
u32 localVariableStartCount = this->m_localVariables.back()->size();
|
||||||
|
u32 localVariableStackStartSize = this->m_localStack.size();
|
||||||
|
|
||||||
|
if (std::visit([](auto &&value) { return value != 0; }, condition->getValue()))
|
||||||
|
returnResult = this->evaluateFunctionBody(conditionalNode->getTrueBody());
|
||||||
|
else
|
||||||
|
returnResult = this->evaluateFunctionBody(conditionalNode->getFalseBody());
|
||||||
|
|
||||||
|
for (u32 i = localVariableStartCount; i < this->m_localVariables.size(); i++)
|
||||||
|
delete (*this->m_localVariables.back())[i];
|
||||||
|
this->m_localVariables.back()->resize(localVariableStartCount);
|
||||||
|
this->m_localStack.resize(localVariableStackStartSize);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this->getConsole().abortEvaluation("invalid rvalue used in return statement");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnResult.has_value())
|
||||||
|
return returnResult.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
PatternData* Evaluator::evaluateAttributes(ASTNode *currNode, PatternData *currPattern) {
|
PatternData* Evaluator::evaluateAttributes(ASTNode *currNode, PatternData *currPattern) {
|
||||||
auto attributableNode = dynamic_cast<Attributable*>(currNode);
|
auto attributableNode = dynamic_cast<Attributable*>(currNode);
|
||||||
if (attributableNode == nullptr)
|
if (attributableNode == nullptr)
|
||||||
|
@ -388,31 +388,41 @@ namespace hex::lang {
|
|||||||
};
|
};
|
||||||
|
|
||||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||||
ASTNode *statement;
|
body.push_back(this->parseFunctionStatement());
|
||||||
if (MATCHES(sequence(IDENTIFIER, SEPARATOR_ROUNDBRACKETOPEN)))
|
|
||||||
statement = parseFunctionCall();
|
|
||||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN) && sequence<Not>(SEPARATOR_SQUAREBRACKETOPEN)))
|
|
||||||
statement = parseMemberArrayVariable();
|
|
||||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
|
||||||
statement = parseMemberVariable();
|
|
||||||
else if (MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT)))
|
|
||||||
statement = parseVariableAssignment();
|
|
||||||
else if (MATCHES(sequence(KEYWORD_RETURN)))
|
|
||||||
statement = parseReturnStatement();
|
|
||||||
else
|
|
||||||
throwParseError("invalid sequence", 0);
|
|
||||||
|
|
||||||
body.push_back(statement);
|
|
||||||
|
|
||||||
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
|
|
||||||
throwParseError("missing ';' at end of expression", -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyCleanup.release();
|
bodyCleanup.release();
|
||||||
return new ASTNodeFunctionDefinition(functionName, params, body);
|
return new ASTNodeFunctionDefinition(functionName, params, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode* Parser::parseVariableAssignment() {
|
ASTNode* Parser::parseFunctionStatement() {
|
||||||
|
bool needsSemicolon = true;
|
||||||
|
ASTNode *statement;
|
||||||
|
|
||||||
|
if (MATCHES(sequence(IDENTIFIER, SEPARATOR_ROUNDBRACKETOPEN)))
|
||||||
|
statement = parseFunctionCall();
|
||||||
|
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
||||||
|
statement = parseMemberVariable();
|
||||||
|
else if (MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT)))
|
||||||
|
statement = parseFunctionVariableAssignment();
|
||||||
|
else if (MATCHES(sequence(KEYWORD_RETURN)))
|
||||||
|
statement = parseFunctionReturnStatement();
|
||||||
|
else if (MATCHES(sequence(KEYWORD_IF, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||||
|
statement = parseFunctionConditional();
|
||||||
|
needsSemicolon = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throwParseError("invalid sequence", 0);
|
||||||
|
|
||||||
|
if (needsSemicolon && !MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION))) {
|
||||||
|
delete statement;
|
||||||
|
throwParseError("missing ';' at end of expression", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTNode* Parser::parseFunctionVariableAssignment() {
|
||||||
const auto &lvalue = getValue<std::string>(-2);
|
const auto &lvalue = getValue<std::string>(-2);
|
||||||
|
|
||||||
auto rvalue = this->parseMathematicalExpression();
|
auto rvalue = this->parseMathematicalExpression();
|
||||||
@ -420,10 +430,47 @@ namespace hex::lang {
|
|||||||
return new ASTNodeAssignment(lvalue, rvalue);
|
return new ASTNodeAssignment(lvalue, rvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode* Parser::parseReturnStatement() {
|
ASTNode* Parser::parseFunctionReturnStatement() {
|
||||||
|
if (peek(SEPARATOR_ENDOFEXPRESSION))
|
||||||
|
return new ASTNodeReturnStatement(nullptr);
|
||||||
|
else
|
||||||
return new ASTNodeReturnStatement(this->parseMathematicalExpression());
|
return new ASTNodeReturnStatement(this->parseMathematicalExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTNode* Parser::parseFunctionConditional() {
|
||||||
|
auto condition = parseMathematicalExpression();
|
||||||
|
std::vector<ASTNode*> trueBody, falseBody;
|
||||||
|
|
||||||
|
auto cleanup = SCOPE_GUARD {
|
||||||
|
delete condition;
|
||||||
|
for (auto &statement : trueBody)
|
||||||
|
delete statement;
|
||||||
|
for (auto &statement : falseBody)
|
||||||
|
delete statement;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE, SEPARATOR_CURLYBRACKETOPEN))) {
|
||||||
|
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||||
|
trueBody.push_back(parseFunctionStatement());
|
||||||
|
}
|
||||||
|
} else if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) {
|
||||||
|
trueBody.push_back(parseFunctionStatement());
|
||||||
|
} else
|
||||||
|
throwParseError("expected body of conditional statement");
|
||||||
|
|
||||||
|
if (MATCHES(sequence(KEYWORD_ELSE, SEPARATOR_CURLYBRACKETOPEN))) {
|
||||||
|
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||||
|
falseBody.push_back(parseFunctionStatement());
|
||||||
|
}
|
||||||
|
} else if (MATCHES(sequence(KEYWORD_ELSE))) {
|
||||||
|
falseBody.push_back(parseFunctionStatement());
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup.release();
|
||||||
|
|
||||||
|
return new ASTNodeConditionalStatement(condition, trueBody, falseBody);
|
||||||
|
}
|
||||||
|
|
||||||
/* Control flow */
|
/* Control flow */
|
||||||
|
|
||||||
// if ((parseMathematicalExpression)) { (parseMember) }
|
// if ((parseMathematicalExpression)) { (parseMember) }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user