diff --git a/src/collection.h b/src/collection.h index de97a38..8dde98c 100644 --- a/src/collection.h +++ b/src/collection.h @@ -37,6 +37,7 @@ class String final : public TCollection, public Traits::Indexable, public Traits { public: using data_t = std::string; + using utype_t = data_t; private: data_t value; diff --git a/src/help.cpp b/src/help.cpp index a9a5ce8..853bdb5 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -104,9 +104,7 @@ void Help::init() addOperator("!", OpHelpEntry::unary(TYPE_LAMBDA, TYPE_UNKNOWN, "apply", Topic::FUNCTIONAL, "pop first value from stack and executes it as a lambda", "1 [2+] !", "3")); addOperator("!", OpHelpEntry::unary(TYPE_INT, TYPE_FLOAT, "factorial", Topic::NUMERICS, "computes factorial", "", "")); addOperator("=", OpHelpEntry::binary(TYPE_GENERIC, TYPE_GENERIC, TYPE_BOOL, "eq", Topic::LOGIC, "push true on stack if two topmost values are equal", "", "")); - - addOperator("^", OpHelpEntry::unary(TYPE_GENERIC, "peek", Topic::UTILITY, "prints stack topmost value", "", "")); - + addOperator("s", OpHelpEntry::unary(TYPE_GENERIC, TYPE_STRING, "string cast", Topic::TEXT, "convert the value to string", "", "")); addOperator("?", OpHelpEntry::binary(TYPE_BOOL, TYPE_LAMBDA, TYPE_UNKNOWN, "if", Topic::LOGIC, "executes lambda if boolean value is true", "", "")); diff --git a/src/instruction.cpp b/src/instruction.cpp index e0d2174..719233d 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -158,16 +158,6 @@ void Instruction::execute(VM *vm) const break; } - case OP_PEEK: - { - Value v = vm->peek(); - - if (v.valid()) - std::cout << v.svalue(); - - break; - } - case OP_RAND: { if (vm->popOne(v1)) @@ -561,10 +551,7 @@ void Instruction::execute(VM *vm) const } break; } - - case OP_RAISE_STACK: { vm->raiseStack(); break; } - case OP_LOWER_STACK: { vm->lowerStack(); break; } - + case OP_RAISE_STACKV: { if (vm->popOne(v1) && v1.type == TYPE_INT) diff --git a/src/main.cpp b/src/main.cpp index 12a73c0..78a7002 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -96,9 +96,13 @@ int main (int argc, const char * argv[]) else if (input == "info") { cout << " arch: " << (sizeof(void*) == 4 ? "x86" : "x86-64") << endl; - cout << " size of value : " << sizeof(Value) << (sizeof(Value) == sizeof(value_data) + sizeof(Type) ? " (packed)" : "") << endl; - cout << " size of instruction : " << sizeof(Instruction) << endl; - cout << " size of opcode : " << sizeof(Opcode) << endl; + cout << " size of value : " << sizeof(Value) << (sizeof(Value) == sizeof(value_data) + sizeof(Type) ? " (packed)" : "") << endl; + cout << " size of instruction : " << sizeof(Instruction) << endl; + cout << " size of opcode : " << sizeof(Opcode) << endl; + cout << " known types : " << TypeTraits::traits().size() << endl; + cout << " known operators : " << Opcode::OPCODES_COUNT << endl; + cout << " implemented operators : " << mc.vocabulary().size() << endl; + } else { diff --git a/src/microcode.cpp b/src/microcode.cpp index d897e03..a4f7483 100644 --- a/src/microcode.cpp +++ b/src/microcode.cpp @@ -73,6 +73,14 @@ void registerTernary(MicroCode& mc, Topic topic, const std::string& name, const Help::addOperator(signature.opcode, signature.args, retn, topic, name, desc, examples); } +template +void reverseCollection(VM* vm, const Value& v) +{ + const auto& data = v->as->raw(); + auto nv = T::utype_t(data.rbegin(), data.rend()); + vm->push(new T(nv)); +} + void registerFunctions(MicroCode& mc) { registerBinary(mc, @@ -666,7 +674,24 @@ void registerStackFunctions(MicroCode& mc) { OP_DROP, TRAIT_ANY_TYPE }, { }, [] (VM* vm, const Value& v) { } ); - + + registerUnary(mc, + Topic::UTILITY, "peek", "prints stack topmost value", + {}, + { OP_PEEK, TRAIT_ANY_TYPE }, { }, + [](VM* vm, const Value& v) { + /* TODO: optimize by avoiding popping and pushing */ + if (v.valid()) + std::cout << v.svalue(); + + vm->push(v); + + } + ); + + registerNullary(mc, Topic::UTILITY, "raise-stack", "switch to higher stack", {}, { OP_RAISE_STACK }, { }, [](VM* vm) { vm->raiseStack(); }); + registerNullary(mc, Topic::UTILITY, "lower-stack", "switch to lower stack", {}, { OP_LOWER_STACK }, { }, [](VM* vm) { vm->lowerStack(); }); + //TODO: check return signature for rise and sink registerTernary(mc, Topic::STACK, "rise", "cycle top three stack element left", diff --git a/src/types/traits.cpp b/src/types/traits.cpp index c02a81a..aa3814d 100644 --- a/src/types/traits.cpp +++ b/src/types/traits.cpp @@ -59,6 +59,7 @@ static const CollectionPrinter TuplePrinter = { "[[", "]]", " ", [] (cons static const auto unary_false = [](const Value&) { return false; }; static const auto binary_false = [](const Value&, const Value&) { return false; }; +static const auto to_zero = [](const Value&) { return 0; }; static const auto null_hasher = [](const Value&) { return 0UL; }; static const auto default_collector = [](size_t hint) { return std::make_pair(TYPE_NONE, nullptr); }; @@ -71,6 +72,7 @@ const std::unordered_map TypeTraits::spec [] (const Value& v1, const Value& v2) { return v2.type == TYPE_INT && v2.data.i == v1.data.i; }, [] (const Value& v) { return std::hash()(v.integral()); }, unary_false, + [](const Value& v) { return v.integral(); }, default_collector, } }, @@ -83,7 +85,8 @@ const std::unordered_map TypeTraits::spec }, [] (const Value& v1, const Value& v2) { return v2.type == TYPE_FLOAT && v2.data.f == v1.data.f; }, [] (const Value& v) { return std::hash()(v.real()); }, - unary_false + unary_false, + [](const Value& v) { return (int)v.real(); } } }, { TYPE_BOOL, @@ -112,6 +115,7 @@ const std::unordered_map TypeTraits::spec [] (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()); }, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_STRING, new String()); } } }, @@ -156,6 +160,7 @@ const std::unordered_map TypeTraits::spec binary_false, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_ARRAY, new Array()); } } }, @@ -166,6 +171,7 @@ const std::unordered_map TypeTraits::spec [] (const Value& v1, const Value& v2) { return v2.type == TYPE_LIST && v2.list()->raw() == v1.list()->raw(); }, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_LIST, new List()); } } }, @@ -176,6 +182,7 @@ const std::unordered_map TypeTraits::spec binary_false, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_ARRAY, new Array()); } } }, @@ -186,6 +193,7 @@ const std::unordered_map TypeTraits::spec binary_false, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_SET, new Set()); } } }, @@ -195,6 +203,7 @@ const std::unordered_map TypeTraits::spec [] (const Value& v1, const Value& v2) { return v2.type == TYPE_STACK && v2.list()->raw() == v1.list()->raw(); }, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_LIST, new List()); } } }, @@ -204,6 +213,7 @@ const std::unordered_map TypeTraits::spec [] (const Value& v1, const Value& v2) { return v2.type == TYPE_QUEUE && v2.list()->raw() == v1.list()->raw(); }, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_LIST, new List()); } } }, @@ -221,6 +231,7 @@ const std::unordered_map TypeTraits::spec binary_false, null_hasher, unary_false, + to_zero, [] (size_t hint) { return std::make_pair(TYPE_ARRAY, new Array()); } } }, @@ -355,6 +366,9 @@ const std::unordered_map TypeTraits::spec case OP_RECUR: return "[#]"; case OP_RECURV: return "{#}"; case OP_WHILE: return "<>"; + + case OP_RAISE_STACK: return "R"; + case OP_LOWER_STACK: return "L"; } assert(false); diff --git a/src/types/traits.h b/src/types/traits.h index 775e9d5..0128604 100644 --- a/src/types/traits.h +++ b/src/types/traits.h @@ -106,6 +106,7 @@ class TypeTraits std::function hasher; std::function to_bool = [] (const Value& ) { return false; }; + std::function to_int = [](const Value&) { return 0; }; std::function(size_t)> to_collector = [] (size_t) { return std::make_pair(TYPE_NONE, nullptr); };