From 270077ee6469e2938b5982a20ffc05ca97e4e2f2 Mon Sep 17 00:00:00 2001 From: Conlan Wesson Date: Sat, 19 Aug 2023 13:44:22 -0700 Subject: [PATCH] Add TRDS, currently only age of the universe supported --- src/Defunge.cpp | 6 +-- src/Field.cpp | 19 +++----- src/FingerprintStrategy.cpp | 2 + src/FishStrategy.cpp | 6 +-- src/FungeRunner.cpp | 3 -- src/FungeUniverse.cpp | 56 +++++++++++++---------- src/Stack.cpp | 8 ++++ src/Unefunge98Strategy.cpp | 4 +- src/fingerprint/FingerprintTRDS.cpp | 27 +++++++++++ src/fingerprint/include/FingerprintTRDS.h | 21 +++++++++ src/include/FingerprintStrategy.h | 4 +- src/include/FungeStateNormal.h | 4 +- src/include/FungeUniverse.h | 2 + src/include/Stack.h | 6 +++ src/include/funge_types.h | 5 +- src/util/include/FishUtil.h | 8 ++-- test/99.bf | 4 +- test/smoketest.sh | 1 + test/test_int.bf | 4 +- test/test_multi2.fmv | 2 +- test/test_trds.b98 | 1 + 21 files changed, 129 insertions(+), 64 deletions(-) create mode 100644 src/fingerprint/FingerprintTRDS.cpp create mode 100644 src/fingerprint/include/FingerprintTRDS.h create mode 100644 test/test_trds.b98 diff --git a/src/Defunge.cpp b/src/Defunge.cpp index e02b280..3a68110 100644 --- a/src/Defunge.cpp +++ b/src/Defunge.cpp @@ -211,11 +211,7 @@ Defunge::Error Defunge::peekCommand(std::istringstream& iss){ iss >> c; if(c == 0){ for(size_t j = 0; j < stack->size(); ++j){ - std::cout << "[0] "; - for(size_t i = stack->at(j).size(); i > 0; --i){ - std::cout << stack->at(j).get(i) << " "; - } - std::cout << std::endl; + std::cout << stack->at(j) << std::endl; } }else{ size_t s = 0; diff --git a/src/Field.cpp b/src/Field.cpp index c29e6ca..619c470 100644 --- a/src/Field.cpp +++ b/src/Field.cpp @@ -259,25 +259,20 @@ void Field::put(const Vector& p, inst_t v){ field.erase(find); } for(size_t i = 0; i < p.size(); ++i){ - if(maxs[i] == p[i]){ - // scan for new max - dim_t max = std::numeric_limits::min() ; - for(auto s = field.cbegin(); s != field.cend(); ++s){ - if(s->first[i] > max){ - max = s->first[i]; - } - } - maxs[i] = max; - } - if(mins[i] == p[i]){ - // scan for new min + if(maxs[i] == p[i] || mins[i] == p[i]){ + // scan for new min/max dim_t min = std::numeric_limits::max(); + dim_t max = std::numeric_limits::min() ; for(auto s = field.cbegin(); s != field.cend(); ++s){ if(s->first[i] < min){ min = s->first[i]; } + if(s->first[i] > max){ + max = s->first[i]; + } } mins[i] = min; + maxs[i] = max; } } }else{ diff --git a/src/FingerprintStrategy.cpp b/src/FingerprintStrategy.cpp index d9e25a6..c8b6459 100644 --- a/src/FingerprintStrategy.cpp +++ b/src/FingerprintStrategy.cpp @@ -33,6 +33,7 @@ #include "FingerprintSTRN.h" #include "FingerprintSUBR.h" #include "FingerprintTOYS.h" +#include "FingerprintTRDS.h" #include "FungeUniverse.h" #include @@ -91,6 +92,7 @@ Fingerprint* FingerprintStrategy::loadBuiltin(uint64_t fingerprint){ case 0x5354524E: fing = new FingerprintSTRN(runner); break; case 0x53554252: fing = new FingerprintSUBR(runner); break; case 0x544F5953: fing = new FingerprintTOYS(runner); break; + case 0x54524453: fing = new FingerprintTRDS(runner); break; case FingerprintDynamic::ID: if(runner.getUniverse().getCreator() != nullptr){ fing = new FingerprintDynamic(runner, runner.getUniverse().getCreator()); diff --git a/src/FishStrategy.cpp b/src/FishStrategy.cpp index 5035955..4967e54 100644 --- a/src/FishStrategy.cpp +++ b/src/FishStrategy.cpp @@ -225,7 +225,7 @@ FungeError FishStrategy::instructionDiv(){ double x = pop(TOP); double y = pop(TOP); if(x == 0){ - return ERROR_UNSPEC; + return ERROR_DIV0; } push(TOP, y / x); return ERROR_NONE; @@ -236,7 +236,7 @@ FungeError FishStrategy::instructionModu(){ stack_t x = pop(TOP); stack_t y = pop(TOP); if(x == 0){ - return ERROR_UNSPEC; + return ERROR_DIV0; } push(TOP, y % x); return ERROR_NONE; @@ -511,8 +511,6 @@ FungeError FishStrategy::errorHandler(FungeError e){ return ERROR_NONE; } [[fallthrough]]; - case ERROR_NOTAVAIL: - case ERROR_UNSPEC: [[unlikely]] default: std::cerr << "something smells fishy..." << std::endl; runner.getUniverse().killAll(1); diff --git a/src/FungeRunner.cpp b/src/FungeRunner.cpp index f5b9743..461ec12 100644 --- a/src/FungeRunner.cpp +++ b/src/FungeRunner.cpp @@ -141,9 +141,6 @@ void FungeRunner::tick(){ break; case ERROR_BLOCK: break; - case ERROR_UNIMP: - case ERROR_NOTAVAIL: - case ERROR_UNSPEC: [[unlikely]] default: getUniverse().getDebugger().trap(*this); if(errorHandler != nullptr){ diff --git a/src/FungeUniverse.cpp b/src/FungeUniverse.cpp index 26d6ba6..e2e4a3a 100644 --- a/src/FungeUniverse.cpp +++ b/src/FungeUniverse.cpp @@ -11,6 +11,7 @@ namespace Funge { FungeUniverse::FungeUniverse(std::istream& file, Field::FileFormat fmt, const FungeConfig& cfg): + age(0), running(true), exitcode(0), config(cfg), @@ -31,6 +32,7 @@ FungeUniverse::FungeUniverse(std::istream& file, Field::FileFormat fmt, const Fu } FungeUniverse::FungeUniverse(const FungeConfig& cfg): + age(0), running(true), exitcode(0), config(cfg), @@ -56,9 +58,9 @@ FungeUniverse::~FungeUniverse(){ std::lock_guard guard(mutex); while(threads.size() > 0){ - std::thread* thread = threads.front(); - thread->join(); - delete thread; + std::thread* native = threads.front(); + native->join(); + delete native; } while(runners.size() > 0){ FungeRunner* runner = runners.front(); @@ -96,8 +98,8 @@ void FungeUniverse::addRunner(FungeRunner* runner){ std::lock_guard guard(mutex); runner->setMode(config.mode); if(config.threads == THREAD_NATIVE){ - std::thread* thread = new std::thread(std::ref(*runner)); - threads.push(thread); + std::thread* native = new std::thread(std::ref(*runner)); + threads.push(native); } runners.push_back(runner); semaphore.release(); @@ -109,40 +111,42 @@ void FungeUniverse::operator()(){ if(config.threads == THREAD_NATIVE){ mutex.lock(); while(threads.size() > 0){ - std::thread* thread = threads.front(); - if(thread->joinable()){ + std::thread* native = threads.front(); + if(native->joinable()){ mutex.unlock(); - thread->join(); + native->join(); mutex.lock(); } threads.pop(); - delete thread; + delete native; } mutex.unlock(); }else{ mutex.lock(); while(runners.size() > 0){ - FungeRunner* thread = runners.front(); + for(auto it = runners.begin(); it != runners.end(); ){ + FungeRunner* runner = *it; - mutex.unlock(); - if(thread->isRunning()){ - thread->tick(); - } - mutex.lock(); + mutex.unlock(); + if(runner->isRunning()){ + runner->tick(); + } + mutex.lock(); - runners.pop_front(); - if(&thread->getUniverse() == this){ - if(thread->isRunning()){ - runners.push_back(thread); + if(&runner->getUniverse() == this){ + if(runner->isRunning()){ + ++it; + }else{ + debug.endThread(*runner); + it = runners.erase(it); + } }else{ - debug.endThread(*thread); - delete thread; - cv.notify_all(); + it = runners.erase(it); } - }else{ - cv.notify_all(); } + ++age; } + cv.notify_all(); mutex.unlock(); } } @@ -251,6 +255,10 @@ FungeMode FungeUniverse::getMode() const { return config.mode; } +size_t FungeUniverse::getAge() const { + return age; +} + bool FungeUniverse::isMode(FungeMode m) const { return !!(config.mode & m); } diff --git a/src/Stack.cpp b/src/Stack.cpp index b6d2272..a75718f 100644 --- a/src/Stack.cpp +++ b/src/Stack.cpp @@ -111,4 +111,12 @@ void Stack::setMode(FungeMode m){ mode = m; } +std::ostream& operator<<(std::ostream& os, const Stack& rhs){ + os << "[0] "; + for(auto i : rhs.stack){ + os << i << " "; + } + return os; +} + } diff --git a/src/Unefunge98Strategy.cpp b/src/Unefunge98Strategy.cpp index c1089c7..828da3f 100644 --- a/src/Unefunge98Strategy.cpp +++ b/src/Unefunge98Strategy.cpp @@ -176,7 +176,7 @@ FungeError Unefunge98Strategy::instructionUnder(){ } } }else{ - ret = ERROR_UNSPEC; + ret = ERROR_NOSTACK; } return ret; } @@ -228,7 +228,7 @@ FungeError Unefunge98Strategy::instructionEnd(){ } stack.pop(); }else{ - ret = ERROR_UNSPEC; + ret = ERROR_NOSTACK; } if(runner.isMode(FUNGE_MODE_SWITCH)){ diff --git a/src/fingerprint/FingerprintTRDS.cpp b/src/fingerprint/FingerprintTRDS.cpp new file mode 100644 index 0000000..eda4bdb --- /dev/null +++ b/src/fingerprint/FingerprintTRDS.cpp @@ -0,0 +1,27 @@ +/** + * @file FingerprintTRDS.cpp + * IP travel in time and space. + * @author Conlan Wesson + */ + +#include "FingerprintTRDS.h" +#include "FungeUniverse.h" + +namespace Funge { + +FingerprintTRDS::FingerprintTRDS(FungeRunner& r) : + Fingerprint(r, {'P'}) +{} + +FungeError FingerprintTRDS::execute(inst_t cmd){ + switch(cmd){ + case 'P':{ + stack.top().push(runner.getUniverse().getAge()); + } break; + default: + return ERROR_UNIMP; + } + return ERROR_NONE; +} + +} diff --git a/src/fingerprint/include/FingerprintTRDS.h b/src/fingerprint/include/FingerprintTRDS.h new file mode 100644 index 0000000..903cb0c --- /dev/null +++ b/src/fingerprint/include/FingerprintTRDS.h @@ -0,0 +1,21 @@ +/** + * @file FingerprintTRDS.h + * IP travel in time and space. + * @author Conlan Wesson + */ + +#pragma once + +#include "Fingerprint.h" + +namespace Funge { + +class FingerprintTRDS : public Fingerprint { + public: + explicit FingerprintTRDS(FungeRunner& r); + virtual ~FingerprintTRDS() = default; + + virtual FungeError execute(inst_t cmd) override; +}; + +} diff --git a/src/include/FingerprintStrategy.h b/src/include/FingerprintStrategy.h index 8e96e3a..7134485 100644 --- a/src/include/FingerprintStrategy.h +++ b/src/include/FingerprintStrategy.h @@ -8,7 +8,7 @@ #include "FungeStrategy.h" #include "Fingerprint.h" -#include +#include #include namespace Funge { @@ -30,7 +30,7 @@ class FingerprintStrategy : public FungeStrategy { std::string intToStr(uint64_t i); void activate(Fingerprint* fing); - std::map available; + std::unordered_map available; std::vector loaded; }; diff --git a/src/include/FungeStateNormal.h b/src/include/FungeStateNormal.h index 005b234..072426c 100644 --- a/src/include/FungeStateNormal.h +++ b/src/include/FungeStateNormal.h @@ -9,7 +9,7 @@ #include "FungeState.h" #include "FungeStrategy.h" #include "FungeSemantic.h" -#include +#include #include namespace Funge { @@ -29,7 +29,7 @@ class FungeStateNormal : public FungeState { FungeStateNormal& operator=(const FungeStateNormal&) = delete; protected: - std::map> semantics; + std::unordered_map> semantics; }; } diff --git a/src/include/FungeUniverse.h b/src/include/FungeUniverse.h index 954bfee..2879839 100644 --- a/src/include/FungeUniverse.h +++ b/src/include/FungeUniverse.h @@ -116,6 +116,7 @@ class FungeUniverse { void clearMode(FungeMode m); void toggleMode(FungeMode m); FungeMode getMode() const; + size_t getAge() const; bool isMode(FungeMode m) const; bool allowConcurrent() const; bool allowExecute() const; @@ -124,6 +125,7 @@ class FungeUniverse { bool invertHL() const; private: + size_t age; bool running; int exitcode; FungeConfig config; diff --git a/src/include/Stack.h b/src/include/Stack.h index 9fae7d6..f113641 100644 --- a/src/include/Stack.h +++ b/src/include/Stack.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace Funge { class StackStack; @@ -85,6 +86,11 @@ class Stack { * @note FUNGE_MODE_INVERT pushes to the bottom of the stack. */ void setMode(FungeMode m); + + /** + * Output stream operator. + */ + friend std::ostream& operator<<(std::ostream& os, const Stack& rhs); private: FungeMode mode; diff --git a/src/include/funge_types.h b/src/include/funge_types.h index 2c5861c..d6e1635 100644 --- a/src/include/funge_types.h +++ b/src/include/funge_types.h @@ -137,9 +137,12 @@ enum FungeError { ERROR_NONE, ///< No error. ERROR_SKIP, ///< Skip instruction. ERROR_BLOCK, ///< Instruction blocked. - ERROR_UNIMP, ///< Unimplemented unstruction. + ERROR_UNIMP, ///< Unimplemented instruction. ERROR_NOTAVAIL, ///< Feature not available. ERROR_UNSPEC, ///< General execution error. + ERROR_DIV0, ///< Divide by zero. + ERROR_EMPTY, ///< Not enough elements in stack. + ERROR_NOSTACK, ///< Stack does not exist. }; } diff --git a/src/util/include/FishUtil.h b/src/util/include/FishUtil.h index 51727c8..c8c3640 100644 --- a/src/util/include/FishUtil.h +++ b/src/util/include/FishUtil.h @@ -9,15 +9,15 @@ /** * Check if a stack exists. * @param _s Stack index. - * @warning Returns ERROR_UNSPEC from the current function if the check fails. + * @warning Returns ERROR_NOSTACK from the current function if the check fails. */ -#define check_selected(_s) if((_s) >= stack.size()) { return ERROR_UNSPEC; } +#define check_selected(_s) if((_s) >= stack.size()) { return ERROR_NOSTACK; } /** * Check if a stack exists and has enough elements. * @param _s Stack index. * @param _n Number of elements. - * @warning Returns ERROR_UNSPEC from the current function if the check fails. + * @warning Returns ERROR_EMPTY from the current function if the check fails. */ -#define check_stack(_s, _n) if(stack._s().size() < (_n)) { return ERROR_UNSPEC; } +#define check_stack(_s, _n) if(stack._s().size() < (_n)) { return ERROR_EMPTY; } diff --git a/test/99.bf b/test/99.bf index 47ff5a5..227275d 100644 --- a/test/99.bf +++ b/test/99.bf @@ -3,8 +3,8 @@ "Take one down and pass it around, "200g`#v_> v > v,_v#:< >v - >"s"> ^^ <"s"< . > ^ #n + v <_v#`1g00 < >200g`#v_> v > v,_v#:< >_v + >"s"> ^^ <"s"< . > ^ #v< Written by Conlan Wesson | :$ < p Version 1.0 Aug. 01, 2009 >$00g1-:00^ "99 bottles of beer on the wall."+91 ::#v_@ - ^-1.< \ No newline at end of file +91+91+91+91+***>::#v_@ + ^-1.< \ No newline at end of file diff --git a/test/test_multi2.fmv b/test/test_multi2.fmv index 52917a0..9515319 100644 --- a/test/test_multi2.fmv +++ b/test/test_multi2.fmv @@ -1,2 +1,2 @@ -fizzbuzz.bf +fizzbuzz.b98 example5d.beq \ No newline at end of file diff --git a/test/test_trds.b98 b/test/test_trds.b98 new file mode 100644 index 0000000..48e8709 --- /dev/null +++ b/test/test_trds.b98 @@ -0,0 +1 @@ +"SDRT"4(P.)@ \ No newline at end of file