diff --git a/src/collection.h b/src/collection.h index b8e77b3..7817b36 100644 --- a/src/collection.h +++ b/src/collection.h @@ -147,7 +147,7 @@ class List : public TCollection, public Traits::Iterable, public Traits::Appenda public: using list_t = std::list; using utype_t = list_t; -private: +protected: list_t data; public: @@ -196,6 +196,7 @@ class Stack : public List Stack() : List() { } Stack(const std::list& data) : List(data) { } + void put(Value value) override { data.push_front(value); } }; class Queue : public List @@ -203,6 +204,8 @@ class Queue : public List public: Queue() : List() { } Queue(const std::list& data) : List(data) { } + + void put(Value value) override { data.push_back(value); } }; #pragma mark Array diff --git a/src/instruction.cpp b/src/instruction.cpp index d92f33a..97841b5 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -157,41 +157,6 @@ void Instruction::execute(VM *vm) const } break; } - - case OP_QUESTION: - { - if (vm->popTwo(v1, v2)) - { - { - switch (TYPES(v1.type, v2.type)) - { - case TYPES(TYPE_BOOL,TYPE_LAMBDA): - { - if (v1.boolean()) - vm->execute(v2.lambda()->code()); - break; - } - } - - } - } - break; - } - case OP_DQUESTION: - { - if (vm->popThree(v1, v2, v3)) - { - if (v1.type == TYPE_BOOL && v2.type == TYPE_LAMBDA && v3.type == TYPE_LAMBDA) - { - if (v1.boolean()) - vm->execute(v2.lambda()->code()); - else - vm->execute(v3.lambda()->code()); - } - } - break; - } - case OP_PEEK: { @@ -381,54 +346,32 @@ void Instruction::execute(VM *vm) const case OP_HASH: { - if (vm->popTwo(v2, v3)) + if (vm->popThree(v1, v2, v3)) { - if (v2.type == TYPE_SET) + if (v1.type == TYPE_MAP) { - Set *set = v2.set(); - set->put(v3); - vm->push(v2); - } - else if (v2.type == TYPE_STACK) - { - v2.stack()->raw().push_front(v3); - vm->push(v2); - } - else if (v2.type == TYPE_QUEUE) - { - v2.queue()->raw().push_back(v3); - vm->push(v2); + v1.map()->raw().emplace(std::make_pair(v2, v3)); + vm->push(v1); } else - { - if (vm->popOne(v1)) + { + switch (TYPES(v1.type, v2.type)) { - if (v1.type == TYPE_MAP) + case TYPES(TYPE_ARRAY, TYPE_INT): { - v1.map()->raw().emplace(std::make_pair(v2, v3)); - vm->push(v1); - } - else - { - switch (TYPES(v1.type, v2.type)) - { - case TYPES(TYPE_ARRAY, TYPE_INT): - { - auto& values = v1.array()->raw(); - integral_t i = v2.integral(); + auto& values = v1.array()->raw(); + integral_t i = v2.integral(); - if (i >= values.size() && i >= values.capacity()) - values.resize(i+1, Value()); + if (i >= values.size() && i >= values.capacity()) + values.resize(i+1, Value()); - values[v2.integral()] = v3; + values[v2.integral()] = v3; - vm->push(v1); - break; - } - } + vm->push(v1); + break; } } - } + } } break; } diff --git a/src/main.cpp b/src/main.cpp index 04f5026..acee77a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,7 @@ int main (int argc, const char * argv[]) string input; bool finished = false; - input = "(?0:[1]1:[1][1<>2<>+])2@"; + /*input = "(?0:[1]1:[1][1<>2<>+])2@"; compiler::Compiler compiler; Code*code = compiler.compile(input); if (code) @@ -46,7 +46,7 @@ int main (int argc, const char * argv[]) vm.execute(code); vm.printTopStack(); } - return 0; + return 0;*/ while (!finished) { diff --git a/src/microcode.cpp b/src/microcode.cpp index 3635c7f..b573377 100644 --- a/src/microcode.cpp +++ b/src/microcode.cpp @@ -9,6 +9,7 @@ using V = const Value&; void registerStackFunctions(MicroCode& mc); void registerNumericFunctions(MicroCode& mc); void registerStringFunctions(MicroCode& mc); +void registerFlowFunctions(MicroCode& mc); SignatureArguments normalize(const SignatureArguments& args) { @@ -324,6 +325,14 @@ void registerFunctions(MicroCode& mc) vm->push(true); }); + + registerBinary(mc, Topic::COLLECTIONS, "append", "add an element to an appendable collection, following semantics of the collection", {}, + { 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); + }); std::initializer_list> embedded_helpers = { @@ -482,11 +491,10 @@ void registerFunctions(MicroCode& mc) registerUnary(mc, {OP_ANY, TYPE_TUPLE}, { TRAIT_ANY_TYPE }, [](VM* vm, V v1) { vm->push(v1.tuple()->at(0)); }); registerUnary(mc, {OP_EVERY, TYPE_TUPLE}, { TRAIT_ANY_TYPE }, [](VM* vm, V v1) { vm->push(v1.tuple()->at(1)); }); - - registerStackFunctions(mc); registerNumericFunctions(mc); registerStringFunctions(mc); + registerFlowFunctions(mc); } namespace math @@ -646,10 +654,11 @@ void registerFlowFunctions(MicroCode& mc) Topic::LOGIC, "if-else", "executes first lambdfa if value on stack is true, second lambda otherwise", {}, { OP_DQUESTION, TYPE_BOOL, TYPE_LAMBDA, TYPE_LAMBDA }, { }, + [] (VM* vm, V v1, V v2, V v3) { if (v1.boolean()) - vm->execute(v2.lambda()->code()); + vm->execute(v2.lambda()->code()); else - vm->execute(v3.lambda()->code()); + vm->execute(v3.lambda()->code()); }); } diff --git a/src/parser/impossible.l b/src/parser/impossible.l index a6525fc..3e92737 100755 --- a/src/parser/impossible.l +++ b/src/parser/impossible.l @@ -33,6 +33,7 @@ "(?" { return Parser::make_LARRAY_OPEN(loc); } "{>" { return Parser::make_STACK_OPEN(loc); } +"{<" { return Parser::make_QUEUE_OPEN(loc); } "[[" { return Parser::make_TUPLE_OPEN(loc); } "]]" { return Parser::make_TUPLE_CLOSE(loc); } diff --git a/src/parser/impossible.ypp b/src/parser/impossible.ypp index 52231dd..3396e5e 100755 --- a/src/parser/impossible.ypp +++ b/src/parser/impossible.ypp @@ -3,7 +3,7 @@ %defines %define api.namespace {compiler} -%define parser_class_name {Parser} +%define api.parser.class {Parser} %define api.token.constructor %define api.value.type variant @@ -66,6 +66,7 @@ LARRAY_OPEN "(?" STACK_OPEN "{>" + QUEUE_OPEN "{<" TUPLE_OPEN "[[" TUPLE_CLOSE "]]" @@ -243,8 +244,8 @@ value: | STACK_OPEN values RBRACE { $$ = new Stack($2); } | STACK_OPEN RBRACE { $$ = new Stack(); } - | LBRACE LESSER values RBRACE { $$ = new Queue($3); } - | LBRACE LESSER RBRACE { $$ = new Queue(); } + | QUEUE_OPEN values RBRACE { $$ = new Queue($2); } + | QUEUE_OPEN RBRACE { $$ = new Queue(); } | LBRACE PERIOD values RBRACE { $$ = new Set(Set::set_t($3.begin(), $3.end())); diff --git a/src/value.cpp b/src/value.cpp index d05493e..9e537d6 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -53,6 +53,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(); } Value Value::INVALID = Value(TYPE_INVALID); diff --git a/src/value.h b/src/value.h index 4f9312d..c2d397a 100644 --- a/src/value.h +++ b/src/value.h @@ -153,6 +153,7 @@ class Value final Traits::Indexable* indexable() const; Traits::Iterable* iterable() const; + Traits::Appendable* appendable() const; Lambda* lambda() const; diff --git a/src/vm.h b/src/vm.h index f3e720c..8b6f6a5 100644 --- a/src/vm.h +++ b/src/vm.h @@ -58,7 +58,7 @@ class VM const MicroCode& microcode; public: - VM(MicroCode& microcode) : valueStack(new stack_t()), exec(ActivationRecord()), running(false), stackPreserve(false), memory(), + VM(MicroCode& microcode) : valueStack(new stack_t()), exec(ActivationRecord()), running(false), stackPreserve(true), memory(), microcode(microcode) { } @@ -68,11 +68,15 @@ class VM return exec.code; } + bool preserveCollectionOnStack() const { return stackPreserve; } + void pushRecord(ActivationRecord&& record); void popRecord(); const auto& record() const { return exec; } + void pushCollection(const Value& value) { if (preserveCollectionOnStack()) push(value); } + void push(const Value& value) { valueStack->push_back(value);