diff --git a/demos/calc.cpp b/demos/calc.cpp index df4c6bf..abe235e 100644 --- a/demos/calc.cpp +++ b/demos/calc.cpp @@ -5,6 +5,7 @@ #include "guecs.hpp" #include "constants.hpp" #include +#include #define FSM_DEBUG 1 #include "fsm.hpp" @@ -14,94 +15,114 @@ constexpr const int WINDOW_HEIGHT=400; using std::string, std::wstring; -const std::unordered_map LABELS { - {"readout", L""}, {"clear", L"CLR"}, {"btn0", L"0"}, {"btn1", L"1"}, - {"btn2", L"2"}, {"btn3", L"3"}, {"btn4", L"4"}, - {"btn5", L"5"}, {"btn6", L"6"}, {"btn7", L"7"}, - {"btn8", L"8"}, {"btn9", L"9"}, {"mult", L"*"}, - {"minus", L"-"}, {"plus", L"+"}, {"neg", L"±"}, - {"div", L"/"}, {"eq", L"="} }; - enum class Event { NUMBER, ADD, SUB, MUL, - DIV, CLR, NOT, EQ, + DIV, CLR, NEG, EQ, PUSH, POP }; -enum class State { - START, - CALCULATING, - CLEARED, - DISPLAYED -}; - - -struct Calculator : DeadSimpleFSM { +const std::unordered_map LABELS { + {"readout", L""}, {"clear", L"CLR"}, {"btn0", L"0"}, {"btn1", L"1"}, + {"btn2", L"2"}, {"btn3", L"3"}, {"btn4", L"4"}, + {"btn5", L"5"}, {"btn6", L"6"}, {"btn7", L"7"}, + {"btn8", L"8"}, {"btn9", L"9"}, {"mul", L"*"}, + {"sub", L"-"}, {"add", L"+"}, {"neg", L"±"}, + {"div", L"/"}, {"eq", L"="}, + {"push", L"^"}, {"pop", L"v"} }; + +const std::unordered_map EVENTS { + {L'0', Event::NUMBER}, {L'1', Event::NUMBER}, + {L'2', Event::NUMBER}, {L'3', Event::NUMBER}, + {L'4', Event::NUMBER}, {L'5', Event::NUMBER}, + {L'6', Event::NUMBER}, {L'7', Event::NUMBER}, + {L'8', Event::NUMBER}, {L'9', Event::NUMBER}, + {L'*', Event::MUL}, {L'-', Event::SUB}, + {L'+', Event::ADD}, {L'/', Event::DIV}, + {L'C', Event::CLR}, {L'^', Event::PUSH}, + {L'±', Event::NEG}, {L'v', Event::POP}, + {L'=', Event::EQ} }; + + +struct Calculator { wstring input; - double value = 0.0; - - void event(Event ev, wchar_t op) { - switch($state) { - FSM_STATE(State, START, ev, op); - FSM_STATE(State, CALCULATING, ev, op); - FSM_STATE(State, CLEARED, ev, op); - FSM_STATE(State, DISPLAYED, ev, op); + std::deque stack; + double temp = 0.0; + double result = 0.0; + + void dump() { + fmt::println("STACK: "); + for(auto num : stack) { + fmt::println("{}", num); } } - void START(Event ev, wchar_t op) { - if(ev == Event::NUMBER) { - input += op; - state(State::CALCULATING); + void do_op(Event ev) { + if(stack.size() < 2) return; + using enum Event; + + double left = stack.back(); + stack.pop_back(); + double right = stack.back(); + stack.pop_back(); + + switch(ev) { + case MUL: + temp = left * right; + break; + case ADD: + temp = left + right; + break; + case SUB: + temp = left - right; + break; + case DIV: + temp = left / right; + break; + default: + dbc::sentinel("invalid op passed to op()"); } + + stack.push_back(temp); } - void CALCULATING(Event ev, wchar_t op) { + void event(Event ev, wchar_t op) { using enum Event; - switch(ev) { case NUMBER: input += op; break; - case ADD: - value += std::stof(input); - input = L""; - break; - case SUB: - value -= std::stof(input); + case MUL: do_op(MUL); break; + case ADD: do_op(ADD); break; + case SUB: do_op(SUB); break; + case DIV: do_op(DIV); break; + case CLR: input = L""; + stack.clear(); break; - case MUL: - value *= std::stof(input); - input = L""; + case POP: + if(!stack.empty()) { + temp = stack.back(); + input = fmt::format(L"{}", temp); + stack.pop_back(); + } break; - case DIV: - value /= std::stof(input); - input = L""; + case PUSH: + if(input.size() > 0) { + temp = std::stof(input); + input = L""; + stack.push_back(temp); + } break; - case NOT: - value = std::stof(input) * -1; - input = L""; + case NEG: + if(input.size() > 0) { + temp = std::stof(input); + input = fmt::format(L"{}", temp * -1); + } break; case EQ: - value = std::stof(input); - break; - case CLR: - input = L""; - state(State::CLEARED); break; } - } - - void CLEARED(Event ev, wchar_t op) { - if(ev == Event::NUMBER) { - input += op; - state(State::CALCULATING); - } - } - void DISPLAYED(Event ev, wchar_t op) { - fmt::println(L"ev={}, op={}", (int)ev, op); - state(State::CALCULATING); + dump(); } }; @@ -112,11 +133,13 @@ struct CalculatorUI { CalculatorUI() { $gui.position(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); $gui.layout( - "[*%(400)readout|_|_|_|clear]" - "[btn7|btn8|btn9|mult]" - "[btn4|btn5|btn6|minus]" - "[btn1|btn2|btn3|plus]" - "[neg|btn0|eq|div]"); + "[*%(400)readout|_|_|_]" + "[push|pop|clear|eq]" + "[add|sub|mul|div]" + "[btn7|btn8|btn9]" + "[btn4|btn5|btn6]" + "[btn1|btn2|btn3]" + "[neg|btn0|_]"); } void init() { @@ -133,9 +156,10 @@ struct CalculatorUI { $gui.set(id, {L"", 40}); } else { $gui.set(id, { label }); + wchar_t op = label[0]; $gui.set(id, { - [&, name](auto, auto) { handle_button(label[0]); } - }); + [&, op](auto, auto) { handle_button(op); } + }); } } @@ -152,52 +176,13 @@ struct CalculatorUI { } void handle_button(wchar_t op) { - using enum Event; - - switch(op) { - case L'0': - case L'1': - case L'2': - case L'3': - case L'4': - case L'5': - case L'6': - case L'7': - case L'8': - case L'9': - $fsm.event(NUMBER, op); - break; - case L'*': - $fsm.event(MUL, op); - break; - case L'-': - $fsm.event(SUB, op); - break; - case L'+': - $fsm.event(ADD, op); - break; - case L'/': - $fsm.event(DIV, op); - break; - case L'±': - $fsm.event(NOT, op); - break; - case L'=': - $fsm.event(EQ, op); - break; - case L'C': - $fsm.event(CLR, op); - break; - } - + $fsm.event(EVENTS.at(op), op); auto readout = $gui.entity("readout"); auto& label = $gui.get(readout); label.update($fsm.input); } }; - - int main() { sound::init(); shaders::init();