Fixed various bugs
This commit is contained in:
parent
6726107d03
commit
ec3d4ffaea
3
Makefile
3
Makefile
@ -2,7 +2,8 @@ TARGET = dc
|
||||
CC = g++
|
||||
CXXFLAGS = -Wall -Wextra -Werror -pedantic-errors -fstack-protector-strong \
|
||||
-D_FORTIFY_SOURCE=2 -Wformat-security -fsanitize=address -fsanitize=undefined \
|
||||
-fstack-clash-protection -std=c++20
|
||||
-fstack-clash-protection -Wundef -Wshadow -Wpointer-arith \
|
||||
-Wcast-align -Wwrite-strings -ftrapv -std=c++20 -O3
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
4
main.cpp
4
main.cpp
@ -9,7 +9,7 @@
|
||||
#include "src/eval.h"
|
||||
#include "src/macro.h" // for split static method
|
||||
|
||||
#define DC_VERSION "1.0.0"
|
||||
#define DC_VERSION "1.0.1"
|
||||
|
||||
void helper() {
|
||||
std::cout << "RPN desktop calculator with macro support. Usage: \n"
|
||||
@ -27,7 +27,7 @@ int main(int argc, char **argv) {
|
||||
std::string stdin_expression = "";
|
||||
bool execute_expression = false;
|
||||
bool execute_file = false;
|
||||
stack_t stack;
|
||||
dc_stack_t stack;
|
||||
std::unordered_map<char, Register> regs;
|
||||
struct option long_opts[] = {
|
||||
{"expression", required_argument, nullptr, 'e'},
|
||||
|
58
src/eval.cpp
58
src/eval.cpp
@ -119,56 +119,56 @@ std::optional<std::string> Evaluate::eval() {
|
||||
// STACK OPERATIONS
|
||||
//
|
||||
else if(val == "p") { // PRINT TOP ELEMENT OF STACK
|
||||
auto stack = std::make_unique<Stack>(OPType::PCG);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::PCG);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "P") { // PRINT TOP ELEMENT WITHOUT NEWLINE
|
||||
auto stack = std::make_unique<Stack>(OPType::P);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::P);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "c") { // CLEAR THE STACK
|
||||
auto stack = std::make_unique<Stack>(OPType::CLR);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::CLR);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "R") { // POP HEAD OF THE STACK WITHOUT PRINTING IT
|
||||
auto stack = std::make_unique<Stack>(OPType::PH);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::PH);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "r") { // SWAP ORDER OF THE TWO TOP ELEMENTS
|
||||
auto stack = std::make_unique<Stack>(OPType::SO);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::SO);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "d") { // DUPLICATE THE HEAD OF THE STACK
|
||||
auto stack = std::make_unique<Stack>(OPType::DP);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::DP);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "f") { // PRINT THE WHOLE STACK
|
||||
auto stack = std::make_unique<Stack>(OPType::PS);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::PS);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "Z") { // COMPUTE HEAD SIZE(NUM. OF CHARS/DIGITS)
|
||||
auto stack = std::make_unique<Stack>(OPType::CH);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::CH);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
} else if(val == "z") { // COMPUTE STACK SIZE
|
||||
auto stack = std::make_unique<Stack>(OPType::CS);
|
||||
err = stack->exec(this->stack);
|
||||
auto op = std::make_unique<Stack>(OPType::CS);
|
||||
err = op->exec(this->stack);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
@ -187,7 +187,7 @@ std::optional<std::string> Evaluate::eval() {
|
||||
} else if(val == "q") { // QUIT GRACEFULLY
|
||||
std::exit(0);
|
||||
} else {
|
||||
err = handle_special(val, idx, expr);
|
||||
err = handle_special(val, idx);
|
||||
if(err != std::nullopt) {
|
||||
return err;
|
||||
}
|
||||
@ -197,11 +197,11 @@ std::optional<std::string> Evaluate::eval() {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Evaluate::handle_special(std::string val, size_t &idx, std::vector<std::string> &expr) {
|
||||
std::optional<std::string> Evaluate::handle_special(std::string val, size_t &idx) {
|
||||
std::optional<std::string> err = std::nullopt;
|
||||
|
||||
if(MACRO_COND(val)) {
|
||||
err = parse_macro(idx, expr);
|
||||
err = parse_macro(idx);
|
||||
} else if(MACRO_CMD_COND(val)) {
|
||||
err = parse_macro_command(val);
|
||||
} else if(REGISTER_COND(val)) {
|
||||
@ -217,7 +217,7 @@ std::optional<std::string> Evaluate::handle_special(std::string val, size_t &idx
|
||||
return err;
|
||||
}
|
||||
|
||||
std::optional<std::string> Evaluate::parse_macro(size_t &idx, std::vector<std::string> &expr) {
|
||||
std::optional<std::string> Evaluate::parse_macro(size_t &idx) {
|
||||
// A macro is any string surrounded by square brackets
|
||||
std::string dc_macro = "";
|
||||
bool closing_bracket = false;
|
||||
@ -226,9 +226,9 @@ std::optional<std::string> Evaluate::parse_macro(size_t &idx, std::vector<std::s
|
||||
idx++;
|
||||
|
||||
// Parse the macro
|
||||
while(idx < expr.size()) {
|
||||
while(idx < this->expr.size()) {
|
||||
// Continue to parse until the clsoing square brackets
|
||||
if(expr.at(idx) == "]") {
|
||||
if(this->expr.at(idx) == "]") {
|
||||
closing_bracket = true;
|
||||
break;
|
||||
}
|
||||
@ -237,9 +237,9 @@ std::optional<std::string> Evaluate::parse_macro(size_t &idx, std::vector<std::s
|
||||
// If the macro is not empty, add some spacing
|
||||
// before the new token
|
||||
if(dc_macro.empty()) {
|
||||
dc_macro += expr.at(idx);
|
||||
dc_macro += this->expr.at(idx);
|
||||
} else {
|
||||
dc_macro += ' ' + expr.at(idx);
|
||||
dc_macro += ' ' + this->expr.at(idx);
|
||||
}
|
||||
|
||||
// Go to the next token
|
||||
@ -435,7 +435,7 @@ std::optional<std::string> Evaluate::parse_array_command(std::string val) {
|
||||
// Extract two elements from the main stack
|
||||
auto idx_str = this->stack.back();
|
||||
this->stack.pop_back();
|
||||
auto val = this->stack.back();
|
||||
auto arr_val = this->stack.back();
|
||||
this->stack.pop_back();
|
||||
|
||||
// Check whether the index is an integer
|
||||
@ -450,11 +450,11 @@ std::optional<std::string> Evaluate::parse_array_command(std::string val) {
|
||||
// If array does not exist, allocate a new array first
|
||||
auto it = this->regs.find(reg_name);
|
||||
if(it != this->regs.end()) { // Register exists
|
||||
it->second.array.insert(std::pair<int, std::string>(idx, val));
|
||||
it->second.array.insert(std::pair<int, std::string>(idx, arr_val));
|
||||
} else { // Register doesn't exist
|
||||
this->regs[reg_name] = Register{
|
||||
std::vector<std::string>(),
|
||||
std::unordered_map<int, std::string>{{idx, val}}
|
||||
std::unordered_map<int, std::string>{{idx, arr_val}}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
|
14
src/eval.h
14
src/eval.h
@ -8,20 +8,20 @@
|
||||
|
||||
class Evaluate {
|
||||
public:
|
||||
Evaluate(const std::vector<std::string> expr, std::unordered_map<char, Register> ®s, stack_t &stack)
|
||||
: expr(std::move(expr)), regs(regs), stack(stack) {}
|
||||
Evaluate(std::unordered_map<char, Register> ®s, stack_t &stack)
|
||||
: regs(regs), stack(stack) {}
|
||||
Evaluate(const std::vector<std::string> e, std::unordered_map<char, Register> &r, dc_stack_t &s)
|
||||
: expr(std::move(e)), regs(r), stack(s) {}
|
||||
Evaluate(std::unordered_map<char, Register> &r, dc_stack_t &s)
|
||||
: regs(r), stack(s) {}
|
||||
std::optional<std::string> eval();
|
||||
|
||||
private:
|
||||
std::optional<std::string> handle_special(std::string val, size_t &idx, std::vector<std::string> &expr);
|
||||
std::optional<std::string> parse_macro(size_t &idx, std::vector<std::string> &expr);
|
||||
std::optional<std::string> handle_special(std::string val, size_t &idx);
|
||||
std::optional<std::string> parse_macro(size_t &idx);
|
||||
std::optional<std::string> parse_macro_command(std::string val);
|
||||
std::optional<std::string> parse_register_command(std::string val);
|
||||
std::optional<std::string> parse_array_command(std::string val);
|
||||
|
||||
std::vector<std::string> expr;
|
||||
std::unordered_map<char, Register> ®s;
|
||||
stack_t &stack;
|
||||
dc_stack_t &stack;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "macro.h"
|
||||
#include "is_num.h"
|
||||
|
||||
std::optional<std::string> Macro::exec(stack_t &stack) {
|
||||
std::optional<std::string> Macro::exec(dc_stack_t &stack) {
|
||||
std::optional<std::string> err = std::nullopt;
|
||||
|
||||
switch(this->op_type) {
|
||||
@ -20,7 +20,7 @@ std::optional<std::string> Macro::exec(stack_t &stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
std::optional<std::string> Macro::fn_execute(stack_t &stack) {
|
||||
std::optional<std::string> Macro::fn_execute(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "This operation does not work on empty stack";
|
||||
@ -43,7 +43,7 @@ std::optional<std::string> Macro::fn_execute(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Macro::fn_evaluate_macro(stack_t &stack) {
|
||||
std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
|
||||
// Check whether the main stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "This operation requires two elements";
|
||||
@ -145,7 +145,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Macro::fn_read_input(stack_t &stack) {
|
||||
std::optional<std::string> Macro::fn_read_input(dc_stack_t &stack) {
|
||||
// Read user input from stdin
|
||||
std::string user_input = "";
|
||||
|
||||
|
16
src/macro.h
16
src/macro.h
@ -8,17 +8,17 @@ enum class Operator {
|
||||
|
||||
class Macro : public IOperation {
|
||||
public:
|
||||
Macro(const OPType op_type, const Operator op, const char dc_register, std::unordered_map<char, Register> ®s)
|
||||
: op_type(std::move(op_type)), op(std::move(op)), dc_register(std::move(dc_register)), regs(regs) {}
|
||||
Macro(const OPType op_type, std::unordered_map<char, Register> ®s)
|
||||
: op_type(std::move(op_type)), regs(regs) {}
|
||||
std::optional<std::string> exec(stack_t &stack) override;
|
||||
Macro(const OPType op_t, const Operator o, const char dc_r, std::unordered_map<char, Register> &r)
|
||||
: op_type(std::move(op_t)), op(std::move(o)), dc_register(std::move(dc_r)), regs(r) {}
|
||||
Macro(const OPType op_t, std::unordered_map<char, Register> &r)
|
||||
: op_type(std::move(op_t)), regs(r) {}
|
||||
std::optional<std::string> exec(dc_stack_t &stack) override;
|
||||
static std::vector<std::string> split(std::string str);
|
||||
|
||||
private:
|
||||
std::optional<std::string> fn_execute(stack_t &stack);
|
||||
std::optional<std::string> fn_evaluate_macro(stack_t &stack);
|
||||
std::optional<std::string> fn_read_input(stack_t &stack);
|
||||
std::optional<std::string> fn_execute(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_evaluate_macro(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_read_input(dc_stack_t &stack);
|
||||
|
||||
OPType op_type;
|
||||
Operator op;
|
||||
|
63
src/math.cpp
63
src/math.cpp
@ -1,9 +1,10 @@
|
||||
#include <cmath>
|
||||
#include <numbers>
|
||||
|
||||
#include "math.h"
|
||||
#include "is_num.h"
|
||||
|
||||
std::optional<std::string> Math::exec(stack_t &stack) {
|
||||
std::optional<std::string> Math::exec(dc_stack_t &stack) {
|
||||
std::optional<std::string> err = std::nullopt;
|
||||
|
||||
switch(this->op_type) {
|
||||
@ -28,7 +29,7 @@ std::optional<std::string> Math::exec(stack_t &stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_add(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_add(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'+' requires two operands";
|
||||
@ -58,7 +59,7 @@ std::optional<std::string> Math::fn_add(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_sub(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_sub(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'-' requires two operands";
|
||||
@ -88,7 +89,7 @@ std::optional<std::string> Math::fn_sub(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_mul(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_mul(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'*' requires two operands";
|
||||
@ -118,7 +119,7 @@ std::optional<std::string> Math::fn_mul(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_div(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_div(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'/' requires two operands";
|
||||
@ -140,7 +141,7 @@ std::optional<std::string> Math::fn_div(stack_t &stack) {
|
||||
stack.pop_back();
|
||||
|
||||
// Check whether divisor is equal to zero
|
||||
if(divisor == (double)0) {
|
||||
if(divisor == 0.0) {
|
||||
return "Cannot divide by zero";
|
||||
}
|
||||
|
||||
@ -153,7 +154,7 @@ std::optional<std::string> Math::fn_div(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_mod(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_mod(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'%' requires two operands";
|
||||
@ -175,7 +176,7 @@ std::optional<std::string> Math::fn_mod(stack_t &stack) {
|
||||
stack.pop_back();
|
||||
|
||||
// Check whether divisor is equal to zero
|
||||
if(rhs == (double)0) {
|
||||
if(rhs == 0.0) {
|
||||
return "Cannot divide by zero";
|
||||
}
|
||||
|
||||
@ -188,7 +189,7 @@ std::optional<std::string> Math::fn_mod(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_div_mod(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_div_mod(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'~' requires two operands";
|
||||
@ -210,7 +211,7 @@ std::optional<std::string> Math::fn_div_mod(stack_t &stack) {
|
||||
stack.pop_back();
|
||||
|
||||
// Check if divisor is not equal to zero
|
||||
if(divisor != (double)0) {
|
||||
if(divisor != 0.0) {
|
||||
auto quotient = std::trunc(dividend / divisor);
|
||||
auto remainder = ((int)dividend % (int)divisor);
|
||||
|
||||
@ -225,7 +226,7 @@ std::optional<std::string> Math::fn_div_mod(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_mod_exp(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_mod_exp(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 3) {
|
||||
return "'|' requires three operands";
|
||||
@ -278,7 +279,7 @@ std::optional<std::string> Math::fn_mod_exp(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_exp(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_exp(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'^' requires two operands";
|
||||
@ -308,7 +309,7 @@ std::optional<std::string> Math::fn_exp(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_sqrt(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_sqrt(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'v' requires one operand";
|
||||
@ -321,15 +322,15 @@ std::optional<std::string> Math::fn_sqrt(stack_t &stack) {
|
||||
|
||||
// Check whether the entry is a number
|
||||
if(is_x_num) {
|
||||
auto x = std::stod(stack.back());
|
||||
auto val = std::stod(stack.back());
|
||||
stack.pop_back();
|
||||
|
||||
if(x <= (double)0) {
|
||||
if(val <= 0.0) {
|
||||
return "'v' domain error";
|
||||
}
|
||||
|
||||
// Push back the result as a string
|
||||
stack.push_back(trim_zeros(sqrt(x)));
|
||||
stack.push_back(trim_zeros(sqrt(val)));
|
||||
} else {
|
||||
return "'v' requires numeric values";
|
||||
}
|
||||
@ -337,7 +338,7 @@ std::optional<std::string> Math::fn_sqrt(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_sin(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_sin(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'sin' requires one operand";
|
||||
@ -350,11 +351,11 @@ std::optional<std::string> Math::fn_sin(stack_t &stack) {
|
||||
|
||||
// Check whether the entry is a number
|
||||
if(is_x_num) {
|
||||
auto x = std::stod(stack.back());
|
||||
auto val = std::stod(stack.back());
|
||||
stack.pop_back();
|
||||
|
||||
// Push back the result as a string
|
||||
stack.push_back(trim_zeros(sin(x)));
|
||||
stack.push_back(trim_zeros(sin(val)));
|
||||
} else {
|
||||
return "'sin' requires numeric values";
|
||||
}
|
||||
@ -362,7 +363,7 @@ std::optional<std::string> Math::fn_sin(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_cos(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_cos(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'cos' requires one operand";
|
||||
@ -375,11 +376,11 @@ std::optional<std::string> Math::fn_cos(stack_t &stack) {
|
||||
|
||||
// Check whether the entry is a number
|
||||
if(is_x_num) {
|
||||
auto x = std::stod(stack.back());
|
||||
auto val = std::stod(stack.back());
|
||||
stack.pop_back();
|
||||
|
||||
// Push back the result as a string
|
||||
stack.push_back(trim_zeros(cos(x)));
|
||||
stack.push_back(trim_zeros(cos(val)));
|
||||
} else {
|
||||
return "'cos' requires numeric values";
|
||||
}
|
||||
@ -387,7 +388,7 @@ std::optional<std::string> Math::fn_cos(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_tan(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_tan(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'tan' requires one operand";
|
||||
@ -400,11 +401,11 @@ std::optional<std::string> Math::fn_tan(stack_t &stack) {
|
||||
|
||||
// Check whether the entry is a number
|
||||
if(is_x_num) {
|
||||
auto x = std::stod(stack.back());
|
||||
auto val = std::stod(stack.back());
|
||||
stack.pop_back();
|
||||
|
||||
// Push back the result as a string
|
||||
stack.push_back(trim_zeros(tan(x)));
|
||||
stack.push_back(trim_zeros(tan(val)));
|
||||
} else {
|
||||
return "'tan' requires numeric values";
|
||||
}
|
||||
@ -412,7 +413,7 @@ std::optional<std::string> Math::fn_tan(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_fact(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_fact(dc_stack_t &stack) {
|
||||
// Check if stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'!' requires one operand";
|
||||
@ -426,14 +427,14 @@ std::optional<std::string> Math::fn_fact(stack_t &stack) {
|
||||
// Check whether the entry is a number
|
||||
if(is_x_num) {
|
||||
unsigned long factorial = 1;
|
||||
auto x = std::stod(stack.back());
|
||||
auto val = std::stod(stack.back());
|
||||
stack.pop_back();
|
||||
|
||||
if(x == (double)0) {
|
||||
if(val == 0.0) {
|
||||
factorial = 1;
|
||||
}
|
||||
|
||||
for(size_t i = 2; i <= (size_t)x; i++) {
|
||||
for(size_t i = 2; i <= (size_t)val; i++) {
|
||||
factorial *= i;
|
||||
}
|
||||
|
||||
@ -446,13 +447,13 @@ std::optional<std::string> Math::fn_fact(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_pi(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_pi(dc_stack_t &stack) {
|
||||
stack.push_back(trim_zeros(std::numbers::pi));
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Math::fn_e(stack_t &stack) {
|
||||
std::optional<std::string> Math::fn_e(dc_stack_t &stack) {
|
||||
stack.push_back(trim_zeros(std::numbers::e));
|
||||
|
||||
return std::nullopt;
|
||||
|
34
src/math.h
34
src/math.h
@ -4,25 +4,25 @@
|
||||
|
||||
class Math : public IOperation {
|
||||
public:
|
||||
Math(const OPType op_type) : op_type(std::move(op_type)) {}
|
||||
std::optional<std::string> exec(stack_t &stack) override;
|
||||
Math(const OPType op_t) : op_type(std::move(op_t)) {}
|
||||
std::optional<std::string> exec(dc_stack_t &stack) override;
|
||||
|
||||
private:
|
||||
std::optional<std::string> fn_add(stack_t &stack);
|
||||
std::optional<std::string> fn_sub(stack_t &stack);
|
||||
std::optional<std::string> fn_mul(stack_t &stack);
|
||||
std::optional<std::string> fn_div(stack_t &stack);
|
||||
std::optional<std::string> fn_mod(stack_t &stack);
|
||||
std::optional<std::string> fn_div_mod(stack_t &stack);
|
||||
std::optional<std::string> fn_mod_exp(stack_t &stack);
|
||||
std::optional<std::string> fn_exp(stack_t &stack);
|
||||
std::optional<std::string> fn_sqrt(stack_t &stack);
|
||||
std::optional<std::string> fn_sin(stack_t &stack);
|
||||
std::optional<std::string> fn_cos(stack_t &stack);
|
||||
std::optional<std::string> fn_tan(stack_t &stack);
|
||||
std::optional<std::string> fn_fact(stack_t &stack);
|
||||
std::optional<std::string> fn_pi(stack_t &stack);
|
||||
std::optional<std::string> fn_e(stack_t &stack);
|
||||
std::optional<std::string> fn_add(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_sub(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_mul(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_div(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_mod(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_div_mod(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_mod_exp(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_exp(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_sqrt(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_sin(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_cos(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_tan(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_fact(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_pi(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_e(dc_stack_t &stack);
|
||||
static std::string trim_zeros(double number);
|
||||
|
||||
OPType op_type;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
class IOperation {
|
||||
public:
|
||||
virtual std::optional<std::string> exec(stack_t &stack) = 0;
|
||||
virtual std::optional<std::string> exec(dc_stack_t &stack) = 0;
|
||||
virtual ~IOperation() = default;
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "stack.h"
|
||||
#include "is_num.h"
|
||||
|
||||
std::optional<std::string> Stack::exec(stack_t &stack) {
|
||||
std::optional<std::string> Stack::exec(dc_stack_t &stack) {
|
||||
std::optional<std::string> err = std::nullopt;
|
||||
|
||||
switch(this->op_type) {
|
||||
@ -23,7 +23,7 @@ std::optional<std::string> Stack::exec(stack_t &stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_print(stack_t &stack, bool new_line) {
|
||||
std::optional<std::string> Stack::fn_print(dc_stack_t &stack, bool new_line) {
|
||||
// Check if the stack is empty
|
||||
if(stack.empty()) {
|
||||
return "Cannot print empty stack";
|
||||
@ -38,7 +38,7 @@ std::optional<std::string> Stack::fn_print(stack_t &stack, bool new_line) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_pop_head(stack_t &stack) {
|
||||
std::optional<std::string> Stack::fn_pop_head(dc_stack_t &stack) {
|
||||
// Check if stack is empty
|
||||
if(stack.empty()) {
|
||||
return "'R' does not work on empty stack";
|
||||
@ -49,7 +49,7 @@ std::optional<std::string> Stack::fn_pop_head(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_swap_xy(stack_t &stack) {
|
||||
std::optional<std::string> Stack::fn_swap_xy(dc_stack_t &stack) {
|
||||
// Check if the stack has enough elements
|
||||
if(stack.size() < 2) {
|
||||
return "'r' requires two elements";
|
||||
@ -65,7 +65,7 @@ std::optional<std::string> Stack::fn_swap_xy(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_dup_head(stack_t &stack) {
|
||||
std::optional<std::string> Stack::fn_dup_head(dc_stack_t &stack) {
|
||||
// Check if the stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'d' requires one element";
|
||||
@ -77,7 +77,7 @@ std::optional<std::string> Stack::fn_dup_head(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_print_stack(stack_t &stack) {
|
||||
std::optional<std::string> Stack::fn_print_stack(dc_stack_t &stack) {
|
||||
for(auto it = stack.rbegin(); it != stack.rend(); it++) {
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
@ -85,7 +85,7 @@ std::optional<std::string> Stack::fn_print_stack(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_head_size(stack_t &stack) {
|
||||
std::optional<std::string> Stack::fn_head_size(dc_stack_t &stack) {
|
||||
// Check if the stack has enough elements
|
||||
if(stack.empty()) {
|
||||
return "'Z' does not work on empty stack";
|
||||
@ -116,7 +116,7 @@ std::optional<std::string> Stack::fn_head_size(stack_t &stack) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Stack::fn_stack_size(stack_t &stack) {
|
||||
std::optional<std::string> Stack::fn_stack_size(dc_stack_t &stack) {
|
||||
stack.push_back(std::to_string(stack.size()));
|
||||
|
||||
return std::nullopt;
|
||||
|
18
src/stack.h
18
src/stack.h
@ -4,17 +4,17 @@
|
||||
|
||||
class Stack : public IOperation {
|
||||
public:
|
||||
Stack(const OPType op_type) : op_type(std::move(op_type)) {}
|
||||
std::optional<std::string> exec(stack_t &stack) override;
|
||||
Stack(const OPType op_t) : op_type(std::move(op_t)) {}
|
||||
std::optional<std::string> exec(dc_stack_t &stack) override;
|
||||
|
||||
private:
|
||||
std::optional<std::string> fn_print(stack_t &stack, bool new_line);
|
||||
std::optional<std::string> fn_pop_head(stack_t &stack);
|
||||
std::optional<std::string> fn_swap_xy(stack_t &stack);
|
||||
std::optional<std::string> fn_dup_head(stack_t &stack);
|
||||
std::optional<std::string> fn_print_stack(stack_t &stack);
|
||||
std::optional<std::string> fn_head_size(stack_t &stack);
|
||||
std::optional<std::string> fn_stack_size(stack_t &stack);
|
||||
std::optional<std::string> fn_print(dc_stack_t &stack, bool new_line);
|
||||
std::optional<std::string> fn_pop_head(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_swap_xy(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_dup_head(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_print_stack(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_head_size(dc_stack_t &stack);
|
||||
std::optional<std::string> fn_stack_size(dc_stack_t &stack);
|
||||
|
||||
OPType op_type;
|
||||
};
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
using stack_t = std::vector<std::string>;
|
||||
using dc_stack_t = std::vector<std::string>;
|
||||
typedef struct {
|
||||
stack_t stack;
|
||||
dc_stack_t stack;
|
||||
std::unordered_map<int, std::string> array;
|
||||
} Register;
|
||||
|
Loading…
Reference in New Issue
Block a user