Fix while (turing complete now!)
This commit is contained in:
@@ -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") {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user