Custom types and the location of the patch node "I/O structures" (feature request)


#1

If I copy and paste an example of the generated XOD C++ for a node which accepts a custom type as input, say this UART write-byte node:

//-----------------------------------------------------------------------------
// xod/uart/write-byte implementation
//-----------------------------------------------------------------------------
namespace xod__uart__write_byte {

struct State {
};

// clang-format off

struct Node {
    State state;
    Logic output_DONE;
    Logic output_ERR;

    union {
        struct {
            bool isOutputDirty_DONE : 1;
            bool isOutputDirty_ERR : 1;
            bool isNodeDirty : 1;
        };

        DirtyFlags dirtyFlags;
    };
};

struct input_UART { };
struct input_BYTE { };
struct input_SEND { };
struct output_DONE { };
struct output_ERR { };

template<typename PinT> struct ValueType { using T = void; };
template<> struct ValueType<input_UART> { using T = xod__uart__uart::Type; };
template<> struct ValueType<input_BYTE> { using T = uint8_t; };
template<> struct ValueType<input_SEND> { using T = Logic; };
template<> struct ValueType<output_DONE> { using T = Logic; };
template<> struct ValueType<output_ERR> { using T = Logic; };

struct ContextObject {
    Node* _node;

    xod__uart__uart::Type _input_UART;
    uint8_t _input_BYTE;
    Logic _input_SEND;

    bool _isInputDirty_SEND;
};

Would it cause any problems to put the ValueType lines before the user-defined “State” structure when the code is generated? e.g.:

//-----------------------------------------------------------------------------
// xod/uart/write-byte implementation
//-----------------------------------------------------------------------------
namespace xod__uart__write_byte {

struct input_UART { };
struct input_BYTE { };
struct input_SEND { };
struct output_DONE { };
struct output_ERR { };

template<typename PinT> struct ValueType { using T = void; };
template<> struct ValueType<input_UART> { using T = xod__uart__uart::Type; };
template<> struct ValueType<input_BYTE> { using T = uint8_t; };
template<> struct ValueType<input_SEND> { using T = Logic; };
template<> struct ValueType<output_DONE> { using T = Logic; };
template<> struct ValueType<output_ERR> { using T = Logic; };

struct State {
};

// clang-format off

struct Node {
    State state;
    Logic output_DONE;
    Logic output_ERR;

    union {
        struct {
            bool isOutputDirty_DONE : 1;
            bool isOutputDirty_ERR : 1;
            bool isNodeDirty : 1;
        };

        DirtyFlags dirtyFlags;
    };
};

struct ContextObject {
    Node* _node;

    xod__uart__uart::Type _input_UART;
    uint8_t _input_BYTE;
    Logic _input_SEND;

    bool _isInputDirty_SEND;
};

The reason I ask is that in a situation where I say wanted to use the incoming custom type as a template parameter for some member in the user-defined “State” I could simply put something like “typedef ValueType<input_UART>::T input_type_t” at the top of my implementation and then I should be able to write:

typedef  ValueType<input_UART>::T input_type_t;

template <typename Input>
MyTemplateClass {};

State {
     MyTemplateClass<input_type_t> my_template_class;
};

However if they’re defined after where the State is defined in the generated code I can’t do this, as far as I know I have to resort to “hacks.” :frowning:


#2

I see your pain. Unfortunately, in the current implementation, the exact place where the generated code goes is dictated solely by the {{ GENERATED_CODE }} placeholder. That code requires a definition of State, so it should go after it. The split you’ve suggested is possible however it would require new placeholders in the current implementation…

Unrelated, but, there’s an issue #1325 which seems to be able to automatically solve the problem. There the State comes after all the metaprogramming stuff. Vote up :+1: on GitHub if it’s what you need to raise the priority in the backlog.