Added [] overload and namespace to dc's data structures
dc / build (push) Failing after 8s Details

This commit is contained in:
Marco Cetica 2024-03-12 15:34:14 +01:00
parent 674d6deef6
commit 3c257a1fd1
Signed by: marco
GPG Key ID: 45060A949E90D0FD
15 changed files with 319 additions and 304 deletions

View File

@ -13,9 +13,8 @@ jobs:
- name: Build dc
run: |
apt -y update && apt -y install cmake build-essential
mkdir build && cd build
cmake ..
make
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug .
cmake --build build
- name: Run unit tests
run: |
./utest.sh tests

View File

@ -12,9 +12,9 @@ jobs:
uses: actions/checkout@main
- name: Build dc
run: |
mkdir build && cd build
cmake ..
make
apt -y update && apt -y install cmake build-essential
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug .
cmake --build build
- name: Run unit tests
run: |
./utest.sh tests

View File

@ -51,13 +51,13 @@ Some of the supported features are:
And much more. You can find the complete manual [here](https://github.com/ice-bit/dc/blob/master/man.md).
## Installation
`dc` is written in C++20 without using any additional dependency. In order to build it, install a recent version of CMake and issue
the following command:
`dc` is written in C++20 without using any additional dependency. In order to build it, install [CMake](https://cmake.org/), [Ninja](https://ninja-build.org/)
and issue the following commands:
```sh
$> mkdir build && cd build
$> cmake -DCMAKE_BUILD_TYPE=Release .. && make
$> cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release .
$> cmake --build build
```
A new statically-compiled binary called `dc` will be created in your local folder. To generate a man page from the `man.md` document,
A new statically-compiled binary called `dc` will be created in the `build/` directory. To generate a man page from the `man.md` document,
use the following command(note: needs pandoc):
```sh
$> pandoc man.md -s -t man > dc.1

View File

@ -9,6 +9,8 @@
#include "src/eval.h"
#include "src/macro.h" // for split static method
using namespace dc;
#define DC_VERSION "1.0.3"
void helper() {
@ -27,7 +29,7 @@ int main(int argc, char **argv) {
std::string stdin_expression;
bool execute_expression = false;
bool execute_file = false;
DCStack<std::string> stack;
Stack<std::string> stack;
std::unordered_map<char, Register> regs;
Parameters parameters = {
.precision = 0,

View File

@ -4,128 +4,139 @@
#define GET_Y this->stack.at(this->stack.size() - 2)
#define GET_Z this->stack.at(this->stack.size() - 3)
/**
* Add @value to the stack
*/
template<typename T>
requires is_num_or_str<T>
void DCStack<T>::push(T value) {
this->stack.push_back(value);
}
/**
* Clear the stack
*/
template<typename T>
requires is_num_or_str<T>
void DCStack<T>::clear() {
if(!this->stack.empty()) {
this->stack.clear();
}
}
/**
* If @remove is true, pop head of the stack
* otherwise return it without popping.
* If stack is empty it causes undefined behavior
*/
template<typename T>
requires is_num_or_str<T>
T DCStack<T>::pop(bool remove) {
T value = this->stack.back();
if(remove) {
this->stack.pop_back();
namespace dc {
/**
* Add @value to the stack
*/
template<typename T>
requires is_num_or_str<T>
void Stack<T>::push(T value) {
this->stack.push_back(value);
}
return value;
}
/**
* Make a copy of head, 2nd and 3rd element
* of the stack
*/
template<typename T>
requires is_num_or_str<T>
void DCStack<T>::copy_xyz() {
if(this->stack.size() >= 1) {
this->last_x = GET_X;
/**
* Clear the stack
*/
template<typename T>
requires is_num_or_str<T>
void Stack<T>::clear() {
if(!this->stack.empty()) {
this->stack.clear();
}
}
if(this->stack.size() >= 2) {
this->last_y = GET_Y;
/**
* If @remove is true, pop head of the stack
* otherwise return it without popping.
* If stack is empty it causes undefined behavior
*/
template<typename T>
requires is_num_or_str<T>
T Stack<T>::pop(bool remove) {
T value = this->stack.back();
if(remove) {
this->stack.pop_back();
}
return value;
}
if(this->stack.size() >= 3) {
this->last_z = GET_Z;
/**
* Make a copy of head, 2nd and 3rd element
* of the stack
*/
template<typename T>
requires is_num_or_str<T>
void Stack<T>::copy_xyz() {
if(this->stack.size() >= 1) {
this->last_x = GET_X;
}
if(this->stack.size() >= 2) {
this->last_y = GET_Y;
}
if(this->stack.size() >= 3) {
this->last_z = GET_Z;
}
}
/**
* Returns last x of the stack
* If stack is empty returns '0' or empty string
*/
template<typename T>
requires is_num_or_str<T>
T Stack<T>::get_last_x() {
return this->last_x;
}
/**
* Returns last y of the stack
* If stack is empty returns '0' or empty string
*/
template<typename T>
requires is_num_or_str<T>
T Stack<T>::get_last_y() {
return this->last_y;
}
/**
* Returns last z of the stack
* If stack is empty returns '0' or empty string
*/
template<typename T>
requires is_num_or_str<T>
T Stack<T>::get_last_z() {
return this->last_z;
}
/**
* Reads stack at @index
*/
template<typename T>
requires is_num_or_str<T>
T& Stack<T>::at(std::size_t index) {
T &value = this->stack.at(index);
return value;
}
/**
* Reads stack at @index using '[]' syntax
*/
template<typename T>
requires is_num_or_str<T>
T& Stack<T>::operator[](std::size_t index) {
return at(index);
}
/**
* Returns stack size
*/
template<typename T>
requires is_num_or_str<T>
std::size_t Stack<T>::size() {
return this->stack.size();
}
/**
* Returns true if stack is empty
* false otherwise
*/
template<typename T>
requires is_num_or_str<T>
bool Stack<T>::empty() {
return this->stack.empty();
}
/**
* Returns a const reference to the stack
*/
template<typename T>
requires is_num_or_str<T>
const std::vector<T>& Stack<T>::get_ref() const {
return this->stack;
}
}
/**
* Returns last x of the stack
* If stack is empty returns '0' or empty string
*/
template<typename T>
requires is_num_or_str<T>
T DCStack<T>::get_last_x() {
return this->last_x;
}
/**
* Returns last y of the stack
* If stack is empty returns '0' or empty string
*/
template<typename T>
requires is_num_or_str<T>
T DCStack<T>::get_last_y() {
return this->last_y;
}
/**
* Returns last z of the stack
* If stack is empty returns '0' or empty string
*/
template<typename T>
requires is_num_or_str<T>
T DCStack<T>::get_last_z() {
return this->last_z;
}
/**
* Reads stack at @index
*/
template<typename T>
requires is_num_or_str<T>
T& DCStack<T>::at(size_t index) {
T &value = this->stack.at(index);
return value;
}
/**
* Returns stack size
*/
template<typename T>
requires is_num_or_str<T>
size_t DCStack<T>::size() {
return this->stack.size();
}
/**
* Returns true if stack is empty
* false otherwise
*/
template<typename T>
requires is_num_or_str<T>
bool DCStack<T>::empty() {
return this->stack.empty();
}
/**
* Returns a const reference to the stack
*/
template<typename T>
requires is_num_or_str<T>
const std::vector<T>& DCStack<T>::get_ref() const {
return this->stack;
}

View File

@ -4,40 +4,43 @@
#include <cstdint>
#include <unordered_map>
template<typename T>
concept is_num_or_str = (std::is_arithmetic_v<T> || std::is_same_v<T, std::string>);
namespace dc {
template<typename T>
concept is_num_or_str = (std::is_arithmetic_v<T> || std::is_same_v<T, std::string>);
template<typename T>
requires is_num_or_str<T>
class DCStack {
public:
void push(T value);
void clear();
void copy_xyz();
T pop(bool remove);
T get_last_x();
T get_last_y();
T get_last_z();
T& at(size_t index);
size_t size();
bool empty();
[[nodiscard]] const std::vector<T>& get_ref() const;
template<typename T>
requires is_num_or_str<T>
class Stack {
public:
void push(T value);
void clear();
void copy_xyz();
T pop(bool remove);
T get_last_x();
T get_last_y();
T get_last_z();
T& at(std::size_t index);
T& operator[](std::size_t index);
std::size_t size();
bool empty();
[[nodiscard]] const std::vector<T>& get_ref() const;
private:
std::vector<T> stack;
T last_x{};
T last_y{};
T last_z{};
};
private:
std::vector<T> stack;
T last_x{};
T last_y{};
T last_z{};
};
typedef struct {
DCStack<std::string> stack;
std::unordered_map<int, std::string> array;
} Register;
typedef struct {
Stack<std::string> stack;
std::unordered_map<int, std::string> array;
} Register;
enum class radix_base : std::uint8_t { BIN = 2, OCT = 8, DEC = 10, HEX = 16 };
typedef struct {
unsigned int precision;
unsigned short iradix;
radix_base oradix;
} Parameters;
enum class radix_base : std::uint8_t { BIN = 2, OCT = 8, DEC = 10, HEX = 16 };
typedef struct {
unsigned int precision;
unsigned short iradix;
radix_base oradix;
} Parameters;
}

View File

@ -71,7 +71,7 @@ std::optional<std::string> Evaluate::eval() {
// Set up environment
init_environment();
for(size_t idx = 0; idx < this->expr.size(); idx++) {
for(std::size_t idx = 0; idx < this->expr.size(); idx++) {
std::optional<std::string> err = std::nullopt;
auto token = this->expr.at(idx);
@ -123,7 +123,7 @@ std::optional<std::string> Evaluate::parse_base_n(const std::string& token) {
return std::nullopt;
}
std::optional<std::string> Evaluate::parse_macro(size_t &idx) {
std::optional<std::string> Evaluate::parse_macro(std::size_t &idx) {
// A macro is any string surrounded by square brackets
std::string dc_macro;
bool closing_bracket = false;
@ -250,8 +250,8 @@ std::optional<std::string> Evaluate::parse_register_command(std::string token) {
// i.e., initialize a new instance of register 'reg_name'
this->regs.erase(reg_name);
this->regs.insert(
std::make_pair(reg_name, Register{
DCStack<std::string>(),
std::make_pair(reg_name, dc::Register{
dc::Stack<std::string>(),
std::unordered_map<int, std::string>()
})
);
@ -279,8 +279,8 @@ std::optional<std::string> Evaluate::parse_register_command(std::string token) {
if(it != this->regs.end()) { // Register exists
it->second.stack.push(head);
} else { // Register doesn't exist
this->regs[reg_name] = Register{
DCStack<std::string>(),
this->regs[reg_name] = dc::Register{
dc::Stack<std::string>(),
std::unordered_map<int, std::string>()
};
}
@ -359,8 +359,8 @@ std::optional<std::string> Evaluate::parse_array_command(std::string token) {
it->second.array.erase(idx);
it->second.array.insert(std::pair<int, std::string>(idx, arr_val));
} else { // Register doesn't exist
this->regs[reg_name] = Register{
DCStack<std::string>(),
this->regs[reg_name] = dc::Register{
dc::Stack<std::string>(),
std::unordered_map<int, std::string>{{idx, arr_val}}
};
}

View File

@ -11,15 +11,15 @@
class Evaluate {
public:
Evaluate(const std::vector<std::string>& e, std::unordered_map<char, Register> &r,
DCStack<std::string> &s, Parameters &p)
Evaluate(const std::vector<std::string>& e, std::unordered_map<char, dc::Register> &r,
dc::Stack<std::string> &s, dc::Parameters &p)
: expr(e), regs(r), stack(s), parameters(p) {}
Evaluate(std::unordered_map<char, Register> &r, DCStack<std::string> &s, Parameters &p)
Evaluate(std::unordered_map<char, dc::Register> &r, dc::Stack<std::string> &s, dc::Parameters &p)
: regs(r), stack(s), parameters(p) {}
std::optional<std::string> eval();
private:
std::optional<std::string> parse_macro(size_t &idx);
std::optional<std::string> parse_macro(std::size_t &idx);
std::optional<std::string> parse_macro_command(std::string token);
std::optional<std::string> parse_register_command(std::string token);
std::optional<std::string> parse_array_command(std::string token);
@ -28,8 +28,8 @@ private:
using op_factory_t = std::function<std::unique_ptr<IOperation>()>;
std::vector<std::string> expr;
std::unordered_map<char, Register> &regs;
std::unordered_map<char, dc::Register> &regs;
std::unordered_map<std::string, op_factory_t> op_factory;
DCStack<std::string> &stack;
Parameters &parameters;
dc::Stack<std::string> &stack;
dc::Parameters &parameters;
};

View File

@ -8,7 +8,7 @@
#include "macro.h"
#include "is_num.h"
std::optional<std::string> Macro::exec(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) {
std::optional<std::string> Macro::exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) {
std::optional<std::string> err = std::nullopt;
switch(this->op_type) {
@ -21,7 +21,7 @@ std::optional<std::string> Macro::exec(DCStack<std::string> &stack, Parameters &
return err;
}
std::optional<std::string> Macro::fn_execute(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) {
std::optional<std::string> Macro::fn_execute(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) {
// Check if stack has enough elements
if(stack.empty()) {
return "This operation does not work on empty stack";
@ -45,7 +45,7 @@ std::optional<std::string> Macro::fn_execute(DCStack<std::string> &stack, Parame
return std::nullopt;
}
std::optional<std::string> Macro::fn_evaluate_macro(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) {
std::optional<std::string> Macro::fn_evaluate_macro(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) {
// Check whether the main stack has enough elements
if(stack.size() < 2) {
return "This operation requires two elements";
@ -146,7 +146,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(DCStack<std::string> &stack,
return std::nullopt;
}
std::optional<std::string> Macro::fn_read_input(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) {
std::optional<std::string> Macro::fn_read_input(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) {
// Read user input from stdin
std::string user_input;

View File

@ -10,13 +10,13 @@ class Macro : public IOperation {
public:
Macro(const OPType op_t, const Operator o, const char dc_r) : op_type(op_t), op(o), dc_register(dc_r) {}
explicit Macro(const OPType op_t) : op_type(op_t) {}
std::optional<std::string> exec(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) override;
std::optional<std::string> exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) override;
static std::vector<std::string> split(const std::string& str);
private:
static std::optional<std::string> fn_execute(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs);
std::optional<std::string> fn_evaluate_macro(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs);
static std::optional<std::string> fn_read_input(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs);
static std::optional<std::string> fn_execute(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs);
std::optional<std::string> fn_evaluate_macro(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs);
static std::optional<std::string> fn_read_input(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs);
OPType op_type;
Operator op{};

View File

@ -6,7 +6,7 @@
#include "math.h"
#include "is_num.h"
std::optional<std::string> Math::exec(DCStack<std::string> &stack, Parameters &parameters, __attribute__((unused)) std::unordered_map<char, Register> &regs) {
std::optional<std::string> Math::exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, __attribute__((unused)) std::unordered_map<char, dc::Register> &regs) {
std::optional<std::string> err = std::nullopt;
switch(this->op_type) {
@ -34,7 +34,7 @@ std::optional<std::string> Math::exec(DCStack<std::string> &stack, Parameters &p
return err;
}
std::optional<std::string> Math::fn_add(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_add(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'+' requires two operands";
@ -42,8 +42,8 @@ std::optional<std::string> Math::fn_add(DCStack<std::string> &stack, Parameters
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -62,7 +62,7 @@ std::optional<std::string> Math::fn_add(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_sub(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_sub(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'-' requires two operands";
@ -70,8 +70,8 @@ std::optional<std::string> Math::fn_sub(DCStack<std::string> &stack, Parameters
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -100,7 +100,7 @@ std::optional<std::string> Math::fn_sub(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_mul(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_mul(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'*' requires two operands";
@ -108,8 +108,8 @@ std::optional<std::string> Math::fn_mul(DCStack<std::string> &stack, Parameters
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -128,7 +128,7 @@ std::optional<std::string> Math::fn_mul(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_div(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_div(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'/' requires two operands";
@ -136,8 +136,8 @@ std::optional<std::string> Math::fn_div(DCStack<std::string> &stack, Parameters
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -161,7 +161,7 @@ std::optional<std::string> Math::fn_div(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_mod(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_mod(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'%' requires two operands";
@ -169,8 +169,8 @@ std::optional<std::string> Math::fn_mod(DCStack<std::string> &stack, Parameters
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -194,7 +194,7 @@ std::optional<std::string> Math::fn_mod(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_div_mod(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_div_mod(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'~' requires two operands";
@ -202,8 +202,8 @@ std::optional<std::string> Math::fn_div_mod(DCStack<std::string> &stack, Paramet
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -229,7 +229,7 @@ std::optional<std::string> Math::fn_div_mod(DCStack<std::string> &stack, Paramet
return std::nullopt;
}
std::optional<std::string> Math::fn_mod_exp(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_mod_exp(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 3) {
return "'|' requires three operands";
@ -239,9 +239,9 @@ std::optional<std::string> Math::fn_mod_exp(DCStack<std::string> &stack, Paramet
// The first one is the modulus(n), the second one
// is the exponent(e) and the third one is the base(b)
auto len = stack.size()-1;
auto n = stack.at(len);
auto e = stack.at(len-1);
auto b = stack.at(len-2);
auto n = stack[len];
auto e = stack[len-1];
auto b = stack[len-2];
auto is_n_num = is_num<double>(n);
auto is_e_num = is_num<double>(e);
auto is_b_num = is_num<double>(b);
@ -278,7 +278,7 @@ std::optional<std::string> Math::fn_mod_exp(DCStack<std::string> &stack, Paramet
return std::nullopt;
}
std::optional<std::string> Math::fn_exp(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_exp(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.size() < 2) {
return "'^' requires two operands";
@ -286,8 +286,8 @@ std::optional<std::string> Math::fn_exp(DCStack<std::string> &stack, Parameters
// Extract two entries from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto y = stack.at(len-1);
auto x = stack[len];
auto y = stack[len-1];
auto is_x_num = is_num<double>(x);
auto is_y_num = is_num<double>(y);
@ -306,7 +306,7 @@ std::optional<std::string> Math::fn_exp(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_sqrt(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_sqrt(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'v' requires one operand";
@ -314,7 +314,7 @@ std::optional<std::string> Math::fn_sqrt(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -335,7 +335,7 @@ std::optional<std::string> Math::fn_sqrt(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_sin(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_sin(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'sin' requires one operand";
@ -343,7 +343,7 @@ std::optional<std::string> Math::fn_sin(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -360,7 +360,7 @@ std::optional<std::string> Math::fn_sin(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_cos(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_cos(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'cos' requires one operand";
@ -368,7 +368,7 @@ std::optional<std::string> Math::fn_cos(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -385,7 +385,7 @@ std::optional<std::string> Math::fn_cos(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_tan(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_tan(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'tan' requires one operand";
@ -393,7 +393,7 @@ std::optional<std::string> Math::fn_tan(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -410,7 +410,7 @@ std::optional<std::string> Math::fn_tan(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_asin(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_asin(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'asin' requires one operand";
@ -418,7 +418,7 @@ std::optional<std::string> Math::fn_asin(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -435,7 +435,7 @@ std::optional<std::string> Math::fn_asin(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_acos(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_acos(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'acos' requires one operand";
@ -443,7 +443,7 @@ std::optional<std::string> Math::fn_acos(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -460,7 +460,7 @@ std::optional<std::string> Math::fn_acos(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_atan(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_atan(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'atan' requires one operand";
@ -468,7 +468,7 @@ std::optional<std::string> Math::fn_atan(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -485,7 +485,7 @@ std::optional<std::string> Math::fn_atan(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_fact(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_fact(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'!' requires one operand";
@ -493,7 +493,7 @@ std::optional<std::string> Math::fn_fact(DCStack<std::string> &stack, Parameters
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
@ -506,7 +506,7 @@ std::optional<std::string> Math::fn_fact(DCStack<std::string> &stack, Parameters
factorial = 1;
}
for(size_t i = 2; i <= (size_t)val; i++) {
for(std::size_t i = 2; i <= (std::size_t)val; i++) {
factorial *= i;
}
@ -519,13 +519,13 @@ std::optional<std::string> Math::fn_fact(DCStack<std::string> &stack, Parameters
return std::nullopt;
}
std::optional<std::string> Math::fn_pi(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_pi(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
stack.push(trim_digits(std::numbers::pi, parameters.precision));
return std::nullopt;
}
std::optional<std::string> Math::fn_e(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Math::fn_e(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
stack.push(trim_digits(std::numbers::e, parameters.precision));
return std::nullopt;

View File

@ -5,27 +5,27 @@
class Math : public IOperation {
public:
explicit Math(const OPType op_t) : op_type(op_t) {}
std::optional<std::string> exec(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) override;
std::optional<std::string> exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) override;
private:
static std::optional<std::string> fn_add(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_sub(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_mul(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_div(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_mod(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_div_mod(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_mod_exp(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_exp(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_sqrt(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_sin(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_cos(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_tan(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_asin(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_acos(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_atan(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_fact(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_pi(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_e(DCStack<std::string> &stack, Parameters &parameters) ;
static std::optional<std::string> fn_add(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_sub(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_mul(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_div(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_mod(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_div_mod(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_mod_exp(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_exp(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_sqrt(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_sin(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_cos(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_tan(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_asin(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_acos(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_atan(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_fact(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_pi(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::optional<std::string> fn_e(dc::Stack<std::string> &stack, dc::Parameters &parameters) ;
static std::string trim_digits(double number, unsigned int precision);
OPType op_type;

View File

@ -5,7 +5,7 @@
class IOperation {
public:
virtual std::optional<std::string> exec(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) = 0;
virtual std::optional<std::string> exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) = 0;
virtual ~IOperation() = default;
};

View File

@ -6,10 +6,10 @@
#include "stack.h"
#include "is_num.h"
std::optional<std::string> Stack::exec(DCStack<std::string> &stack, Parameters &parameters, __attribute__((unused)) std::unordered_map<char, Register> &regs) {
std::optional<std::string> Stack::exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, __attribute__((unused)) std::unordered_map<char, dc::Register> &regs) {
std::optional<std::string> err = std::nullopt;
auto print_oradix = [&stack, &parameters, this](radix_base base) {
auto print_oradix = [&stack, &parameters, this](dc::radix_base base) {
auto old_rdx = parameters.oradix;
parameters.oradix = base;
auto res = fn_print(stack, parameters, false);
@ -21,9 +21,9 @@ std::optional<std::string> Stack::exec(DCStack<std::string> &stack, Parameters &
switch(this->op_type) {
case OPType::PCG: err = fn_print(stack, parameters, true); break;
case OPType::P: err = fn_print(stack, parameters, false); break;
case OPType::PBB: err = print_oradix(radix_base::BIN); break;
case OPType::PBO: err = print_oradix(radix_base::OCT); break;
case OPType::PBH: err = print_oradix(radix_base::HEX); break;
case OPType::PBB: err = print_oradix(dc::radix_base::BIN); break;
case OPType::PBO: err = print_oradix(dc::radix_base::OCT); break;
case OPType::PBH: err = print_oradix(dc::radix_base::HEX); break;
case OPType::CLR: stack.clear(); break;
case OPType::PH: err = fn_pop_head(stack); break;
case OPType::SO: err = fn_swap_xy(stack); break;
@ -46,7 +46,7 @@ std::optional<std::string> Stack::exec(DCStack<std::string> &stack, Parameters &
return err;
}
std::optional<std::string> Stack::fn_print(DCStack<std::string> &stack, Parameters &parameters, bool new_line) {
std::optional<std::string> Stack::fn_print(dc::Stack<std::string> &stack, dc::Parameters &parameters, bool new_line) {
// Check if the stack is empty
if(stack.empty()) {
return "Cannot print empty stack";
@ -58,7 +58,7 @@ std::optional<std::string> Stack::fn_print(DCStack<std::string> &stack, Paramete
}
switch(parameters.oradix) {
case radix_base::DEC: {
case dc::radix_base::DEC: {
if(new_line) {
std::cout << stack.pop(false) << std::endl;
} else {
@ -66,17 +66,17 @@ std::optional<std::string> Stack::fn_print(DCStack<std::string> &stack, Paramete
}
break;
}
case radix_base::BIN: {
case dc::radix_base::BIN: {
auto head = std::stol(stack.pop(false));
std::cout << to_bin(head) << 'b' << std::endl;
break;
}
case radix_base::OCT: {
case dc::radix_base::OCT: {
auto head = std::stol(stack.pop(false));
std::cout << std::oct << head << 'o' << std::dec << std::endl;
break;
}
case radix_base::HEX: {
case dc::radix_base::HEX: {
auto head = std::stol(stack.pop(false));
std::cout << std::hex << std::uppercase << head << 'h'
<< std::dec << std::nouppercase << std::endl;
@ -88,7 +88,7 @@ std::optional<std::string> Stack::fn_print(DCStack<std::string> &stack, Paramete
return std::nullopt;
}
std::optional<std::string> Stack::fn_pop_head(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_pop_head(dc::Stack<std::string> &stack) {
// Check if stack is empty
if(stack.empty()) {
return "'R' does not work on empty stack";
@ -100,7 +100,7 @@ std::optional<std::string> Stack::fn_pop_head(DCStack<std::string> &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_swap_xy(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_swap_xy(dc::Stack<std::string> &stack) {
// Check if the stack has enough elements
if(stack.size() < 2) {
return "'r' requires two elements";
@ -108,16 +108,16 @@ std::optional<std::string> Stack::fn_swap_xy(DCStack<std::string> &stack) {
// Swap top two elements
auto len = stack.size()-1;
auto x = stack.at(len);
auto x = stack[len];
stack.copy_xyz();
stack.at(len) = stack.at(len-1);
stack.at(len-1) = x;
stack[len] = stack[len-1];
stack[len-1] = x;
return std::nullopt;
}
std::optional<std::string> Stack::fn_dup_head(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_dup_head(dc::Stack<std::string> &stack) {
// Check if the stack has enough elements
if(stack.empty()) {
return "'d' requires one element";
@ -129,29 +129,29 @@ std::optional<std::string> Stack::fn_dup_head(DCStack<std::string> &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_print_stack(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_print_stack(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
const auto& const_ref = stack.get_ref();
switch(parameters.oradix) {
case radix_base::DEC: {
case dc::radix_base::DEC: {
for(auto & it : std::ranges::reverse_view(const_ref)) {
std::cout << it << std::endl;
}
break;
}
case radix_base::BIN: {
case dc::radix_base::BIN: {
for(auto & it : std::ranges::reverse_view(const_ref)) {
std::cout << to_bin(std::stol(it)) << 'b' << std::endl;
}
break;
}
case radix_base::OCT: {
case dc::radix_base::OCT: {
for(auto & it : std::ranges::reverse_view(const_ref)) {
std::cout << std::oct << std::stol(it) << 'o' << std::dec << std::endl;
}
break;
}
case radix_base::HEX: {
case dc::radix_base::HEX: {
for(auto & it : std::ranges::reverse_view(const_ref)) {
std::cout << std::hex << std::uppercase << std::stol(it) << 'h'
<< std::dec << std::nouppercase << std::endl;
@ -163,7 +163,7 @@ std::optional<std::string> Stack::fn_print_stack(DCStack<std::string> &stack, Pa
return std::nullopt;
}
std::optional<std::string> Stack::fn_head_size(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_head_size(dc::Stack<std::string> &stack) {
// Check if the stack has enough elements
if(stack.empty()) {
return "'Z' does not work on empty stack";
@ -179,7 +179,7 @@ std::optional<std::string> Stack::fn_head_size(DCStack<std::string> &stack) {
stack.copy_xyz();
stack.pop(true);
size_t len = 0;
std::size_t len = 0;
while(num > 0) {
num /= 10;
len++;
@ -197,13 +197,13 @@ std::optional<std::string> Stack::fn_head_size(DCStack<std::string> &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_stack_size(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_stack_size(dc::Stack<std::string> &stack) {
stack.push(std::to_string(stack.size()));
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_precision(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_set_precision(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'k' requires one operand";
@ -224,13 +224,13 @@ std::optional<std::string> Stack::fn_set_precision(DCStack<std::string> &stack,
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_precision(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_get_precision(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
stack.push(std::to_string(parameters.precision));
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_oradix(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_set_oradix(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'o' requires one operand";
@ -246,23 +246,23 @@ std::optional<std::string> Stack::fn_set_oradix(DCStack<std::string> &stack, Par
// 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;
case 2: parameters.oradix = dc::radix_base::BIN; break;
case 8: parameters.oradix = dc::radix_base::OCT; break;
case 10: parameters.oradix = dc::radix_base::DEC; break;
case 16: parameters.oradix = dc::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(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_get_oradix(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
stack.push(std::to_string(static_cast<int>(parameters.oradix)));
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_iradix(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_set_iradix(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
// Check if stack has enough elements
if(stack.empty()) {
return "'i' requires one operand";
@ -283,13 +283,13 @@ std::optional<std::string> Stack::fn_set_iradix(DCStack<std::string> &stack, Par
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_iradix(DCStack<std::string> &stack, Parameters &parameters) {
std::optional<std::string> Stack::fn_get_iradix(dc::Stack<std::string> &stack, dc::Parameters &parameters) {
stack.push(std::to_string(parameters.iradix));
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_lastx(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_get_lastx(dc::Stack<std::string> &stack) {
// Retrieve last x from the stack and push it back
auto last_x = stack.get_last_x();
last_x.empty() ? stack.push("0") : stack.push(last_x);
@ -297,7 +297,7 @@ std::optional<std::string> Stack::fn_get_lastx(DCStack<std::string> &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_lasty(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_get_lasty(dc::Stack<std::string> &stack) {
// Retrieve last y from the stack and push it back
auto last_y = stack.get_last_y();
last_y.empty() ? stack.push("0") : stack.push(last_y);
@ -305,7 +305,7 @@ std::optional<std::string> Stack::fn_get_lasty(DCStack<std::string> &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_lastz(DCStack<std::string> &stack) {
std::optional<std::string> Stack::fn_get_lastz(dc::Stack<std::string> &stack) {
// Retrieve last y from the stack and push it back
auto last_z = stack.get_last_z();
last_z.empty() ? stack.push("0") : stack.push(last_z);

View File

@ -5,25 +5,25 @@
class Stack : public IOperation {
public:
explicit Stack(const OPType op_t) : op_type(op_t) {}
std::optional<std::string> exec(DCStack<std::string> &stack, Parameters &parameters, std::unordered_map<char, Register> &regs) override;
std::optional<std::string> exec(dc::Stack<std::string> &stack, dc::Parameters &parameters, std::unordered_map<char, dc::Register> &regs) override;
private:
std::optional<std::string> fn_print(DCStack<std::string> &stack, Parameters &parameters, bool new_line);
static std::optional<std::string> fn_pop_head(DCStack<std::string> &stack);
static std::optional<std::string> fn_swap_xy(DCStack<std::string> &stack);
static std::optional<std::string> fn_dup_head(DCStack<std::string> &stack);
std::optional<std::string> fn_print_stack(DCStack<std::string> &stack, Parameters &parameters);
static std::optional<std::string> fn_head_size(DCStack<std::string> &stack);
static std::optional<std::string> fn_stack_size(DCStack<std::string> &stack);
static std::optional<std::string> fn_set_precision(DCStack<std::string> &stack, Parameters &parameters);
static std::optional<std::string> fn_get_precision(DCStack<std::string> &stack, Parameters &parameters);
static std::optional<std::string> fn_set_oradix(DCStack<std::string> &stack, Parameters &parameters);
static std::optional<std::string> fn_get_oradix(DCStack<std::string> &stack, Parameters &parameters);
static std::optional<std::string> fn_set_iradix(DCStack<std::string> &stack, Parameters &parameters);
static std::optional<std::string> fn_get_iradix(DCStack<std::string> &stack, Parameters &parameters);
std::optional<std::string> fn_get_lastx(DCStack<std::string> &stack);
std::optional<std::string> fn_get_lasty(DCStack<std::string> &stack);
std::optional<std::string> fn_get_lastz(DCStack<std::string> &stack);
std::optional<std::string> fn_print(dc::Stack<std::string> &stack, dc::Parameters &parameters, bool new_line);
static std::optional<std::string> fn_pop_head(dc::Stack<std::string> &stack);
static std::optional<std::string> fn_swap_xy(dc::Stack<std::string> &stack);
static std::optional<std::string> fn_dup_head(dc::Stack<std::string> &stack);
std::optional<std::string> fn_print_stack(dc::Stack<std::string> &stack, dc::Parameters &parameters);
static std::optional<std::string> fn_head_size(dc::Stack<std::string> &stack);
static std::optional<std::string> fn_stack_size(dc::Stack<std::string> &stack);
static std::optional<std::string> fn_set_precision(dc::Stack<std::string> &stack, dc::Parameters &parameters);
static std::optional<std::string> fn_get_precision(dc::Stack<std::string> &stack, dc::Parameters &parameters);
static std::optional<std::string> fn_set_oradix(dc::Stack<std::string> &stack, dc::Parameters &parameters);
static std::optional<std::string> fn_get_oradix(dc::Stack<std::string> &stack, dc::Parameters &parameters);
static std::optional<std::string> fn_set_iradix(dc::Stack<std::string> &stack, dc::Parameters &parameters);
static std::optional<std::string> fn_get_iradix(dc::Stack<std::string> &stack, dc::Parameters &parameters);
std::optional<std::string> fn_get_lastx(dc::Stack<std::string> &stack);
std::optional<std::string> fn_get_lasty(dc::Stack<std::string> &stack);
std::optional<std::string> fn_get_lastz(dc::Stack<std::string> &stack);
constexpr std::string to_bin(auto num);
OPType op_type;