Further addition improvements
This commit is contained in:
@@ -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)) {}
|
||||||
|
|||||||
@@ -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,30 +269,51 @@ 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()));
|
exit(1);
|
||||||
} 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()));
|
ASTNode valueNode = valueNodeOpt.value();
|
||||||
} else if (std::holds_alternative<std::shared_ptr<ASTOperator>>(valueNode.value())) {
|
|
||||||
ASTValue result = evaluateOperator(std::get<std::shared_ptr<ASTOperator>>(valueNode.value()));
|
ASTValue rhs;
|
||||||
variables.emplace(std::get<std::shared_ptr<ASTIdentifier>>(node.value())->name, result);
|
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 {
|
} else {
|
||||||
std::cout << "Expected value or function after = sign" << std::endl;
|
std::cout << "Invalid right-hand side for assignment" << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op_str == "=") {
|
||||||
|
variables[varName] = rhs;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Expected value after = sign" << std::endl;
|
if (variables.find(varName) == variables.end()) {
|
||||||
|
std::cout << "Variable " << varName << " not defined for compound assignment" << std::endl;
|
||||||
exit(1);
|
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 {
|
} else {
|
||||||
std::cout << "Expected function or operator after identifier" << std::endl;
|
std::cout << "Expected function or operator after identifier" << std::endl;
|
||||||
@@ -292,6 +321,7 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// if we see a function call
|
// if we see a function call
|
||||||
// note: we only accept calls to import() in the root function
|
// note: we only accept calls to import() in the root function
|
||||||
if (std::holds_alternative<std::shared_ptr<ASTFunctionCall>>(node.value())) {
|
if (std::holds_alternative<std::shared_ptr<ASTFunctionCall>>(node.value())) {
|
||||||
|
|||||||
@@ -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
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