Further addition improvements
This commit is contained in:
@@ -18,11 +18,7 @@ std::map<std::string, OperatorType> ASTOperator::operatorMap = {
|
||||
{"+", OperatorType::Add},
|
||||
{"-", OperatorType::Subtract},
|
||||
{"*", OperatorType::Multiply},
|
||||
{"/", OperatorType::Divide},
|
||||
{"+=", OperatorType::AddBy},
|
||||
{"-=", OperatorType::SubtractBy},
|
||||
{"*=", OperatorType::MultiplyBy},
|
||||
{"/=", OperatorType::DivideBy}
|
||||
{"/", OperatorType::Divide}
|
||||
};
|
||||
|
||||
ASTList::ASTList(std::vector<ASTNode> in) : elements(std::move(in)) {}
|
||||
|
||||
@@ -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) {
|
||||
std::vector<ASTValue> stack;
|
||||
auto args = op->getArguments();
|
||||
@@ -117,70 +188,7 @@ ASTValue Executor::evaluateOperator(const std::shared_ptr<ASTOperator>& 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<std::string, Objec
|
||||
// eg: main func { ... }
|
||||
// eg: dingus func { ... }
|
||||
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())) {
|
||||
std::string id = std::get<std::shared_ptr<ASTIdentifier>>(next.value())->name;
|
||||
if (id == "=") {
|
||||
// setting a variable
|
||||
std::optional<ASTNode> valueNode = consume();
|
||||
if (valueNode.has_value()) {
|
||||
ASTValue next;
|
||||
if (std::holds_alternative<std::shared_ptr<ASTValue>>(valueNode.value())) {
|
||||
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;
|
||||
std::string op_str = std::get<std::shared_ptr<ASTIdentifier>>(next.value())->name;
|
||||
if (op_str == "=" || op_str == "+=" || op_str == "-=" || op_str == "*=" || op_str == "/=") {
|
||||
std::string varName = std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name;
|
||||
|
||||
std::optional<ASTNode> 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<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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class Executor {
|
||||
std::optional<ASTNode> peek(int ahead = 1);
|
||||
void printValue(const ASTValue& arg);
|
||||
ASTValue evaluateOperator(const std::shared_ptr<ASTOperator>& op);
|
||||
ASTValue applyOperator(const ASTValue& lhs, const ASTValue& rhs, OperatorType opType);
|
||||
public:
|
||||
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
||||
std::map<std::string, Object> getVariables();
|
||||
|
||||
7
tests/math.funk
Normal file
7
tests/math.funk
Normal 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
7
tests/to1000.funk
Normal file
@@ -0,0 +1,7 @@
|
||||
main func {
|
||||
x = 0
|
||||
while (x == 1000) {
|
||||
x = 1 + x
|
||||
println(x)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user