|
16 | 16 | #include "UTIL/color.h" |
17 | 17 | #include "UTIL/ground.h" |
18 | 18 |
|
| 19 | +static errorcode_t enforce_polymorph( |
| 20 | + compiler_t *compiler, |
| 21 | + object_t *object, |
| 22 | + ast_poly_catalog_t *catalog, |
| 23 | + ast_elem_polymorph_t *polymorph_elem, |
| 24 | + ast_poly_catalog_type_t *type_var, |
| 25 | + ast_type_t *concrete_replacement |
| 26 | +){ |
| 27 | + if(type_var == NULL){ |
| 28 | + // No existing type variable was found, so add to it to the catalog |
| 29 | + ast_poly_catalog_add_type(catalog, polymorph_elem->name, concrete_replacement); |
| 30 | + return SUCCESS; |
| 31 | + } |
| 32 | + |
| 33 | + if(!ast_types_identical(concrete_replacement, &type_var->binding)){ |
| 34 | + // Allow built-in auto conversion regardless of 'polymorph_elem->allow_auto_conversion' flag from before v2.6 |
| 35 | + |
| 36 | + if(!is_allowed_builtin_auto_conversion(compiler, object, concrete_replacement, &type_var->binding)){ |
| 37 | + // Given arguments don't meet consistency requirements of type variables |
| 38 | + return FAILURE; |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + return SUCCESS; |
| 43 | +} |
| 44 | + |
19 | 45 | static errorcode_t enforce_prereq( |
20 | 46 | compiler_t *compiler, |
21 | 47 | object_t *object, |
@@ -50,7 +76,7 @@ static errorcode_t enforce_prereq( |
50 | 76 | ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, prereq->name); |
51 | 77 |
|
52 | 78 | // Determine special allowed auto conversions |
53 | | - if(type_var ? is_allowed_builtin_auto_conversion(compiler, object, &type_var->binding, concrete_type) : false){ |
| 79 | + if(type_var && is_allowed_builtin_auto_conversion(compiler, object, &type_var->binding, concrete_type)){ |
54 | 80 | return SUCCESS; |
55 | 81 | } |
56 | 82 | } |
@@ -139,32 +165,24 @@ static errorcode_t ir_gen_polymorphable_elem_prereq( |
139 | 165 | } |
140 | 166 |
|
141 | 167 | if(enforce_prereq(compiler, object, polymorphic_type, concrete_type, catalog, index)) return FAILURE; |
142 | | - |
143 | | - // DANGEROUS: Manually managed AST type with semi-ownership |
144 | | - // DANGEROUS: Potentially bad memory tricks |
145 | | - ast_type_t replacement; |
146 | | - replacement.elements_length = concrete_type->elements_length - index; |
147 | | - replacement.elements = malloc(sizeof(ast_elem_t*) * replacement.elements_length); |
148 | | - memcpy(replacement.elements, &concrete_type->elements[index], sizeof(ast_elem_t*) * replacement.elements_length); |
149 | | - replacement.source = replacement.elements[0]->source; |
| 168 | + |
| 169 | + // DANGEROUS: AST type with semi-ownership |
| 170 | + length_t replacement_length = concrete_type->elements_length - index; |
| 171 | + |
| 172 | + ast_type_t replacement = (ast_type_t){ |
| 173 | + .elements = memclone((void*) &concrete_type->elements[index], sizeof(ast_elem_t*) * replacement_length), |
| 174 | + .elements_length = replacement_length, |
| 175 | + .source = concrete_type->elements[index]->source, |
| 176 | + }; |
150 | 177 |
|
151 | 178 | // Ensure consistency with catalog |
152 | 179 | ast_elem_polymorph_prereq_t *prereq = (ast_elem_polymorph_prereq_t*) polymorphic_type->elements[index]; |
153 | 180 | ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, prereq->name); |
154 | 181 |
|
155 | | - if(type_var){ |
156 | | - if(!ast_types_identical(&replacement, &type_var->binding)){ |
157 | | - // Given arguments don't meet consistency requirements of type variables |
158 | | - free(replacement.elements); |
159 | | - return FAILURE; |
160 | | - } |
161 | | - } else { |
162 | | - // Add to catalog since it's not already present |
163 | | - ast_poly_catalog_add_type(catalog, prereq->name, &replacement); |
164 | | - } |
165 | | - |
| 182 | + // Ok since 'ast_elem_polymorph_t' is guaranteed to overlap with 'ast_elem_polymorph_t' |
| 183 | + errorcode_t res = enforce_polymorph(compiler, object, catalog, (ast_elem_polymorph_t*) prereq, type_var, &replacement); |
166 | 184 | free(replacement.elements); |
167 | | - return SUCCESS; |
| 185 | + return res; |
168 | 186 | } |
169 | 187 |
|
170 | 188 | errorcode_t ir_gen_polymorphable(compiler_t *compiler, object_t *object, ast_type_t *polymorphic_type, ast_type_t *concrete_type, ast_poly_catalog_t *catalog){ |
@@ -232,29 +250,22 @@ errorcode_t ir_gen_polymorphable(compiler_t *compiler, object_t *object, ast_typ |
232 | 250 | return ALT_FAILURE; |
233 | 251 | } |
234 | 252 |
|
235 | | - // DANGEROUS: Manually managed AST type with semi-ownership |
236 | | - // DANGEROUS: Potentially bad memory tricks |
237 | | - ast_type_t replacement; |
238 | | - replacement.elements_length = concrete_type->elements_length - i; |
239 | | - replacement.elements = malloc(sizeof(ast_elem_t*) * replacement.elements_length); |
240 | | - memcpy(replacement.elements, &concrete_type->elements[i], sizeof(ast_elem_t*) * replacement.elements_length); |
241 | | - replacement.source = replacement.elements[0]->source; |
| 253 | + // DANGEROUS: AST type with semi-ownership |
| 254 | + length_t replacement_length = concrete_type->elements_length - i; |
| 255 | + |
| 256 | + ast_type_t replacement = (ast_type_t){ |
| 257 | + .elements = memclone(&concrete_type->elements[i], sizeof(ast_elem_t*) * replacement_length), |
| 258 | + .elements_length = replacement_length, |
| 259 | + .source = concrete_type->elements[i]->source, |
| 260 | + }; |
242 | 261 |
|
243 | 262 | // Ensure consistency with catalog |
244 | 263 | ast_elem_polymorph_t *polymorphic_elem = (ast_elem_polymorph_t*) polymorphic_type->elements[i]; |
245 | 264 | ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, polymorphic_elem->name); |
246 | 265 |
|
247 | | - if(type_var){ |
248 | | - if(!ast_types_identical(&replacement, &type_var->binding)){ |
249 | | - if(!polymorphic_elem->allow_auto_conversion || !is_allowed_builtin_auto_conversion(compiler, object, &replacement, &type_var->binding)){ |
250 | | - // Given arguments don't meet consistency requirements of type variables |
251 | | - free(replacement.elements); |
252 | | - return FAILURE; |
253 | | - } |
254 | | - } |
255 | | - } else { |
256 | | - // Add to catalog since it's not already present |
257 | | - ast_poly_catalog_add_type(catalog, polymorphic_elem->name, &replacement); |
| 266 | + if(enforce_polymorph(compiler, object, catalog, polymorphic_elem, type_var, &replacement)){ |
| 267 | + free(replacement.elements); |
| 268 | + return FAILURE; |
258 | 269 | } |
259 | 270 |
|
260 | 271 | i = concrete_type->elements_length - 1; |
|
0 commit comments