Refactor your MSDscript implementation so that Expr::interp returns Val* instead of int. For now, your only implementation of Val will be NumVal for numbers (but you'll add boolean values in the next assignment). You can use whatever name you prefer for the classes (e.g., virtual base class Value with subclass NumberValue); the point is just to change over to value objects instead of using int for values.
For clarity, you might rename existing classes like Add to AddExpr, etc., but that's up to you. Although it's optional, renaming those classes is easy compared to the refactoring of Expr::interp, so consider starting with that renaming.
More recommendations:
Val classes.class Val; declaration near the top so that the declaration of Expr::interp can refer to Val*. Do not use #include "val.h", because the declaration of Expr classes should not need the implementation of Val classes.#include "val.h", because the implementation of Expr methods will need to use the implementation of Val classes and methods.class Expr; to allow Val::to_expr's return type to be Expr*. In "val.cpp", use #include "expr.h" in addition to #include "val.h".Expr::interp tests to use number-value objects instead of integers. Remember to change == for comparing integers to ->equals for comparing value objects.NumVal::equals, you'll need a pointer of type Val* that is not a pointer to a NumVal object — but NumVal is the only instantiable Val class at first! To work around that problem, use nullptr in tests for now (even though that's usually a bad idea), since nullptr can have type Val* and is not a pointer to a NumVal object.AddExpr::interp, see the slides for a recommendation on adding a method Val::add_to.Val* that is the result of Expr::interp, you'll need something like a Val::to_string method. If you send a Val* object directly to std::cout <<, it will just print as the hexadecimal address where the object is allocated, which is not useful.