Moved radix and precision commands to Stack class
Some checks failed
dc / build (push) Failing after 46s

This commit is contained in:
Marco Cetica 2024-03-08 12:18:26 +01:00
parent 505ed8b148
commit b9235470e3
Signed by: marco
GPG Key ID: 45060A949E90D0FD
6 changed files with 117 additions and 103 deletions

View File

@ -1,7 +1,7 @@
name: dc
on:
push:
branches: [master, unit_testing]
branches: [master, factory_parsing]
workflow_dispatch:
jobs:

View File

@ -248,32 +248,38 @@ std::optional<std::string> Evaluate::eval() {
return err;
}
} else if(val == "k") { // SET PRECISION
err = fn_set_precision();
auto op = std::make_unique<Stack>(OPType::SP);
err = op->exec(this->stack, this->parameters, this->regs);
if(err != std::nullopt) {
return err;
}
} else if(val == "K") { // GET PRECISION
err = fn_get_precision();
auto op = std::make_unique<Stack>(OPType::GP);
err = op->exec(this->stack, this->parameters, this->regs);
if(err != std::nullopt) {
return err;
}
} else if(val == "o") { // SET OUTPUT BASE
err = fn_set_oradix();
auto op = std::make_unique<Stack>(OPType::SOR);
err = op->exec(this->stack, this->parameters, this->regs);
if(err != std::nullopt) {
return err;
}
} else if(val == "O") { // GET OUTPUT BASE
err = fn_get_oradix();
auto op = std::make_unique<Stack>(OPType::GOR);
err = op->exec(this->stack, this->parameters, this->regs);
if(err != std::nullopt) {
return err;
}
} else if(val == "i") { // SET INPUT BASE
err = fn_set_iradix();
auto op = std::make_unique<Stack>(OPType::SIR);
err = op->exec(this->stack, this->parameters, this->regs);
if(err != std::nullopt) {
return err;
}
} else if(val == "I") { // GET INPUT BASE
err = fn_get_iradix();
auto op = std::make_unique<Stack>(OPType::GIR);
err = op->exec(this->stack, this->parameters, this->regs);
if(err != std::nullopt) {
return err;
}
@ -632,86 +638,3 @@ std::optional<std::string> Evaluate::parse_array_command(std::string val) {
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_set_precision() {
// Check if stack has enough elements
if(this->stack.empty()) {
return "'k' requires one operand";
}
// Check whether head is a non negative number
auto head = this->stack.back();
if(!is_num<int>(head) || std::stoi(head) < 0) {
return "Precision must be a non-negative number";
}
// Otherwise extract head of the stack and use it
// to set precision parameter
this->stack.pop_back();
this->parameters.precision = std::stoi(head);
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_get_precision() {
this->stack.push_back(std::to_string(this->parameters.precision));
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_set_oradix() {
// Check if stack has enough elements
if(this->stack.empty()) {
return "'o' requires one operand";
}
// Check whether the head is a number
auto head = this->stack.back();
if(!is_num<int>(head)) {
return "'o' requires numeric values only";
}
// Otherwise convert it to int
auto oradix = std::stoi(head);
switch(oradix) {
case 2: this->parameters.oradix = radix_base::BIN; break;
case 8: this->parameters.oradix = radix_base::OCT; break;
case 10: this->parameters.oradix = radix_base::DEC; break;
case 16: this->parameters.oradix = radix_base::HEX; break;
default: return "'o' accepts either BIN, OCT, DEC or HEX bases";
}
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_get_oradix() {
this->stack.push_back(std::to_string(static_cast<int>(this->parameters.oradix)));
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_set_iradix() {
// Check if stack has enough elements
if(this->stack.empty()) {
return "'i' requires one operand";
}
// Check whether head is a number within the range 2-16
auto head = this->stack.back();
if(!is_num<double>(head) || std::stoi(head) < 2 || std::stoi(head) > 16) {
return "Input base must be a number within the range 2-16(inclusive)";
}
// Otherwise extract head of the stack and use it
// to set input base
this->stack.pop_back();
this->parameters.iradix = std::stoi(head);
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_get_iradix() {
this->stack.push_back(std::to_string(this->parameters.iradix));
return std::nullopt;
}

View File

@ -25,12 +25,7 @@ private:
std::optional<std::string> parse_register_command(std::string val);
std::optional<std::string> parse_array_command(std::string val);
std::optional<std::string> parse_base_n(const std::string& val);
std::optional<std::string> fn_set_precision();
std::optional<std::string> fn_get_precision();
std::optional<std::string> fn_set_oradix();
std::optional<std::string> fn_get_oradix();
std::optional<std::string> fn_set_iradix();
std::optional<std::string> fn_get_iradix();
void init_op_factory();
using op_factory_t = std::function<std::unique_ptr<IOperation>()>;

View File

@ -14,7 +14,8 @@ enum class OPType {
ADD, SUB, MUL, DIV, MOD, DIV_MOD, MOD_EXP, EXP,
SQRT, SIN, COS, TAN, ASIN, ACOS, ATAN, FACT, PI, E,
// Stack operations
PCG, P, PBB, PBH, PBO, CLR, PH, SO, DP, PS, CH, CS,
PCG, P, PBB, PBH, PBO, CLR, PH, SO, DP, PS, CH, CS,
SP, GP, SOR, GOR, SIR, GIR,
// Macro operations
EX, CMP, RI
};

View File

@ -24,12 +24,18 @@ std::optional<std::string> Stack::exec(dc_stack_t &stack, Parameters &parameters
case OPType::PBO: err = print_oradix(radix_base::OCT); break;
case OPType::PBH: err = print_oradix(radix_base::HEX); break;
case OPType::CLR: stack.clear(); break;
case OPType::PH: fn_pop_head(stack); break;
case OPType::SO: fn_swap_xy(stack); break;
case OPType::DP: fn_dup_head(stack); break;
case OPType::PS: fn_print_stack(stack, parameters); break;
case OPType::CH: fn_head_size(stack); break;
case OPType::CS: fn_stack_size(stack); break;
case OPType::PH: err = fn_pop_head(stack); break;
case OPType::SO: err = fn_swap_xy(stack); break;
case OPType::DP: err = fn_dup_head(stack); break;
case OPType::PS: err = fn_print_stack(stack, parameters); break;
case OPType::CH: err = fn_head_size(stack); break;
case OPType::CS: err = fn_stack_size(stack); break;
case OPType::SP: err = fn_set_precision(stack, parameters); break;
case OPType::GP: err = fn_get_precision(stack, parameters); break;
case OPType::SOR: err = fn_set_oradix(stack, parameters); break;
case OPType::GOR: err = fn_get_oradix(stack, parameters); break;
case OPType::SIR: err = fn_set_iradix(stack, parameters); break;
case OPType::GIR: err = fn_get_iradix(stack, parameters); break;
default: break;
}
@ -186,6 +192,89 @@ std::optional<std::string> Stack::fn_stack_size(dc_stack_t &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_precision(dc_stack_t &stack, Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'k' requires one operand";
}
// Check whether head is a non-negative number
auto head = stack.back();
if(!is_num<int>(head) || std::stoi(head) < 0) {
return "Precision must be a non-negative number";
}
// Otherwise extract head of the stack and use it
// to set precision parameter
stack.pop_back();
parameters.precision = std::stoi(head);
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_precision(dc_stack_t &stack, Parameters &parameters) {
stack.push_back(std::to_string(parameters.precision));
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_oradix(dc_stack_t &stack, Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'o' requires one operand";
}
// Check whether the head is a number
auto head = stack.back();
if(!is_num<int>(head)) {
return "'o' requires numeric values only";
}
// Otherwise convert it to int
auto oradix = std::stoi(head);
switch(oradix) {
case 2: parameters.oradix = radix_base::BIN; break;
case 8: parameters.oradix = radix_base::OCT; break;
case 10: parameters.oradix = radix_base::DEC; break;
case 16: parameters.oradix = radix_base::HEX; break;
default: return "'o' accepts either BIN, OCT, DEC or HEX bases";
}
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_oradix(dc_stack_t &stack, Parameters &parameters) {
stack.push_back(std::to_string(static_cast<int>(parameters.oradix)));
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_iradix(dc_stack_t &stack, Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'i' requires one operand";
}
// Check whether head is a number within the range 2-16
auto head = stack.back();
if(!is_num<double>(head) || std::stoi(head) < 2 || std::stoi(head) > 16) {
return "Input base must be a number within the range 2-16(inclusive)";
}
// Otherwise extract head of the stack and use it
// to set input base
stack.pop_back();
parameters.iradix = std::stoi(head);
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_iradix(dc_stack_t &stack, Parameters &parameters) {
stack.push_back(std::to_string(parameters.iradix));
return std::nullopt;
}
constexpr std::string Stack::to_bin(auto num) {
if(num == 0) {
return "0";

View File

@ -15,6 +15,12 @@ private:
std::optional<std::string> fn_print_stack(dc_stack_t &stack, Parameters &parameters);
static std::optional<std::string> fn_head_size(dc_stack_t &stack);
static std::optional<std::string> fn_stack_size(dc_stack_t &stack);
static std::optional<std::string> fn_set_precision(dc_stack_t &stack, Parameters &parameters);
static std::optional<std::string> fn_get_precision(dc_stack_t &stack, Parameters &parameters);
static std::optional<std::string> fn_set_oradix(dc_stack_t &stack, Parameters &parameters);
static std::optional<std::string> fn_get_oradix(dc_stack_t &stack, Parameters &parameters);
static std::optional<std::string> fn_set_iradix(dc_stack_t &stack, Parameters &parameters);
static std::optional<std::string> fn_get_iradix(dc_stack_t &stack, Parameters &parameters);
constexpr std::string to_bin(auto num);
OPType op_type;