From d823ea901978a96a8a3d07b90cf2d2b8fcea8491 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Thu, 30 Oct 2025 11:58:22 +0000 Subject: [PATCH] Further addition improvements --- src/parser/parser.cpp | 6 +- src/runner/runner.cpp | 206 ++++++++++++++++++++++++------------------ src/runner/runner.h | 1 + tests/math.funk | 7 ++ tests/to1000.funk | 7 ++ 5 files changed, 134 insertions(+), 93 deletions(-) create mode 100644 tests/math.funk create mode 100644 tests/to1000.funk diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 39a3cf8..95bbca3 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -18,11 +18,7 @@ std::map ASTOperator::operatorMap = { {"+", OperatorType::Add}, {"-", OperatorType::Subtract}, {"*", OperatorType::Multiply}, - {"/", OperatorType::Divide}, - {"+=", OperatorType::AddBy}, - {"-=", OperatorType::SubtractBy}, - {"*=", OperatorType::MultiplyBy}, - {"/=", OperatorType::DivideBy} + {"/", OperatorType::Divide} }; ASTList::ASTList(std::vector in) : elements(std::move(in)) {} diff --git a/src/runner/runner.cpp b/src/runner/runner.cpp index e3132eb..283037c 100644 --- a/src/runner/runner.cpp +++ b/src/runner/runner.cpp @@ -82,6 +82,77 @@ void Executor::printValue(const ASTValue& arg) { } } +ASTValue Executor::applyOperator(const ASTValue& lhs_in, const ASTValue& rhs_in, OperatorType opType) { + ASTValue left = lhs_in; + ASTValue right = rhs_in; + // Type promotion + if (left.type == ValueType::Float && right.type == ValueType::Int) { + right = ASTValue((double)right.getInt().value()); + } + if (left.type == ValueType::Int && right.type == ValueType::Float) { + left = ASTValue((double)left.getInt().value()); + } + + if ((left.type == ValueType::Int || left.type == ValueType::Float) && + (right.type == ValueType::Int || right.type == ValueType::Float)) { + + double l = left.type == ValueType::Int ? (double)left.getInt().value() : left.getFloat().value(); + double r = right.type == ValueType::Int ? (double)right.getInt().value() : right.getFloat().value(); + bool resultIsFloat = left.type == ValueType::Float || right.type == ValueType::Float; + + switch (opType) { + case OperatorType::Add: + case OperatorType::AddBy: + return resultIsFloat ? ASTValue(l + r) : ASTValue((long long)(l + r)); + case OperatorType::Subtract: + case OperatorType::SubtractBy: + return resultIsFloat ? ASTValue(l - r) : ASTValue((long long)(l - r)); + case OperatorType::Multiply: + case OperatorType::MultiplyBy: + return resultIsFloat ? ASTValue(l * r) : ASTValue((long long)(l * r)); + case OperatorType::Divide: + case OperatorType::DivideBy: + if (r == 0) { std::cout << "Division by zero" << std::endl; exit(1); } + return ASTValue(l / r); + case OperatorType::Equal: + return ASTValue(l == r); + case OperatorType::Inequal: + return ASTValue(l != r); + case OperatorType::Greater: + return ASTValue(l > r); + case OperatorType::GreaterEqual: + return ASTValue(l >= r); + case OperatorType::Less: + return ASTValue(l < r); + case OperatorType::LessEqual: + return ASTValue(l <= r); + default: + std::cout << "Unsupported operator for numeric types" << std::endl; + exit(1); + } + } else if (left.type == ValueType::String && (opType == OperatorType::Add || opType == OperatorType::AddBy)) { + std::string r_str; + if (right.type == ValueType::String) r_str = right.getString().value(); + else if (right.type == ValueType::Int) r_str = std::to_string(right.getInt().value()); + else if (right.type == ValueType::Float) r_str = std::to_string(right.getFloat().value()); + else if (right.type == ValueType::Bool) r_str = right.getBool().value() ? "true" : "false"; + else { std::cout << "Unsupported type for string concatenation" << std::endl; exit(1); } + return ASTValue(left.getString().value() + r_str); + } else if (left.type == ValueType::Bool && right.type == ValueType::Bool) { + bool l = left.getBool().value(); + bool r = right.getBool().value(); + switch (opType) { + case OperatorType::Equal: return ASTValue(l == r); + case OperatorType::Inequal: return ASTValue(l != r); + default: std::cout << "Unsupported operator for booleans" << std::endl; exit(1); + } + } + else { + std::cout << "Unsupported operand types in expression" << std::endl; + exit(1); + } +} + ASTValue Executor::evaluateOperator(const std::shared_ptr& op) { std::vector stack; auto args = op->getArguments(); @@ -117,70 +188,7 @@ ASTValue Executor::evaluateOperator(const std::shared_ptr& op) { ASTValue left = stack.back(); stack.pop_back(); - if ((left.type == ValueType::Int || left.type == ValueType::Float) && - (right.type == ValueType::Int || right.type == ValueType::Float)) { - - double l = left.type == ValueType::Int ? (double)left.getInt().value() : left.getFloat().value(); - double r = right.type == ValueType::Int ? (double)right.getInt().value() : right.getFloat().value(); - bool resultIsFloat = left.type == ValueType::Float || right.type == ValueType::Float; - - switch (opType) { - case OperatorType::Add: - resultIsFloat ? stack.emplace_back(l + r) : stack.emplace_back((long long)(l + r)); - break; - case OperatorType::Subtract: - resultIsFloat ? stack.emplace_back(l - r) : stack.emplace_back((long long)(l - r)); - break; - case OperatorType::Multiply: - resultIsFloat ? stack.emplace_back(l * r) : stack.emplace_back((long long)(l * r)); - break; - case OperatorType::Divide: - if (r == 0) { std::cout << "Division by zero" << std::endl; exit(1); } - stack.emplace_back(l / r); - break; - case OperatorType::Equal: - stack.emplace_back(l == r); - break; - case OperatorType::Inequal: - stack.emplace_back(l != r); - break; - case OperatorType::Greater: - stack.emplace_back(l > r); - break; - case OperatorType::GreaterEqual: - stack.emplace_back(l >= r); - break; - case OperatorType::Less: - stack.emplace_back(l < r); - break; - case OperatorType::LessEqual: - stack.emplace_back(l <= r); - break; - default: - std::cout << "Unsupported operator for numeric types" << std::endl; - exit(1); - } - } else if (left.type == ValueType::String && opType == OperatorType::Add) { - std::string r_str; - if (right.type == ValueType::String) r_str = right.getString().value(); - else if (right.type == ValueType::Int) r_str = std::to_string(right.getInt().value()); - else if (right.type == ValueType::Float) r_str = std::to_string(right.getFloat().value()); - else if (right.type == ValueType::Bool) r_str = right.getBool().value() ? "true" : "false"; - else { std::cout << "Unsupported type for string concatenation" << std::endl; exit(1); } - stack.emplace_back(left.getString().value() + r_str); - } else if (left.type == ValueType::Bool && right.type == ValueType::Bool) { - bool l = left.getBool().value(); - bool r = right.getBool().value(); - switch (opType) { - case OperatorType::Equal: stack.emplace_back(l == r); break; - case OperatorType::Inequal: stack.emplace_back(l != r); break; - default: std::cout << "Unsupported operator for booleans" << std::endl; exit(1); - } - } - else { - std::cout << "Unsupported operand types in expression" << std::endl; - exit(1); - } + stack.push_back(applyOperator(left, right, opType)); } } @@ -261,34 +269,56 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map>(next.value())) { - variables.emplace(std::get>(node.value())->name, *std::get>(next.value())); + variables[std::get>(node.value())->name] = *std::get>(next.value()); } else if (std::holds_alternative>(next.value())) { - std::string id = std::get>(next.value())->name; - if (id == "=") { - // setting a variable - std::optional valueNode = consume(); - if (valueNode.has_value()) { - ASTValue next; - if (std::holds_alternative>(valueNode.value())) { - variables.emplace(std::get>(node.value())->name, *std::get>(valueNode.value())); - } else if (std::holds_alternative>(valueNode.value())) { - variables.emplace(std::get>(node.value())->name, *std::get>(valueNode.value())); - } else if (std::holds_alternative>(valueNode.value())) { - ASTValue result = evaluateOperator(std::get>(valueNode.value())); - variables.emplace(std::get>(node.value())->name, result); - } else { - std::cout << "Expected value or function after = sign" << std::endl; - exit(1); - } - - } else { - std::cout << "Expected value after = sign" << std::endl; + std::string op_str = std::get>(next.value())->name; + if (op_str == "=" || op_str == "+=" || op_str == "-=" || op_str == "*=" || op_str == "/=") { + std::string varName = std::get>(node.value())->name; + + std::optional valueNodeOpt = consume(); + if (!valueNodeOpt.has_value()) { + std::cout << "Expected value after " << op_str << " sign" << std::endl; exit(1); } + ASTNode valueNode = valueNodeOpt.value(); + + ASTValue rhs; + if (std::holds_alternative>(valueNode)) { + rhs = *std::get>(valueNode); + } else if (std::holds_alternative>(valueNode)) { + rhs = evaluateOperator(std::get>(valueNode)); + } else { + std::cout << "Invalid right-hand side for assignment" << std::endl; + exit(1); + } + + if (op_str == "=") { + variables[varName] = rhs; + } else { + if (variables.find(varName) == variables.end()) { + std::cout << "Variable " << varName << " not defined for compound assignment" << std::endl; + exit(1); + } + Object existingObj = variables[varName]; + if (existingObj.isCustomObject || !std::holds_alternative(existingObj.value)) { + std::cout << "Compound assignment on non-value type not supported" << std::endl; + exit(1); + } + ASTValue lhs = std::get(existingObj.value); + + OperatorType opType; + if (op_str == "+=") opType = OperatorType::AddBy; + if (op_str == "-=") opType = OperatorType::SubtractBy; + if (op_str == "*=") opType = OperatorType::MultiplyBy; + if (op_str == "/=") opType = OperatorType::DivideBy; + + ASTValue result = applyOperator(lhs, rhs, opType); + variables[varName] = result; + } + } else { + std::cout << "Expected function or operator after identifier" << std::endl; + exit(1); } - } else { - std::cout << "Expected function or operator after identifier" << std::endl; - exit(1); } } } diff --git a/src/runner/runner.h b/src/runner/runner.h index 1574d30..92d6309 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -37,6 +37,7 @@ class Executor { std::optional peek(int ahead = 1); void printValue(const ASTValue& arg); ASTValue evaluateOperator(const std::shared_ptr& op); + ASTValue applyOperator(const ASTValue& lhs, const ASTValue& rhs, OperatorType opType); public: explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map scopeVals = {}, std::vector args = {}); std::map getVariables(); diff --git a/tests/math.funk b/tests/math.funk new file mode 100644 index 0000000..3bc5c0e --- /dev/null +++ b/tests/math.funk @@ -0,0 +1,7 @@ +main func { + println(1 + 1) + x = 2 * 2 + if (x == 4) { + println("It's working!") + } +} diff --git a/tests/to1000.funk b/tests/to1000.funk new file mode 100644 index 0000000..9de4c1d --- /dev/null +++ b/tests/to1000.funk @@ -0,0 +1,7 @@ +main func { + x = 0 + while (x == 1000) { + x = 1 + x + println(x) + } +}