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 7 /// Resolve all symbol references (variable/type/function/enum name uses) 8 /// using information collected on previous pass 9 module vox.fe.passes.names_resolve; 10 11 import std.stdio; 12 import std.string : format; 13 import vox.all; 14 15 void pass_names_resolve(ref CompilationContext context, CompilePassPerModule[] subPasses) 16 { 17 auto state = NameResolveState(&context); 18 19 foreach (ref SourceFileInfo file; context.files.data) { 20 AstIndex modIndex = file.mod.get_ast_index(&context); 21 require_name_resolve(modIndex, state); 22 assert(context.analisysStack.length == 0); 23 } 24 } 25 26 struct NameResolveState 27 { 28 CompilationContext* context; 29 } 30 31 void require_name_resolve(ref AstIndex nodeIndex, CompilationContext* context) 32 { 33 auto state = NameResolveState(context); 34 require_name_resolve(nodeIndex, state); 35 } 36 37 void require_name_resolve(ref AstNodes items, ref NameResolveState state) 38 { 39 foreach(ref AstIndex item; items) require_name_resolve(item, state); 40 } 41 42 void require_name_resolve(ref AstIndex nodeIndex, ref NameResolveState state) 43 { 44 AstNode* node = state.context.getAstNode(nodeIndex); 45 46 switch(node.state) with(AstNodeState) 47 { 48 case name_register_self, name_register_nested, name_resolve, type_check: 49 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.name_resolve)); 50 state.context.circular_dependency; 51 case parse_done: 52 auto name_state = NameRegisterState(state.context); 53 require_name_register_self(0, nodeIndex, name_state); 54 state.context.throwOnErrors; 55 goto case; 56 case name_register_self_done: 57 require_name_register(nodeIndex, state.context); 58 state.context.throwOnErrors; 59 break; 60 case name_register_nested_done: break; // all requirement are done 61 case name_resolve_done, type_check_done, ir_gen_done: return; // already name resolved 62 default: state.context.internal_error(node.loc, "Node %s in %s state", node.astType, node.state); 63 } 64 65 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.name_resolve)); 66 scope(success) state.context.pop_analized_node; 67 68 if (node.hasAttributes) { 69 name_resolve_attributes(node.attributeInfo, state); 70 } 71 72 final switch(node.astType) with(AstType) 73 { 74 case error: state.context.internal_error(node.loc, "Visiting error node"); 75 case abstract_node: state.context.internal_error(node.loc, "Visiting abstract node"); 76 77 case decl_alias: name_resolve_alias(cast(AliasDeclNode*)node, state); break; 78 case decl_alias_array: assert(false); 79 case decl_builtin: assert(false); 80 case decl_builtin_attribute: assert(false); 81 case decl_module: name_resolve_module(cast(ModuleDeclNode*)node, state); break; 82 case decl_package: assert(false); 83 case decl_import: assert(false); 84 case decl_function: name_resolve_func(cast(FunctionDeclNode*)node, state); break; 85 case decl_var: name_resolve_var(cast(VariableDeclNode*)node, state); break; 86 case decl_struct: name_resolve_struct(cast(StructDeclNode*)node, state); break; 87 case decl_enum: name_resolve_enum(cast(EnumDeclaration*)node, state); break; 88 case decl_enum_member: name_resolve_enum_member(cast(EnumMemberDecl*)node, state); break; 89 case decl_static_assert: name_resolve_static_assert(cast(StaticAssertDeclNode*)node, state); break; 90 case decl_static_foreach: assert(false); 91 case decl_static_if: assert(false); 92 case decl_static_version: assert(false); 93 case decl_template: assert(false); 94 case decl_template_param: assert(false); 95 96 case stmt_block: name_resolve_block(cast(BlockStmtNode*)node, state); break; 97 case stmt_if: name_resolve_if(cast(IfStmtNode*)node, state); break; 98 case stmt_while: name_resolve_while(cast(WhileStmtNode*)node, state); break; 99 case stmt_do_while: name_resolve_do(cast(DoWhileStmtNode*)node, state); break; 100 case stmt_for: name_resolve_for(cast(ForStmtNode*)node, state); break; 101 case stmt_switch: name_resolve_switch(cast(SwitchStmtNode*)node, state); break; 102 case stmt_return: name_resolve_return(cast(ReturnStmtNode*)node, state); break; 103 case stmt_break: assert(false); 104 case stmt_continue: assert(false); 105 106 case expr_name_use: name_resolve_name_use(nodeIndex, cast(NameUseExprNode*)node, state); break; 107 case expr_member: name_resolve_member(cast(MemberExprNode*)node, state); break; 108 case expr_bin_op: name_resolve_binary_op(cast(BinaryExprNode*)node, state); break; 109 case expr_un_op: name_resolve_unary_op(cast(UnaryExprNode*)node, state); break; 110 case expr_call: name_resolve_call(cast(CallExprNode*)node, state); break; 111 case expr_named_argument: name_resolve_named_argument(cast(NamedArgumenExprNode*)node, state); break; 112 case expr_index: name_resolve_index(nodeIndex, cast(IndexExprNode*)node, state); break; 113 case expr_slice: name_resolve_expr_slice(cast(SliceExprNode*)node, state); break; 114 case expr_type_conv: name_resolve_type_conv(cast(TypeConvExprNode*)node, state); break; 115 116 case literal_int: assert(false); 117 case literal_float: assert(false); 118 case literal_string: assert(false); 119 case literal_null: assert(false); 120 case literal_bool: assert(false); 121 case literal_array: assert(false); 122 case literal_special: assert(false); 123 124 case type_basic: assert(false); 125 case type_func_sig: name_resolve_func_sig(cast(FunctionSignatureNode*)node, state); break; 126 case type_ptr: name_resolve_ptr(cast(PtrTypeNode*)node, state); break; 127 case type_static_array: name_resolve_static_array(cast(StaticArrayTypeNode*)node, state); break; 128 case type_slice: name_resolve_slice(cast(SliceTypeNode*)node, state); break; 129 } 130 } 131 132 /// Error means that lookup failed due to earlier failure or error, so no new error should be produced 133 enum LookupResult : ubyte { 134 success, 135 failure, 136 error 137 } 138 139 /// Look up symbol by Identifier. Searches the stack of scopes. 140 // Returns errorNode if not found or error occured 141 AstIndex lookupScopeIdRecursive(Scope* scop, const Identifier id, TokenIndex from, CompilationContext* context) 142 { 143 Scope* sc = scop; 144 145 //writefln("lookup %s", context.idString(id)); 146 // first phase 147 while(sc) 148 { 149 AstIndex symIndex = sc.symbols.get(id, AstIndex.init); 150 //writefln(" scope %s %s %s", context.getAstNodeIndex(sc), sc.debugName, symIndex); 151 152 if (symIndex) 153 { 154 AstNode* symNode = context.getAstNode(symIndex); 155 if (sc.kind == ScopeKind.local) 156 { 157 // we need to skip forward references in function scope 158 uint fromStart = context.tokenLocationBuffer[from].start; 159 uint toStart = context.tokenLocationBuffer[symNode.loc].start; 160 //writefln(" local %s %s", fromStart, toStart); 161 // backward reference 162 if (fromStart > toStart) { 163 return symIndex; 164 } 165 } 166 else 167 { 168 // forward reference allowed in global and member scopes 169 return symIndex; 170 } 171 } 172 173 sc = sc.parentScope.get_scope(context); 174 } 175 176 // second phase 177 return lookupImports(scop, id, from, context); 178 } 179 180 // Returns errorNode if not found or error occured 181 AstIndex lookupImports(Scope* scop, const Identifier id, TokenIndex from, CompilationContext* c) 182 { 183 while (scop) 184 { 185 AstIndex symIndex; 186 ModuleDeclNode* symMod; 187 188 foreach (AstIndex impIndex; scop.imports) 189 { 190 ModuleDeclNode* imp = c.getAst!ModuleDeclNode(impIndex); 191 // TODO: check that import is higher in ordered scopes 192 AstIndex scopeSym = imp.memberScope.lookup_scope(id, c); 193 if (!scopeSym) continue; 194 195 if (scopeSym && symIndex && scopeSym != symIndex) 196 { 197 c.error(from, 198 "`%s` at %s conflicts with `%s` at %s", 199 symIndex.get_node_id(c).pr(c), FmtSrcLoc(c.getAstNode(symIndex).loc, c), 200 scopeSym.get_node_id(c).pr(c), FmtSrcLoc(c.getAstNode(scopeSym).loc, c)); 201 return CommonAstNodes.node_error; 202 } 203 204 symIndex = scopeSym; 205 symMod = imp; 206 } 207 208 if (symIndex) return symIndex; 209 210 scop = scop.parentScope.get_scope(c); 211 } 212 213 return CommonAstNodes.node_error; 214 } 215