Further addition improvements

This commit is contained in:
2025-10-30 11:58:22 +00:00
parent 817cf5a1a9
commit d823ea9019
5 changed files with 134 additions and 93 deletions

View File

@@ -18,11 +18,7 @@ std::map<std::string, OperatorType> ASTOperator::operatorMap = {
{"+", OperatorType::Add}, {"+", OperatorType::Add},
{"-", OperatorType::Subtract}, {"-", OperatorType::Subtract},
{"*", OperatorType::Multiply}, {"*", OperatorType::Multiply},
{"/", OperatorType::Divide}, {"/", OperatorType::Divide}
{"+=", OperatorType::AddBy},
{"-=", OperatorType::SubtractBy},
{"*=", OperatorType::MultiplyBy},
{"/=", OperatorType::DivideBy}
}; };
ASTList::ASTList(std::vector<ASTNode> in) : elements(std::move(in)) {} ASTList::ASTList(std::vector<ASTNode> in) : elements(std::move(in)) {}

View File

@@ -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<ASTOperator>& op) { ASTValue Executor::evaluateOperator(const std::shared_ptr<ASTOperator>& op) {
std::vector<ASTValue> stack; std::vector<ASTValue> stack;
auto args = op->getArguments(); auto args = op->getArguments();
@@ -117,70 +188,7 @@ ASTValue Executor::evaluateOperator(const std::shared_ptr<ASTOperator>& op) {
ASTValue left = stack.back(); ASTValue left = stack.back();
stack.pop_back(); stack.pop_back();
if ((left.type == ValueType::Int || left.type == ValueType::Float) && stack.push_back(applyOperator(left, right, opType));
(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);
}
} }
} }
@@ -261,34 +269,56 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
// eg: main func { ... } // eg: main func { ... }
// eg: dingus func { ... } // eg: dingus func { ... }
if (std::holds_alternative<std::shared_ptr<ASTFunction>>(next.value())) { if (std::holds_alternative<std::shared_ptr<ASTFunction>>(next.value())) {
variables.emplace(std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name, *std::get<std::shared_ptr<ASTFunction>>(next.value())); variables[std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name] = *std::get<std::shared_ptr<ASTFunction>>(next.value());
} else if (std::holds_alternative<std::shared_ptr<ASTIdentifier>>(next.value())) { } else if (std::holds_alternative<std::shared_ptr<ASTIdentifier>>(next.value())) {
std::string id = std::get<std::shared_ptr<ASTIdentifier>>(next.value())->name; std::string op_str = std::get<std::shared_ptr<ASTIdentifier>>(next.value())->name;
if (id == "=") { if (op_str == "=" || op_str == "+=" || op_str == "-=" || op_str == "*=" || op_str == "/=") {
// setting a variable std::string varName = std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name;
std::optional<ASTNode> valueNode = consume();
if (valueNode.has_value()) { std::optional<ASTNode> valueNodeOpt = consume();
ASTValue next; if (!valueNodeOpt.has_value()) {
if (std::holds_alternative<std::shared_ptr<ASTValue>>(valueNode.value())) { std::cout << "Expected value after " << op_str << " sign" << std::endl;
variables.emplace(std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name, *std::get<std::shared_ptr<ASTValue>>(valueNode.value()));
} else if (std::holds_alternative<std::shared_ptr<ASTFunction>>(valueNode.value())) {
variables.emplace(std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name, *std::get<std::shared_ptr<ASTFunction>>(valueNode.value()));
} else if (std::holds_alternative<std::shared_ptr<ASTOperator>>(valueNode.value())) {
ASTValue result = evaluateOperator(std::get<std::shared_ptr<ASTOperator>>(valueNode.value()));
variables.emplace(std::get<std::shared_ptr<ASTIdentifier>>(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;
exit(1); exit(1);
} }
ASTNode valueNode = valueNodeOpt.value();
ASTValue rhs;
if (std::holds_alternative<std::shared_ptr<ASTValue>>(valueNode)) {
rhs = *std::get<std::shared_ptr<ASTValue>>(valueNode);
} else if (std::holds_alternative<std::shared_ptr<ASTOperator>>(valueNode)) {
rhs = evaluateOperator(std::get<std::shared_ptr<ASTOperator>>(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<ASTValue>(existingObj.value)) {
std::cout << "Compound assignment on non-value type not supported" << std::endl;
exit(1);
}
ASTValue lhs = std::get<ASTValue>(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);
} }
} }
} }

View File

@@ -37,6 +37,7 @@ class Executor {
std::optional<ASTNode> peek(int ahead = 1); std::optional<ASTNode> peek(int ahead = 1);
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);
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();

7
tests/math.funk Normal file
View File

@@ -0,0 +1,7 @@
main func {
println(1 + 1)
x = 2 * 2
if (x == 4) {
println("It's working!")
}
}

7
tests/to1000.funk Normal file
View File

@@ -0,0 +1,7 @@
main func {
x = 0
while (x == 1000) {
x = 1 + x
println(x)
}
}