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 Executor::applyOperator(const ASTValue& lhs_in, const ASTValue& rhs_in, OperatorType opType) {
|
||||||
ASTValue left = lhs_in;
|
ASTValue left = lhs_in;
|
||||||
ASTValue right = rhs_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())) {
|
if (std::holds_alternative<std::shared_ptr<ASTFunctionCall>>(node.value())) {
|
||||||
std::string fnName = std::get<std::shared_ptr<ASTFunctionCall>>(node.value())->func;
|
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;
|
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;
|
std::vector<Object> callArgs;
|
||||||
for (auto &callArgNode : callArgNodes) {
|
for (auto &callArgNode : callArgNodes) {
|
||||||
if (std::holds_alternative<std::shared_ptr<ASTValue>>(callArgNode)) {
|
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 (arg.getBool().value()) {
|
||||||
if (std::holds_alternative<std::shared_ptr<ASTCodeBlock>>(block.value())) {
|
if (std::holds_alternative<std::shared_ptr<ASTCodeBlock>>(block.value())) {
|
||||||
Executor newExecutor(*std::get<std::shared_ptr<ASTCodeBlock>>(block.value()), false, variables);
|
Executor bodyExecutor(*std::get<std::shared_ptr<ASTCodeBlock>>(block.value()), false, variables);
|
||||||
for (const auto& [key, value] : newExecutor.getVariables()) {
|
variables = bodyExecutor.getVariables();
|
||||||
if (variables.find(key) != variables.end()) {
|
|
||||||
variables[key] = newExecutor.getVariables()[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (fnName == "while") {
|
} else if (fnName == "while") {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Executor {
|
|||||||
void printValue(const ASTValue& arg);
|
void printValue(const ASTValue& arg);
|
||||||
ASTValue evaluateOperator(const std::shared_ptr<ASTOperator>& op);
|
ASTValue evaluateOperator(const std::shared_ptr<ASTOperator>& op);
|
||||||
ASTValue applyOperator(const ASTValue& lhs, const ASTValue& rhs, OperatorType opType);
|
ASTValue applyOperator(const ASTValue& lhs, const ASTValue& rhs, OperatorType opType);
|
||||||
|
ASTValue evaluateCondition(const ASTNode& conditionNode);
|
||||||
public:
|
public:
|
||||||
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
||||||
std::map<std::string, Object> getVariables();
|
std::map<std::string, Object> getVariables();
|
||||||
|
|||||||
Reference in New Issue
Block a user