Added 'zR' option and fixed bug related to registers
dc / build (push) Successful in 15s
Details
dc / build (push) Successful in 15s
Details
This commit is contained in:
parent
5de860a089
commit
19ceac3e88
8
man.md
8
man.md
|
@ -367,6 +367,14 @@ The previous of the register becomes inaccessible, thus it follows the LIFO poli
|
|||
Pop the value off the top of register _r_'s stack and push it onto the main stack. The previous value in register _r_'s stack, if any,
|
||||
is now accessible via the **l**r command.
|
||||
|
||||
**c**`r`
|
||||
|
||||
Clear the register `r` from memory.
|
||||
|
||||
**z**`r`
|
||||
|
||||
Pushes the current register's stack depth: the number of objects on the register's stack before the execution of the **z**`r` command.
|
||||
|
||||
## Register(Array)
|
||||
Arrays support random access through an index. You can store a value in an array and retrieve it later.
|
||||
|
||||
|
|
30
src/eval.cpp
30
src/eval.cpp
|
@ -14,7 +14,8 @@
|
|||
VAL.at(0) == '=' || VAL.at(0) == '!'))
|
||||
#define REGISTER_COND(VAL) ((VAL.length() == 2) && \
|
||||
(VAL.at(0) == 's' || VAL.at(0) == 'S' || \
|
||||
VAL.at(0) == 'l' || VAL.at(0) == 'L'))
|
||||
VAL.at(0) == 'l' || VAL.at(0) == 'L' || \
|
||||
VAL.at(0) == 'c' || VAL.at(0) == 'z'))
|
||||
#define ARRAY_COND(VAL) ((VAL.length() == 2) && \
|
||||
(VAL.at(0) == ':' || VAL.at(0) == ';'))
|
||||
|
||||
|
@ -43,6 +44,8 @@ void Evaluate::init_environment() {
|
|||
this->op_factory.emplace("e", MAKE_UNIQUE_PTR(Mathematics, OPType::E));
|
||||
this->op_factory.emplace("@", MAKE_UNIQUE_PTR(Mathematics, OPType::RND));
|
||||
this->op_factory.emplace("$", MAKE_UNIQUE_PTR(Mathematics, OPType::INT));
|
||||
// Statistical operations
|
||||
|
||||
// Bitwise operations
|
||||
this->op_factory.emplace("{", MAKE_UNIQUE_PTR(Bitwise, OPType::BAND));
|
||||
this->op_factory.emplace("}", MAKE_UNIQUE_PTR(Bitwise, OPType::BOR));
|
||||
|
@ -262,13 +265,17 @@ std::optional<std::string> Evaluate::parse_register_command(std::string token) {
|
|||
auto reg_name = token.at(1);
|
||||
auto head = this->stack.pop(true);
|
||||
|
||||
|
||||
// if register's stack exist, overwrite top of the stack
|
||||
// If register's stack exist, overwrite top of the stack
|
||||
// Otherwise allocate a new instance of the register
|
||||
auto it = this->regs.find(reg_name);
|
||||
if(it != this->regs.end()) { // Register exist
|
||||
auto head_idx = it->second.stack.size()-1;
|
||||
it->second.stack[head_idx] = head;
|
||||
// If register exists but stack is empty, push the first element
|
||||
if(it->second.stack.empty()) {
|
||||
it->second.stack.push(head);
|
||||
} else {
|
||||
auto head_idx = it->second.stack.size()-1;
|
||||
it->second.stack[head_idx] = head;
|
||||
}
|
||||
} else { // Register does not exist
|
||||
this->regs[reg_name] = dc::Register{
|
||||
dc::Stack<std::string>(),
|
||||
|
@ -322,7 +329,7 @@ std::optional<std::string> Evaluate::parse_register_command(std::string token) {
|
|||
// Otherwise, pop an element from the register's stack and push it onto the main stack
|
||||
auto value = this->regs[reg_name].stack.pop(true);
|
||||
this->stack.push(value);
|
||||
} else {
|
||||
} else if(token.at(0) == 'l') {
|
||||
// Otherwise retrieve the register name and push its value
|
||||
// to the stack without altering the register's stack.
|
||||
// If the register is empty, push '0' to the stack
|
||||
|
@ -338,6 +345,17 @@ std::optional<std::string> Evaluate::parse_register_command(std::string token) {
|
|||
// Otherwise, peek an element from the register's stack and push it onto the main stack
|
||||
auto value = this->regs[reg_name].stack.pop(false);
|
||||
this->stack.push(value);
|
||||
} else if(token.at(0) == 'c') {
|
||||
// Delete register from memory
|
||||
auto reg_name = token.at(1);
|
||||
this->regs.erase(reg_name);
|
||||
} else if(token.at(0) == 'z') {
|
||||
// Pushes register's stack size on main stack
|
||||
auto reg_name = token.at(1);
|
||||
auto size = std::to_string(this->regs[reg_name].stack.size());
|
||||
this->stack.push(size);
|
||||
} else {
|
||||
return "Unmanaged error";
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
|
|
|
@ -14,6 +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, RND, INT,
|
||||
// Statistical operations
|
||||
PERM, COMB, SUMX, SUMXX, MEAN, SDEV, LREG,
|
||||
// Bitwise operations
|
||||
BAND, BOR, BNOT, BXOR, BSL, BSR,
|
||||
// Stack operations
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
utest() {
|
||||
PROGRAM="$PWD/build/dc"
|
||||
# Fill some values into the register
|
||||
EXPECTED="1 2"
|
||||
ACTUAL=$("$PROGRAM" -e '1 2 SA SA 2 0 :A lA p. 0 ;A p cA')
|
||||
assert_eq "$EXPECTED" "$ACTUAL"
|
||||
|
||||
# Test whether the register stack is empty
|
||||
EXPECTED="0"
|
||||
ACTUAL=$("$PROGRAM" -e 'lA p')
|
||||
assert_eq "$EXPECTED" "$ACTUAL"
|
||||
|
||||
# Test whether the register array is empty
|
||||
EXPECTED="Register 'A' is undefined"
|
||||
ACTUAL=$("$PROGRAM" -e '0 ;A' 2>&1) || true
|
||||
assert_eq "$EXPECTED" "$ACTUAL"
|
||||
}
|
||||
# vim: ts=4 sw=4 softtabstop=4 expandtab:
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
utest() {
|
||||
PROGRAM="$PWD/build/dc"
|
||||
# Fill some values into the register
|
||||
EXPECTED="4"
|
||||
ACTUAL=$("$PROGRAM" -e '1 2 3 4 SA SA SA SA zA p')
|
||||
assert_eq "$EXPECTED" "$ACTUAL"
|
||||
|
||||
# Test with empty register
|
||||
EXPECTED="0"
|
||||
ACTUAL=$("$PROGRAM" -e 'zA p')
|
||||
assert_eq "$EXPECTED" "$ACTUAL"
|
||||
}
|
||||
# vim: ts=4 sw=4 softtabstop=4 expandtab:
|
Loading…
Reference in New Issue