1 /** 2 Copyright: Copyright (c) 2017-2019 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module vox.fe.passes.type_check; 7 8 import std.stdio; 9 import std.string : format; 10 import vox.all; 11 12 void pass_type_check(ref CompilationContext context, CompilePassPerModule[] subPasses) 13 { 14 auto state = TypeCheckState(&context); 15 16 foreach (ref SourceFileInfo file; context.files.data) { 17 AstIndex modIndex = file.mod.get_ast_index(&context); 18 require_type_check(modIndex, state); 19 assert(context.analisysStack.length == 0); 20 21 if (context.printAstSema && modIndex) { 22 writefln("// AST typed `%s`", file.name); 23 print_ast(context.getAstNodeIndex(file.mod), &context, 2); 24 } 25 } 26 } 27 28 // TODO: remove later, when no calls that pass IsNested.no remain. 29 enum IsNested : bool { 30 no = false, 31 yes = true, 32 } 33 34 struct TypeCheckState 35 { 36 CompilationContext* context; 37 AstIndex parentType; 38 } 39 40 /// Type checking for static context 41 void require_type_check(ref AstIndex nodeIndex, CompilationContext* context, IsNested isNested = IsNested.yes) 42 { 43 auto state = TypeCheckState(context); 44 require_type_check(nodeIndex, state, isNested); 45 } 46 47 // Assumes IsNested.yes 48 void require_type_check(ref AstNodes items, ref TypeCheckState state, IsNested isNested = IsNested.yes) 49 { 50 foreach(ref AstIndex item; items) require_type_check(item, state, isNested); 51 } 52 53 /// Annotates all expression nodes with their type 54 /// Type checking, casting 55 /// isNested: 56 /// If true, then type check must be performed. If check is already in progress then it is an error. 57 /// Indirect check requests over expr_name_use, expr_member pass false. 58 void require_type_check(ref AstIndex nodeIndex, ref TypeCheckState state, IsNested isNested = IsNested.yes) 59 { 60 AstNode* node = state.context.getAstNode(nodeIndex); 61 //writefln("require_type_check %s %s %s", node.astType, node.state, isNested); 62 63 switch(node.state) with(AstNodeState) 64 { 65 case name_register_self, name_register_nested, name_resolve: 66 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.type_check)); 67 state.context.circular_dependency; 68 case type_check: 69 if (isNested == IsNested.no) { 70 // this is allowed. We simply return. 71 return; 72 } 73 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.type_check)); 74 state.context.circular_dependency; 75 case parse_done: 76 auto name_state = NameRegisterState(state.context); 77 require_name_register_self(0, nodeIndex, name_state); 78 state.context.throwOnErrors; 79 goto case; 80 case name_register_self_done: 81 auto name_state = NameRegisterState(state.context); 82 require_name_register(nodeIndex, name_state); 83 state.context.throwOnErrors; 84 goto case; 85 case name_register_nested_done: 86 require_name_resolve(nodeIndex, state.context); 87 state.context.throwOnErrors; 88 break; 89 case name_resolve_done: break; // all requirement are done 90 case type_check_done, ir_gen_done: return; // already type checked 91 default: state.context.internal_error(node.loc, "Node %s in %s state", node.astType, node.state); 92 } 93 94 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.type_check)); 95 scope(success) state.context.pop_analized_node; 96 97 if (node.hasAttributes) { 98 type_check_attributes(node.attributeInfo, state); 99 } 100 101 final switch(node.astType) with(AstType) 102 { 103 case error: state.context.internal_error(node.loc, "Visiting error node"); 104 case abstract_node: state.context.internal_error(node.loc, "Visiting abstract node"); 105 106 case decl_alias: type_check_alias(cast(AliasDeclNode*)node, state); break; 107 case decl_alias_array: assert(false); 108 case decl_builtin: assert(false); 109 case decl_builtin_attribute: type_check_builtin_attribute(cast(BuiltinAttribNode*)node, state); break; 110 case decl_module: type_check_module(cast(ModuleDeclNode*)node, state); break; 111 case decl_package: assert(false); 112 case decl_import: assert(false); 113 case decl_function: type_check_func(cast(FunctionDeclNode*)node, state); break; 114 case decl_var: type_check_var(cast(VariableDeclNode*)node, state); break; 115 case decl_struct: type_check_struct(cast(StructDeclNode*)node, state); break; 116 case decl_enum: type_check_enum(cast(EnumDeclaration*)node, state); break; 117 case decl_enum_member: type_check_enum_member(cast(EnumMemberDecl*)node, state); break; 118 case decl_static_assert: type_check_static_assert(cast(StaticAssertDeclNode*)node, state); break; 119 case decl_static_foreach: assert(false); 120 case decl_static_if: assert(false); 121 case decl_static_version: assert(false); 122 case decl_template: assert(false); 123 case decl_template_param: assert(false); 124 125 case stmt_block: type_check_block(cast(BlockStmtNode*)node, state); break; 126 case stmt_if: type_check_if(cast(IfStmtNode*)node, state); break; 127 case stmt_while: type_check_while(cast(WhileStmtNode*)node, state); break; 128 case stmt_do_while: type_check_do(cast(DoWhileStmtNode*)node, state); break; 129 case stmt_for: type_check_for(cast(ForStmtNode*)node, state); break; 130 case stmt_switch: type_check_switch(cast(SwitchStmtNode*)node, state); break; 131 case stmt_return: type_check_return(cast(ReturnStmtNode*)node, state); break; 132 case stmt_break: assert(false); 133 case stmt_continue: assert(false); 134 135 case expr_name_use: type_check_name_use(nodeIndex, cast(NameUseExprNode*)node, state); break; 136 case expr_member: type_check_member(nodeIndex, cast(MemberExprNode*)node, state); break; 137 case expr_bin_op: type_check_binary_op(cast(BinaryExprNode*)node, state); break; 138 case expr_un_op: type_check_unary_op(cast(UnaryExprNode*)node, state); break; 139 case expr_call: type_check_call(nodeIndex, cast(CallExprNode*)node, state); break; 140 case expr_named_argument: type_check_named_argument(cast(NamedArgumenExprNode*)node, state); break; 141 case expr_index: type_check_index(nodeIndex, cast(IndexExprNode*)node, state); break; 142 case expr_slice: type_check_expr_slice(cast(SliceExprNode*)node, state); break; 143 case expr_type_conv: type_check_type_conv(cast(TypeConvExprNode*)node, state); break; 144 145 case literal_int: type_check_literal_int(cast(IntLiteralExprNode*)node, state); break; 146 case literal_float: type_check_literal_float(cast(FloatLiteralExprNode*)node, state); break; 147 case literal_string: type_check_literal_string(cast(StringLiteralExprNode*)node, state); break; 148 case literal_null: type_check_literal_null(cast(NullLiteralExprNode*)node, state); break; 149 case literal_bool: type_check_literal_bool(cast(BoolLiteralExprNode*)node, state); break; 150 case literal_array: type_check_literal_array(cast(ArrayLiteralExprNode*)node, state); break; 151 case literal_special: assert(false); 152 153 case type_basic: assert(false); 154 case type_func_sig: type_check_func_sig(cast(FunctionSignatureNode*)node, state); break; 155 case type_ptr: type_check_ptr(cast(PtrTypeNode*)node, state); break; 156 case type_static_array: type_check_static_array(cast(StaticArrayTypeNode*)node, state); break; 157 case type_slice: type_check_slice(cast(SliceTypeNode*)node, state); break; 158 } 159 } 160 161 void require_type_check_expr(AstIndex targetType, ref AstIndex nodeIndex, CompilationContext* context) 162 { 163 auto state = TypeCheckState(context); 164 state.parentType = targetType; 165 require_type_check(nodeIndex, state); 166 } 167 168 void require_type_check_expr(AstIndex targetType, ref AstIndex nodeIndex, ref TypeCheckState state) 169 { 170 auto temp = state.parentType; 171 state.parentType = targetType; 172 require_type_check(nodeIndex, state); 173 state.parentType = temp; 174 } 175 176 TypeConvResKind checkTypeConversion(AstIndex fromTypeIndex, AstIndex toTypeIndex, ref AstIndex expr, CompilationContext* c) 177 { 178 if (same_type(fromTypeIndex, toTypeIndex, c)) return TypeConvResKind.no_i; 179 180 if (fromTypeIndex == CommonAstNodes.type_error || toTypeIndex == CommonAstNodes.type_error) 181 return TypeConvResKind.no_i; 182 183 TypeNode* fromType = fromTypeIndex.get_type(c); 184 TypeNode* toType = toTypeIndex.get_type(c); 185 186 //writefln("checkTypeConversion %s -> %s", printer(fromTypeIndex, c), printer(toTypeIndex, c)); 187 //writefln("checkTypeConversion %s -> %s", printer(c.getAstNodeIndex(fromType), c), printer(c.getAstNodeIndex(toType), c)); 188 //writefln("checkTypeConversion %s", fromType.astType); 189 190 switch (fromType.astType) with(AstType) { 191 case type_basic: return type_conv_basic(fromType.as_basic, toTypeIndex, expr, c); 192 case type_ptr: return type_conv_ptr(fromType.as_ptr, toTypeIndex, expr, c); 193 case type_slice: return type_conv_slice(fromType.as_slice, toTypeIndex, expr, c); 194 case type_static_array: return type_conv_static_array(fromType.as_static_array, toTypeIndex, expr, c); 195 case decl_enum: return checkTypeConversion(fromType.as_enum.memberType, toTypeIndex, expr, c); 196 case type_func_sig: return type_conv_func_sig(fromType.as_func_sig, toTypeIndex, expr, c); 197 case decl_struct: return type_conv_struct(fromType.as_struct, toTypeIndex, expr, c); 198 default: 199 c.internal_error(expr.loc(c), "Unhandled type conversion %s, %s", cast(AstType)fromTypeIndex.astType(c), toType.astType); 200 } 201 } 202 203 struct CommonTypeResult { 204 AstIndex commonType; 205 TypeConvResKind kindA; 206 TypeConvResKind kindB; 207 } 208 209 // leftExpr, rightExpr can be null 210 CommonTypeResult calcCommonType(AstIndex indexA, AstIndex indexB, AstIndex leftExpr, AstIndex rightExpr, CompilationContext* c) 211 out(res; res.commonType.isDefined) 212 { 213 if (same_type(indexA, indexB, c)) return CommonTypeResult(indexA, TypeConvResKind.no_i, TypeConvResKind.no_i); 214 215 TypeNode* typeA = indexA.get_type(c); 216 TypeNode* typeB = indexB.get_type(c); 217 218 if (typeB.astType == AstType.decl_enum) { 219 indexB = typeB.as_enum.memberType; 220 typeB = indexB.get_type(c); 221 } 222 223 restart_enum: 224 225 switch (typeA.astType) with(AstType) { 226 case type_basic: return common_type_basic(typeA.as_basic, indexB, leftExpr, rightExpr, c); 227 case type_slice: return CommonTypeResult(CommonAstNodes.type_error); 228 case type_ptr: return common_type_ptr(typeA.as_ptr, indexB, c); 229 case decl_enum: 230 indexA = typeA.as_enum.memberType; 231 typeA = indexA.get_type(c); 232 goto restart_enum; 233 default: 234 return CommonTypeResult(CommonAstNodes.type_error); 235 } 236 } 237 238 void autoconvToBool(ref AstIndex exprIndex, CompilationContext* context) 239 { 240 ExpressionNode* expr = exprIndex.get_expr(context); 241 if (expr.type.isErrorType) return; 242 if (!autoconvTo(exprIndex, CommonAstNodes.type_bool, context)) 243 context.error(expr.loc, "Cannot implicitly convert `%s` to bool", 244 expr.type.typeName(context)); 245 } 246 247 void insertCast(ref AstIndex exprIndex, AstIndex typeIndex, TypeConvResKind kind, CompilationContext* c) 248 { 249 //writefln("cast %s", kind); 250 final switch(kind) with(TypeConvResKind) 251 { 252 case fail: assert(false); 253 case no_e, no_i: return; 254 case ii_e, ii_i, if_e, if_i, ff_e, ff_i, fi_e, fi_i, string_literal_to_u8_ptr: 255 exprIndex = c.appendAst!TypeConvExprNode(exprIndex.loc(c), typeIndex, exprIndex); 256 exprIndex.setState(c, AstNodeState.type_check_done); 257 exprIndex.get_node(c).subType = kind; 258 return; 259 case override_expr_type_e, override_expr_type_i: 260 exprIndex.get_expr(c).type = typeIndex; 261 return; 262 case array_literal_to_slice: 263 ExpressionNode* expr = exprIndex.get_expr(c); 264 exprIndex = c.appendAst!UnaryExprNode(expr.loc, typeIndex, UnOp.staticArrayToSlice, exprIndex); 265 return; 266 } 267 } 268 269 bool autoconvToCommonType(ref AstIndex leftIndex, ref AstIndex rightIndex, CompilationContext* c) 270 { 271 AstIndex leftType = leftIndex.get_expr_type(c); 272 AstIndex rightType = rightIndex.get_expr_type(c); 273 CommonTypeResult res = calcCommonType(leftType, rightType, leftIndex, rightIndex, c); 274 //writefln("autoconvToCommonType %s %s %s", printer(leftType, c), printer(rightType, c), res); 275 if (res.commonType == CommonAstNodes.type_error) return false; 276 insertCast(leftIndex, res.commonType, res.kindA, c); 277 insertCast(rightIndex, res.commonType, res.kindB, c); 278 return true; 279 } 280 281 /// Returns true if conversion was successful. False otherwise 282 bool autoconvTo(ref AstIndex exprIndex, AstIndex typeIndex, CompilationContext* c) 283 { 284 AstIndex exprType = exprIndex.get_expr_type(c); 285 //writefln("autoconvTo %s -> %s", printer(exprType, c), printer(typeIndex, c)); 286 if (exprType == typeIndex) return true; 287 288 TypeConvResKind res = checkTypeConversion(exprType, typeIndex, exprIndex, c); 289 //writefln("autoconvTo %s %s %s", printer(exprType, c), printer(typeIndex, c), res); 290 if (res.canConvertImplicitly) 291 { 292 insertCast(exprIndex, typeIndex, res, c); 293 return true; 294 } 295 return false; 296 }