diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c5a9f32e..9071b5bf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ Author: Bérenger Dalle-Cort, 2017-2024 ### v1.0: - graph is now always abstract - interpreter (build, run, debug etc) is disabled by default and is considered out of scope, but can be enabled via the Developer>Experimental menu, - - improved the Graph user interface to create graph more easily, + - improved the Graph user interface to create_new graph more easily, - implemented an optimized StateMachine to simplify code (it avoids an OOP version of it! Thanks to Rémi ;)), - refactor the whole app (uses init/get/shutdown pattern for managers), - fix memory leaks, diff --git a/CMakeLists.txt b/CMakeLists.txt index 688386664..813098540 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,8 +163,6 @@ add_library( src/tools/core/reflection/Operator_t.h src/tools/core/reflection/Initializer.h src/tools/core/reflection/enum.h - src/tools/core/reflection/FuncType.cpp - src/tools/core/reflection/FuncType.h src/tools/core/reflection/qword.cpp src/tools/core/reflection/qword.h src/tools/core/reflection/reflection @@ -199,7 +197,7 @@ target_link_libraries( add_executable( test-tools-core src/tools/core/reflection/reflection.specs.cpp - src/tools/core/reflection/FuncType.builder.specs.cpp + src/tools/core/reflection/Type.specs.cpp src/tools/core/memory/Pool.specs.cpp src/tools/core/memory/MemoryManager.specs.cpp ) @@ -356,7 +354,7 @@ add_library( src/ndbl/core/ForLoopNode.cpp src/ndbl/core/Graph.cpp src/ndbl/core/GraphUtil.cpp - src/ndbl/core/InvokableNode.cpp + src/ndbl/core/FunctionNode.cpp src/ndbl/core/LiteralNode.cpp src/ndbl/core/Node.cpp src/ndbl/core/NodeFactory.cpp diff --git a/HOW-TO-BUILD.md b/HOW-TO-BUILD.md index 3a79299d5..81aeb0bdd 100644 --- a/HOW-TO-BUILD.md +++ b/HOW-TO-BUILD.md @@ -38,5 +38,5 @@ Few details about the commands above: - `--recurse-submodules` is important when cloning since *Nodable* needs other git repositories to be built. - `--branch v..` is to target a specific tag, it is recommended to get a stable version. You can try a more recent if you wish. Browse [tags list](https://github.com/berdal84/nodable/tags). -- `--target install` is to create a clean `out/app` directory with only the necessary files to run the software. +- `--target install` is to create_new a clean `out/app` directory with only the necessary files to run the software. diff --git a/src/ndbl/cli/CLI.cpp b/src/ndbl/cli/CLI.cpp index dd7f3bf78..8c7acc484 100644 --- a/src/ndbl/cli/CLI.cpp +++ b/src/ndbl/cli/CLI.cpp @@ -53,7 +53,7 @@ void CLI::update() } // Priority 1: call a static function immediately - const ClassDesc* api_class = type::get_class(); + const ClassDescriptor* api_class = type::get_class(); if( auto static_fct = api_class->get_static(user_input.c_str()) ) { try @@ -96,7 +96,7 @@ void CLI::clear() NodableHeadless::clear(); } -void CLI::log_function_call(const variant &result, const FuncType *type) +void CLI::log_function_call(const variant &result, const FunctionDescriptor *type) { LOG_MESSAGE("CLI", "CLI::%s() done (result: %s)\n",type->get_identifier(), result.to().c_str()) } @@ -167,7 +167,7 @@ void CLI::PublicApi::help() { std::vector command_names; - const ClassDesc* api_class = type::get_class(); + const ClassDescriptor* api_class = type::get_class(); for ( const IInvokable* invokable : api_class->get_statics() ) { @@ -222,7 +222,7 @@ bool CLI::PublicApi::run() return m_cli->run(); } -variant CLI::invoke_static(const FuncType* _func_type, std::vector&& _args) const +variant CLI::invoke_static(const FunctionDescriptor* _func_type, std::vector&& _args) const { variant result; @@ -232,7 +232,7 @@ variant CLI::invoke_static(const FuncType* _func_type, std::vector&& _a return result; } -variant CLI::invoke_method(const FuncType* _func_type, std::vector&& _args) const +variant CLI::invoke_method(const FunctionDescriptor* _func_type, std::vector&& _args) const { variant result; diff --git a/src/ndbl/cli/CLI.h b/src/ndbl/cli/CLI.h index 8ef17d294..ba527977b 100644 --- a/src/ndbl/cli/CLI.h +++ b/src/ndbl/cli/CLI.h @@ -49,10 +49,10 @@ namespace ndbl ~CLI() override = default; private: - tools::variant invoke_static(const tools::FuncType* _func_type, std::vector&& _args) const; - tools::variant invoke_method(const tools::FuncType* _func_type, std::vector&& _args) const; + tools::variant invoke_static(const tools::FunctionDescriptor* _func_type, std::vector&& _args) const; + tools::variant invoke_method(const tools::FunctionDescriptor* _func_type, std::vector&& _args) const; static std::string get_line() ; - static void log_function_call(const tools::variant &result, const tools::FuncType *type) ; + static void log_function_call(const tools::variant &result, const tools::FunctionDescriptor *type) ; }; } diff --git a/src/ndbl/core/Compiler.cpp b/src/ndbl/core/Compiler.cpp index 9031754d8..8f01dc586 100644 --- a/src/ndbl/core/Compiler.cpp +++ b/src/ndbl/core/Compiler.cpp @@ -12,7 +12,7 @@ #include "ndbl/core/ForLoopNode.h" #include "ndbl/core/Graph.h" #include "ndbl/core/IfNode.h" -#include "ndbl/core/InvokableNode.h" +#include "ndbl/core/FunctionNode.h" #include "ndbl/core/LiteralNode.h" #include "ndbl/core/Scope.h" #include "ndbl/core/VariableNode.h" @@ -65,7 +65,7 @@ bool Compiler::is_syntax_tree_valid(const Graph* _graph) case NodeType_OPERATOR: { - auto* invokable = static_cast(each_node); + auto* invokable = static_cast(each_node); if ( !language->find_operator_fct(invokable->get_func_type()) ) { std::string signature; @@ -76,7 +76,7 @@ bool Compiler::is_syntax_tree_valid(const Graph* _graph) } case NodeType_FUNCTION: { - auto* invokable = static_cast(each_node); + auto* invokable = static_cast(each_node); if ( !language->find_function(invokable->get_func_type()) ) { std::string signature; @@ -198,7 +198,7 @@ void Compiler::compile_node( const Node* _node ) case NodeType_OPERATOR: { Instruction* instr = m_temp_code->push_instr(OpCode_call); - const FuncType* func_type = static_cast(_node)->get_func_type(); + const FunctionDescriptor* func_type = static_cast(_node)->get_func_type(); const IInvokable* invokable = get_language()->find_function( func_type ); // Get exact OR fallback function (in case of arg cast) VERIFY(invokable != nullptr, "Unable to find this function") @@ -345,7 +345,7 @@ const Code* Compiler::compile_syntax_tree(const Graph* _graph) { delete m_temp_code; m_temp_code = nullptr; - LOG_ERROR("Compiler", "Unable to create assembly code for program. Reason: %s\n", e.what()); + LOG_ERROR("Compiler", "Unable to create_new assembly code for program. Reason: %s\n", e.what()); } return m_temp_code; } diff --git a/src/ndbl/core/InvokableNode.cpp b/src/ndbl/core/FunctionNode.cpp similarity index 60% rename from src/ndbl/core/InvokableNode.cpp rename to src/ndbl/core/FunctionNode.cpp index 71f405840..b6e937672 100644 --- a/src/ndbl/core/InvokableNode.cpp +++ b/src/ndbl/core/FunctionNode.cpp @@ -1,28 +1,28 @@ -#include "InvokableNode.h" +#include "FunctionNode.h" #include "tools/core/log.h" #include "tools/core/memory/memory.h" -#include "tools/core/reflection/FuncType.h" +#include "tools/core/reflection/Type.h" using namespace ndbl; using namespace tools; REFLECT_STATIC_INIT { - type::Initializer("InvokableNode").extends(); + type::Initializer("FunctionNode").extends(); } -void InvokableNode::init(NodeType _type, tools::FuncType&& _func_type ) +void FunctionNode::init(NodeType _type, const tools::FunctionDescriptor* _func_type ) { - Node::init(_type, _func_type.get_identifier()); + Node::init(_type, _func_type->get_identifier()); m_func_type = _func_type; m_identifier_token = { Token_t::identifier, - _func_type.get_identifier() + _func_type->get_identifier() }; - m_argument_slot.resize(_func_type.get_arg_count()); - m_argument_props.resize(_func_type.get_arg_count()); + m_argument_slot.resize(_func_type->get_arg_count()); + m_argument_props.resize(_func_type->get_arg_count()); add_slot( SlotFlag_PREV, Slot::MAX_CAPACITY ); add_slot(SlotFlag_OUTPUT, 1); @@ -30,11 +30,11 @@ void InvokableNode::init(NodeType _type, tools::FuncType&& _func_type ) switch ( _type ) { case NodeType_OPERATOR: - set_name(_func_type.get_identifier()); + set_name(_func_type->get_identifier()); break; case NodeType_FUNCTION: { - const std::string& id = _func_type.get_identifier(); + const std::string& id = _func_type->get_identifier(); std::string label = id + "()"; std::string short_label = id.substr(0, 2) + "..()"; // ------- improve, not great. set_name(label.c_str()); @@ -45,19 +45,19 @@ void InvokableNode::init(NodeType _type, tools::FuncType&& _func_type ) } // Create a result/value - Property* value = add_prop(_func_type.get_return_type(), VALUE_PROPERTY ); + Property* value = add_prop(_func_type->get_return_type(), VALUE_PROPERTY ); add_slot(SlotFlag_OUTPUT, Slot::MAX_CAPACITY, value); // Create arguments if ( _type == NodeType_OPERATOR ) { - VERIFY(_func_type.get_arg_count() >= 1, "An operator must have one argument minimum"); - VERIFY(_func_type.get_arg_count() <= 2, "An operator cannot have more than 2 arguments"); + VERIFY(_func_type->get_arg_count() >= 1, "An operator must have one argument minimum"); + VERIFY(_func_type->get_arg_count() <= 2, "An operator cannot have more than 2 arguments"); } - for (size_t i = 0; i < _func_type.get_arg_count(); i++ ) + for (size_t i = 0; i < _func_type->get_arg_count(); i++ ) { - const FuncArg& arg = _func_type.get_arg(i); + const FuncArg& arg = _func_type->get_arg(i); const char* name; // TODO: this could be done in the NodeView instead... @@ -81,9 +81,4 @@ void InvokableNode::init(NodeType _type, tools::FuncType&& _func_type ) m_argument_slot[i] = add_slot(SlotFlag_INPUT, 1, property); m_argument_props[i] = property; } -} - -const std::vector& InvokableNode::get_arg_slots() const -{ - return m_argument_slot; } \ No newline at end of file diff --git a/src/ndbl/core/InvokableNode.h b/src/ndbl/core/FunctionNode.h similarity index 61% rename from src/ndbl/core/InvokableNode.h rename to src/ndbl/core/FunctionNode.h index 2d56e200e..04ff82257 100644 --- a/src/ndbl/core/InvokableNode.h +++ b/src/ndbl/core/FunctionNode.h @@ -7,23 +7,19 @@ namespace ndbl { - /** - * @brief ComputeFunction extends Compute base to provide a Component that represents a Function. - * This function has_flags some arguments. - */ - class InvokableNode : public Node + class FunctionNode : public Node { public: - void init(NodeType node_type, tools::FuncType&& func_type); - const std::vector& get_arg_slots() const; - const tools::FuncType* get_func_type()const { return &m_func_type; } + void init(NodeType node_type, const tools::FunctionDescriptor* func_type); + const std::vector& get_arg_slots() const { return m_argument_slot; } + const tools::FunctionDescriptor* get_func_type()const { return m_func_type; } const Token& get_identifier_token() const { return m_identifier_token; } void set_identifier_token(const Token& tok) { m_identifier_token = tok; } Slot* get_lvalue() const { return m_argument_slot[0]; } Slot* get_rvalue() const { return m_argument_slot[1]; } protected: Token m_identifier_token = Token::s_null; - tools::FuncType m_func_type; + const tools::FunctionDescriptor* m_func_type; // not owned std::vector m_argument_slot; std::vector m_argument_props; diff --git a/src/ndbl/core/Graph.cpp b/src/ndbl/core/Graph.cpp index 8b9c4780d..06053d04b 100644 --- a/src/ndbl/core/Graph.cpp +++ b/src/ndbl/core/Graph.cpp @@ -110,23 +110,23 @@ void Graph::ensure_has_root() } } -VariableNode* Graph::create_variable(const TypeDesc *_type, const std::string& _name, Scope* _scope) +VariableNode* Graph::create_variable(const TypeDescriptor *_type, const std::string& _name, Scope* _scope) { VariableNode* node = m_factory->create_variable(_type, _name, _scope); add(node); return node; } -InvokableNode* Graph::create_function(FuncType&& _type) +FunctionNode* Graph::create_function(const FunctionDescriptor* _type) { - InvokableNode* node = m_factory->create_function(std::move(_type), NodeType_FUNCTION); + FunctionNode* node = m_factory->create_function(_type, NodeType_FUNCTION); add(node); return node; } -InvokableNode* Graph::create_operator(FuncType&& _type) +FunctionNode* Graph::create_operator(const FunctionDescriptor* _type) { - InvokableNode* node = m_factory->create_function(std::move(_type), NodeType_OPERATOR); + FunctionNode* node = m_factory->create_function(_type, NodeType_OPERATOR); add(node); return node; } @@ -477,14 +477,14 @@ Node* Graph::create_node() return node; } -LiteralNode* Graph::create_literal(const TypeDesc *_type) +LiteralNode* Graph::create_literal(const TypeDescriptor *_type) { LiteralNode* node = m_factory->create_literal(_type); add(node); return node; } -Node* Graph::create_node( CreateNodeType _type, const FuncType* _signature ) +Node* Graph::create_node( CreateNodeType _type, const FunctionDescriptor* _signature ) { switch ( _type ) { @@ -508,23 +508,23 @@ Node* Graph::create_node( CreateNodeType _type, const FuncType* _signature ) case CreateNodeType_LITERAL_INTEGER: return create_literal(); case CreateNodeType_LITERAL_STRING: return create_literal(); - case CreateNodeType_INVOKABLE: + case CreateNodeType_FUNCTION: { VERIFY(_signature != nullptr, "_signature is expected when dealing with functions or operators") Nodlang* language = get_language(); // Currently, we handle operators and functions the exact same way - FuncType signature = *language->find_function(_signature)->get_sig(); - bool is_operator = language->find_operator_fct( &signature ) != nullptr; + const FunctionDescriptor* signature = language->find_function(_signature)->get_sig(); + bool is_operator = language->find_operator_fct( signature ) != nullptr; if ( is_operator ) - return create_operator(std::move(signature)); - return create_function(std::move(signature)); + return create_operator(signature); + return create_function(signature); } default: VERIFY(false, "Unhandled CreateNodeType."); } } -VariableNode* Graph::create_variable_decl(const TypeDesc* _type, const char* _name, Scope* _scope) +VariableNode* Graph::create_variable_decl(const TypeDescriptor* _type, const char* _name, Scope* _scope) { if( !_scope) { diff --git a/src/ndbl/core/Graph.h b/src/ndbl/core/Graph.h index 2a99604b3..7d4b7049d 100644 --- a/src/ndbl/core/Graph.h +++ b/src/ndbl/core/Graph.h @@ -12,7 +12,6 @@ #include "tools/core/types.h" #include "IScope.h" -#include "tools/core/reflection/FuncType.h" namespace ndbl { @@ -43,7 +42,7 @@ namespace ndbl CreateNodeType_LITERAL_DOUBLE, CreateNodeType_LITERAL_INTEGER, CreateNodeType_LITERAL_STRING, - CreateNodeType_INVOKABLE, + CreateNodeType_FUNCTION, }; /** @@ -63,19 +62,19 @@ namespace ndbl // node related Node* create_node(); // Create a raw node. - Node* create_node(CreateNodeType, const tools::FuncType* _signature = nullptr); // Create a given node type in a simple way. + Node* create_node(CreateNodeType, const tools::FunctionDescriptor* _signature = nullptr); // Create a given node type in a simple way. Node* create_root(); - VariableNode* create_variable(const tools::TypeDesc *_type, const std::string &_name, Scope* _scope); - VariableNode* create_variable_decl(const tools::TypeDesc* _type, const char* _name, Scope* _scope); + VariableNode* create_variable(const tools::TypeDescriptor *_type, const std::string &_name, Scope* _scope); + VariableNode* create_variable_decl(const tools::TypeDescriptor* _type, const char* _name, Scope* _scope); template VariableNode* create_variable_decl(const char* _name = "var", Scope* _scope = {}) { return create_variable_decl(tools::type::get(), _name, _scope); } - LiteralNode* create_literal(const tools::TypeDesc *_type); + LiteralNode* create_literal(const tools::TypeDescriptor *_type); template LiteralNode* create_literal() { return create_literal( tools::type::get()); } - InvokableNode* create_function(tools::FuncType&&); - InvokableNode* create_operator(tools::FuncType&&); + FunctionNode* create_function(const tools::FunctionDescriptor*); + FunctionNode* create_operator(const tools::FunctionDescriptor*); Node* create_scope(); IfNode* create_cond_struct(); ForLoopNode* create_for_loop(); diff --git a/src/ndbl/core/Graph.specs.cpp b/src/ndbl/core/Graph.specs.cpp index c320eef2c..00ea53b48 100644 --- a/src/ndbl/core/Graph.specs.cpp +++ b/src/ndbl/core/Graph.specs.cpp @@ -1,9 +1,9 @@ #include -#include "tools/core/reflection/FuncType.h" +#include "tools/core/reflection/Type.h" #include "Graph.h" -#include "InvokableNode.h" +#include "FunctionNode.h" #include "Node.h" #include "Scope.h" #include "DirectedEdge.h" @@ -67,11 +67,11 @@ TEST_F(Graph_, clear) EXPECT_TRUE( graph->get_edge_registry().empty() ); VariableNode* variable = graph->create_variable(type::get(), "var", nullptr); - FuncType fct_type = FuncTypeBuilder("+").construct(); - const IInvokable* invokable = app.get_language()->find_operator_fct_exact(&fct_type); + FunctionDescriptor* fct_type = FunctionDescriptor::create("+"); + const IInvokable* invokable = app.get_language()->find_operator_fct_exact(fct_type); EXPECT_TRUE(invokable != nullptr); - auto operator_node = graph->create_operator(std::move(fct_type)); + auto operator_node = graph->create_operator(fct_type); EXPECT_TRUE( graph->get_edge_registry().empty() ); @@ -89,6 +89,8 @@ TEST_F(Graph_, clear) // test EXPECT_TRUE( graph->get_node_registry().empty() ); EXPECT_TRUE( graph->get_edge_registry().empty() ); + + delete fct_type; } diff --git a/src/ndbl/core/Instruction.h b/src/ndbl/core/Instruction.h index 90b1987c8..eb6da5687 100644 --- a/src/ndbl/core/Instruction.h +++ b/src/ndbl/core/Instruction.h @@ -61,7 +61,7 @@ namespace ndbl { OpCode opcode; const tools::qword* ptr; - const tools::TypeDesc* type; // pointed data's type. + const tools::TypeDescriptor* type; // pointed data's type. }; // Compare two operands (test if equals) diff --git a/src/ndbl/core/Interpreter.cpp b/src/ndbl/core/Interpreter.cpp index 710352522..0ee755e50 100644 --- a/src/ndbl/core/Interpreter.cpp +++ b/src/ndbl/core/Interpreter.cpp @@ -1,7 +1,7 @@ #include "Interpreter.h" #include -#include "InvokableNode.h" +#include "FunctionNode.h" #include "VariableNode.h" using namespace ndbl; @@ -127,7 +127,7 @@ bool Interpreter::step_over() const qword* qword = next_instr->uref.ptr; m_cpu.write(Register_rax, *qword ); - const TypeDesc* ptr_type = next_instr->uref.type; + const TypeDescriptor* ptr_type = next_instr->uref.type; if(ptr_type->is() ) { LOG_VERBOSE("Interpreter", "deref_qword bool: %b\n", qword->b); diff --git a/src/ndbl/core/LiteralNode.cpp b/src/ndbl/core/LiteralNode.cpp index a6dc51f56..088513cc1 100644 --- a/src/ndbl/core/LiteralNode.cpp +++ b/src/ndbl/core/LiteralNode.cpp @@ -9,7 +9,7 @@ REFLECT_STATIC_INIT type::Initializer("LiteralNode").extends(); } -void LiteralNode::init(const TypeDesc* _type, const std::string& _name) +void LiteralNode::init(const TypeDescriptor* _type, const std::string& _name) { Node::init(NodeType_LITERAL, _name); m_type = _type; diff --git a/src/ndbl/core/LiteralNode.h b/src/ndbl/core/LiteralNode.h index c031b71c9..0148177dd 100644 --- a/src/ndbl/core/LiteralNode.h +++ b/src/ndbl/core/LiteralNode.h @@ -13,7 +13,7 @@ namespace ndbl LiteralNode() {}; ~LiteralNode() override {}; - void init(const tools::TypeDesc* _type, const std::string& _name); + void init(const tools::TypeDescriptor* _type, const std::string& _name); Property* value() { ASSERT(m_value_property != nullptr); return m_value_property; } const Property* value() const { ASSERT(m_value_property != nullptr); return m_value_property; } Slot& output_slot(); @@ -21,7 +21,7 @@ namespace ndbl private: Property* m_value_property = nullptr; - const tools::TypeDesc* m_type = nullptr; + const tools::TypeDescriptor* m_type = nullptr; REFLECT_DERIVED_CLASS() }; } \ No newline at end of file diff --git a/src/ndbl/core/Node.cpp b/src/ndbl/core/Node.cpp index ffb3bd69e..aecc50dd6 100644 --- a/src/ndbl/core/Node.cpp +++ b/src/ndbl/core/Node.cpp @@ -36,7 +36,7 @@ size_t Node::adjacent_slot_count(SlotFlags _flags )const return filter_adjacent_slots( _flags ).size(); } -const FuncType* Node::get_connected_function_type(const char* property_name) const +const FunctionDescriptor* Node::get_connected_function_type(const char* property_name) const { const Slot* slot = find_slot_by_property_name( property_name, SlotFlag_INPUT ); VERIFY(slot!= nullptr, "Unable to find input slot for this property name") @@ -44,7 +44,7 @@ const FuncType* Node::get_connected_function_type(const char* property_name) con if ( adjacent_slot ) if ( adjacent_slot->get_node()->is_invokable() ) - return static_cast(adjacent_slot->get_node())->get_func_type(); + return static_cast(adjacent_slot->get_node())->get_func_type(); return nullptr; } @@ -171,7 +171,7 @@ std::vector Node::filter_adjacent( SlotFlags _flags ) const return GraphUtil::get_adjacent_nodes(this, _flags); } -Slot* Node::find_slot_by_property_type(SlotFlags flags, const TypeDesc* _type) +Slot* Node::find_slot_by_property_type(SlotFlags flags, const TypeDescriptor* _type) { for(Slot* slot : filter_slots( flags ) ) { @@ -200,7 +200,7 @@ Slot& Node::get_nth_slot( size_t _n, SlotFlags _flags ) VERIFY(false, "Not found") } -Property* Node::add_prop(const TypeDesc* _type, const char *_name, PropertyFlags _flags) +Property* Node::add_prop(const TypeDescriptor* _type, const char *_name, PropertyFlags _flags) { return m_props.add(_type, _name, _flags); } @@ -331,7 +331,7 @@ bool Node::can_be_instruction() const bool Node::is_unary_operator() const { if ( m_type == NodeType_OPERATOR ) - if ( static_cast(this)->get_func_type()->get_arg_count() == 1 ) + if (static_cast(this)->get_func_type()->get_arg_count() == 1 ) return true; return false; } @@ -339,7 +339,7 @@ bool Node::is_unary_operator() const bool Node::is_binary_operator() const { if ( m_type == NodeType_OPERATOR ) - if ( static_cast(this)->get_func_type()->get_arg_count() == 2 ) + if (static_cast(this)->get_func_type()->get_arg_count() == 2 ) return true; return false; } diff --git a/src/ndbl/core/Node.h b/src/ndbl/core/Node.h index 6f82cbe51..67e2cd8f5 100644 --- a/src/ndbl/core/Node.h +++ b/src/ndbl/core/Node.h @@ -47,10 +47,10 @@ namespace ndbl The role of this class is to provide connectable Objects as Nodes. A node is an Object (composed with Properties) that can be linked - together in order to create graphs. + together in order to create_new graphs. Every Node has_flags a parent Graph. All nodes are built from a Graph, - which first create an instance of this class (or derived) and then + which first create_new an instance of this class (or derived) and then add some Component on it. */ class Node @@ -100,7 +100,7 @@ namespace ndbl const Slot* find_slot_at( SlotFlags, size_t _position ) const; // implicitly THIS_PROPERTY's slot Slot* find_slot_by_property_name(const char* _property_name, SlotFlags ); const Slot* find_slot_by_property_name(const char* property_name, SlotFlags ) const; - Slot* find_slot_by_property_type(SlotFlags _way, const tools::TypeDesc *_type); + Slot* find_slot_by_property_type(SlotFlags _way, const tools::TypeDescriptor *_type); Slot* find_slot_by_property(const Property*, SlotFlags ); const Slot* find_slot_by_property(const Property*, SlotFlags ) const; Slot* find_adjacent_at(SlotFlags, size_t _index ) const; @@ -119,12 +119,12 @@ namespace ndbl // Property related //----------------- - Property* add_prop(const tools::TypeDesc*, const char* /* name */, PropertyFlags = PropertyFlag_NONE); + Property* add_prop(const tools::TypeDescriptor*, const char* /* name */, PropertyFlags = PropertyFlag_NONE); Property* get_prop_at(size_t); const Property* get_prop_at(size_t) const; Property* get_prop(const char* _name); const Property* get_prop(const char* _name) const; - const tools::FuncType* get_connected_function_type(const char *property_name) const; // + const tools::FunctionDescriptor* get_connected_function_type(const char *property_name) const; // bool has_input_connected( const Property*) const; template diff --git a/src/ndbl/core/NodeFactory.cpp b/src/ndbl/core/NodeFactory.cpp index 2af64ea7c..12299d681 100644 --- a/src/ndbl/core/NodeFactory.cpp +++ b/src/ndbl/core/NodeFactory.cpp @@ -8,7 +8,7 @@ #include "ForLoopNode.h" #include "IfNode.h" -#include "InvokableNode.h" +#include "FunctionNode.h" #include "LiteralNode.h" #include "NodeUtils.h" #include "Scope.h" @@ -56,7 +56,7 @@ void NodeFactory::destroy_node(Node* node) const #endif } -VariableNode* NodeFactory::create_variable(const TypeDesc* _type, const std::string& _name, Scope* _scope) const +VariableNode* NodeFactory::create_variable(const TypeDescriptor* _type, const std::string& _name, Scope* _scope) const { // create auto node = create(); @@ -75,11 +75,11 @@ VariableNode* NodeFactory::create_variable(const TypeDesc* _type, const std::str return node; } -InvokableNode* NodeFactory::create_function(tools::FuncType&& _func_type, NodeType _node_type) const +FunctionNode* NodeFactory::create_function(const FunctionDescriptor* _func_type, NodeType _node_type) const { - auto* node = create(); + auto* node = create(); ASSERT( _node_type == NodeType_OPERATOR || _node_type == NodeType_FUNCTION ) - node->init(_node_type, std::move(_func_type)); + node->init(_node_type, _func_type); m_post_process(node); return node; } @@ -151,7 +151,7 @@ Node* NodeFactory::create_node() const return node; } -LiteralNode* NodeFactory::create_literal(const TypeDesc *_type) const +LiteralNode* NodeFactory::create_literal(const TypeDescriptor *_type) const { auto node = create(); node->init(_type, "Literal"); diff --git a/src/ndbl/core/NodeFactory.h b/src/ndbl/core/NodeFactory.h index 867e38a36..c7f416b01 100644 --- a/src/ndbl/core/NodeFactory.h +++ b/src/ndbl/core/NodeFactory.h @@ -8,7 +8,7 @@ #include "IfNode.h" #include "WhileLoopNode.h" #include "IScope.h" -#include "InvokableNode.h" +#include "FunctionNode.h" namespace ndbl { @@ -33,9 +33,9 @@ namespace ndbl ~NodeFactory(){} Node* create_program()const; - VariableNode* create_variable(const tools::TypeDesc *_type, const std::string &_name, Scope* _scope)const; - LiteralNode* create_literal(const tools::TypeDesc *_type)const; - InvokableNode* create_function(tools::FuncType&&, NodeType node_type = NodeType_FUNCTION)const; + VariableNode* create_variable(const tools::TypeDescriptor *_type, const std::string &_name, Scope* _scope)const; + LiteralNode* create_literal(const tools::TypeDescriptor *_type)const; + FunctionNode* create_function(const tools::FunctionDescriptor*, NodeType node_type = NodeType_FUNCTION)const; Node* create_scope()const; IfNode* create_cond_struct()const; ForLoopNode* create_for_loop()const; diff --git a/src/ndbl/core/NodeUtils.h b/src/ndbl/core/NodeUtils.h index a14148b39..6c79d68c7 100644 --- a/src/ndbl/core/NodeUtils.h +++ b/src/ndbl/core/NodeUtils.h @@ -10,7 +10,7 @@ namespace ndbl class NodeComponent; /** - * Static class responsible for create/destroy/attach/remove components + * Static class responsible for create_new/destroy/attach/remove components * All Components are owned by the manager. * Therefore new / delete are handled by this class. */ diff --git a/src/ndbl/core/Property.cpp b/src/ndbl/core/Property.cpp index 17215ca6d..edb26c591 100644 --- a/src/ndbl/core/Property.cpp +++ b/src/ndbl/core/Property.cpp @@ -7,7 +7,7 @@ using namespace ndbl; using namespace tools; -void Property::init(const TypeDesc* _type, PropertyFlags _flags, Node* _owner, const char* _name) +void Property::init(const TypeDescriptor* _type, PropertyFlags _flags, Node* _owner, const char* _name) { VERIFY(m_type == nullptr, "must be initialized once") VERIFY(_type != nullptr, "type can't be nullptr") @@ -22,7 +22,7 @@ void Property::digest(Property* _property) m_token = std::move( _property->m_token ); } -bool Property::is_type(const TypeDesc* other) const +bool Property::is_type(const TypeDescriptor* other) const { return m_type->equals( other ); } diff --git a/src/ndbl/core/Property.h b/src/ndbl/core/Property.h index b8678bd07..f1851b211 100644 --- a/src/ndbl/core/Property.h +++ b/src/ndbl/core/Property.h @@ -27,7 +27,7 @@ namespace ndbl class Property { public: - void init(const tools::TypeDesc*, PropertyFlags, Node*, const char* _name); // must be called once before use + void init(const tools::TypeDescriptor*, PropertyFlags, Node*, const char* _name); // must be called once before use void digest(Property *_property); bool has_flags(PropertyFlags flags)const { return (m_flags & flags) == flags; }; void set_flags(PropertyFlags flags) { m_flags |= flags; } @@ -35,8 +35,8 @@ namespace ndbl //void set_name(const char* _name) { m_name = _name; } names are indexed in PropertyBag, can't change const std::string& get_name()const { return m_name; } Node* get_owner()const { return m_owner; } - const tools::TypeDesc* get_type()const { return m_type; } - bool is_type(const tools::TypeDesc* other) const; + const tools::TypeDescriptor* get_type()const { return m_type; } + bool is_type(const tools::TypeDescriptor* other) const; void set_token(const Token& _token) { m_token = _token; } Token& get_token() { return m_token; } const Token& get_token() const { return m_token; } @@ -44,7 +44,7 @@ namespace ndbl private: Node* m_owner = nullptr; PropertyFlags m_flags = PropertyFlag_NONE; - const tools::TypeDesc* m_type = nullptr; + const tools::TypeDescriptor* m_type = nullptr; std::string m_name; Token m_token; }; diff --git a/src/ndbl/core/PropertyBag.cpp b/src/ndbl/core/PropertyBag.cpp index fdf903c4e..b49e50ff5 100644 --- a/src/ndbl/core/PropertyBag.cpp +++ b/src/ndbl/core/PropertyBag.cpp @@ -9,7 +9,7 @@ bool PropertyBag::has(const char* _name) const return m_properties_by_name.find(_name) != m_properties_by_name.end(); } -Property* PropertyBag::add(const TypeDesc* _type, const char* _name, PropertyFlags _flags ) +Property* PropertyBag::add(const TypeDescriptor* _type, const char* _name, PropertyFlags _flags ) { VERIFY(m_owner != nullptr, "PropertyBag must be initialized") ASSERT(!has(_name)); @@ -26,17 +26,17 @@ Property* PropertyBag::add(const TypeDesc* _type, const char* _name, PropertyFla return new_property; } -const Property* PropertyBag::find_first( PropertyFlags _flags, const TypeDesc *_type) const +const Property* PropertyBag::find_first( PropertyFlags _flags, const TypeDescriptor *_type) const { return _find_first( _flags, _type ); } -Property* PropertyBag::find_first( PropertyFlags _flags, const TypeDesc *_type) +Property* PropertyBag::find_first( PropertyFlags _flags, const TypeDescriptor *_type) { return const_cast( _find_first( _flags, _type ) ); } -const Property* PropertyBag::_find_first( PropertyFlags _flags, const TypeDesc *_type) const +const Property* PropertyBag::_find_first( PropertyFlags _flags, const TypeDescriptor *_type) const { auto filter = [_flags, _type](const std::pair& pair) -> bool { diff --git a/src/ndbl/core/PropertyBag.h b/src/ndbl/core/PropertyBag.h index 78ec1308e..0861d1c46 100644 --- a/src/ndbl/core/PropertyBag.h +++ b/src/ndbl/core/PropertyBag.h @@ -37,19 +37,19 @@ namespace ndbl const Property* at( size_t pos ) const; Property* find_by_name(const char* _name); const Property* find_by_name(const char* _name) const; - Property* find_first( PropertyFlags, const tools::TypeDesc* ); - const Property* find_first( PropertyFlags, const tools::TypeDesc* ) const; + Property* find_first( PropertyFlags, const tools::TypeDescriptor* ); + const Property* find_first( PropertyFlags, const tools::TypeDescriptor* ) const; Property* find_id_from_name(const char*) const; Property* get_this(); const Property* get_this() const; - Property* add(const tools::TypeDesc* _type, const char *_name, PropertyFlags = PropertyFlag_NONE ); + Property* add(const tools::TypeDescriptor* _type, const char *_name, PropertyFlags = PropertyFlag_NONE ); template Property* add( const char* _name, PropertyFlags _flags = PropertyFlag_NONE ) { return add(tools::type::get(), _name, _flags); } private: - const Property* _find_first( PropertyFlags _flags, const tools::TypeDesc *_type) const; + const Property* _find_first( PropertyFlags _flags, const tools::TypeDescriptor *_type) const; Node* m_owner; std::vector m_properties; std::map m_properties_by_name; diff --git a/src/ndbl/core/Token.h b/src/ndbl/core/Token.h index 4d466e786..042adabef 100644 --- a/src/ndbl/core/Token.h +++ b/src/ndbl/core/Token.h @@ -99,7 +99,7 @@ namespace ndbl , m_word_start_pos(other.m_word_start_pos) , m_word_length(other.m_word_length) { - VERIFY(other.m_is_buffer_owned == false, "Can't construct a Token from an owned const char*") + VERIFY(other.m_is_buffer_owned == false, "Can't create a Token from an owned const char*") } Token(Token&& other); diff --git a/src/ndbl/core/VariableNode.cpp b/src/ndbl/core/VariableNode.cpp index f4d63badb..65b751343 100644 --- a/src/ndbl/core/VariableNode.cpp +++ b/src/ndbl/core/VariableNode.cpp @@ -10,7 +10,7 @@ REFLECT_STATIC_INIT type::Initializer("VariableNode").extends(); } -void VariableNode::init(const tools::TypeDesc* _type, const char* _identifier) +void VariableNode::init(const tools::TypeDescriptor* _type, const char* _identifier) { // Init node Node::init(NodeType_VARIABLE, "Variable"); diff --git a/src/ndbl/core/VariableNode.h b/src/ndbl/core/VariableNode.h index db7698c99..08af9e3fc 100644 --- a/src/ndbl/core/VariableNode.h +++ b/src/ndbl/core/VariableNode.h @@ -31,7 +31,7 @@ namespace ndbl public: ~VariableNode() override {}; - void init(const tools::TypeDesc* _type, const char* _identifier); + void init(const tools::TypeDescriptor* _type, const char* _identifier); bool has_vflags(VariableFlags flags)const { return (m_vflags & flags) == flags; }; void set_vflags(VariableFlags flags) { m_vflags |= flags; } void clear_vflags(VariableFlags flags = VariableFlag_ALL) { m_vflags &= ~flags; } @@ -43,7 +43,7 @@ namespace ndbl const Slot& input_slot() const; // input slot for variable initialisation Slot& output_slot(); // output slot to reference this variable const Slot& output_slot() const; // output slot to reference this variable - const tools::TypeDesc* get_type() const { return m_identifier->get_type(); } + const tools::TypeDescriptor* get_type() const { return m_identifier->get_type(); } const Token& get_type_token() const { return m_type_token; } std::string get_identifier() const { return get_identifier_token().word_to_string(); } const Token& get_identifier_token() const { return m_identifier->get_token(); } diff --git a/src/ndbl/core/language/Nodlang.basics.specs.cpp b/src/ndbl/core/language/Nodlang.basics.specs.cpp index 91e58e465..6f3f03e30 100644 --- a/src/ndbl/core/language/Nodlang.basics.specs.cpp +++ b/src/ndbl/core/language/Nodlang.basics.specs.cpp @@ -1,7 +1,7 @@ #include #include "ndbl/core/fixtures/core.h" -#include "tools/core/reflection/FuncType.h" +#include "tools/core/reflection/reflection" using namespace ndbl; using namespace tools; @@ -16,22 +16,26 @@ TEST_F(Language_basics, can_get_add_operator_with_short_identifier ) TEST_F(Language_basics, can_get_add_operator_with_signature ) { - const FuncType signature = FuncTypeBuilder("+").construct(); - EXPECT_TRUE(language->find_operator_fct(&signature)); + const FunctionDescriptor descriptor = FunctionDescriptor::construct("+"); + EXPECT_TRUE(language->find_operator_fct(&descriptor)); } TEST_F(Language_basics, can_get_invert_operator_with_signature ) { - const FuncType signature = FuncTypeBuilder("-").construct(); - EXPECT_TRUE(language->find_operator_fct(&signature)); + const FunctionDescriptor descriptor = FunctionDescriptor::construct("-"); + EXPECT_TRUE(language->find_operator_fct(&descriptor)); } TEST_F(Language_basics, by_ref_assign ) { - const FuncType signature = FuncTypeBuilder("=").construct(); - auto operator_func = language->find_operator_fct(&signature); - EXPECT_TRUE(operator_func != nullptr); - EXPECT_TRUE(operator_func->get_sig()->get_args()[0].m_by_reference); + const FunctionDescriptor descriptor = FunctionDescriptor::construct("="); + + EXPECT_TRUE(descriptor.get_args()[0].m_by_reference); + + const IInvokable* invokable = language->find_operator_fct(&descriptor); + + EXPECT_TRUE(invokable != nullptr); + EXPECT_TRUE(invokable->get_sig()->get_args()[0].m_by_reference); } TEST_F(Language_basics, token_t_to_type) diff --git a/src/ndbl/core/language/Nodlang.cpp b/src/ndbl/core/language/Nodlang.cpp index 53223c93a..0e1931302 100644 --- a/src/ndbl/core/language/Nodlang.cpp +++ b/src/ndbl/core/language/Nodlang.cpp @@ -26,7 +26,7 @@ #include "ndbl/core/ForLoopNode.h" #include "ndbl/core/Graph.h" #include "ndbl/core/IfNode.h" -#include "ndbl/core/InvokableNode.h" +#include "ndbl/core/FunctionNode.h" #include "ndbl/core/LiteralNode.h" #include "ndbl/core/Property.h" #include "ndbl/core/Scope.h" @@ -357,13 +357,11 @@ Slot *Nodlang::parse_binary_operator_expression(u8_t _precedence, Slot& _left) } // Create a function signature according to ltype, rtype and operator word - FuncType type; - type.set_identifier(ope->identifier); - type.set_return_type(type::any()); - type.push_arg( _left.get_property()->get_type()); - type.push_arg(right->get_property()->get_type()); + FunctionDescriptor* type = FunctionDescriptor::create(ope->identifier.c_str()); + type->push_arg( _left.get_property()->get_type()); + type->push_arg(right->get_property()->get_type()); - InvokableNode* binary_op = parser_state.graph->create_operator(std::move(type)); + FunctionNode* binary_op = parser_state.graph->create_operator(std::move(type)); binary_op->set_identifier_token( operator_token ); parser_state.graph->connect_or_merge( _left, *binary_op->get_lvalue()); parser_state.graph->connect_or_merge( *right, *binary_op->get_rvalue() ); @@ -411,12 +409,10 @@ Slot *Nodlang::parse_unary_operator_expression(u8_t _precedence) } // Create a function signature - FuncType type; - type.set_identifier(operator_token.word_to_string()); - type.set_return_type(type::any()); - type.push_arg( out_atomic->get_property()->get_type()); + FunctionDescriptor* type = FunctionDescriptor::create(operator_token.word_to_string().c_str()); + type->push_arg( out_atomic->get_property()->get_type()); - InvokableNode* node = parser_state.graph->create_operator(std::move(type)); + FunctionNode* node = parser_state.graph->create_operator(std::move(type)); node->set_identifier_token( operator_token ); parser_state.graph->connect_or_merge( *out_atomic, *node->find_slot_by_property_name( LEFT_VALUE_PROPERTY, SlotFlag_INPUT ) ); @@ -1010,9 +1006,7 @@ Slot* Nodlang::parse_function_call() std::vector result_slots; // Declare a new function prototype - FuncType signature; - signature.set_identifier(fct_id); - signature.set_return_type(type::any()); + FunctionDescriptor* signature = FunctionDescriptor::create(fct_id.c_str()); bool parsingError = false; while (!parsingError && parser_state.ribbon.can_eat() && @@ -1022,7 +1016,7 @@ Slot* Nodlang::parse_function_call() if ( expression_out != nullptr ) { result_slots.push_back( expression_out ); - signature.push_arg( expression_out->get_property()->get_type() ); + signature->push_arg( expression_out->get_property()->get_type() ); parser_state.ribbon.eat_if(Token_t::list_separator); } else @@ -1041,7 +1035,7 @@ Slot* Nodlang::parse_function_call() // Find the prototype in the language library - InvokableNode* fct_node = parser_state.graph->create_function(std::move(signature)); + FunctionNode* fct_node = parser_state.graph->create_function(std::move(signature)); for ( const FuncArg& signature_arg : fct_node->get_func_type()->get_args() ) { @@ -1333,7 +1327,7 @@ Slot* Nodlang::parse_variable_declaration() if (type_token.is_keyword_type() && identifier_token.m_type == Token_t::identifier) { - const TypeDesc* variable_type = get_type(type_token.m_type); + const TypeDescriptor* variable_type = get_type(type_token.m_type); auto* scope = get_current_scope(); ASSERT(scope != nullptr ) // There must always be a scope! VariableNode* variable_node = parser_state.graph->create_variable(variable_type, identifier_token.word_to_string(), scope ); @@ -1373,21 +1367,21 @@ Slot* Nodlang::parse_variable_declaration() // [SECTION] C. Serializer -------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------- -std::string &Nodlang::serialize_invokable(std::string &_out, const InvokableNode* _node) const +std::string &Nodlang::serialize_invokable(std::string &_out, const FunctionNode* _node) const { if ( _node->type() == NodeType_OPERATOR ) { const std::vector& args = _node->get_arg_slots(); int precedence = get_precedence(_node->get_func_type()); - const FuncType* func_type = _node->get_func_type(); + const FunctionDescriptor* func_type = _node->get_func_type(); switch (func_type->get_arg_count()) { case 2: { // Left part of the expression { - const FuncType* l_func_type = _node->get_connected_function_type(LEFT_VALUE_PROPERTY); + const FunctionDescriptor* l_func_type = _node->get_connected_function_type(LEFT_VALUE_PROPERTY); bool needs_braces = l_func_type && get_precedence(l_func_type) < precedence; SerializeFlags flags = SerializeFlag_RECURSE | needs_braces * SerializeFlag_WRAP_WITH_BRACES ; @@ -1400,7 +1394,7 @@ std::string &Nodlang::serialize_invokable(std::string &_out, const InvokableNode // Right part of the expression { - const FuncType* r_func_type = _node->get_connected_function_type(RIGHT_VALUE_PROPERTY); + const FunctionDescriptor* r_func_type = _node->get_connected_function_type(RIGHT_VALUE_PROPERTY); bool needs_braces = r_func_type && get_precedence(r_func_type) < precedence; SerializeFlags flags = SerializeFlag_RECURSE | needs_braces * SerializeFlag_WRAP_WITH_BRACES ; @@ -1432,7 +1426,7 @@ std::string &Nodlang::serialize_invokable(std::string &_out, const InvokableNode return _out; } -std::string &Nodlang::serialize_func_call(std::string &_out, const FuncType *_signature, const std::vector &inputs) const +std::string &Nodlang::serialize_func_call(std::string &_out, const FunctionDescriptor *_signature, const std::vector &inputs) const { _out.append( _signature->get_identifier() ); serialize_token_t(_out, Token_t::parenthesis_open); @@ -1456,7 +1450,7 @@ std::string &Nodlang::serialize_invokable_sig(std::string &_out, const IInvokabl return serialize_func_sig(_out, _invokable->get_sig()); } -std::string &Nodlang::serialize_func_sig(std::string &_out, const FuncType *_signature) const +std::string &Nodlang::serialize_func_sig(std::string &_out, const FunctionDescriptor *_signature) const { serialize_type(_out, _signature->get_return_type()); _out.append(" "); @@ -1483,7 +1477,7 @@ std::string &Nodlang::serialize_token_t(std::string &_out, const Token_t &_type) return _out.append(to_string(_type)); } -std::string &Nodlang::serialize_type(std::string &_out, const TypeDesc* _type) const +std::string &Nodlang::serialize_type(std::string &_out, const TypeDescriptor* _type) const { return _out.append(to_string(_type)); } @@ -1613,7 +1607,7 @@ std::string & Nodlang::serialize_node(std::string &_out, const Node* node, Seria case NodeType_FUNCTION: [[fallthrough]]; case NodeType_OPERATOR: - serialize_invokable(_out, static_cast(node) ); + serialize_invokable(_out, static_cast(node) ); break; default: VERIFY(false, "Unhandled NodeType, can't serialize"); @@ -1783,7 +1777,7 @@ const tools::IInvokable* Nodlang::find_function(u32_t _hash) const return nullptr; } -const tools::IInvokable* Nodlang::find_function(const FuncType* _type) const +const tools::IInvokable* Nodlang::find_function(const FunctionDescriptor* _type) const { if (!_type) { @@ -1799,7 +1793,7 @@ std::string& Nodlang::serialize_property(std::string& _out, const Property* _pro return serialize_token(_out, _property->get_token()); } -const tools::IInvokable* Nodlang::find_function_exact(const FuncType* _other_type) const +const tools::IInvokable* Nodlang::find_function_exact(const FunctionDescriptor* _other_type) const { for(auto* invokable : m_functions) if ( invokable->get_sig()->is_exactly(_other_type) ) @@ -1807,7 +1801,7 @@ const tools::IInvokable* Nodlang::find_function_exact(const FuncType* _other_typ return nullptr; } -const tools::IInvokable* Nodlang::find_function_fallback(const FuncType* _other_type) const +const tools::IInvokable* Nodlang::find_function_fallback(const FunctionDescriptor* _other_type) const { for(auto* invokable : m_functions) if ( invokable->get_sig()->is_compatible(_other_type) ) @@ -1815,7 +1809,7 @@ const tools::IInvokable* Nodlang::find_function_fallback(const FuncType* _other_ return nullptr; } -const tools::IInvokable* Nodlang::find_operator_fct_exact(const FuncType* _other_type) const +const tools::IInvokable* Nodlang::find_operator_fct_exact(const FunctionDescriptor* _other_type) const { if (!_other_type) return nullptr; @@ -1827,7 +1821,7 @@ const tools::IInvokable* Nodlang::find_operator_fct_exact(const FuncType* _other return nullptr; } -const tools::IInvokable* Nodlang::find_operator_fct(const FuncType *_type) const +const tools::IInvokable* Nodlang::find_operator_fct(const FunctionDescriptor *_type) const { if (!_type) { @@ -1839,7 +1833,7 @@ const tools::IInvokable* Nodlang::find_operator_fct(const FuncType *_type) const return find_operator_fct_fallback(_type); } -const tools::IInvokable* Nodlang::find_operator_fct_fallback(const FuncType* _other_type) const +const tools::IInvokable* Nodlang::find_operator_fct_fallback(const FunctionDescriptor* _other_type) const { if (!_other_type) return nullptr; @@ -1884,7 +1878,7 @@ const Operator *Nodlang::find_operator(const std::string &_identifier, Operator_ return nullptr; } -std::string &Nodlang::to_string(std::string &_out, const TypeDesc* _type) const +std::string &Nodlang::to_string(std::string &_out, const TypeDescriptor* _type) const { auto found = m_keyword_by_type_id.find(_type->id()); if (found != m_keyword_by_type_id.cend()) @@ -1924,7 +1918,7 @@ std::string &Nodlang::to_string(std::string &_out, Token_t _token_t) const } } -std::string Nodlang::to_string(const TypeDesc* _type) const +std::string Nodlang::to_string(const TypeDescriptor* _type) const { std::string result; return to_string(result, _type); @@ -1936,7 +1930,7 @@ std::string Nodlang::to_string(Token_t _token) const return to_string(result, _token); } -int Nodlang::get_precedence( const tools::FuncType* _func_type) const +int Nodlang::get_precedence( const tools::FunctionDescriptor* _func_type) const { if (!_func_type) return std::numeric_limits::min(); // default @@ -1948,7 +1942,7 @@ int Nodlang::get_precedence( const tools::FuncType* _func_type) const return std::numeric_limits::max(); } -const TypeDesc* Nodlang::get_type(Token_t _token) const +const TypeDescriptor* Nodlang::get_type(Token_t _token) const { VERIFY(is_a_type_keyword(_token), "_token_t is not a type keyword!"); return m_type_by_token_t.find(_token)->second; diff --git a/src/ndbl/core/language/Nodlang.h b/src/ndbl/core/language/Nodlang.h index 6b24f58e2..403745c5a 100644 --- a/src/ndbl/core/language/Nodlang.h +++ b/src/ndbl/core/language/Nodlang.h @@ -20,7 +20,7 @@ namespace ndbl{ class ForLoopNode; class IScope; class InstructionNode; - class InvokableNode; + class FunctionNode; class Scope; class WhileLoopNode; class Graph; @@ -99,13 +99,13 @@ namespace ndbl{ // Serializer ------------------------------------------------------------------ public: - std::string& serialize_invokable(std::string&_out, const InvokableNode*) const; + std::string& serialize_invokable(std::string&_out, const FunctionNode*) const; std::string& serialize_invokable_sig(std::string& _out, const tools::IInvokable*)const; - std::string& serialize_func_call(std::string& _out, const tools::FuncType *_signature, const std::vector& inputs)const; - std::string& serialize_func_sig(std::string& _out, const tools::FuncType*)const; + std::string& serialize_func_call(std::string& _out, const tools::FunctionDescriptor *_signature, const std::vector& inputs)const; + std::string& serialize_func_sig(std::string& _out, const tools::FunctionDescriptor*)const; std::string& serialize_token_t(std::string& _out, const Token_t&)const; std::string& serialize_token(std::string& _out, const Token &) const; - std::string& serialize_type(std::string& _out, const tools::TypeDesc*) const; + std::string& serialize_type(std::string& _out, const tools::TypeDescriptor*) const; std::string& serialize_input(std::string& _out, const Slot &_slot, SerializeFlags _flags = SerializeFlag_NONE )const; std::string& serialize_output(std::string& _out, const Slot &_slot, SerializeFlags flags = SerializeFlag_NONE )const; std::string& serialize_node(std::string &_out, const Node* node, SerializeFlags _flags = SerializeFlag_NONE ) const; @@ -122,27 +122,27 @@ namespace ndbl{ const tools::IInvokable* find_function(u32_t _hash) const; public: const tools::IInvokable* find_function(const char* _signature ) const; // Find a function by signature as string (ex: "int multiply(int,int)" ) - const tools::IInvokable* find_function(const tools::FuncType*) const; // Find a function by signature (strict first, then cast allowed) - const tools::IInvokable* find_function_exact(const tools::FuncType*) const; // Find a function by signature (no cast allowed). - const tools::IInvokable* find_function_fallback(const tools::FuncType*) const; // Find a function by signature (casts allowed). - const tools::IInvokable* find_operator_fct(const tools::FuncType*) const; // Find an operator's function by signature (strict first, then cast allowed) - const tools::IInvokable* find_operator_fct_exact(const tools::FuncType*) const; // Find an operator's function by signature (no cast allowed). - const tools::IInvokable* find_operator_fct_fallback(const tools::FuncType*) const; // Find an operator's function by signature (casts allowed). + const tools::IInvokable* find_function(const tools::FunctionDescriptor*) const; // Find a function by signature (strict first, then cast allowed) + const tools::IInvokable* find_function_exact(const tools::FunctionDescriptor*) const; // Find a function by signature (no cast allowed). + const tools::IInvokable* find_function_fallback(const tools::FunctionDescriptor*) const; // Find a function by signature (casts allowed). + const tools::IInvokable* find_operator_fct(const tools::FunctionDescriptor*) const; // Find an operator's function by signature (strict first, then cast allowed) + const tools::IInvokable* find_operator_fct_exact(const tools::FunctionDescriptor*) const; // Find an operator's function by signature (no cast allowed). + const tools::IInvokable* find_operator_fct_fallback(const tools::FunctionDescriptor*) const; // Find an operator's function by signature (casts allowed). const tools::Operator* find_operator(const std::string& , tools::Operator_t) const;// Find an operator by symbol and type (unary, binary or ternary). const std::vector& get_api()const { return m_functions; } // Get all the functions registered in the language. - std::string& to_string(std::string& /*out*/, const tools::TypeDesc*)const; // Convert a type to string (by ref). + std::string& to_string(std::string& /*out*/, const tools::TypeDescriptor*)const; // Convert a type to string (by ref). std::string& to_string(std::string& /*out*/, Token_t)const; // Convert a type to a token_t (by ref). - std::string to_string(const tools::TypeDesc *) const; // Convert a type to string. + std::string to_string(const tools::TypeDescriptor *) const; // Convert a type to string. std::string to_string(Token_t)const; // Convert a type to a token_t. - const tools::TypeDesc* get_type(Token_t _token)const; // Get the type corresponding to a given token_t (must be a type keyword) + const tools::TypeDescriptor* get_type(Token_t _token)const; // Get the type corresponding to a given token_t (must be a type keyword) void add_function(const tools::IInvokable*); // Adds a new function (regular or operator's implementation). - int get_precedence(const tools::FuncType*)const; // Get the precedence of a given function (precedence may vary because function could be an operator implementation). + int get_precedence(const tools::FunctionDescriptor*)const; // Get the precedence of a given function (precedence may vary because function could be an operator implementation). template void load_library(); // Instantiate a library from its type (uses reflection to get all its static methods). private: struct { std::vector> keywords; - std::vector> types; + std::vector> types; std::vector> operators; std::vector> chars; } m_definition; // language definition @@ -157,7 +157,7 @@ namespace ndbl{ std::unordered_map m_token_t_by_single_char; std::unordered_map m_token_t_by_keyword; // keyword reserved by the language (ex: int, string, operator, if, for, etc.) std::unordered_map m_token_t_by_type_id; - std::unordered_map m_type_by_token_t; // token_t to type. Works only if token_t refers to a type keyword. + std::unordered_map m_type_by_token_t; // token_t to type. Works only if token_t refers to a type keyword. }; diff --git a/src/ndbl/core/language/Nodlang.parse_function_call.specs.cpp b/src/ndbl/core/language/Nodlang.parse_function_call.specs.cpp index c55a50d69..97920dbfc 100644 --- a/src/ndbl/core/language/Nodlang.parse_function_call.specs.cpp +++ b/src/ndbl/core/language/Nodlang.parse_function_call.specs.cpp @@ -1,7 +1,7 @@ #include "../fixtures/core.h" #include #include "tools/core/log.h" -#include "ndbl/core/InvokableNode.h" +#include "ndbl/core/FunctionNode.h" using namespace ndbl; diff --git a/src/ndbl/gui/CreateNodeCtxMenu.cpp b/src/ndbl/gui/CreateNodeCtxMenu.cpp index 360da081f..bc4ac64a0 100644 --- a/src/ndbl/gui/CreateNodeCtxMenu.cpp +++ b/src/ndbl/gui/CreateNodeCtxMenu.cpp @@ -22,7 +22,7 @@ void CreateNodeCtxMenu::update_cache_based_on_signature(SlotView* dragged_slot) for (auto& action: items ) { - const TypeDesc* dragged_property_type = dragged_slot->get_property_type(); + const TypeDescriptor* dragged_property_type = dragged_slot->get_property_type(); switch ( action->event_data.node_type ) { diff --git a/src/ndbl/gui/Event.h b/src/ndbl/gui/Event.h index 2bc9b5f85..712e08cf8 100644 --- a/src/ndbl/gui/Event.h +++ b/src/ndbl/gui/Event.h @@ -15,7 +15,7 @@ namespace ndbl // forward declaration class NodeView; using tools::Vec2; - using tools::FuncType; + using tools::FunctionDescriptor; enum EventID_ : tools::EventID { @@ -89,7 +89,7 @@ namespace ndbl struct EventPayload_CreateNode { CreateNodeType node_type; // The note type to create - const FuncType* node_signature; // The signature of the node that must be created + const FunctionDescriptor* node_signature; // The signature of the node that must be created SlotView* active_slotview; // The slot view being dragged. Graph* graph; // The graph to create the node into Vec2 desired_screen_pos; // The desired position for the new node view @@ -101,7 +101,7 @@ namespace ndbl , graph(nullptr) {} - EventPayload_CreateNode(CreateNodeType node_type, const tools::FuncType* signature ) + EventPayload_CreateNode(CreateNodeType node_type, const tools::FunctionDescriptor* signature ) : node_type(node_type) , node_signature(signature) {} diff --git a/src/ndbl/gui/File.cpp b/src/ndbl/gui/File.cpp index c82adb1c1..811581d79 100644 --- a/src/ndbl/gui/File.cpp +++ b/src/ndbl/gui/File.cpp @@ -3,7 +3,7 @@ #include #include "ndbl/core/NodeUtils.h" -#include "ndbl/core/InvokableNode.h" +#include "ndbl/core/FunctionNode.h" #include "ndbl/core/LiteralNode.h" #include "ndbl/core/language/Nodlang.h" diff --git a/src/ndbl/gui/Nodable.cpp b/src/ndbl/gui/Nodable.cpp index 78c72d8b8..75ccf0893 100644 --- a/src/ndbl/gui/Nodable.cpp +++ b/src/ndbl/gui/Nodable.cpp @@ -6,7 +6,7 @@ #include "tools/core/System.h" #include "tools/core/EventManager.h" -#include "ndbl/core/InvokableNode.h" +#include "ndbl/core/FunctionNode.h" #include "ndbl/core/LiteralNode.h" #include "ndbl/core/Slot.h" #include "ndbl/core/Interpreter.h" @@ -309,7 +309,7 @@ void Nodable::update() // 1) create the node if ( !_event->data.graph->get_root() ) { - LOG_ERROR("Nodable", "Unable to create node, no root found on this graph.\n"); + LOG_ERROR("Nodable", "Unable to create_new node, no root found on this graph.\n"); continue; } @@ -335,7 +335,7 @@ void Nodable::update() case CreateNodeType_LITERAL_DOUBLE: case CreateNodeType_LITERAL_INTEGER: case CreateNodeType_LITERAL_STRING: - case CreateNodeType_INVOKABLE: + case CreateNodeType_FUNCTION: break; } diff --git a/src/ndbl/gui/NodableView.cpp b/src/ndbl/gui/NodableView.cpp index 6daebca7a..579981d4a 100644 --- a/src/ndbl/gui/NodableView.cpp +++ b/src/ndbl/gui/NodableView.cpp @@ -29,10 +29,10 @@ using namespace ndbl; using namespace tools; template -static FuncType* create_variable_node_signature() +static FunctionDescriptor* create_variable_node_signature() { - static FuncType type = FuncTypeBuilder{ "variable" }.construct(); - return &type; + static FunctionDescriptor descriptor = FunctionDescriptor::construct("variable"); + return &descriptor; } void NodableView::init(Nodable * _app) @@ -136,7 +136,7 @@ void NodableView::init(Nodable * _app) { std::string label; language->serialize_invokable_sig( label, invokable ); - action_manager->new_action(label.c_str(), Shortcut{}, EventPayload_CreateNode{CreateNodeType_INVOKABLE, invokable->get_sig() } ); + action_manager->new_action(label.c_str(), Shortcut{}, EventPayload_CreateNode{CreateNodeType_FUNCTION, invokable->get_sig() } ); } LOG_VERBOSE("ndbl::NodableView", "init_ex " OK "\n"); @@ -456,7 +456,7 @@ void NodableView::draw_help_window() const ImGui::TextWrapped("Nodable UI is designed as following:\n"); ImGuiEx::BulletTextWrapped("On the left side a (light) text editor allows to edit source code.\n"); ImGuiEx::BulletTextWrapped( - "At the center, there is the graph editor where you can create/delete/connect nodes\n"); + "At the center, there is the graph editor where you can create_new/delete/connect nodes\n"); ImGuiEx::BulletTextWrapped( "On the right side (this side) you will find many tabs to manage additional config such as node, interpreter, or app properties\n"); ImGuiEx::BulletTextWrapped("At the top, between the menu and the editors, there is a tool bar." diff --git a/src/ndbl/gui/NodeView.cpp b/src/ndbl/gui/NodeView.cpp index 57c8a4f11..f180a1129 100644 --- a/src/ndbl/gui/NodeView.cpp +++ b/src/ndbl/gui/NodeView.cpp @@ -6,7 +6,7 @@ #include "tools/core/math.h" #include "ndbl/core/GraphUtil.h" -#include "ndbl/core/InvokableNode.h" +#include "ndbl/core/FunctionNode.h" #include "ndbl/core/LiteralNode.h" #include "ndbl/core/language/Nodlang.h" diff --git a/src/ndbl/gui/SlotView.cpp b/src/ndbl/gui/SlotView.cpp index 49d0be83e..107989eca 100644 --- a/src/ndbl/gui/SlotView.cpp +++ b/src/ndbl/gui/SlotView.cpp @@ -32,7 +32,7 @@ Node* SlotView::get_node()const return m_slot->get_node(); } -const TypeDesc* SlotView::get_property_type()const +const TypeDescriptor* SlotView::get_property_type()const { Property* property = get_property(); return property ? property->get_type() : nullptr; diff --git a/src/ndbl/gui/SlotView.h b/src/ndbl/gui/SlotView.h index 3af90097a..708ee50a3 100644 --- a/src/ndbl/gui/SlotView.h +++ b/src/ndbl/gui/SlotView.h @@ -33,7 +33,7 @@ namespace ndbl bool draw() override; Property* get_property()const; - const tools::TypeDesc*get_property_type()const; + const tools::TypeDescriptor*get_property_type()const; tools::string64 compute_tooltip() const; Node* get_node()const; bool has_node_connected() const; diff --git a/src/tools/core/Delegate.h b/src/tools/core/Delegate.h index 63381249c..6dd0e7afd 100644 --- a/src/tools/core/Delegate.h +++ b/src/tools/core/Delegate.h @@ -1,6 +1,6 @@ #pragma once #include -#include "tools/core/reflection/function_traits.h" +#include "tools/core/reflection/FunctionTraits.h" namespace tools { diff --git a/src/tools/core/memory/Pool.bench.cpp b/src/tools/core/memory/Pool.bench.cpp index f9739c055..28bede817 100644 --- a/src/tools/core/memory/Pool.bench.cpp +++ b/src/tools/core/memory/Pool.bench.cpp @@ -66,8 +66,8 @@ static void mutate_N_instances__enterlaced_with_another_type__using_Pool_create( for( auto i = 0; i < COUNT; i++ ) { - ids.emplace_back( pool->create>() ); - ids2.emplace_back( pool->create>() ); + ids.emplace_back(pool->create>() ); + ids2.emplace_back(pool->create>() ); } if( VECTOR ) diff --git a/src/tools/core/reflection/FuncType.builder.specs.cpp b/src/tools/core/reflection/FuncType.builder.specs.cpp deleted file mode 100644 index 104f51c81..000000000 --- a/src/tools/core/reflection/FuncType.builder.specs.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include "tools/core/reflection/FuncType.h" -using namespace tools; - -TEST(func_type_builder, no_arg_fct) -{ - auto no_arg_fct = FuncTypeBuilder("fct").construct(); - EXPECT_EQ(no_arg_fct.get_arg_count(), 0); -} - -TEST(func_type_builder, push_single_arg) -{ - FuncType single_arg_fct = FuncTypeBuilder("fct").construct(); - - EXPECT_EQ(single_arg_fct.get_arg_count(), 1); - EXPECT_EQ(single_arg_fct.get_return_type(), type::get()); - EXPECT_EQ(single_arg_fct.get_args().at(0).m_type, type::get()); -} - -TEST(func_type_builder, push_two_args) -{ - auto two_arg_fct = FuncTypeBuilder("fct").construct(); - - EXPECT_EQ(two_arg_fct.get_arg_count(), 2); - EXPECT_EQ(two_arg_fct.get_return_type(), type::get()); - EXPECT_EQ(two_arg_fct.get_args().at(0).m_type, type::get()); - EXPECT_EQ(two_arg_fct.get_args().at(1).m_type, type::get()); -} - -TEST(func_type_builder, match_check_for_arg_count) -{ - FuncType single_arg_fct = FuncTypeBuilder("fct").construct(); - FuncType two_arg_fct = FuncTypeBuilder("fct").construct(); - - EXPECT_EQ(two_arg_fct.is_compatible(&single_arg_fct), false); - EXPECT_EQ(single_arg_fct.is_compatible(&two_arg_fct), false); -} - -TEST(func_type_builder, match_check_identifier) -{ - FuncType two_arg_fct = FuncTypeBuilder("fct").construct(); - FuncType two_arg_fct_modified = FuncTypeBuilder("fct").construct(); - - two_arg_fct_modified.push_arg(type::get() ); - two_arg_fct_modified.push_arg(type::get() ); - - EXPECT_EQ(two_arg_fct.is_compatible(&two_arg_fct_modified), false); - EXPECT_EQ(two_arg_fct_modified.is_compatible(&two_arg_fct), false); -} - -TEST(func_type_builder, match_check_absence_of_arg) -{ - FuncType two_arg_fct = FuncTypeBuilder("fct").construct(); - FuncType two_arg_fct_without_args = FuncTypeBuilder("fct").construct(); - - EXPECT_EQ(two_arg_fct.is_compatible(&two_arg_fct_without_args), false); - EXPECT_EQ(two_arg_fct_without_args.is_compatible(&two_arg_fct), false); -} - -TEST(func_type_builder, push_args_template_0) -{ - auto ref = FuncTypeBuilder("fct").construct(); - auto fct = FuncTypeBuilder("fct").construct(); - - using Args = std::tuple<>; // create arg tuple - fct.push_args(); // push those args to signature - - EXPECT_EQ(ref.is_compatible(&fct), true); - EXPECT_EQ(fct.get_arg_count(), 0); -} - -TEST(func_type_builder, push_args_template_1) -{ - auto ref = FuncTypeBuilder("fct").construct(); - auto fct = FuncTypeBuilder("fct").construct(); - - fct.push_args< std::tuple >(); - - EXPECT_EQ(ref.is_compatible(&fct), true); - EXPECT_EQ(fct.get_arg_count(), 2); -} - -TEST(func_type_builder, push_args_template_4) -{ - auto ref = FuncTypeBuilder("fct").construct(); - auto fct = FuncTypeBuilder("fct").construct(); - fct.push_args< std::tuple >(); - - EXPECT_EQ(ref.is_compatible(&fct), true); - EXPECT_EQ(fct.get_arg_count(), 4); -} diff --git a/src/tools/core/reflection/FuncType.cpp b/src/tools/core/reflection/FuncType.cpp deleted file mode 100644 index efd7082d4..000000000 --- a/src/tools/core/reflection/FuncType.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "FuncType.h" -#include // find_if -#include "Operator.h" - -using namespace tools; - -void FuncType::push_arg(const TypeDesc* _type, bool _by_reference) -{ - auto index = (u8_t)m_args.size(); - std::string name{"arg_" + std::to_string(index)}; - m_args.emplace_back(index, _type, _by_reference, name ); -} - -bool FuncType::is_exactly(const FuncType* _other)const -{ - if ( this == _other ) - return true; - if ( m_args.size() != _other->m_args.size()) - return false; - if ( !m_identifier.equals(_other->m_identifier) ) - return false; - if ( m_args.empty() ) - return true; - - size_t i = 0; - while( i < m_args.size() ) - { - const TypeDesc* arg_t = m_args[i].m_type; - const TypeDesc* other_arg_t = _other->m_args[i].m_type; - - if ( !arg_t->equals(other_arg_t) ) - { - return false; - } - i++; - } - return true; -} - -bool FuncType::is_compatible(const FuncType* _other)const -{ - if ( this == _other ) - return true; - if ( m_args.size() != _other->m_args.size()) - return false; - if ( !m_identifier.equals(_other->m_identifier) ) - return false; - if ( m_args.empty() ) - return true; - - size_t i = 0; - while( i < m_args.size() ) - { - const TypeDesc* arg_t = m_args[i].m_type; - const TypeDesc* other_arg_t = _other->m_args[i].m_type; - - if ( !arg_t->equals(other_arg_t) && - !other_arg_t->is_implicitly_convertible(arg_t) ) - { - return false; - } - i++; - } - return true; - -} - -bool FuncType::has_an_arg_of_type(const TypeDesc* _type) const -{ - auto found = std::find_if( m_args.begin(), m_args.end(), [&_type](const FuncArg& each) { return each.m_type->equals(_type); } ); - return found != m_args.end(); -} - -void FuncType::set_identifier(const std::string &_identifier) -{ - VERIFY(_identifier.size() < m_identifier.capacity(), "Identifier is too long"); - m_identifier.clear(); - m_identifier.append(_identifier.c_str()); -} diff --git a/src/tools/core/reflection/FuncType.h b/src/tools/core/reflection/FuncType.h deleted file mode 100644 index 94707a1ef..000000000 --- a/src/tools/core/reflection/FuncType.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "Type.h" - -namespace tools -{ - // forward declarations - class Operator; - - /* - * Simple object to store a named function argument - */ - struct FuncArg - { - FuncArg(u8_t index, const TypeDesc* _type, bool _by_reference, const std::string& _name) - : m_index( index) - , m_type(_type) - , m_by_reference(_by_reference) - , m_name(_name) - { - } - - u8_t m_index; - const TypeDesc* m_type; - bool m_by_reference; - std::string m_name; - }; - - /* - * Class to store a function signature. - * We can check if two function signature are matching using this->match(other) - */ - class FuncType - { - public: - void set_identifier(const std::string& _identifier); - void push_arg(const TypeDesc* _type, bool _by_reference = false); - bool has_an_arg_of_type(const TypeDesc* type)const; - bool is_exactly(const FuncType* _other)const; - bool is_compatible(const FuncType* _other)const; - const char* get_identifier()const { return m_identifier.c_str(); }; - const FuncArg& get_arg(size_t i) const { return m_args[i]; } - std::vector& get_args() { return m_args;}; - const std::vector& get_args()const { return m_args;}; - size_t get_arg_count() const { return m_args.size(); } - const TypeDesc* get_return_type() const { return m_return_type; } - void set_return_type(const TypeDesc* _type) { m_return_type = _type; }; - private: - tools::string64 m_identifier; - std::vector m_args; - const TypeDesc* m_return_type = type::null(); - - public: - - /** Push Arg helpers */ - - template // push N+1 arguments - struct arg_pusher - { - static void push_into(FuncType *_signature) - { - arg_pusher::push_into(_signature); - - using T = std::tuple_element_t; - _signature->push_arg(type::get(), std::is_reference::value ); - } - }; - - template // push 1 arguments - struct arg_pusher - { - static void push_into(FuncType *_signature) - { - using T = std::tuple_element_t<0, Tuple>; - _signature->push_arg(type::get(), std::is_reference::value ); - }; - }; - - // create an argument_pusher and push arguments into signature - template != 0, int> = 0> - void push_args() - { - arg_pusher>::push_into(this); - } - - // empty function when pushing an empty arguments - template == 0, int> = 0> - void push_args(){} - }; - - template - struct FuncTypeBuilder; - - /** - * Builder to create function/operator signatures for a given language - * @tparam T is the function's return type - * @tparam Args is the function's argument(s) type - * - * usage: auto* sig = FuncTypeBuilder("+"); - */ - template - struct FuncTypeBuilder - { - std::string m_id; - - FuncTypeBuilder(const char* id) - : m_id(id) - { - VERIFY(!m_id.empty(), "No identifier specified! use with_id()" ); - } - - FuncType* decorate(FuncType* type) - { - type->set_identifier(m_id); - type->set_return_type(type::get()); - type->push_args>(); - return type; - } - - FuncType* make_instance() - { - auto* type = new FuncType(); - decorate(type); - return type; - } - - FuncType construct() - { - FuncType type; - decorate(&type); - return std::move(type); - } - - }; - - template - struct FuncTypeBuilder : FuncTypeBuilder {}; - - -} \ No newline at end of file diff --git a/src/tools/core/reflection/function_traits.h b/src/tools/core/reflection/FunctionTraits.h similarity index 100% rename from src/tools/core/reflection/function_traits.h rename to src/tools/core/reflection/FunctionTraits.h diff --git a/src/tools/core/reflection/Initializer.h b/src/tools/core/reflection/Initializer.h index 477bdcb0a..8776b4061 100644 --- a/src/tools/core/reflection/Initializer.h +++ b/src/tools/core/reflection/Initializer.h @@ -1,6 +1,5 @@ #pragma once #include "Invokable.h" -#include "FuncType.h" #include "Type.h" #include "TypeRegister.h" #include @@ -24,11 +23,11 @@ namespace tools struct Initializer { static_assert(!std::is_class_v); - TypeDesc *m_type; + TypeDescriptor *m_type; explicit Initializer(const char *_name) { - TypeDesc *type = type::create(_name); + TypeDescriptor *type = TypeDescriptor::create(_name); m_type = TypeRegister::insert_or_merge(type); } }; @@ -38,20 +37,18 @@ namespace tools struct Initializer { static_assert(std::is_class_v); - ClassDesc *m_class; + ClassDescriptor *m_class; explicit Initializer(const char *_name) { - TypeDesc *type = type::create(_name); - m_class = (ClassDesc *) TypeRegister::insert_or_merge(type); + TypeDescriptor *type = ClassDescriptor::create(_name); + m_class = (ClassDescriptor *) TypeRegister::insert_or_merge(type); } template - Initializer &add_method(F *func_ptr, const char *_name, const char *_alt_name = "") + Initializer &add_method(F* func_ptr, const char *_name, const char *_alt_name = "") { - FuncTypeBuilder builder{_name}; - auto *invokable = new InvokableStaticFunction(builder.make_instance(), func_ptr); - + auto *invokable = new InvokableStaticFunction( _name, func_ptr); // TODO: delete? m_class->add_static(_name, invokable); if (_alt_name[0] != '\0') @@ -63,8 +60,7 @@ namespace tools template Initializer &add_method(R(C::*func_ptr)(Ts...), const char *_name) // non static { - FuncTypeBuilder builder{_name}; - auto *invokable = new InvokableMethod(builder.make_instance(), func_ptr); + auto *invokable = new InvokableMethod(_name, func_ptr); // TODO: delete? m_class->add_method(_name, invokable); return *this; } @@ -72,9 +68,10 @@ namespace tools template Initializer &extends() { + static_assert(std::is_class_v); static_assert(std::is_base_of_v); - auto base_class = const_cast( type::get_class()); // get or create + auto base_class = const_cast( type::get_class()); // get or create m_class->add_parent(base_class->id()); base_class->add_child(m_class->id()); return *this; diff --git a/src/tools/core/reflection/Invokable.h b/src/tools/core/reflection/Invokable.h index c77757e32..eccd24f6c 100644 --- a/src/tools/core/reflection/Invokable.h +++ b/src/tools/core/reflection/Invokable.h @@ -7,8 +7,7 @@ #include "tools/core/types.h" #include "variant.h" #include "Type.h" -#include "FuncType.h" -#include "function_traits.h" +#include "FunctionTraits.h" namespace tools { @@ -17,7 +16,7 @@ namespace tools { public: virtual ~IInvokable() = default; - virtual const FuncType* get_sig() const = 0; + virtual const FunctionDescriptor* get_sig() const = 0; virtual variant invoke(const std::vector &_args) const = 0; }; @@ -25,7 +24,7 @@ namespace tools { public: virtual ~IInvokableMethod() = default; - virtual const FuncType* get_sig() const = 0; + virtual const FunctionDescriptor* get_sig() const = 0; virtual variant invoke(void* _instance, const std::vector &_args) const = 0; }; @@ -186,20 +185,20 @@ namespace tools static_assert( std::is_function_v ); static_assert( !std::is_member_function_pointer_v ); - InvokableStaticFunction(const FuncType* _function_type, const FunctionT* _function_pointer) + InvokableStaticFunction(const char* _name, const FunctionT* _function_pointer) : m_function_pointer( _function_pointer ) - , m_function_signature(_function_type) + , m_function_signature(FunctionDescriptor::create(_name) ) { ASSERT( m_function_pointer ) } variant invoke(const std::vector &_args) const override { return tools::Apply( m_function_pointer, _args ); } - const FuncType* get_sig() const override + const FunctionDescriptor* get_sig() const override { return m_function_signature; } private: const FunctionT* m_function_pointer; - const FuncType* m_function_signature; + const FunctionDescriptor* m_function_signature; }; /** @@ -212,13 +211,13 @@ namespace tools static_assert( std::is_void_v::class_t> == false ); static_assert( FunctionTrait::is_member_function ); - const FuncType* m_method_signature; + const FunctionDescriptor* m_method_signature; MethodT m_method_pointer; public: - InvokableMethod(const FuncType* _method_type, MethodT _method_pointer ) + InvokableMethod(const char* _name, MethodT _method_pointer ) : m_method_pointer( _method_pointer ) - , m_method_signature(_method_type ) + , m_method_signature(FunctionDescriptor::create(_name) ) { ASSERT( m_method_pointer ) } variant invoke( void* _instance, const std::vector& _args ) const override @@ -227,7 +226,7 @@ namespace tools return tools::Apply( m_method_pointer, (ClassT*)_instance, _args ); }; - const FuncType* get_sig() const override + const FunctionDescriptor* get_sig() const override { return m_method_signature; }; }; diff --git a/src/tools/core/reflection/Type.cpp b/src/tools/core/reflection/Type.cpp index ce23455c6..7f9640d6e 100644 --- a/src/tools/core/reflection/Type.cpp +++ b/src/tools/core/reflection/Type.cpp @@ -3,6 +3,9 @@ #include "reflection" #include // std::runtime_error +#include // find_if +#include "Operator.h" + using namespace tools; REFLECT_STATIC_INIT @@ -22,44 +25,30 @@ REFLECT_STATIC_INIT type::Initializer("null"); } -TypeDesc::TypeDesc( - std::type_index _id, - std::type_index _primitive_id, - const char* _name, - const char* _compiler_name, - TypeFlags _flags) -: m_id(_id) -, m_primitive_id(_primitive_id) -, m_name(_name) -, m_compiler_name(_compiler_name) -, m_flags(_flags) -{ -} - -bool type::equals(const TypeDesc* left, const TypeDesc* right) +bool type::equals(const TypeDescriptor* left, const TypeDescriptor* right) { ASSERT(left != nullptr) return right != nullptr && left->id() == right->id(); } -const TypeDesc* type::any() +const TypeDescriptor* type::any() { - static const TypeDesc* any = type::get(); + static const TypeDescriptor* any = type::get(); return any; } -const TypeDesc* type::null() +const TypeDescriptor* type::null() { - static const TypeDesc* null = type::get(); + static const TypeDescriptor* null = type::get(); return null; } -bool type::is_implicitly_convertible(const TypeDesc* _src, const TypeDesc* _dst ) +bool type::is_implicitly_convertible(const TypeDescriptor* _src, const TypeDescriptor* _dst ) { return _src->is_implicitly_convertible(_dst); } -bool TypeDesc::is_implicitly_convertible(const TypeDesc* _dst ) const +bool TypeDescriptor::is_implicitly_convertible(const TypeDescriptor* _dst ) const { if( _dst->is_const() ) return false; @@ -81,7 +70,7 @@ bool TypeDesc::is_implicitly_convertible(const TypeDesc* _dst ) const this->is() && _dst->is(); } -bool TypeDesc::any_of(std::vector types) const +bool TypeDescriptor::any_of(std::vector types) const { for ( auto each : types ) if(equals(each)) @@ -89,22 +78,7 @@ bool TypeDesc::any_of(std::vector types) const return false; } -ClassDesc::ClassDesc( - std::type_index _id, - std::type_index _primitive_id, - const char* _name, - const char* _compiler_name, - TypeFlags _flags) -: TypeDesc( - _id, - _primitive_id, - _name, - _compiler_name, - _flags | TypeFlag_IS_CLASS ) -{ -} - -ClassDesc::~ClassDesc() +ClassDescriptor::~ClassDescriptor() { for (auto* each : m_methods ) delete each; @@ -114,7 +88,7 @@ ClassDesc::~ClassDesc() } -bool ClassDesc::is_child_of(std::type_index _possible_parent_id, bool _selfCheck) const +bool ClassDescriptor::is_child_of(std::type_index _possible_parent_id, bool _selfCheck) const { if (_selfCheck && m_id == _possible_parent_id ) { @@ -147,31 +121,31 @@ bool ClassDesc::is_child_of(std::type_index _possible_parent_id, bool _selfCheck return false; }; -void ClassDesc::add_parent(std::type_index parent) +void ClassDescriptor::add_parent(std::type_index parent) { m_parents.insert(parent); m_flags |= TypeFlag_HAS_PARENT; } -void ClassDesc::add_child(std::type_index _child) +void ClassDescriptor::add_child(std::type_index _child) { m_children.insert( _child ); m_flags |= TypeFlag_HAS_CHILD; } -void ClassDesc::add_static(const char* _name, const IInvokable* _func_type) +void ClassDescriptor::add_static(const char* _name, const IInvokable* _func_type) { m_static_methods.insert(_func_type); m_static_methods_by_name.insert({_name, _func_type}); } -void ClassDesc::add_method(const char* _name, const IInvokableMethod* _func_type) +void ClassDescriptor::add_method(const char* _name, const IInvokableMethod* _func_type) { m_methods.insert(_func_type); m_methods_by_name.insert({_name, _func_type}); } -const IInvokableMethod* ClassDesc::get_method(const char* _name) const +const IInvokableMethod* ClassDescriptor::get_method(const char* _name) const { auto found = m_methods_by_name.find(_name); if( found != m_methods_by_name.end() ) @@ -181,7 +155,7 @@ const IInvokableMethod* ClassDesc::get_method(const char* _name) const return nullptr; } -const IInvokable* ClassDesc::get_static(const char* _name)const +const IInvokable* ClassDescriptor::get_static(const char* _name)const { auto found = m_static_methods_by_name.find(_name); if( found != m_static_methods_by_name.end() ) @@ -191,3 +165,72 @@ const IInvokable* ClassDesc::get_static(const char* _name)const return nullptr; } +void FunctionDescriptor::push_arg(const TypeDescriptor* _type, bool _by_reference) +{ + auto next_index = (u8_t)m_args.size(); + auto& arg = m_args.emplace_back(); + arg.m_index = next_index; + arg.m_type = _type; + arg.m_by_reference = _by_reference; + arg.m_name = "arg_" + std::to_string(arg.m_index); +} + +bool FunctionDescriptor::is_exactly(const FunctionDescriptor* _other)const +{ + if ( this == _other ) + return true; + if ( m_args.size() != _other->m_args.size()) + return false; + if ( m_name != _other->m_name ) + return false; + if ( m_args.empty() ) + return true; + + size_t i = 0; + while( i < m_args.size() ) + { + const TypeDescriptor* arg_t = m_args[i].m_type; + const TypeDescriptor* other_arg_t = _other->m_args[i].m_type; + + if ( !arg_t->equals(other_arg_t) ) + { + return false; + } + i++; + } + return true; +} + +bool FunctionDescriptor::is_compatible(const FunctionDescriptor* _other)const +{ + if ( this == _other ) + return true; + if ( m_args.size() != _other->m_args.size()) + return false; + if ( m_name != _other->m_name ) + return false; + if ( m_args.empty() ) + return true; + + size_t i = 0; + while( i < m_args.size() ) + { + const TypeDescriptor* arg_t = m_args[i].m_type; + const TypeDescriptor* other_arg_t = _other->m_args[i].m_type; + + if ( !arg_t->equals(other_arg_t) && + !other_arg_t->is_implicitly_convertible(arg_t) ) + { + return false; + } + i++; + } + return true; + +} + +bool FunctionDescriptor::has_an_arg_of_type(const TypeDescriptor* _type) const +{ + auto found = std::find_if( m_args.begin(), m_args.end(), [&_type](const FuncArg& each) { return each.m_type->equals(_type); } ); + return found != m_args.end(); +} diff --git a/src/tools/core/reflection/Type.h b/src/tools/core/reflection/Type.h index c75109a04..3a98d7c09 100644 --- a/src/tools/core/reflection/Type.h +++ b/src/tools/core/reflection/Type.h @@ -6,13 +6,14 @@ #include #include +#include "FunctionTraits.h" #include "TypeRegister.h" #include "tools/core/assertions.h" // add this macro to a class declaration to enable reflection on it #define REFLECT_BASE_CLASS() \ public:\ - virtual const tools::ClassDesc* get_class() const \ + virtual const tools::ClassDescriptor* get_class() const \ { return tools::type::get_class(this); }\ private: @@ -20,18 +21,18 @@ public:\ // Must have a parent class having REFLECT_BASE_CLASS macro. #define REFLECT_DERIVED_CLASS() \ public:\ - virtual const tools::ClassDesc* get_class() const override \ + virtual const tools::ClassDescriptor* get_class() const override \ { return tools::type::get_class(this); }\ private: namespace tools { // forward declarations - class FuncType; + class FunctionDescriptor; class IInvokable; class IInvokableMethod; - class TypeDesc; - class ClassDesc; + class TypeDescriptor; + class ClassDescriptor; /** Empty structure to act like any type, @related tools::variant class */ struct any_t{}; @@ -70,20 +71,20 @@ namespace tools // Type utilities namespace type { - bool is_implicitly_convertible(const TypeDesc* _src, const TypeDesc* _dst); - bool equals(const TypeDesc* left, const TypeDesc* right); - const TypeDesc* any(); - const TypeDesc* null(); - - template std::type_index id(); - template std::type_index primitive_id(); - template const char* compiler_name(); - template TypeFlags flags(); - template const TypeDesc* get(); - template const ClassDesc* get_class(T* ptr); - template const ClassDesc* get_class(); - template TypeDesc* create(const char* _name = ""); - template const TypeDesc* get(T value) { return get(); } + bool is_implicitly_convertible(const TypeDescriptor* _src, const TypeDescriptor* _dst); + bool equals(const TypeDescriptor* left, const TypeDescriptor* right); + const TypeDescriptor* any(); + const TypeDescriptor* null(); + + template std::type_index get_id(); + template std::type_index get_primitive_id(); + template const char* get_compiler_name(); + template TypeFlags get_flags(); + template const TypeDescriptor* get(); + template const ClassDescriptor* get_class(T* ptr); + template const ClassDescriptor* get_class(); + template TypeDescriptor* create(const char* _name = ""); + template const TypeDescriptor* get(T value) { return get(); } // template // struct get_all @@ -117,18 +118,6 @@ namespace tools // }; }; - template - std::type_index type::id() - { return std::type_index(typeid(T)); } - - template - std::type_index type::primitive_id() - { return id::type>(); } - - template - const char* type::compiler_name() - { return typeid(T).name(); } - /** * @class TypeDesc (type descriptor) holds meta data relative to a given type. * @@ -136,39 +125,83 @@ namespace tools * const TypeDesc* t = type::get(); * assert( t->is_ptr() == false ); */ - class TypeDesc + class TypeDescriptor { friend class TypeRegister; public: - - TypeDesc( - std::type_index _id, - std::type_index _primitive_id, - const char* _name, - const char* _compiler_name, - TypeFlags _flags); + TypeDescriptor(std::type_index _id, std::type_index _primitive_id) + : m_id(_id), m_primitive_id(_primitive_id) {} - TypeDesc(const TypeDesc&) = delete; // a type must be unique - TypeDesc(TypeDesc&&) = delete; - virtual ~TypeDesc() {}; + virtual ~TypeDescriptor() {}; + template + static TypeDescriptor* create(const char* _name); std::type_index id() const { return m_id; } - const char* get_name() const { return m_name; }; + const char* get_name() const { return m_name.c_str(); }; bool is_class() const { return m_flags & TypeFlag_IS_CLASS; } - bool any_of(std::vector args)const; + bool any_of(std::vector args)const; bool has_parent() const { return m_flags & TypeFlag_HAS_PARENT; } bool is_ptr() const { return m_flags & TypeFlag_IS_POINTER; } bool is_const() const { return m_flags & TypeFlag_IS_CONST; } - bool equals(const TypeDesc* other) const { return type::equals(this, other); } + bool equals(const TypeDescriptor* other) const { return type::equals(this, other); } template bool is() const; - bool is_implicitly_convertible(const TypeDesc* _dst ) const; + bool is_implicitly_convertible(const TypeDescriptor* _dst ) const; protected: - const char* m_name; - const char* m_compiler_name; - TypeFlags m_flags; - const std::type_index m_primitive_id; // ex: int - const std::type_index m_id; // ex: int**, int* + std::string m_name; + const char* m_compiler_name = nullptr; + TypeFlags m_flags = TypeFlag_NONE; + std::type_index m_primitive_id; // ex: int + std::type_index m_id; // ex: int**, int* + }; + + // forward declarations + class Operator; + + /* + * Simple object to store a named function argument + */ + struct FuncArg + { + u8_t m_index; + const TypeDescriptor* m_type; + bool m_by_reference; + std::string m_name; + }; + + /* + * Class to store a function signature. + * We can check if two function signature are matching using this->match(other) + */ + class FunctionDescriptor : public TypeDescriptor + { + public: + + template static FunctionDescriptor* create(const char* _name); + template static FunctionDescriptor construct(const char* _name); + + FunctionDescriptor(std::type_index _id, std::type_index _primitive_id): TypeDescriptor(_id, _primitive_id) {} + + template + void push_nth_arg(); + template + void push_args(); + void push_arg(const TypeDescriptor* _type, bool _by_reference = false); + bool has_an_arg_of_type(const TypeDescriptor* type)const; + bool is_exactly(const FunctionDescriptor* _other)const; + bool is_compatible(const FunctionDescriptor* _other)const; + const char* get_identifier()const { return m_name.c_str(); }; + const FuncArg& get_arg(size_t i) const { return m_args[i]; } + std::vector& get_args() { return m_args;}; + const std::vector& get_args()const { return m_args;}; + size_t get_arg_count() const { return m_args.size(); } + const TypeDescriptor* get_return_type() const { return m_return_type; } + void set_return_type(const TypeDescriptor* _type) { m_return_type = _type; }; + private: + template static void init(FunctionDescriptor*, const char* _name); + + std::vector m_args; + const TypeDescriptor* m_return_type = type::null(); }; /** @@ -178,21 +211,18 @@ namespace tools * const TypeDesc* class_desc = type::get(); * assert( class_desc->is_class() ); */ - class ClassDesc : public TypeDesc + class ClassDescriptor : public TypeDescriptor { friend class TypeRegister; public: + ClassDescriptor(std::type_index _id, std::type_index _primitive_id) + : TypeDescriptor(_id, _primitive_id) + {}; - ClassDesc( - std::type_index _id, - std::type_index _primitive_id, - const char* _name, - const char* _compiler_name, - TypeFlags _flags); + ~ClassDescriptor(); - ClassDesc(const ClassDesc&) = delete; // a type must be unique - ClassDesc(ClassDesc&&) = delete; - ~ClassDesc(); + template + static ClassDescriptor* create(const char* _name); void add_parent(std::type_index _parent); void add_child(std::type_index _child); @@ -218,41 +248,136 @@ namespace tools }; template - bool TypeDesc::is() const + std::type_index type::get_id() + { return std::type_index(typeid(T)); } + + template + std::type_index type::get_primitive_id() + { return type::get_id::type>(); } + + template + const char* type::get_compiler_name() + { return typeid(T).name(); } + + template + void FunctionDescriptor::push_nth_arg() + { + using NTH_ARG = std::tuple_element_t; + const TypeDescriptor* type_descriptor = type::get(); + push_arg(type_descriptor, std::is_reference_v); + } + + template + void FunctionDescriptor::push_args() + { + constexpr size_t ARG_COUNT = std::tuple_size_v; + static_assert(ARG_COUNT <= 8, "maximum 8 arguments can be pushed at once"); + + // note: I duplicate instead of using template recursion hell. :) + + if constexpr (ARG_COUNT > 0 ) push_nth_arg<0, Args...>(); + if constexpr (ARG_COUNT > 1 ) push_nth_arg<1, Args...>(); + if constexpr (ARG_COUNT > 2 ) push_nth_arg<2, Args...>(); + if constexpr (ARG_COUNT > 3 ) push_nth_arg<3, Args...>(); + if constexpr (ARG_COUNT > 4 ) push_nth_arg<4, Args...>(); + if constexpr (ARG_COUNT > 5 ) push_nth_arg<5, Args...>(); + if constexpr (ARG_COUNT > 6 ) push_nth_arg<6, Args...>(); + if constexpr (ARG_COUNT > 7 ) push_nth_arg<7, Args...>(); + } + + template + bool TypeDescriptor::is() const { return type::equals(this, type::get()); } template - const ClassDesc* type::get_class() + TypeDescriptor* TypeDescriptor::create(const char* _name) + { + static_assert( std::is_class_v == false ); + + TypeDescriptor* descriptor = new TypeDescriptor(type::get_id(), type::get_primitive_id() ); + + descriptor->m_name = _name; + descriptor->m_compiler_name = type::get_compiler_name(); + descriptor->m_flags = type::get_flags(); + + return descriptor; + } + + template + ClassDescriptor* ClassDescriptor::create(const char* _name) + { + static_assert( std::is_class_v ); + + ClassDescriptor* descriptor = new ClassDescriptor(type::get_id(), type::get_primitive_id() ); + + descriptor->m_name = _name; + descriptor->m_compiler_name = type::get_compiler_name(); + descriptor->m_flags = type::get_flags(); + + return descriptor; + } + + template + void FunctionDescriptor::init(FunctionDescriptor* _descriptor, const char* _name) + { + _descriptor->m_name = _name; + _descriptor->m_compiler_name = type::get_compiler_name(); + _descriptor->m_flags = type::get_flags(); + _descriptor->m_return_type = type::get::result_t >(); + + using Args = typename FunctionTrait::args_t; + if constexpr ( std::tuple_size_v != 0) + _descriptor->push_args(); + } + + template + FunctionDescriptor FunctionDescriptor::construct(const char* _name) + { + FunctionDescriptor descriptor(type::get_id(), type::get_primitive_id()); + FunctionDescriptor::init(&descriptor, _name); + return descriptor; + } + + template + FunctionDescriptor* FunctionDescriptor::create(const char* _name) + { + FunctionDescriptor* descriptor = new FunctionDescriptor(type::get_id(), type::get_primitive_id()); + FunctionDescriptor::init(descriptor, _name); + return descriptor; + } + + template + const ClassDescriptor* type::get_class() { static_assert( std::is_class_v ); - return (const ClassDesc*)get(); + return (const ClassDescriptor*)get(); } template - const ClassDesc* type::get_class(T* ptr) + const ClassDescriptor* type::get_class(T* ptr) { static_assert( std::is_class_v ); - return (const ClassDesc*)get(); + return (const ClassDescriptor*)get(); } template - const TypeDesc* type::get() + const TypeDescriptor* type::get() { - auto id = type::id(); + auto id = type::get_id(); if ( TypeRegister::has(id) ) { return TypeRegister::get(id); } - TypeDesc* type = create(); - TypeRegister::insert(type); + TypeDescriptor* descriptor = type::create(); + TypeRegister::insert(descriptor); - return type; + return descriptor; } template - TypeFlags type::flags() + TypeFlags type::get_flags() { return (TypeFlag_IS_POINTER * std::is_pointer_v) | (TypeFlag_IS_CONST * std::is_const_v) @@ -261,12 +386,14 @@ namespace tools } template - TypeDesc* type::create(const char* _name) + TypeDescriptor* type::create(const char* _name) { - // TODO: it would be interesting to have a ClassDesc* type::create(...) version using SFINAE. + if constexpr ( std::is_member_function_pointer_v || std::is_function_v) + return FunctionDescriptor::create(_name); if constexpr ( std::is_class_v ) - return new ClassDesc(type::id(), type::primitive_id(), _name, type::compiler_name(), type::flags() ); - return new TypeDesc(type::id(), type::primitive_id(), _name, type::compiler_name(), type::flags() ); + return ClassDescriptor::create(_name); + else + return TypeDescriptor::create(_name); } /** @@ -280,8 +407,8 @@ namespace tools static_assert(IsReflectedClass); // check if source_type is a child of possibly_base_class - const ClassDesc* source_type = source_ptr->get_class(); - const TypeDesc* possibly_base_class = type::get(); + const ClassDescriptor* source_type = source_ptr->get_class(); + const TypeDescriptor* possibly_base_class = type::get(); return source_type->is_child_of(possibly_base_class->id(), self_check ); } @@ -306,15 +433,4 @@ namespace tools { return source_ptr; } - - template - constexpr bool has_get_type = std::is_member_pointer::value; - - template - struct is_base_of - { - static_assert( tools::has_get_type, "BaseT must have polymorphic reflection"); - static_assert( tools::has_get_type, "DerivedT must have polymorphic reflection"); - static constexpr bool value = std::is_same_v || std::is_base_of_v; - }; } \ No newline at end of file diff --git a/src/tools/core/reflection/Type.specs.cpp b/src/tools/core/reflection/Type.specs.cpp new file mode 100644 index 000000000..c3d8cec5c --- /dev/null +++ b/src/tools/core/reflection/Type.specs.cpp @@ -0,0 +1,71 @@ +#include +#include "tools/core/reflection/Type.h" +using namespace tools; + +TEST(FunctionDescriptor, no_arg_fct) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + EXPECT_EQ(f.get_arg_count(), 0); +} + +TEST(FunctionDescriptor, push_single_arg) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + + EXPECT_EQ(f.get_arg_count(), 1); + EXPECT_TRUE(f.get_return_type()->is()); + EXPECT_TRUE(f.get_args().at(0).m_type->is() ); +} + +TEST(FunctionDescriptor, push_two_args) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + + EXPECT_EQ(f.get_arg_count(), 1); + EXPECT_TRUE(f.get_return_type()->is()); + EXPECT_TRUE(f.get_args().at(0).m_type->is() ); + EXPECT_TRUE(f.get_args().at(0).m_type->is() ); +} + +TEST(FunctionDescriptor, match_check_for_arg_count) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + const FunctionDescriptor g = FunctionDescriptor::construct("fct"); + + EXPECT_EQ(g.is_compatible(&f), false); + EXPECT_EQ(f.is_compatible(&g), false); +} + +TEST(FunctionDescriptor, push_args_template_0) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + FunctionDescriptor g = FunctionDescriptor::construct("fct"); + + using ZeroArgs = std::tuple<>; + g.push_args(); + + EXPECT_EQ(f.is_compatible(&g), true); + EXPECT_EQ(g.get_arg_count(), 0); +} + +TEST(FunctionDescriptor, push_args_template_1) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + FunctionDescriptor g = FunctionDescriptor::construct("fct"); + + g.push_args< std::tuple >(); + + EXPECT_EQ(f.is_compatible(&g), true); + EXPECT_EQ(g.get_arg_count(), 2); +} + +TEST(FunctionDescriptor, push_args_template_4) +{ + const FunctionDescriptor f = FunctionDescriptor::construct("fct"); + FunctionDescriptor g = FunctionDescriptor::construct("fct"); + + g.push_args< std::tuple >(); + + EXPECT_EQ(f.is_compatible(&g), true); + EXPECT_EQ(g.get_arg_count(), 4); +} diff --git a/src/tools/core/reflection/TypeRegister.cpp b/src/tools/core/reflection/TypeRegister.cpp index 74954c113..3e6aaaeb4 100644 --- a/src/tools/core/reflection/TypeRegister.cpp +++ b/src/tools/core/reflection/TypeRegister.cpp @@ -5,29 +5,29 @@ using namespace tools; -TypeDesc* TypeRegister::get(std::type_index index) +TypeDescriptor* TypeRegister::get(std::type_index index) { auto found = by_index().find(index); VERIFY(found != by_index().end(), "reflection: type not found!") return found->second; } -ClassDesc* TypeRegister::get_class(std::type_index index) +ClassDescriptor* TypeRegister::get_class(std::type_index index) { - TypeDesc* type = get(index); + TypeDescriptor* type = get(index); if ( type->is_class() ) - return static_cast( type ); + return static_cast( type ); return nullptr; } -std::unordered_map& TypeRegister::by_index() +std::unordered_map& TypeRegister::by_index() { - static std::unordered_map meta_type_register_by_typeid; + static std::unordered_map meta_type_register_by_typeid; return meta_type_register_by_typeid; } -bool TypeRegister::has(const TypeDesc* _type) +bool TypeRegister::has(const TypeDescriptor* _type) { return by_index().find(_type->id()) != by_index().end(); } @@ -38,19 +38,19 @@ bool TypeRegister::has(std::type_index index) return found != by_index().end(); } -TypeDesc* TypeRegister::insert(TypeDesc* _type) +TypeDescriptor* TypeRegister::insert(TypeDescriptor* _type) { by_index().insert({_type->id(), _type}); return _type; } -TypeDesc* TypeRegister::merge(TypeDesc* existing, const TypeDesc* other) +TypeDescriptor* TypeRegister::merge(TypeDescriptor* existing, const TypeDescriptor* other) { LOG_VERBOSE( __FILE__, "Merge existing: \"%s\" (%s), with: \"%s\" (%s)\n", - existing->m_name, existing->m_compiler_name, - other->m_name, other->m_compiler_name + existing->m_name.c_str(), existing->m_compiler_name, + other->m_name.c_str(), other->m_compiler_name ) if( existing->m_name[0] == '\0' ) { @@ -59,8 +59,8 @@ TypeDesc* TypeRegister::merge(TypeDesc* existing, const TypeDesc* other) if ( existing->is_class() ) { - auto* existing_class = reinterpret_cast(existing); - auto* other_class = reinterpret_cast(other); + auto* existing_class = reinterpret_cast(existing); + auto* other_class = reinterpret_cast(other); existing_class->m_children.insert(other_class->m_children.begin(), other_class->m_children.end() ); existing_class->m_parents.insert(other_class->m_parents.begin(), other_class->m_parents.end() ); @@ -76,17 +76,17 @@ void TypeRegister::log_statistics() for ( const auto& [type_hash, type] : by_index() ) { - LOG_MESSAGE("reflection", " %-16llu %-25s %-60s\n", type_hash, type->m_name, type->m_compiler_name ); + LOG_MESSAGE("reflection", " %-16llu %-25s %-60s\n", type_hash, type->m_name.c_str(), type->m_compiler_name ); } LOG_MESSAGE("reflection", "Logging done.\n"); } -TypeDesc* TypeRegister::insert_or_merge(TypeDesc* possibly_existing_type) +TypeDescriptor* TypeRegister::insert_or_merge(TypeDescriptor* possibly_existing_type) { if( has(possibly_existing_type->id()) ) { - TypeDesc* existing_type = get(possibly_existing_type->id()); + TypeDescriptor* existing_type = get(possibly_existing_type->id()); return merge(existing_type, possibly_existing_type); } return insert(possibly_existing_type); diff --git a/src/tools/core/reflection/TypeRegister.h b/src/tools/core/reflection/TypeRegister.h index c97cb9e18..34ae79ff9 100644 --- a/src/tools/core/reflection/TypeRegister.h +++ b/src/tools/core/reflection/TypeRegister.h @@ -9,22 +9,22 @@ namespace tools { // forward declaration - class TypeDesc; - class ClassDesc; + class TypeDescriptor; + class ClassDescriptor; /** * structure to help register types */ struct TypeRegister { - static std::unordered_map& by_index(); - static TypeDesc* get(std::type_index); - static ClassDesc* get_class(std::type_index); - static bool has(const TypeDesc*); + static std::unordered_map& by_index(); + static TypeDescriptor* get(std::type_index); + static ClassDescriptor* get_class(std::type_index); + static bool has(const TypeDescriptor*); static bool has(std::type_index); - static TypeDesc* insert(TypeDesc*); - static TypeDesc* merge(TypeDesc* existing, const TypeDesc* other); - static TypeDesc* insert_or_merge(TypeDesc*); + static TypeDescriptor* insert(TypeDescriptor*); + static TypeDescriptor* merge(TypeDescriptor* existing, const TypeDescriptor* other); + static TypeDescriptor* insert_or_merge(TypeDescriptor*); static void log_statistics(); }; diff --git a/src/tools/core/reflection/reflection b/src/tools/core/reflection/reflection index 0966cc67d..243673d11 100644 --- a/src/tools/core/reflection/reflection +++ b/src/tools/core/reflection/reflection @@ -5,7 +5,6 @@ #include "Operator_t.h" #include "Initializer.h" #include "enum.h" -#include "FuncType.h" #include "Type.h" #include "TypeRegister.h" #include "union.h" \ No newline at end of file diff --git a/src/tools/core/reflection/reflection.specs.cpp b/src/tools/core/reflection/reflection.specs.cpp index 35db00eef..683825553 100644 --- a/src/tools/core/reflection/reflection.specs.cpp +++ b/src/tools/core/reflection/reflection.specs.cpp @@ -69,3 +69,9 @@ TEST(Reflection, is_child_of) EXPECT_FALSE(type::get_class()->is_child_of()); } +TEST(Reflection, by_reference) +{ + ; + auto descriptor = FunctionDescriptor::construct("function"); + EXPECT_TRUE( descriptor.get_arg(0).m_by_reference ); +} diff --git a/src/tools/core/reflection/variant.cpp b/src/tools/core/reflection/variant.cpp index f4d2699f9..a719aa4b2 100644 --- a/src/tools/core/reflection/variant.cpp +++ b/src/tools/core/reflection/variant.cpp @@ -243,7 +243,7 @@ void variant::release_mem() m_flags &= ~Flag_OWNS_HEAP_ALLOCATED_MEMORY; // set flags to 0 } -void variant::change_type(const TypeDesc* _type) +void variant::change_type(const TypeDescriptor* _type) { auto* normalized_type = _type->is_ptr() ? type::get() : _type; // normalize any pointer to void* change_type( type_to_enum(normalized_type) ); @@ -309,7 +309,7 @@ variant::operator i32_t () const { return m_data.i32;} variant::operator std::string() const { return *((std::string*)m_data.ptr);} variant::operator void*() const { return m_data.ptr;} -variant::Type variant::type_to_enum(const tools::TypeDesc* _type) +variant::Type variant::type_to_enum(const tools::TypeDescriptor* _type) { if( _type->is() ) return Type_any; if( _type->is() ) return Type_bool; @@ -323,7 +323,7 @@ variant::Type variant::type_to_enum(const tools::TypeDesc* _type) ASSERT(false) // Unhandled type; } -const tools::TypeDesc* variant::enum_to_type(Type _type) +const tools::TypeDescriptor* variant::enum_to_type(Type _type) { switch ( _type ) { @@ -340,7 +340,7 @@ const tools::TypeDesc* variant::enum_to_type(Type _type) } } -bool variant::is_type(const tools::TypeDesc* _type) const +bool variant::is_type(const tools::TypeDescriptor* _type) const { return m_type == type_to_enum(_type); // compare the internal Type enum values } @@ -352,7 +352,7 @@ bool variant::is_mem_initialized() const return m_flags & Flag_OWNS_HEAP_ALLOCATED_MEMORY; } -const TypeDesc* variant::get_type() const +const TypeDescriptor* variant::get_type() const { return enum_to_type(m_type); } diff --git a/src/tools/core/reflection/variant.h b/src/tools/core/reflection/variant.h index cd2bdf147..06d874a90 100644 --- a/src/tools/core/reflection/variant.h +++ b/src/tools/core/reflection/variant.h @@ -40,9 +40,9 @@ namespace tools void set(i32_t); void set(const variant&); - const TypeDesc* get_type()const; - bool is_type(const TypeDesc*) const; - void change_type(const TypeDesc* _type); + const TypeDescriptor* get_type()const; + bool is_type(const TypeDescriptor*) const; + void change_type(const TypeDescriptor* _type); void clear_data(); const qword*data() const; // get ptr to underlying data (qword) @@ -86,8 +86,8 @@ namespace tools void release_mem(); // undo init_mem() bool is_mem_initialized() const; - static Type type_to_enum(const TypeDesc*) ; - static const tools::TypeDesc* enum_to_type(Type) ; + static Type type_to_enum(const TypeDescriptor*) ; + static const tools::TypeDescriptor* enum_to_type(Type) ; typedef int Flags; enum Flag_ diff --git a/src/tools/gui/ActionManager.h b/src/tools/gui/ActionManager.h index e8b288b65..9d6f73c8f 100644 --- a/src/tools/gui/ActionManager.h +++ b/src/tools/gui/ActionManager.h @@ -4,9 +4,9 @@ #include #include #include +#include #include -#include "tools/core/reflection/FuncType.h" #include "tools/core/Event.h" #include "tools/core/types.h"