Begin writing dynamic map procs and fix using bug in IR

This commit is contained in:
Ginger Bill
2017-02-05 23:52:01 +00:00
parent b1562edccf
commit 00c7489157
11 changed files with 630 additions and 320 deletions
+2 -17
View File
@@ -61,24 +61,9 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
// an extra allocation
Array(Operand) operands;
ArrayOperand operands = {0};
array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count);
// TODO(bill): Allow for type hints from the entities
for_array(i, inits) {
AstNode *rhs = inits.e[i];
Operand o = {0};
check_multi_expr(c, &o, rhs);
if (o.type == NULL || o.type->kind != Type_Tuple) {
array_add(&operands, o);
} else {
TypeTuple *tuple = &o.type->Tuple;
for (isize j = 0; j < tuple->variable_count; j++) {
o.type = tuple->variables[j]->type;
array_add(&operands, o);
}
}
}
check_unpack_arguments(c, &operands, inits);
isize rhs_count = operands.count;
for_array(i, operands) {
+133 -20
View File
@@ -252,7 +252,6 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
return;
}
if (is_type_untyped(operand->type)) {
Type *target_type = type;
if (type == NULL || is_type_any(type)) {
@@ -1094,6 +1093,15 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
return 0;
}
Type *make_map_tuple_type(gbAllocator a, Type *value) {
Type *t = make_type_tuple(a);
t->Tuple.variables = gb_alloc_array(a, Entity *, 2);
t->Tuple.variable_count = 2;
t->Tuple.variables[0] = make_entity_param(a, NULL, blank_token, value, false, false);
t->Tuple.variables[1] = make_entity_param(a, NULL, blank_token, t_bool, false, false);
return t;
}
void check_map_type(Checker *c, Type *type, AstNode *node) {
GB_ASSERT(type->kind == Type_Map);
ast_node(mt, MapType, node);
@@ -1121,6 +1129,75 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
type->Map.key = key;
type->Map.value = value;
gbAllocator a = c->allocator;
{
Type *entry_type = make_type_struct(a);
/*
struct {
hash: u64,
next: int,
key: Key_Type,
value: Value_Type,
}
*/
AstNode *dummy_node = gb_alloc_item(a, AstNode);
dummy_node->kind = AstNode_Invalid;
check_open_scope(c, dummy_node);
isize field_count = 4;
Entity **fields = gb_alloc_array(a, Entity *, field_count);
fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("hash")), t_u64, false, false);
fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, false);
fields[2] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), key, false, false);
fields[3] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, false);
check_close_scope(c);
entry_type->Record.fields = fields;
entry_type->Record.fields_in_src_order = fields;
entry_type->Record.field_count = field_count;
type_set_offsets(c->sizes, a, entry_type);
type->Map.entry_type = entry_type;
}
{
Type *generated_struct_type = make_type_struct(a);
/*
struct {
hashes: [dynamic]int,
entries; [dynamic]Entry_Type,
}
*/
AstNode *dummy_node = gb_alloc_item(a, AstNode);
dummy_node->kind = AstNode_Invalid;
check_open_scope(c, dummy_node);
Type *hashes_type = make_type_dynamic_array(a, t_int);
Type *entries_type = make_type_dynamic_array(a, type->Map.entry_type);
isize field_count = 2;
Entity **fields = gb_alloc_array(a, Entity *, field_count);
fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("hashes")), hashes_type, false, false);
fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("entries")), entries_type, false, false);
check_close_scope(c);
generated_struct_type->Record.fields = fields;
generated_struct_type->Record.fields_in_src_order = fields;
generated_struct_type->Record.field_count = field_count;
type_set_offsets(c->sizes, a, generated_struct_type);
type->Map.generated_struct_type = generated_struct_type;
}
type->Map.lookup_result_type = make_map_tuple_type(a, value);
// error_node(node, "`map` types are not yet implemented");
}
@@ -3335,14 +3412,26 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
operand->mode = Addressing_Value;
} break;
case BuiltinProc_slice_to_bytes: {
// slice_to_bytes :: proc(a: []T) -> []byte
Type *slice_type = base_type(operand->type);
if (!is_type_slice(slice_type)) {
gbString type_str = type_to_string(operand->type);
error_node(call, "Expected a slice type, got `%s`", type_str);
gb_string_free(type_str);
return false;
}
operand->type = t_byte_slice;
operand->mode = Addressing_Value;
} break;
case BuiltinProc_min: {
// min :: proc(a, b: comparable) -> comparable
Type *type = base_type(operand->type);
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
gbString type_str = type_to_string(operand->type);
error_node(call,
"Expected a comparable numeric type to `min`, got `%s`",
type_str);
error_node(call, "Expected a comparable numeric type to `min`, got `%s`", type_str);
gb_string_free(type_str);
return false;
}
@@ -3730,28 +3819,39 @@ int valid_proc_and_score_cmp(void const *a, void const *b) {
return sj < si ? -1 : sj > si;
}
typedef Array(Operand) ArrayOperand;
void check_unpack_arguments(Checker *c, ArrayOperand *operands, AstNodeArray args) {
for_array(i, args) {
Operand o = {0};
check_multi_expr(c, &o, args.e[i]);
if (o.mode == Addressing_MapIndex) {
Type *tuple_type = make_map_tuple_type(c->allocator, o.type);
add_type_and_value(&c->info, o.expr, o.mode, tuple_type, (ExactValue){0});
o.type = tuple_type;
}
if (o.type == NULL || o.type->kind != Type_Tuple) {
array_add(operands, o);
} else {
TypeTuple *tuple = &o.type->Tuple;
for (isize j = 0; j < tuple->variable_count; j++) {
o.type = tuple->variables[j]->type;
array_add(operands, o);
}
}
}
}
Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
GB_ASSERT(call->kind == AstNode_CallExpr);
ast_node(ce, CallExpr, call);
Array(Operand) operands;
ArrayOperand operands;
array_init_reserve(&operands, heap_allocator(), 2*ce->args.count);
for_array(i, ce->args) {
Operand o = {0};
check_multi_expr(c, &o, ce->args.e[i]);
if (o.type == NULL || o.type->kind != Type_Tuple) {
array_add(&operands, o);
} else {
TypeTuple *tuple = &o.type->Tuple;
for (isize j = 0; j < tuple->variable_count; j++) {
o.type = tuple->variables[j]->type;
array_add(&operands, o);
}
}
}
check_unpack_arguments(c, &operands, ce->args);
if (operand->mode == Addressing_Overload) {
GB_ASSERT(operand->overload_entities != NULL &&
@@ -4886,6 +4986,19 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
Type *t = base_type(type_deref(o->type));
bool is_const = o->mode == Addressing_Constant;
if (is_type_map(t)) {
Operand key = {0};
check_expr(c, &key, ie->index);
check_assignment(c, &key, t->Map.key, str_lit("map index"));
if (key.mode == Addressing_Invalid) {
goto error;
}
o->mode = Addressing_MapIndex;
o->type = t->Map.value;
o->expr = node;
return Expr_Expr;
}
i64 max_count = -1;
bool valid = check_set_index_data(o, t, &max_count);
+8
View File
@@ -261,12 +261,20 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
return NULL;
case Addressing_Variable:
break;
case Addressing_MapIndex:
break;
default: {
if (op_b.expr->kind == AstNode_SelectorExpr) {
// NOTE(bill): Extra error checks
Operand op_c = {Addressing_Invalid};
ast_node(se, SelectorExpr, op_b.expr);
check_expr(c, &op_c, se->expr);
if (op_c.mode == Addressing_MapIndex) {
gbString str = expr_to_string(op_b.expr);
error_node(op_b.expr, "Cannot assign to record field `%s` in map", str);
gb_string_free(str);
return NULL;
}
}
gbString str = expr_to_string(op_b.expr);
+4
View File
@@ -54,6 +54,7 @@ typedef enum BuiltinProcId {
// BuiltinProc_ptr_offset,
// BuiltinProc_ptr_sub,
BuiltinProc_slice_ptr,
BuiltinProc_slice_to_bytes,
BuiltinProc_min,
BuiltinProc_max,
@@ -96,6 +97,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
// {STR_LIT("ptr_offset"), 2, false, Expr_Expr},
// {STR_LIT("ptr_sub"), 2, false, Expr_Expr},
{STR_LIT("slice_ptr"), 2, false, Expr_Expr},
{STR_LIT("slice_to_bytes"), 1, false, Expr_Stmt},
{STR_LIT("min"), 2, false, Expr_Expr},
{STR_LIT("max"), 2, false, Expr_Expr},
@@ -115,6 +117,7 @@ typedef enum AddressingMode {
Addressing_Type,
Addressing_Builtin,
Addressing_Overload,
Addressing_MapIndex,
Addressing_Count,
} AddressingMode;
@@ -631,6 +634,7 @@ void init_universal_scope(BuildContext *bc) {
t_int_ptr = make_type_pointer(a, t_int);
t_i64_ptr = make_type_pointer(a, t_i64);
t_f64_ptr = make_type_pointer(a, t_f64);
t_byte_slice = make_type_slice(a, t_byte);
}
+242 -157
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -258,7 +258,7 @@ void ir_opt_blocks(irProcedure *proc) {
if (b == NULL) {
continue;
}
GB_ASSERT(b->index == i);
GB_ASSERT_MSG(b->index == i, "%d, %td", b->index, i);
if (ir_opt_block_fusion(proc, b)) {
changed = true;
@@ -467,7 +467,7 @@ void ir_opt_tree(irGen *s) {
}
ir_opt_blocks(proc);
#if 1
#if 0
ir_opt_build_referrers(proc);
ir_opt_build_dom_tree(proc);
+2 -9
View File
@@ -294,15 +294,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
} return;
case Type_Map: {
if (t->Map.count > 0) {
// ir_fprintf(f, "void");
} else {
ir_fprintf(f, "{");
ir_print_type(f, m, t_raw_dynamic_array);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_raw_dynamic_array);
ir_fprintf(f, "}");
}
GB_ASSERT(t->Map.generated_struct_type != NULL);
ir_print_type(f, m, t->Map.generated_struct_type);
} break;
}
}
+4
View File
@@ -128,6 +128,9 @@ typedef struct TypeRecord {
i64 count; /* 0 if dynamic */ \
Type *key; \
Type *value; \
Type *entry_type; \
Type *generated_struct_type; \
Type *lookup_result_type; \
}) \
@@ -269,6 +272,7 @@ gb_global Type *t_u8_ptr = NULL;
gb_global Type *t_int_ptr = NULL;
gb_global Type *t_i64_ptr = NULL;
gb_global Type *t_f64_ptr = NULL;
gb_global Type *t_byte_slice = NULL;
gb_global Type *t_type_info = NULL;