关于“静态类型检查”,想必使用C 或Java 的各位应该非常熟悉了。在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错。例如结构体之间无法用+ 进行加法运算,指针和数值之间无法用* 进行乘法运算,将数组传递给参数类型为int 型的函数会出现莫名其妙的结果。在编译过程中检查是否符合这样的限制的处理就是静态类型检查。
在静态类型检查过程中也会实施隐式类型转换。
/*入口 * */ public void check(AST ast) throws SemanticException { /* * 第1 个foreach 语句对全局变量的定义进行遍历, */ for (DefinedVariable var : ast.definedVariables()) { checkVariable(var); } /* * 第2 个foreach 语句对函数定义进行遍历,并实施类型检查。 */ for (DefinedFunction f : ast.definedFunctions()) { currentFunction = f; checkReturnType(f); checkParamTypes(f); check(f.body()); } if (errorHandler.errorOccured()) { throw new SemanticException("compile failed."); } }
/* * checkVariable 方法在检查变量的类型是否为非void 的同 时,还对变量的初始化表达式进行遍历。 */ private void checkVariable(DefinedVariable var) { if (isInvalidVariableType(var.type())) { error(var.location(), "invalid variable type"); return; } if (var.hasInitializer()) { if (isInvalidLHSType(var.type())) { error(var.location(), "invalid LHS type: " + var.type()); return; } check(var.initializer()); var.setInitializer(implicitCast(var.type(), var.initializer())); } }
/* * checkReturnType 方法检查函数返回值的类型是否为非结 构体、联合体或数组。这里再重复一下,Ocelot中函数不能返回结构体或联合体。 */ private void checkReturnType(DefinedFunction f) { if (isInvalidReturnType(f.returnType())) { error(f.location(), "returns invalid type: " + f.returnType()); } }
/* * checkParamTypes 方法检查函数形参的类型是否为非结构体、联合体或void。因为Ocelot 中函数参数的类型不能是结构体或联合体。 */ private void checkParamTypes(DefinedFunction f) { for (Parameter param : f.parameters()) { if (isInvalidParameterType(param.type())) { error(param.location(), "invalid parameter type: " + param.type()); } } }
/* * check 是遍历参数节点的方法。各节点类会重写该函数,通过调用check(f. body()) 对函数体进行遍历。 */ private void check(StmtNode node) { visitStmt(node); }