| ... | @@ -74,7 +74,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool | ... | @@ -74,7 +74,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 74 | } | 74 | } |
| 75 | } | 75 | } |
| 76 | | 76 | |
| 77 | static void resolve_type(CodeGen *g, AstNode *node) { | 77 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 78 | assert(!node->codegen_node); | 78 | assert(!node->codegen_node); |
| 79 | node->codegen_node = allocate<CodeGenNode>(1); | 79 | node->codegen_node = allocate<CodeGenNode>(1); |
| 80 | TypeNode *type_node = &node->codegen_node->data.type_node; | 80 | TypeNode *type_node = &node->codegen_node->data.type_node; |
| ... | @@ -90,7 +90,7 @@ static void resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -90,7 +90,7 @@ static void resolve_type(CodeGen *g, AstNode *node) { |
| 90 | buf_sprintf("invalid type name: '%s'", buf_ptr(name))); | 90 | buf_sprintf("invalid type name: '%s'", buf_ptr(name))); |
| 91 | type_node->entry = g->builtin_types.entry_invalid; | 91 | type_node->entry = g->builtin_types.entry_invalid; |
| 92 | } | 92 | } |
| 93 | break; | 93 | return type_node->entry; |
| 94 | } | 94 | } |
| 95 | case AstNodeTypeTypePointer: | 95 | case AstNodeTypeTypePointer: |
| 96 | { | 96 | { |
| ... | @@ -101,12 +101,12 @@ static void resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -101,12 +101,12 @@ static void resolve_type(CodeGen *g, AstNode *node) { |
| 101 | buf_create_from_str("pointer to unreachable not allowed")); | 101 | buf_create_from_str("pointer to unreachable not allowed")); |
| 102 | } | 102 | } |
| 103 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const); | 103 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const); |
| 104 | break; | 104 | return type_node->entry; |
| 105 | } | 105 | } |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | | 108 | |
| 109 | static void resolve_function_proto(CodeGen *g, AstNode *node) { | 109 | static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { |
| 110 | assert(node->type == NodeTypeFnProto); | 110 | assert(node->type == NodeTypeFnProto); |
| 111 | | 111 | |
| 112 | for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) { | 112 | for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) { |
| ... | @@ -120,9 +120,11 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) { | ... | @@ -120,9 +120,11 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) { |
| 120 | AstNode *child = node->data.fn_proto.params.at(i); | 120 | AstNode *child = node->data.fn_proto.params.at(i); |
| 121 | assert(child->type == NodeTypeParamDecl); | 121 | assert(child->type == NodeTypeParamDecl); |
| 122 | | 122 | |
| 123 | // parameter names are not important here. | 123 | Buf *param_name = &child->data.param_decl.name; |
| 124 | | 124 | SymbolTableEntry *symbol_entry = allocate<SymbolTableEntry>(1); |
| 125 | resolve_type(g, child->data.param_decl.type); | 125 | symbol_entry->type_entry = resolve_type(g, child->data.param_decl.type); |
| | 126 | symbol_entry->param_index = i; |
| | 127 | fn_table_entry->symbol_table.put(param_name, symbol_entry); |
| 126 | } | 128 | } |
| 127 | | 129 | |
| 128 | resolve_type(g, node->data.fn_proto.return_type); | 130 | resolve_type(g, node->data.fn_proto.return_type); |
| ... | @@ -148,20 +150,26 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -148,20 +150,26 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 148 | assert(fn_decl->type == NodeTypeFnDecl); | 150 | assert(fn_decl->type == NodeTypeFnDecl); |
| 149 | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; | 151 | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; |
| 150 | bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub); | 152 | bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub); |
| 151 | resolve_function_proto(g, fn_proto); | | |
| 152 | Buf *name = &fn_proto->data.fn_proto.name; | | |
| 153 | | 153 | |
| 154 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); | 154 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 155 | fn_table_entry->proto_node = fn_proto; | 155 | fn_table_entry->proto_node = fn_proto; |
| 156 | fn_table_entry->is_extern = true; | 156 | fn_table_entry->is_extern = true; |
| 157 | fn_table_entry->calling_convention = LLVMCCallConv; | 157 | fn_table_entry->calling_convention = LLVMCCallConv; |
| 158 | fn_table_entry->import_entry = import; | 158 | fn_table_entry->import_entry = import; |
| | 159 | fn_table_entry->symbol_table.init(8); |
| | 160 | |
| | 161 | resolve_function_proto(g, fn_proto, fn_table_entry); |
| 159 | | 162 | |
| | 163 | Buf *name = &fn_proto->data.fn_proto.name; |
| 160 | g->fn_protos.append(fn_table_entry); | 164 | g->fn_protos.append(fn_table_entry); |
| 161 | import->fn_table.put(name, fn_table_entry); | 165 | import->fn_table.put(name, fn_table_entry); |
| 162 | if (is_pub) { | 166 | if (is_pub) { |
| 163 | g->fn_table.put(name, fn_table_entry); | 167 | g->fn_table.put(name, fn_table_entry); |
| 164 | } | 168 | } |
| | 169 | |
| | 170 | assert(!fn_proto->codegen_node); |
| | 171 | fn_proto->codegen_node = allocate<CodeGenNode>(1); |
| | 172 | fn_proto->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 165 | } | 173 | } |
| 166 | break; | 174 | break; |
| 167 | case NodeTypeFnDef: | 175 | case NodeTypeFnDef: |
| ... | @@ -198,6 +206,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -198,6 +206,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 198 | fn_table_entry->fn_def_node = node; | 206 | fn_table_entry->fn_def_node = node; |
| 199 | fn_table_entry->internal_linkage = is_internal; | 207 | fn_table_entry->internal_linkage = is_internal; |
| 200 | fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; | 208 | fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; |
| | 209 | fn_table_entry->symbol_table.init(8); |
| 201 | | 210 | |
| 202 | g->fn_protos.append(fn_table_entry); | 211 | g->fn_protos.append(fn_table_entry); |
| 203 | g->fn_defs.append(fn_table_entry); | 212 | g->fn_defs.append(fn_table_entry); |
| ... | @@ -207,7 +216,11 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -207,7 +216,11 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 207 | g->fn_table.put(proto_name, fn_table_entry); | 216 | g->fn_table.put(proto_name, fn_table_entry); |
| 208 | } | 217 | } |
| 209 | | 218 | |
| 210 | resolve_function_proto(g, proto_node); | 219 | resolve_function_proto(g, proto_node, fn_table_entry); |
| | 220 | |
| | 221 | assert(!proto_node->codegen_node); |
| | 222 | proto_node->codegen_node = allocate<CodeGenNode>(1); |
| | 223 | proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 211 | } | 224 | } |
| 212 | } | 225 | } |
| 213 | break; | 226 | break; |
| ... | @@ -289,6 +302,16 @@ static TypeTableEntry * get_return_type(BlockContext *context) { | ... | @@ -289,6 +302,16 @@ static TypeTableEntry * get_return_type(BlockContext *context) { |
| 289 | return return_type_node->codegen_node->data.type_node.entry; | 302 | return return_type_node->codegen_node->data.type_node.entry; |
| 290 | } | 303 | } |
| 291 | | 304 | |
| | 305 | static FnTableEntry *get_context_fn_entry(BlockContext *context) { |
| | 306 | AstNode *fn_def_node = context->root->node; |
| | 307 | assert(fn_def_node->type == NodeTypeFnDef); |
| | 308 | AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto; |
| | 309 | assert(fn_proto_node->type == NodeTypeFnProto); |
| | 310 | assert(fn_proto_node->codegen_node); |
| | 311 | assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry); |
| | 312 | return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; |
| | 313 | } |
| | 314 | |
| 292 | static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) { | 315 | static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) { |
| 293 | if (expected_type == nullptr) | 316 | if (expected_type == nullptr) |
| 294 | return; // anything will do | 317 | return; // anything will do |
| ... | @@ -482,9 +505,20 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -482,9 +505,20 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 482 | break; | 505 | break; |
| 483 | | 506 | |
| 484 | case NodeTypeSymbol: | 507 | case NodeTypeSymbol: |
| 485 | // look up symbol in symbol table | 508 | { |
| 486 | zig_panic("TODO analyze_expression symbol"); | 509 | Buf *symbol_name = &node->data.symbol; |
| 487 | | 510 | FnTableEntry *fn_table_entry = get_context_fn_entry(context); |
| | 511 | auto table_entry = fn_table_entry->symbol_table.maybe_get(symbol_name); |
| | 512 | if (table_entry) { |
| | 513 | SymbolTableEntry *symbol_entry = table_entry->value; |
| | 514 | return_type = symbol_entry->type_entry; |
| | 515 | } else { |
| | 516 | add_node_error(g, node, |
| | 517 | buf_sprintf("use of undeclared identifier '%s'", buf_ptr(symbol_name))); |
| | 518 | return_type = g->builtin_types.entry_invalid; |
| | 519 | } |
| | 520 | break; |
| | 521 | } |
| 488 | case NodeTypeCastExpr: | 522 | case NodeTypeCastExpr: |
| 489 | zig_panic("TODO analyze_expression cast expr"); | 523 | zig_panic("TODO analyze_expression cast expr"); |
| 490 | break; | 524 | break; |