From cabfcde97041ceb22f76fa2bbd7b83472d8d9db3 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Thu, 30 Oct 2025 12:08:11 +0000 Subject: [PATCH] Fix while (turing complete now!) --- src/runner/runner.cpp | 56 ++++++++++++++++++++++++++++++++++++++----- src/runner/runner.h | 1 + 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/runner/runner.cpp b/src/runner/runner.cpp index 283037c..821e3ad 100644 --- a/src/runner/runner.cpp +++ b/src/runner/runner.cpp @@ -82,6 +82,21 @@ void Executor::printValue(const ASTValue& arg) { } } +ASTValue Executor::evaluateCondition(const ASTNode& conditionNode) { + if (std::holds_alternative>(conditionNode)) { + return evaluateOperator(std::get>(conditionNode)); + } else if (std::holds_alternative>(conditionNode)) { + return *std::get>(conditionNode); + } else if (std::holds_alternative>(conditionNode)) { + std::string varName = std::get>(conditionNode)->name; + if (variables.count(varName) && std::holds_alternative(variables[varName].value)) { + return std::get(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>(node.value())) { std::string fnName = std::get>(node.value())->func; std::vector callArgNodes = std::get>(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 blockOpt = consume(); + if (!blockOpt.has_value() || !std::holds_alternative>(blockOpt.value())) { + std::cout << "While statement expects a body" << std::endl; + exit(1); + } + auto block = std::get>(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 callArgs; for (auto &callArgNode : callArgNodes) { if (std::holds_alternative>(callArgNode)) { @@ -438,12 +486,8 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map>(block.value())) { - Executor newExecutor(*std::get>(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>(block.value()), false, variables); + variables = bodyExecutor.getVariables(); } } } else if (fnName == "while") { diff --git a/src/runner/runner.h b/src/runner/runner.h index 92d6309..234ab77 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -38,6 +38,7 @@ class Executor { void printValue(const ASTValue& arg); ASTValue evaluateOperator(const std::shared_ptr& 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 scopeVals = {}, std::vector args = {}); std::map getVariables();