Fix while (turing complete now!)

This commit is contained in:
2025-10-30 12:08:11 +00:00
parent d823ea9019
commit cabfcde970
2 changed files with 51 additions and 6 deletions

View File

@@ -82,6 +82,21 @@ void Executor::printValue(const ASTValue& arg) {
}
}
ASTValue Executor::evaluateCondition(const ASTNode& conditionNode) {
if (std::holds_alternative<std::shared_ptr<ASTOperator>>(conditionNode)) {
return evaluateOperator(std::get<std::shared_ptr<ASTOperator>>(conditionNode));
} else if (std::holds_alternative<std::shared_ptr<ASTValue>>(conditionNode)) {
return *std::get<std::shared_ptr<ASTValue>>(conditionNode);
} else if (std::holds_alternative<std::shared_ptr<ASTIdentifier>>(conditionNode)) {
std::string varName = std::get<std::shared_ptr<ASTIdentifier>>(conditionNode)->name;
if (variables.count(varName) && std::holds_alternative<ASTValue>(variables[varName].value)) {
return std::get<ASTValue>(variables[varName].value);
}
}
std::cout << "Invalid condition" << std::endl;
exit(1);
}
ASTValue Executor::applyOperator(const ASTValue& lhs_in, const ASTValue& rhs_in, OperatorType opType) {
ASTValue left = lhs_in;
ASTValue right = rhs_in;
@@ -327,6 +342,39 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
if (std::holds_alternative<std::shared_ptr<ASTFunctionCall>>(node.value())) {
std::string fnName = std::get<std::shared_ptr<ASTFunctionCall>>(node.value())->func;
std::vector<ASTNode> callArgNodes = std::get<std::shared_ptr<ASTFunctionCall>>(node.value())->args;
if (fnName == "while") {
if (callArgNodes.empty()) {
std::cout << "Expected at least one argument to while statement" << std::endl;
exit(1);
}
ASTNode conditionNode = callArgNodes[0];
std::optional<ASTNode> blockOpt = consume();
if (!blockOpt.has_value() || !std::holds_alternative<std::shared_ptr<ASTCodeBlock>>(blockOpt.value())) {
std::cout << "While statement expects a body" << std::endl;
exit(1);
}
auto block = std::get<std::shared_ptr<ASTCodeBlock>>(blockOpt.value());
while (true) {
ASTValue conditionResult = evaluateCondition(conditionNode);
if (conditionResult.type != ValueType::Bool) {
std::cout << "While condition must be a boolean" << std::endl;
exit(1);
}
if (!conditionResult.getBool().value()) {
break;
}
Executor bodyExecutor(*block, false, variables);
variables = bodyExecutor.getVariables();
}
continue;
}
std::vector<Object> callArgs;
for (auto &callArgNode : callArgNodes) {
if (std::holds_alternative<std::shared_ptr<ASTValue>>(callArgNode)) {
@@ -438,12 +486,8 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
}
if (arg.getBool().value()) {
if (std::holds_alternative<std::shared_ptr<ASTCodeBlock>>(block.value())) {
Executor newExecutor(*std::get<std::shared_ptr<ASTCodeBlock>>(block.value()), false, variables);
for (const auto& [key, value] : newExecutor.getVariables()) {
if (variables.find(key) != variables.end()) {
variables[key] = newExecutor.getVariables()[key];
}
}
Executor bodyExecutor(*std::get<std::shared_ptr<ASTCodeBlock>>(block.value()), false, variables);
variables = bodyExecutor.getVariables();
}
}
} else if (fnName == "while") {

View File

@@ -38,6 +38,7 @@ class Executor {
void printValue(const ASTValue& arg);
ASTValue evaluateOperator(const std::shared_ptr<ASTOperator>& op);
ASTValue applyOperator(const ASTValue& lhs, const ASTValue& rhs, OperatorType opType);
ASTValue evaluateCondition(const ASTNode& conditionNode);
public:
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
std::map<std::string, Object> getVariables();