Skip to content

Commit

Permalink
Changed '$T' polymorphs to always allow built-in auto conversions (eq…
Browse files Browse the repository at this point in the history
…uivalent to '$~T' in previous versions)
  • Loading branch information
IsaacShelton committed Feb 14, 2022
1 parent bad7b99 commit af5a5f6
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 56 deletions.
21 changes: 11 additions & 10 deletions include/AST/ast_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,15 @@ typedef struct {

// ---------------- ast_elem_polymorph_t ----------------
// Type element for a polymorphic type variable
#define DERIVE_ELEM_POLYMORPH struct { \
unsigned int id; \
source_t source; \
strong_cstr_t name; \
bool allow_auto_conversion; \
}

typedef struct {
unsigned int id;
source_t source;
strong_cstr_t name;
bool allow_auto_conversion;
DERIVE_ELEM_POLYMORPH;
} ast_elem_polymorph_t;

// ---------------- ast_elem_polycount_t ----------------
Expand All @@ -126,13 +130,10 @@ typedef struct {
// ---------------- ast_elem_polymorph_prereq_t ----------------
// Type element for a polymorphic type variable which only fits
// for structs that match the similarity prerequisite
// NOTE: Must overlap with 'ast_elem_polymorph_t'
// NOTE: Guaranteed to overlap with 'ast_elem_polymorph_t'
typedef struct {
unsigned int id;
source_t source;
strong_cstr_t name;
bool allow_auto_conversion;
// ----------------------------
DERIVE_ELEM_POLYMORPH;

strong_cstr_t similarity_prerequisite;
} ast_elem_polymorph_prereq_t;

Expand Down
2 changes: 1 addition & 1 deletion include/UTIL/ground.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ typedef struct {
} lenstr_t, strong_lenstr_t, weak_lenstr_t;

inline bool lenstreq(lenstr_t a, lenstr_t b){
return a.length == b.length ? memcmp(a.cstr, b.cstr, a.length) == 0 : false;
return a.length == b.length && memcmp(a.cstr, b.cstr, a.length) == 0;
}

inline int lenstrcmp(lenstr_t a, lenstr_t b){
Expand Down
4 changes: 4 additions & 0 deletions include/UTIL/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ extern "C" {
#endif
// ----------------------------------------------------------

// ---------------- memclone ----------------
// Clones a section of memory
void *memclone(void *memory, length_t bytes);

// ---------------- expand ----------------
// Expands an array if it won't be able hold new elements
void expand(void **inout_memory, length_t unit_size, length_t length, length_t *inout_capacity,
Expand Down
2 changes: 1 addition & 1 deletion src/DRVR/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ static successful_t config_read_adept_config_value(config_t *config, jsmnh_obj_c
// Since we are using binary file stream mode, don't rely on fprintf
time_t timestamp = time(NULL);
char timestamp_buffer[256];
sprintf(timestamp_buffer, "%zu", (uint64_t) timestamp);
sprintf(timestamp_buffer, "%zu", (size_t) timestamp);
fwrite(timestamp_buffer, 1, strlen(timestamp_buffer), f);

fwrite(buffer.content + last_update.end, 1, buffer.capacity - last_update.end, f);
Expand Down
4 changes: 2 additions & 2 deletions src/IRGEN/ir_gen_check_prereq.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static ast_elem_base_t *try_ast_elem_base(ast_elem_t *elem){

static errorcode_t ir_gen_check_prereq_number(ast_elem_t *concrete_elem, bool *out_meets){
ast_elem_base_t *base_elem = try_ast_elem_base(concrete_elem);
*out_meets = base_elem ? typename_builtin_type(base_elem->base) != BUILTIN_TYPE_NONE : false;
*out_meets = base_elem && typename_builtin_type(base_elem->base) != BUILTIN_TYPE_NONE;
return SUCCESS;
}

Expand All @@ -49,7 +49,7 @@ static errorcode_t ir_gen_check_prereq_pod(compiler_t *compiler, object_t *objec

static errorcode_t ir_gen_check_prereq_primitive(ast_elem_t *concrete_elem, bool *out_meets){
ast_elem_base_t *base_elem = try_ast_elem_base(concrete_elem);
*out_meets = base_elem ? typename_is_extended_builtin_type(base_elem->base) : false;
*out_meets = base_elem && typename_is_extended_builtin_type(base_elem->base);
return SUCCESS;
}

Expand Down
89 changes: 50 additions & 39 deletions src/IRGEN/ir_gen_polymorphable.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@
#include "UTIL/color.h"
#include "UTIL/ground.h"

static errorcode_t enforce_polymorph(
compiler_t *compiler,
object_t *object,
ast_poly_catalog_t *catalog,
ast_elem_polymorph_t *polymorph_elem,
ast_poly_catalog_type_t *type_var,
ast_type_t *concrete_replacement
){
if(type_var == NULL){
// No existing type variable was found, so add to it to the catalog
ast_poly_catalog_add_type(catalog, polymorph_elem->name, concrete_replacement);
return SUCCESS;
}

if(!ast_types_identical(concrete_replacement, &type_var->binding)){
// Allow built-in auto conversion regardless of 'polymorph_elem->allow_auto_conversion' flag from before v2.6

if(!is_allowed_builtin_auto_conversion(compiler, object, concrete_replacement, &type_var->binding)){
// Given arguments don't meet consistency requirements of type variables
return FAILURE;
}
}

return SUCCESS;
}

static errorcode_t enforce_prereq(
compiler_t *compiler,
object_t *object,
Expand Down Expand Up @@ -50,7 +76,7 @@ static errorcode_t enforce_prereq(
ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, prereq->name);

// Determine special allowed auto conversions
if(type_var ? is_allowed_builtin_auto_conversion(compiler, object, &type_var->binding, concrete_type) : false){
if(type_var && is_allowed_builtin_auto_conversion(compiler, object, &type_var->binding, concrete_type)){
return SUCCESS;
}
}
Expand Down Expand Up @@ -139,32 +165,24 @@ static errorcode_t ir_gen_polymorphable_elem_prereq(
}

if(enforce_prereq(compiler, object, polymorphic_type, concrete_type, catalog, index)) return FAILURE;

// DANGEROUS: Manually managed AST type with semi-ownership
// DANGEROUS: Potentially bad memory tricks
ast_type_t replacement;
replacement.elements_length = concrete_type->elements_length - index;
replacement.elements = malloc(sizeof(ast_elem_t*) * replacement.elements_length);
memcpy(replacement.elements, &concrete_type->elements[index], sizeof(ast_elem_t*) * replacement.elements_length);
replacement.source = replacement.elements[0]->source;

// DANGEROUS: AST type with semi-ownership
length_t replacement_length = concrete_type->elements_length - index;

ast_type_t replacement = (ast_type_t){
.elements = memclone((void*) &concrete_type->elements[index], sizeof(ast_elem_t*) * replacement_length),
.elements_length = replacement_length,
.source = concrete_type->elements[index]->source,
};

// Ensure consistency with catalog
ast_elem_polymorph_prereq_t *prereq = (ast_elem_polymorph_prereq_t*) polymorphic_type->elements[index];
ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, prereq->name);

if(type_var){
if(!ast_types_identical(&replacement, &type_var->binding)){
// Given arguments don't meet consistency requirements of type variables
free(replacement.elements);
return FAILURE;
}
} else {
// Add to catalog since it's not already present
ast_poly_catalog_add_type(catalog, prereq->name, &replacement);
}

// Ok since 'ast_elem_polymorph_t' is guaranteed to overlap with 'ast_elem_polymorph_t'
errorcode_t res = enforce_polymorph(compiler, object, catalog, (ast_elem_polymorph_t*) prereq, type_var, &replacement);
free(replacement.elements);
return SUCCESS;
return res;
}

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){
Expand Down Expand Up @@ -232,29 +250,22 @@ errorcode_t ir_gen_polymorphable(compiler_t *compiler, object_t *object, ast_typ
return ALT_FAILURE;
}

// DANGEROUS: Manually managed AST type with semi-ownership
// DANGEROUS: Potentially bad memory tricks
ast_type_t replacement;
replacement.elements_length = concrete_type->elements_length - i;
replacement.elements = malloc(sizeof(ast_elem_t*) * replacement.elements_length);
memcpy(replacement.elements, &concrete_type->elements[i], sizeof(ast_elem_t*) * replacement.elements_length);
replacement.source = replacement.elements[0]->source;
// DANGEROUS: AST type with semi-ownership
length_t replacement_length = concrete_type->elements_length - i;

ast_type_t replacement = (ast_type_t){
.elements = memclone(&concrete_type->elements[i], sizeof(ast_elem_t*) * replacement_length),
.elements_length = replacement_length,
.source = concrete_type->elements[i]->source,
};

// Ensure consistency with catalog
ast_elem_polymorph_t *polymorphic_elem = (ast_elem_polymorph_t*) polymorphic_type->elements[i];
ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, polymorphic_elem->name);

if(type_var){
if(!ast_types_identical(&replacement, &type_var->binding)){
if(!polymorphic_elem->allow_auto_conversion || !is_allowed_builtin_auto_conversion(compiler, object, &replacement, &type_var->binding)){
// Given arguments don't meet consistency requirements of type variables
free(replacement.elements);
return FAILURE;
}
}
} else {
// Add to catalog since it's not already present
ast_poly_catalog_add_type(catalog, polymorphic_elem->name, &replacement);
if(enforce_polymorph(compiler, object, catalog, polymorphic_elem, type_var, &replacement)){
free(replacement.elements);
return FAILURE;
}

i = concrete_type->elements_length - 1;
Expand Down
4 changes: 2 additions & 2 deletions src/PARSE/parse_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ errorcode_t parse_type(parse_ctx_t *ctx, ast_type_t *out_type){
// If polymorph tokens starts with tilde, then we allow auto conversion
if(name[0] == '~'){
allow_auto_conversion = true;
memmove(name, &name[1], strlen(name) /* - 1 + 1*/);
memmove(name, &name[1], strlen(name)); // (includes '\0')
}

if(tokens[*i].id == TOKEN_BIT_COMPLEMENT){
if(!ctx->allow_polymorphic_prereqs){
free(name);
Expand Down
4 changes: 4 additions & 0 deletions src/UTIL/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "UTIL/ground.h"
#include "UTIL/util.h"

void *memclone(void *memory, length_t bytes){
return memcpy(malloc(bytes), memory, bytes);
}

void expand(void **inout_memory, length_t unit_size, length_t length, length_t *inout_capacity, length_t amount, length_t default_capacity){
// Expands an array in memory to be able to fit more units

Expand Down
2 changes: 1 addition & 1 deletion todolists/2.6.todolist
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ LOW-PRIORITY:
#end
}
```
* fix issues with __assign__ auto-generation broken in b32ccdb5d397d645a0f4c65de0bfbc0eff38c61e
* make call to functions like `max($T, $T) $T` allow built-in auto conversions between primitives for arguments

v2.4 COMPLETED:
+ Standard Library Imports
Expand Down

0 comments on commit af5a5f6

Please sign in to comment.