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
唯一的区别是不同派生的不同实现 类.
目前我正在为 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
唯一的区别是不同派生的不同实现 类.