| ... | ... | @@ -28,6 +28,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, |
| 28 | 28 | TypeTableEntry *expected_type, AstNode *node); |
| 29 | 29 | static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node); |
| 30 | 30 | static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn); |
| 31 | static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type); |
| 31 | 32 | static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node); |
| 32 | 33 | static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node); |
| 33 | 34 | |
| ... | ... | @@ -2220,15 +2221,28 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2220 | 2221 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node); |
| 2221 | 2222 | Buf *field_name = &node->data.field_access_expr.field_name; |
| 2222 | 2223 | |
| 2224 | bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call; |
| 2225 | |
| 2223 | 2226 | if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && |
| 2224 | 2227 | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) |
| 2225 | 2228 | { |
| 2226 | 2229 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? |
| 2227 | 2230 | struct_type : struct_type->data.pointer.child_type; |
| 2228 | 2231 | |
| 2232 | node->data.field_access_expr.bare_struct_type = bare_struct_type; |
| 2229 | 2233 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name); |
| 2230 | 2234 | if (node->data.field_access_expr.type_struct_field) { |
| 2231 | 2235 | return node->data.field_access_expr.type_struct_field->type_entry; |
| 2236 | } else if (wrapped_in_fn_call) { |
| 2237 | auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name); |
| 2238 | if (table_entry) { |
| 2239 | node->data.field_access_expr.is_member_fn = true; |
| 2240 | return resolve_expr_const_val_as_fn(g, node, table_entry->value); |
| 2241 | } else { |
| 2242 | add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'", |
| 2243 | buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); |
| 2244 | return g->builtin_types.entry_invalid; |
| 2245 | } |
| 2232 | 2246 | } else { |
| 2233 | 2247 | add_node_error(g, node, |
| 2234 | 2248 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name))); |
| ... | ... | @@ -2251,6 +2265,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2251 | 2265 | |
| 2252 | 2266 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 2253 | 2267 | return g->builtin_types.entry_invalid; |
| 2268 | } else if (wrapped_in_fn_call) { |
| 2269 | return resolve_expr_const_val_as_type(g, node, child_type); |
| 2254 | 2270 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 2255 | 2271 | return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name); |
| 2256 | 2272 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| ... | ... | @@ -4128,72 +4144,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 4128 | 4144 | } |
| 4129 | 4145 | |
| 4130 | 4146 | if (fn_ref_expr->type == NodeTypeFieldAccessExpr) { |
| 4131 | | fn_ref_expr->block_context = context; |
| 4132 | | AstNode *first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr; |
| 4133 | | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, first_param_expr); |
| 4134 | | Buf *name = &fn_ref_expr->data.field_access_expr.field_name; |
| 4135 | | if (struct_type->id == TypeTableEntryIdStruct || |
| 4136 | | (struct_type->id == TypeTableEntryIdPointer && |
| 4137 | | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) |
| 4138 | | { |
| 4139 | | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? |
| 4140 | | struct_type : struct_type->data.pointer.child_type; |
| 4141 | | |
| 4142 | | auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(name); |
| 4143 | | if (table_entry) { |
| 4144 | | return analyze_fn_call_raw(g, import, context, expected_type, node, |
| 4145 | | table_entry->value, bare_struct_type); |
| 4146 | | } else { |
| 4147 | | add_node_error(g, fn_ref_expr, |
| 4148 | | buf_sprintf("no function named '%s' in '%s'", |
| 4149 | | buf_ptr(name), buf_ptr(&bare_struct_type->name))); |
| 4150 | | return g->builtin_types.entry_invalid; |
| 4151 | | } |
| 4152 | | } else if (struct_type->id == TypeTableEntryIdInvalid) { |
| 4153 | | return struct_type; |
| 4154 | | } else if (struct_type->id == TypeTableEntryIdMetaType) { |
| 4155 | | TypeTableEntry *child_type = resolve_type(g, first_param_expr); |
| 4156 | | |
| 4157 | | if (child_type->id == TypeTableEntryIdInvalid) { |
| 4158 | | return g->builtin_types.entry_invalid; |
| 4159 | | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 4160 | | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; |
| 4161 | | int param_count = node->data.fn_call_expr.params.length; |
| 4162 | | if (param_count > 1) { |
| 4163 | | add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)), |
| 4164 | | buf_sprintf("enum values accept only one parameter")); |
| 4165 | | return child_type; |
| 4166 | | } else { |
| 4167 | | AstNode *value_node; |
| 4168 | | if (param_count == 1) { |
| 4169 | | value_node = node->data.fn_call_expr.params.at(0); |
| 4170 | | } else { |
| 4171 | | value_node = nullptr; |
| 4172 | | } |
| 4173 | | |
| 4174 | | return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node, |
| 4175 | | child_type, field_name); |
| 4176 | | } |
| 4177 | | } else if (child_type->id == TypeTableEntryIdStruct) { |
| 4178 | | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; |
| 4179 | | auto entry = child_type->data.structure.fn_table.maybe_get(field_name); |
| 4180 | | if (entry) { |
| 4181 | | return analyze_fn_call_raw(g, import, context, expected_type, node, |
| 4182 | | entry->value, nullptr); |
| 4183 | | } else { |
| 4184 | | add_node_error(g, node, |
| 4185 | | buf_sprintf("struct '%s' has no function called '%s'", |
| 4186 | | buf_ptr(&child_type->name), buf_ptr(field_name))); |
| 4187 | | return g->builtin_types.entry_invalid; |
| 4188 | | } |
| 4189 | | } else { |
| 4190 | | add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum")); |
| 4191 | | return g->builtin_types.entry_invalid; |
| 4192 | | } |
| 4193 | | } else { |
| 4194 | | add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum")); |
| 4195 | | return g->builtin_types.entry_invalid; |
| 4196 | | } |
| 4147 | fn_ref_expr->data.field_access_expr.is_fn_call = true; |
| 4197 | 4148 | } |
| 4198 | 4149 | |
| 4199 | 4150 | TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr); |
| ... | ... | @@ -4207,9 +4158,62 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 4207 | 4158 | |
| 4208 | 4159 | if (const_val->ok) { |
| 4209 | 4160 | if (invoke_type_entry->id == TypeTableEntryIdMetaType) { |
| 4210 | | return analyze_cast_expr(g, import, context, node); |
| 4161 | if (fn_ref_expr->type == NodeTypeFieldAccessExpr) { |
| 4162 | TypeTableEntry *child_type = resolve_type(g, fn_ref_expr); |
| 4163 | |
| 4164 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 4165 | return g->builtin_types.entry_invalid; |
| 4166 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 4167 | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; |
| 4168 | int param_count = node->data.fn_call_expr.params.length; |
| 4169 | if (param_count > 1) { |
| 4170 | add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)), |
| 4171 | buf_sprintf("enum values accept only one parameter")); |
| 4172 | return child_type; |
| 4173 | } else { |
| 4174 | AstNode *value_node; |
| 4175 | if (param_count == 1) { |
| 4176 | value_node = node->data.fn_call_expr.params.at(0); |
| 4177 | } else { |
| 4178 | value_node = nullptr; |
| 4179 | } |
| 4180 | |
| 4181 | node->data.fn_call_expr.enum_type = child_type; |
| 4182 | |
| 4183 | return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node, |
| 4184 | child_type, field_name); |
| 4185 | } |
| 4186 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| 4187 | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; |
| 4188 | auto entry = child_type->data.structure.fn_table.maybe_get(field_name); |
| 4189 | if (entry) { |
| 4190 | return analyze_fn_call_raw(g, import, context, expected_type, node, |
| 4191 | entry->value, nullptr); |
| 4192 | } else { |
| 4193 | add_node_error(g, node, |
| 4194 | buf_sprintf("struct '%s' has no function called '%s'", |
| 4195 | buf_ptr(&child_type->name), buf_ptr(field_name))); |
| 4196 | return g->builtin_types.entry_invalid; |
| 4197 | } |
| 4198 | } else { |
| 4199 | add_node_error(g, fn_ref_expr, buf_sprintf("member reference base type not struct or enum")); |
| 4200 | return g->builtin_types.entry_invalid; |
| 4201 | } |
| 4202 | } else { |
| 4203 | return analyze_cast_expr(g, import, context, node); |
| 4204 | } |
| 4211 | 4205 | } else if (invoke_type_entry->id == TypeTableEntryIdFn) { |
| 4212 | | return analyze_fn_call_raw(g, import, context, expected_type, node, const_val->data.x_fn, nullptr); |
| 4206 | TypeTableEntry *bare_struct_type; |
| 4207 | if (fn_ref_expr->type == NodeTypeFieldAccessExpr && |
| 4208 | fn_ref_expr->data.field_access_expr.is_member_fn) |
| 4209 | { |
| 4210 | bare_struct_type = fn_ref_expr->data.field_access_expr.bare_struct_type; |
| 4211 | } else { |
| 4212 | bare_struct_type = nullptr; |
| 4213 | } |
| 4214 | |
| 4215 | return analyze_fn_call_raw(g, import, context, expected_type, node, |
| 4216 | const_val->data.x_fn, bare_struct_type); |
| 4213 | 4217 | } else { |
| 4214 | 4218 | add_node_error(g, fn_ref_expr, |
| 4215 | 4219 | buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); |