| ... | @@ -28,6 +28,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -28,6 +28,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, |
| 28 | TypeTableEntry *expected_type, AstNode *node); | 28 | TypeTableEntry *expected_type, AstNode *node); |
| 29 | static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node); | 29 | static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node); |
| 30 | static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn); | 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 | static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node); | 32 | static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node); |
| 32 | static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node); | 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,15 +2221,28 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2220 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node); | 2221 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node); |
| 2221 | Buf *field_name = &node->data.field_access_expr.field_name; | 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 | if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && | 2226 | if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && |
| 2224 | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) | 2227 | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) |
| 2225 | { | 2228 | { |
| 2226 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? | 2229 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? |
| 2227 | struct_type : struct_type->data.pointer.child_type; | 2230 | struct_type : struct_type->data.pointer.child_type; |
| 2228 | | 2231 | |
| | 2232 | node->data.field_access_expr.bare_struct_type = bare_struct_type; |
| 2229 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name); | 2233 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name); |
| 2230 | if (node->data.field_access_expr.type_struct_field) { | 2234 | if (node->data.field_access_expr.type_struct_field) { |
| 2231 | return node->data.field_access_expr.type_struct_field->type_entry; | 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 | } else { | 2246 | } else { |
| 2233 | add_node_error(g, node, | 2247 | add_node_error(g, node, |
| 2234 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name))); | 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,6 +2265,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2251 | | 2265 | |
| 2252 | if (child_type->id == TypeTableEntryIdInvalid) { | 2266 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 2253 | return g->builtin_types.entry_invalid; | 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 | } else if (child_type->id == TypeTableEntryIdEnum) { | 2270 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 2255 | return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name); | 2271 | return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name); |
| 2256 | } else if (child_type->id == TypeTableEntryIdStruct) { | 2272 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| ... | @@ -4128,72 +4144,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import | ... | @@ -4128,72 +4144,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 4128 | } | 4144 | } |
| 4129 | | 4145 | |
| 4130 | if (fn_ref_expr->type == NodeTypeFieldAccessExpr) { | 4146 | if (fn_ref_expr->type == NodeTypeFieldAccessExpr) { |
| 4131 | fn_ref_expr->block_context = context; | 4147 | fn_ref_expr->data.field_access_expr.is_fn_call = true; |
| 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 | } | | |
| 4197 | } | 4148 | } |
| 4198 | | 4149 | |
| 4199 | TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr); | 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,9 +4158,62 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 4207 | | 4158 | |
| 4208 | if (const_val->ok) { | 4159 | if (const_val->ok) { |
| 4209 | if (invoke_type_entry->id == TypeTableEntryIdMetaType) { | 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 | } else if (invoke_type_entry->id == TypeTableEntryIdFn) { | 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 | } else { | 4217 | } else { |
| 4214 | add_node_error(g, fn_ref_expr, | 4218 | add_node_error(g, fn_ref_expr, |
| 4215 | buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); | 4219 | buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); |