Skip to content

Commit

Permalink
added Poppable trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakz committed Jun 29, 2019
1 parent ec41663 commit 956bbf7
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 73 deletions.
13 changes: 10 additions & 3 deletions src/collection.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class IteratorWrapper : public BaseIteratorWrapper<T>
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;
Expand All @@ -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<std::string>(value)); }

const std::string& raw() const { return value; }
Expand Down Expand Up @@ -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<Value>;
Expand All @@ -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<std::list<Value>>(data)); }
std::pair<bool, Value> find(const Value& v) const override { return std::make_pair(std::find(data.begin(), data.end(), v) != data.end(), v); }

Expand Down Expand Up @@ -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<Value>& 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
Expand All @@ -206,10 +211,11 @@ class Queue : public List
Queue(const std::list<Value>& 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<Value>;
Expand All @@ -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<std::vector<Value>>(data)); }

Expand Down
4 changes: 3 additions & 1 deletion src/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
98 changes: 35 additions & 63 deletions src/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<integral_t> iv = r.concretize();
nv.reserve(iv.size());
std::vector<integral_t> 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;
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/microcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,14 +326,22 @@ 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();
appendable->put(v2);
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) {
Expand Down
10 changes: 5 additions & 5 deletions src/types/traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const std::unordered_map<Type, TypeTraits::TypeSpec, enum_hash> 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<std::string>()(v.string()->raw()); },
Expand Down Expand Up @@ -161,7 +161,7 @@ const std::unordered_map<Type, TypeTraits::TypeSpec, enum_hash> 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,
Expand All @@ -171,7 +171,7 @@ const std::unordered_map<Type, TypeTraits::TypeSpec, enum_hash> 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,
Expand All @@ -190,7 +190,7 @@ const std::unordered_map<Type, TypeTraits::TypeSpec, enum_hash> 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,
Expand All @@ -199,7 +199,7 @@ const std::unordered_map<Type, TypeTraits::TypeSpec, enum_hash> 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,
Expand Down
5 changes: 5 additions & 0 deletions src/types/traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class Traits
{
public: virtual void put(Value value) = 0;
};

class Poppable
{
public: virtual Value pop() = 0;
};

class Iterable
{
Expand Down
1 change: 1 addition & 0 deletions src/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Error* Value::error() const { assert(type == TYPE_ERROR); return object<Error>()
Traits::Indexable* Value::indexable() const { return object<Traits::Indexable>(); }
Traits::Iterable* Value::iterable() const { return object<Traits::Iterable>(); }
Traits::Appendable* Value::appendable() const { return object<Traits::Appendable>(); }
Traits::Poppable* Value::poppable() const { return object<Traits::Poppable>(); }


Value Value::INVALID = Value(TYPE_INVALID);
Expand Down
1 change: 1 addition & 0 deletions src/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 956bbf7

Please sign in to comment.