1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 5 /// Register identifiers in scope tree 6 module vox.fe.passes.names_register; 7 8 import std.stdio; 9 import std.string : format; 10 import vox.all; 11 12 13 void pass_names_register(ref CompilationContext context, CompilePassPerModule[] subPasses) 14 { 15 auto state = NameRegisterState(&context); 16 17 foreach (ref SourceFileInfo file; context.files.data) { 18 AstIndex modIndex = file.mod.get_ast_index(&context); 19 require_name_register(modIndex, state); 20 assert(context.analisysStack.length == 0); 21 } 22 } 23 24 void require_name_register(ref AstIndex nodeIndex, CompilationContext* context) 25 { 26 auto state = NameRegisterState(context); 27 require_name_register(nodeIndex, state); 28 } 29 30 // solves conditional compilation 31 // must be called inside name_register_nested state 32 void require_name_register(ref AstNodes items, ref NameRegisterState state) 33 { 34 require_name_register_self_sub_array(items, 0, items.length, state); 35 foreach(ref AstIndex item; items) require_name_register(item, state); 36 } 37 38 // returns `items` size delta 39 // walk all items in from..to range. 40 // gather all static ifs into linked list, while doing `require_name_register_self` 41 // for each static if in linked list 42 // eval condition 43 // in array replace static if node with correct branch 44 // call this recursively for inserted subrange 45 private long require_name_register_self_sub_array(ref AstNodes items, uint from, uint to, ref NameRegisterState state) 46 { 47 CompilationContext* c = state.context; 48 state.firstCondDecl = AstIndex(); 49 state.lastCondDecl = AstIndex(); 50 size_t i = from; 51 foreach(ref AstIndex item; items[from..to]) { 52 require_name_register_self(cast(uint)(i++), item, state); 53 } 54 55 if (state.firstCondDecl.isUndefined) return 0; // no static ifs 56 57 long sizeDelta; 58 59 AstIndex condDecl = state.firstCondDecl; 60 while (condDecl) 61 { 62 AstNode* decl = condDecl.get_node(c); 63 if(decl.astType == AstType.decl_static_foreach) 64 { 65 auto staticForeachNode = decl.as!StaticForeachDeclNode(c); 66 require_name_register(staticForeachNode.iterableExpr, state); 67 require_name_resolve(staticForeachNode.iterableExpr, c); 68 69 auto iter = staticForeachNode.iterableExpr.get_node(c); 70 71 if (iter.astType == AstType.decl_alias_array) 72 { 73 auto aliasArray = iter.as!AliasArrayDeclNode(c); 74 75 size_t bodySize = staticForeachNode.body.length; 76 uint numItemsToInsert = cast(uint)(aliasArray.items.length * bodySize); 77 78 uint insertPoint = cast(uint)(staticForeachNode.arrayIndex + sizeDelta); 79 items.replaceAtVoid(c.arrayArena, insertPoint, 1, numItemsToInsert); 80 81 foreach(idx, AstIndex item; aliasArray.items) 82 { 83 // Create scope for key/value vars 84 ScopeIndex instance_scope = c.appendScope; 85 Scope* newScope = c.getAstScope(instance_scope); 86 newScope.parentScope = staticForeachNode.parentScope; 87 newScope.debugName = "#foreach instance"; 88 newScope.kind = newScope.parentScope.get_scope(c).kind; 89 90 CloneState cloneState = clone_node(staticForeachNode.body_start, staticForeachNode.after_body, instance_scope, c); 91 92 if (staticForeachNode.keyId.isDefined) { 93 AstIndex keyNode = c.appendAst!EnumMemberDecl(staticForeachNode.loc); 94 auto enumMemberNode = keyNode.get!EnumMemberDecl(c); 95 enumMemberNode.initValue = c.constants.add(makeIrType(IrBasicType.i64), idx); 96 enumMemberNode.id = staticForeachNode.keyId; 97 enumMemberNode.type = CommonAstNodes.type_u64; 98 enumMemberNode.state = AstNodeState.type_check_done; 99 newScope.insert(staticForeachNode.keyId, keyNode, c); 100 } 101 newScope.insert(staticForeachNode.valueId, item, c); 102 103 size_t insertAt = insertPoint + idx * bodySize; 104 foreach(j, AstIndex node; staticForeachNode.body) 105 { 106 cloneState.fixAstIndex(node); 107 items[insertAt+j] = node; 108 } 109 } 110 111 // we replace #foreach with its children 112 // #foreach is removed from the list (-1) 113 // children are inserted (numItemsToInsert) 114 sizeDelta += numItemsToInsert - 1; 115 sizeDelta += require_name_register_self_sub_array(items, insertPoint, insertPoint+numItemsToInsert, state); 116 } 117 else 118 { 119 c.error(iter.loc, "#foreach cannot iterate over %s", iter.astType); 120 } 121 122 condDecl = staticForeachNode.next; 123 } 124 else 125 { 126 auto condNode = decl.as!ConditionalDeclNode(c); 127 AstNodes itemsToInsert; 128 129 if (decl.astType == AstType.decl_static_if) 130 { 131 auto staticIfNode = condNode.as!StaticIfDeclNode(c); 132 require_name_register(staticIfNode.condition, state); 133 IrIndex val = eval_static_expr(staticIfNode.condition, c); 134 itemsToInsert = c.constants.get(val).i64 ? staticIfNode.thenItems : staticIfNode.elseItems; 135 } 136 else 137 { 138 assert(decl.astType == AstType.decl_static_version); 139 auto versionNode = condNode.as!StaticVersionDeclNode(c); 140 Identifier versionId = versionNode.versionId; 141 bool isEnabled = false; 142 143 // Is built-in version identifier 144 if (versionId.index >= commonId_version_id_first && versionId.index <= commonId_version_id_last) 145 { 146 uint versionIndex = versionId.index - commonId_version_id_first; 147 isEnabled = (c.enabledVersionIdentifiers & (1 << versionIndex)) != 0; 148 } 149 else 150 { 151 c.error(decl.loc, "Only built-in versions are supported, not %s", c.idString(versionId)); 152 } 153 154 itemsToInsert = isEnabled ? versionNode.thenItems : versionNode.elseItems; 155 } 156 157 uint insertPoint = cast(uint)(condNode.arrayIndex + sizeDelta); 158 items.replaceAt(c.arrayArena, insertPoint, 1, itemsToInsert[]); 159 160 // we replace #if with its children 161 // #if is removed from the list (-1) 162 // children are inserted (itemsToInsert.length) 163 sizeDelta += itemsToInsert.length - 1; 164 sizeDelta += require_name_register_self_sub_array(items, insertPoint, insertPoint+itemsToInsert.length, state); 165 166 condDecl = condNode.next; 167 } 168 } 169 170 return sizeDelta; 171 } 172 173 // register own identifier in parent scope 174 void require_name_register_self(uint arrayIndex, ref AstIndex nodeIndex, ref NameRegisterState state) 175 { 176 CompilationContext* c = state.context; 177 AstNode* node = c.getAstNode(nodeIndex); 178 179 switch(node.state) with(AstNodeState) 180 { 181 case name_register_self, name_register_nested, name_resolve, type_check: 182 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.name_register_self)); 183 c.circular_dependency; 184 case parse_done: 185 // all requirement are done 186 break; 187 case name_register_self_done, name_register_nested_done, name_resolve_done, type_check_done: 188 // already name registered 189 return; 190 default: 191 c.internal_error(node.loc, "Node %s in %s state", node.astType, node.state); 192 } 193 194 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.name_register_self)); 195 scope(success) state.context.pop_analized_node; 196 197 switch(node.astType) with(AstType) 198 { 199 case error: c.internal_error(node.loc, "Visiting error node"); 200 case abstract_node: c.internal_error(node.loc, "Visiting abstract node"); 201 202 case decl_alias: name_register_self_alias(nodeIndex, cast(AliasDeclNode*)node, state); break; 203 case decl_import: name_register_self_import(cast(ImportDeclNode*)node, state); break; 204 case decl_function: name_register_self_func(nodeIndex, cast(FunctionDeclNode*)node, state); break; 205 case decl_var: name_register_self_var(nodeIndex, cast(VariableDeclNode*)node, state); break; 206 case decl_struct: name_register_self_struct(nodeIndex, cast(StructDeclNode*)node, state); break; 207 case decl_enum: name_register_self_enum(nodeIndex, cast(EnumDeclaration*)node, state); break; 208 case decl_enum_member: name_register_self_enum_member(nodeIndex, cast(EnumMemberDecl*)node, state); break; 209 case decl_static_if, decl_static_version, decl_static_foreach: 210 auto condDecl = node.as!ConditionalDeclNode(c); 211 if (state.lastCondDecl) 212 state.lastCondDecl.get!ConditionalDeclNode(c).next = nodeIndex; 213 else 214 state.firstCondDecl = nodeIndex; 215 condDecl.prev = state.lastCondDecl; 216 condDecl.arrayIndex = arrayIndex; 217 state.lastCondDecl = nodeIndex; 218 break; 219 case decl_template: name_register_self_template(nodeIndex, cast(TemplateDeclNode*)node, state); break; 220 221 default: c.internal_error(node.loc, "Visiting %s node %s", node.astType, node.state); 222 } 223 } 224 225 // register identifiers of nested nodes 226 void require_name_register(ref AstIndex nodeIndex, ref NameRegisterState state) 227 { 228 AstNode* node = state.context.getAstNode(nodeIndex); 229 230 switch(node.state) with(AstNodeState) 231 { 232 case name_register_self, name_register_nested, name_resolve, type_check: 233 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.name_register_nested)); 234 state.context.circular_dependency; 235 case parse_done: 236 auto name_state = NameRegisterState(state.context); 237 require_name_register_self(0, nodeIndex, name_state); 238 state.context.throwOnErrors; 239 goto case; 240 case name_register_self_done: break; // all requirement are done 241 case name_register_nested_done, name_resolve_done, type_check_done, ir_gen_done: return; // already name registered 242 default: state.context.internal_error(node.loc, "Node %s in %s state", node.astType, node.state); 243 } 244 245 state.context.push_analized_node(AnalysedNode(nodeIndex, NodeProperty.name_register_nested)); 246 scope(success) state.context.pop_analized_node; 247 248 if (node.hasAttributes) { 249 name_register_nested_attributes(node.attributeInfo, state); 250 } 251 252 switch(node.astType) with(AstType) 253 { 254 case error: state.context.internal_error(node.loc, "Visiting error node"); 255 case abstract_node: state.context.internal_error(node.loc, "Visiting abstract node"); 256 257 case decl_alias: assert(false); 258 case decl_module: name_register_nested_module(cast(ModuleDeclNode*)node, state); break; 259 case decl_import: assert(false); 260 case decl_function: name_register_nested_func(nodeIndex, cast(FunctionDeclNode*)node, state); break; 261 case decl_var: name_register_nested_var(nodeIndex, cast(VariableDeclNode*)node, state); break; 262 case decl_struct: name_register_nested_struct(nodeIndex, cast(StructDeclNode*)node, state); break; 263 case decl_enum: name_register_nested_enum(nodeIndex, cast(EnumDeclaration*)node, state); break; 264 case decl_enum_member: name_register_nested_enum_member(nodeIndex, cast(EnumMemberDecl*)node, state); break; 265 case decl_static_assert: name_register_nested_static_assert(cast(StaticAssertDeclNode*)node, state); break; 266 case decl_static_if: assert(false); 267 case decl_static_version: assert(false); 268 269 case stmt_block: name_register_nested_block(cast(BlockStmtNode*)node, state); break; 270 case stmt_if: name_register_nested_if(cast(IfStmtNode*)node, state); break; 271 case stmt_while: name_register_nested_while(cast(WhileStmtNode*)node, state); break; 272 case stmt_do_while: name_register_nested_do(cast(DoWhileStmtNode*)node, state); break; 273 case stmt_for: name_register_nested_for(cast(ForStmtNode*)node, state); break; 274 case stmt_switch: name_register_nested_switch(cast(SwitchStmtNode*)node, state); break; 275 case stmt_return: assert(false); 276 case stmt_break: assert(false); 277 case stmt_continue: assert(false); 278 279 case expr_name_use: assert(false); 280 case expr_member: name_register_nested_member(cast(MemberExprNode*)node, state); break; 281 case expr_bin_op: name_register_nested_binary_op(cast(BinaryExprNode*)node, state); break; 282 case expr_un_op: name_register_nested_unary_op(cast(UnaryExprNode*)node, state); break; 283 case expr_call: name_register_nested_call(cast(CallExprNode*)node, state); break; 284 case expr_named_argument: name_register_nested_named_argument(cast(NamedArgumenExprNode*)node, state); break; 285 case expr_index: name_register_nested_index(cast(IndexExprNode*)node, state); break; 286 case expr_slice: name_register_nested_expr_slice(cast(SliceExprNode*)node, state); break; 287 case expr_type_conv: name_register_nested_type_conv(cast(TypeConvExprNode*)node, state); break; 288 289 case literal_int: assert(false); 290 case literal_float: assert(false); 291 case literal_string: assert(false); 292 case literal_null: assert(false); 293 case literal_bool: assert(false); 294 case literal_array: assert(false); 295 296 case type_basic: assert(false); 297 case type_func_sig: name_register_nested_func_sig(cast(FunctionSignatureNode*)node, state); break; 298 case type_ptr: name_register_nested_ptr(cast(PtrTypeNode*)node, state); break; 299 case type_static_array: name_register_nested_static_array(cast(StaticArrayTypeNode*)node, state); break; 300 case type_slice: name_register_nested_slice(cast(SliceTypeNode*)node, state); break; 301 302 default: state.context.internal_error(node.loc, "Visiting %s node", node.astType); 303 } 304 } 305 306 struct NameRegisterState 307 { 308 CompilationContext* context; 309 310 // first #if or #foreach in a block 311 AstIndex firstCondDecl; 312 // last #if or #foreach in a block 313 AstIndex lastCondDecl; 314 }