From 956bbf75537918e54257f4260f51fc5ce2f3f48a Mon Sep 17 00:00:00 2001 From: Jack Date: Sat, 29 Jun 2019 15:19:59 +0200 Subject: [PATCH] added Poppable trait --- src/collection.h | 13 ++++-- src/defines.h | 4 +- src/instruction.cpp | 98 ++++++++++++++++---------------------------- src/microcode.cpp | 10 ++++- src/types/traits.cpp | 10 ++--- src/types/traits.h | 5 +++ src/value.cpp | 1 + src/value.h | 1 + 8 files changed, 69 insertions(+), 73 deletions(-) diff --git a/src/collection.h b/src/collection.h index 7817b36..de97a38 100644 --- a/src/collection.h +++ b/src/collection.h @@ -33,7 +33,7 @@ class IteratorWrapper : public BaseIteratorWrapper Value value() const override { return *this->it; } }; -class String final : public TCollection, public Traits::Indexable, public Traits::Iterable, public Traits::Appendable +class String final : public TCollection, public Traits::Indexable, public Traits::Iterable, public Traits::Appendable, public Traits::Poppable { public: using data_t = std::string; @@ -50,6 +50,7 @@ class String final : public TCollection, public Traits::Indexable, public Traits integral_t size() const override { return value.length(); } Value at(integral_t index) const override { return value[index]; } void put(Value v) override { value.append(v.svalue()); } + Value pop() override { auto last = value.back(); value.pop_back(); return last; } //TODO: push error if string empty Iterator iterator() const override { return Iterator(new IteratorWrapper(value)); } const std::string& raw() const { return value; } @@ -142,7 +143,7 @@ class Range : public TCollection, public Traits::Iterable, public Traits::Append const RangeVector& raw() const { return data; } }; -class List : public TCollection, public Traits::Iterable, public Traits::Appendable, public Traits::Lookupable +class List : public TCollection, public Traits::Iterable, public Traits::Appendable, public Traits::Poppable, public Traits::Lookupable { public: using list_t = std::list; @@ -157,6 +158,7 @@ class List : public TCollection, public Traits::Iterable, public Traits::Appenda virtual integral_t size() const override { return data.size(); } virtual bool empty() const override { return data.empty(); } void put(Value value) override { data.push_back(value); } + Value pop() override { auto last = data.back(); data.pop_back(); return last; } //TODO: push error if string empty Iterator iterator() const override { return Iterator(new IteratorWrapper>(data)); } std::pair find(const Value& v) const override { return std::make_pair(std::find(data.begin(), data.end(), v) != data.end(), v); } @@ -193,10 +195,13 @@ class Tuple : public managed_object, public Traits::Indexable, public Traits::Co class Stack : public List { public: + //TODO: push and pop are not efficient since they're going front, we sohuld use push_back and iterate it in reverse order Stack() : List() { } Stack(const std::list& data) : List(data) { } void put(Value value) override { data.push_front(value); } + Value pop() override { auto last = data.back(); data.pop_front(); return last; } //TODO: push error if string empty + }; class Queue : public List @@ -206,10 +211,11 @@ class Queue : public List Queue(const std::list& data) : List(data) { } void put(Value value) override { data.push_back(value); } + Value pop() override { auto last = data.back(); data.pop_back(); return last; } //TODO: push error if string empty }; #pragma mark Array -class Array : public TCollection, public Traits::Indexable, public Traits::Iterable, public Traits::Appendable +class Array : public TCollection, public Traits::Indexable, public Traits::Iterable, public Traits::Poppable, public Traits::Appendable { public: using array_t = std::vector; @@ -229,6 +235,7 @@ class Array : public TCollection, public Traits::Indexable, public Traits::Itera virtual bool empty() const override { return this->data.empty(); } void put(Value v) override { this->data.push_back(v); } + Value pop() override { auto last = data.back(); data.pop_back(); return last; } //TODO: push error if string empty Value at(integral_t index) const override { return data[index]; } Iterator iterator() const override { return Iterator(new IteratorWrapper>(data)); } diff --git a/src/defines.h b/src/defines.h index aee372e..8baf48b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -199,7 +199,9 @@ enum Trait : u32 TRAIT_INDEXABLE = 0x00000002, TRAIT_ITERABLE = 0x00000004, TRAIT_APPENDABLE = 0x00000008, - TRAIT_LOOKUPABLE = 0x00000010, + TRAIT_POPPABLE = 0x00000010, + TRAIT_LOOKUPABLE = 0x00000020, + TRAIT_SENTINEL, diff --git a/src/instruction.cpp b/src/instruction.cpp index 9681fd1..f9fb4e3 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -261,82 +261,54 @@ void Instruction::execute(VM *vm) const case OP_AT: { - if (vm->popOne(v2)) + if (vm->popTwo(v1, v2)) { - if (v2.type == TYPE_STACK) - { - List::list_t& stack = v2.stack()->raw(); - vm->push(v2); - - if (!stack.empty()) - { - vm->push(stack.front()); - stack.pop_front(); - } - } - else if (v2.type == TYPE_QUEUE) + if (v1.type == TYPE_MAP) { - List::list_t& queue = v2.queue()->raw(); - vm->push(v2); - - if (!queue.empty()) - { - vm->push(queue.front()); - queue.pop_front(); - } + const Map::map_t& map = v1.map()->raw(); + vm->push(v1); + + auto it = map.find(v2); + + vm->push(it != map.end() ? it->second : Value()); } else - { - if (vm->popOne(v1)) + { + switch (TYPES(v1.type, v2.type)) { - if (v1.type == TYPE_MAP) + case TYPES(TYPE_LAZY_ARRAY, TYPE_INT): { - const Map::map_t& map = v1.map()->raw(); - vm->push(v1); - - auto it = map.find(v2); - - vm->push(it != map.end() ? it->second : Value()); - } - else - { - switch (TYPES(v1.type, v2.type)) - { - case TYPES(TYPE_LAZY_ARRAY, TYPE_INT): - { - LazyArray *array = v1.lazyArray(); - integral_t i = v2.integral(); + LazyArray *array = v1.lazyArray(); + integral_t i = v2.integral(); - const Value& v = array->raw().at(vm, i); + const Value& v = array->raw().at(vm, i); - vm->push(v1); - vm->push(v); - break; - } - case TYPES(TYPE_LAZY_ARRAY, TYPE_RANGE): - { - const RangeVector& r = v2.range()->raw(); - Array::utype_t nv; - LazyArray *ov = v1.lazyArray(); + vm->push(v1); + vm->push(v); + break; + } + case TYPES(TYPE_LAZY_ARRAY, TYPE_RANGE): + { + const RangeVector& r = v2.range()->raw(); + Array::utype_t nv; + LazyArray *ov = v1.lazyArray(); - std::vector iv = r.concretize(); - nv.reserve(iv.size()); + std::vector iv = r.concretize(); + nv.reserve(iv.size()); - for (size_t i = 0; i < iv.size(); ++i) - { - integral_t j = iv[i]; + for (size_t i = 0; i < iv.size(); ++i) + { + integral_t j = iv[i]; - if (j < 0) - continue; + if (j < 0) + continue; - nv.push_back(ov->raw().at(vm, j)); - } - - vm->push(v1); - vm->push(new Array(nv)); - break; - } + nv.push_back(ov->raw().at(vm, j)); } + + vm->push(v1); + vm->push(new Array(nv)); + break; } } } diff --git a/src/microcode.cpp b/src/microcode.cpp index a9ff087..1520d2a 100644 --- a/src/microcode.cpp +++ b/src/microcode.cpp @@ -326,7 +326,7 @@ void registerFunctions(MicroCode& mc) vm->push(true); }); - registerBinary(mc, Topic::COLLECTIONS, "append", "add an element to an appendable collection, following semantics of the collection", {}, + registerBinary(mc, Topic::COLLECTIONS, "append", "add an element to an appendable collection, according to semantics", {}, { OP_HASH, TRAIT_ITERABLE, TRAIT_ANY_TYPE }, { TRAIT_ITERABLE }, [](VM* vm, V v1, V v2) { Traits::Appendable* appendable = v1.appendable(); @@ -334,6 +334,14 @@ void registerFunctions(MicroCode& mc) vm->pushCollection(v1); }); + registerUnary(mc, Topic::COLLECTIONS, "pop", "pop an element from a poppable collection, according to semantics", {}, + { OP_AT, TRAIT_POPPABLE }, { TRAIT_POPPABLE, TRAIT_ANY_TYPE }, + [](VM* vm, V v1) { + Traits::Poppable* poppable = v1.poppable(); + vm->pushCollection(v1); + vm->push(poppable->pop()); + }); + registerBinary(mc, Topic::COLLECTIONS, "partition", "partition an iterable collection according to a predicate", {}, { OP_WHILE, TRAIT_ITERABLE, TYPE_LAMBDA }, { TYPE_MAP }, [](VM* vm, V v1, V v2) { diff --git a/src/types/traits.cpp b/src/types/traits.cpp index 76beba6..e92598a 100644 --- a/src/types/traits.cpp +++ b/src/types/traits.cpp @@ -107,7 +107,7 @@ const std::unordered_map TypeTraits::spec }, { TYPE_STRING, - { TYPE_STRING, { TRAIT_COUNTABLE, TRAIT_INDEXABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE }, "string", + { TYPE_STRING, { TRAIT_COUNTABLE, TRAIT_INDEXABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE, TRAIT_POPPABLE }, "string", [] (const Value& v) { return v.string()->raw(); }, [] (const Value& v1, const Value& v2) { return v2.type == TYPE_STRING && v2.string()->raw() == v1.string()->raw(); }, [] (const Value& v) { return std::hash()(v.string()->raw()); }, @@ -161,7 +161,7 @@ const std::unordered_map TypeTraits::spec }, { TYPE_LIST, - { TYPE_LIST, { TRAIT_COUNTABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE }, "list", + { TYPE_LIST, { TRAIT_COUNTABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE, TRAIT_POPPABLE }, "list", [] (const Value& v) { return ListPrinter.svalue(v.list()); }, [] (const Value& v1, const Value& v2) { return v2.type == TYPE_LIST && v2.list()->raw() == v1.list()->raw(); }, null_hasher, @@ -171,7 +171,7 @@ const std::unordered_map TypeTraits::spec }, { TYPE_ARRAY, - { TYPE_ARRAY, { TRAIT_COUNTABLE, TRAIT_INDEXABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE }, "array", + { TYPE_ARRAY, { TRAIT_COUNTABLE, TRAIT_INDEXABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE, TRAIT_POPPABLE }, "array", [] (const Value& v) { return ArrayPrinter.svalue(v.array()); }, binary_false, null_hasher, @@ -190,7 +190,7 @@ const std::unordered_map TypeTraits::spec } }, { TYPE_STACK, - { TYPE_STACK, { TRAIT_COUNTABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE }, "stack", + { TYPE_STACK, { TRAIT_COUNTABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE, TRAIT_POPPABLE }, "stack", [] (const Value& v) { return StackPrinter.svalue(v.stack()); }, [] (const Value& v1, const Value& v2) { return v2.type == TYPE_STACK && v2.list()->raw() == v1.list()->raw(); }, null_hasher, @@ -199,7 +199,7 @@ const std::unordered_map TypeTraits::spec } }, { TYPE_QUEUE, - { TYPE_QUEUE, { TRAIT_COUNTABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE }, "queue", + { TYPE_QUEUE, { TRAIT_COUNTABLE, TRAIT_ITERABLE, TRAIT_APPENDABLE, TRAIT_POPPABLE }, "queue", [] (const Value& v) { return QueuePrinter.svalue(v.queue()); }, [] (const Value& v1, const Value& v2) { return v2.type == TYPE_QUEUE && v2.list()->raw() == v1.list()->raw(); }, null_hasher, diff --git a/src/types/traits.h b/src/types/traits.h index 1c946f1..18cf4cc 100644 --- a/src/types/traits.h +++ b/src/types/traits.h @@ -38,6 +38,11 @@ class Traits { public: virtual void put(Value value) = 0; }; + + class Poppable + { + public: virtual Value pop() = 0; + }; class Iterable { diff --git a/src/value.cpp b/src/value.cpp index 9e537d6..dc91513 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -54,6 +54,7 @@ Error* Value::error() const { assert(type == TYPE_ERROR); return object() Traits::Indexable* Value::indexable() const { return object(); } Traits::Iterable* Value::iterable() const { return object(); } Traits::Appendable* Value::appendable() const { return object(); } +Traits::Poppable* Value::poppable() const { return object(); } Value Value::INVALID = Value(TYPE_INVALID); diff --git a/src/value.h b/src/value.h index c2d397a..a88178a 100644 --- a/src/value.h +++ b/src/value.h @@ -154,6 +154,7 @@ class Value final Traits::Indexable* indexable() const; Traits::Iterable* iterable() const; Traits::Appendable* appendable() const; + Traits::Poppable* poppable() const; Lambda* lambda() const;