C/C++ 类语言的类型检查器

Typechecker for a C/C++ like language

目前我正在为 C/C++ 类语言开发一个编译器,更具体地说是一个类型检查器。 我已经生成了一个带有语法和 bnfc 工具的解析器。对于我的类型检查器,我需要推断表达式的类型。所有表达式都派生自一个抽象基class Exp,如下所示:

class Exp {
...
}

class ExpPlus : public {
 ...
}

class ExpAnd : public {
 ...
} 
...

ExpPlus 指的是 Exp + Exp,ExpAnd 指的是 Exp && Exp。 我的推断函数接受一个表达式,returns 它的类型如下所示:

ype *TypeChecker::infer(Exp *exp)
{
    // check for kind of expression
    /* Base cases */
    if(dynamic_cast<ETrue*>(exp))
    {
        Type *tBool = new Type_bool;
        return tBool;
    }
    if(dynamic_cast<EFalse*>(exp))
    {
        Type *tBool = new Type_bool;
        return tBool;
    }
    if(dynamic_cast<EInt*>(exp))
    {
        Type *tInt = new Type_int;
        return tInt;
    }
    if(dynamic_cast<EDouble*>(exp))
    {
        Type *tDouble = new Type_double;
        return tDouble;
    }
    if(dynamic_cast<EId*>(exp))   // search for type of given Id in contexts
    {
        EId *eId = dynamic_cast<EId*>(exp);

        Type *typeOfSearchedId = env_->lookupVarTypeFromContext(eId->id_);
        return typeOfSearchedId;
    }
    /* Base cases end*/

    /* check expressions */
    if(dynamic_cast<EApp*>(exp))
    {
        EApp *eApp = dynamic_cast<EApp*>(exp);
        Type *retType = env_->lookupFunTypeFromSymbolTable(eApp->id_).returnType;

        return retType;
    }
    if(dynamic_cast<EUPlus*>(exp))
    {
        // cast exp to type of exp
        EUPlus *eu_plus = dynamic_cast<EUPlus*>(exp);

        // infer till base case is derived
        Type *typeExp = infer(eu_plus->exp_);

        // if type is int or double
        if(dynamic_cast<Type_int*>(typeExp) || dynamic_cast<Type_double*>(typeExp))
            return typeExp;

        throw TypeException("Trying to unary add wrong type: " + env_->getStringRepresentationOfType(typeExp));
    }
...

如您所见,我有一长串 If 语句,用于检查表达式是哪种具体表达式类型,它工作正常等等,但我想知道是否有更优雅的方法来执行此操作。

你搞错了多态性。

而不是这个:

class Base {};

class Derived1 : public Base {};
class Derived2 : public Base {};
class Derived3 : public Base {};
//...

void foo(Base* b) {
    if(dynamic_cast<Derived1*>(b)) {
        do_something( dynamic_cast<Derived1*>(b));
    } else if (dynamic_cast<Derived2*>(b)) {
        do_something( dynamic_cast<Derived2*>(b));
    } else if ....
}

你应该通过使用虚拟方法来真正利用多态性:

class Base {
    virtual void do_something() = 0;
    virtual ~Base() {}
};

class Derived1 : public Base {
    void do_something() override { /*...*/ }
};
class Derived2 : public Base {
    void do_something() override { /*...*/ }
};
//...

void foo(Base* b) {
    b->do_something();
}

请注意,现在并非每个使用 Base* 并根据动态类型期望不同行为的方法都必须真正知道动态类型。 foo 只是调用 do_something 并且 virtual dispatch 选择要调用的正确方法。如果你写了一些 bar(Base*) 你不需要第二块 if-else 而是再次调用虚拟方法。

我简化了这个例子很多,虽然在你的代码中看起来所有分支 return a type 唯一的区别是不同派生的不同实现 类.