0

I have this code:

AST* visit(AST* node)
{
    if (node->name == "BinOp")
    {
        return visit_BinOp(node);
    }
    generic_visit(node);
    return nullptr;
}

AST is a class that only has a name member, defaulted to "undefined". I'm trying to pass an AST object (node) into visit_BinOp, which expects a BinOp object. BinOp is a child of AST. Here is visit_BinOp:

int visit_BinOp(BinOp* node)
{
    if (node->op->type == PLUS)
    {
        //code
    }
}

It is giving me this error:

argument of type "AST *" is incompatible with parameter of type "BinOp *".

I'm unsure of what to do to fix this. "node" is a generic AST* that could be a BinOp* or a different class that is also a child of AST.

AST:

class AST
{
public:
    string name = "undefined";
};

BinOp:

class BinOp : public AST
{
public:
    AST* left;
    Token* op;
    AST* right;

    BinOp(AST* left, Token* op, AST* right)
    {
        this->left = left;
        this->op = op;
        this->right = right;
        name = "BinOp";
    }
};
Anixias
  • 45
  • 1
  • 8
  • How are AST and BinOp defined? – Macmade Feb 06 '20 at 03:22
  • 2
    Do you know what virtual methods are, and how they work? – Sam Varshavchik Feb 06 '20 at 03:23
  • Nope! I'm really inexperienced with C++. I've heard of them but never seen/used them. – Anixias Feb 06 '20 at 03:24
  • Read up on them. They'll probably make this problem child's play. – user4581301 Feb 06 '20 at 03:25
  • 1
    Virtual methods are handy for dynamic dispatch, but if you want decoupled visitors and nodes, you want the visitor pattern: https://en.wikipedia.org/wiki/Visitor_pattern . An AST is literally the example there. – parktomatomi Feb 06 '20 at 03:26
  • Now that I think about it, couldn't AST have a visit method that its children (BinOp, etc.) would override? Or would that still not work since the parent method would take in AST* and the BinOp would take in BinOp*? (EDIT: actually, it wouldn't even need to take an argument, so that would work right? -- EDIT: yeah virtual methods look perfect!) – Anixias Feb 06 '20 at 03:27
  • Well, what you need to do is [get a good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), and learn all about virtual methods. Then, define one in your `AST` superclass, implement it in your `BinOp` class that calls the function, passing `this`, and you're done. You just have to figure out what should the virtual method do in the `AST` superclass. As they say, That Shouldn't Happen[tm], but you'll have to decide what to do when the impossible happens. Unfortunately, stackoverflow.com is not a replacement for a C++ book, so go there for more info. – Sam Varshavchik Feb 06 '20 at 03:27
  • `std::variant` with `std::visit` is an alternative way to dynamically visit multiple node types. https://en.cppreference.com/w/cpp/utility/variant/visit – parktomatomi Feb 06 '20 at 03:32
  • So it turns out that I overlooked another issue. Each visit method has its own return type. visit_BinOp returns an int, while visit returns whatever the corresponding child's visit function returns. I'm not sure how to handle that. I'm trying to translate python into C++, if that helps. – Anixias Feb 06 '20 at 03:45
  • Holy... I think I figured it out. template saved the day! https://stackoverflow.com/questions/17649136/function-which-is-able-to-return-different-types – Anixias Feb 06 '20 at 03:54

0 Answers0