mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 05:08:14 +00:00
Disable struct field reordering (for the time being)
This commit is contained in:
+4
-8
@@ -234,7 +234,6 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
|
|
||||||
case Type_Info_Array:
|
case Type_Info_Array:
|
||||||
write_string(buf, "[");
|
write_string(buf, "[");
|
||||||
fi := Fmt_Info{buf = buf};
|
|
||||||
write_i64(buf, i64(info.count), 10);
|
write_i64(buf, i64(info.count), 10);
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
@@ -313,8 +312,6 @@ _parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := 0;
|
result := 0;
|
||||||
ok := true;
|
|
||||||
|
|
||||||
i := 0;
|
i := 0;
|
||||||
for i < len(s[offset..]) {
|
for i < len(s[offset..]) {
|
||||||
c := rune(s[offset+i]);
|
c := rune(s[offset+i]);
|
||||||
@@ -855,11 +852,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
write_byte(fi.buf, '{');
|
write_byte(fi.buf, '{');
|
||||||
defer write_byte(fi.buf, '}');
|
defer write_byte(fi.buf, '}');
|
||||||
|
|
||||||
hash := fi.hash; defer fi.hash = hash;
|
fi.indent += 1; defer fi.indent -= 1;
|
||||||
indent := fi.indent; defer fi.indent -= 1;
|
hash := fi.hash; defer fi.hash = hash;
|
||||||
|
|
||||||
fi.hash = false;
|
fi.hash = false;
|
||||||
fi.indent += 1;
|
|
||||||
|
|
||||||
if hash do write_byte(fi.buf, '\n');
|
if hash do write_byte(fi.buf, '\n');
|
||||||
|
|
||||||
@@ -1016,7 +1012,7 @@ sbprintln :: proc(buf: ^String_Buffer, args: ...any) -> string {
|
|||||||
fi: Fmt_Info;
|
fi: Fmt_Info;
|
||||||
fi.buf = buf;
|
fi.buf = buf;
|
||||||
|
|
||||||
for arg, i in args {
|
for _, i in args {
|
||||||
if i > 0 do write_byte(buf, ' ');
|
if i > 0 do write_byte(buf, ' ');
|
||||||
|
|
||||||
fmt_value(&fi, args[i], 'v');
|
fmt_value(&fi, args[i], 'v');
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ
|
|||||||
}
|
}
|
||||||
defer close(fd);
|
defer close(fd);
|
||||||
|
|
||||||
bytes_written, write_err := write(fd, data);
|
_, write_err := write(fd, data);
|
||||||
return write_err == 0;
|
return write_err == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
|
|
||||||
case Type_Info_Pointer:
|
case Type_Info_Pointer:
|
||||||
y, ok := b.variant.(Type_Info_Pointer);
|
y, ok := b.variant.(Type_Info_Pointer);
|
||||||
|
if !ok do return false;
|
||||||
return are_types_identical(x.elem, y.elem);
|
return are_types_identical(x.elem, y.elem);
|
||||||
|
|
||||||
case Type_Info_Procedure:
|
case Type_Info_Procedure:
|
||||||
|
|||||||
+10
-14
@@ -30,25 +30,23 @@ encode_surrogate_pair :: proc(r: rune) -> (r1, r2: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encode :: proc(d: []u16, s: []rune) -> int {
|
encode :: proc(d: []u16, s: []rune) -> int {
|
||||||
n := len(s);
|
n, m := 0, len(d);
|
||||||
for r in s do if r >= _surr_self do n += 1;
|
loop: for r in s {
|
||||||
|
|
||||||
max_n := min(len(d), n);
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
for r in s {
|
|
||||||
switch r {
|
switch r {
|
||||||
case 0.._surr1, _surr3 .. _surr_self:
|
case 0.._surr1, _surr3 .. _surr_self:
|
||||||
|
if m+1 < n do break loop;
|
||||||
d[n] = u16(r);
|
d[n] = u16(r);
|
||||||
n += 1;
|
n += 1;
|
||||||
|
|
||||||
case _surr_self .. MAX_RUNE:
|
case _surr_self .. MAX_RUNE:
|
||||||
|
if m+2 < n do break loop;
|
||||||
r1, r2 := encode_surrogate_pair(r);
|
r1, r2 := encode_surrogate_pair(r);
|
||||||
d[n] = u16(r1);
|
d[n] = u16(r1);
|
||||||
d[n+1] = u16(r2);
|
d[n+1] = u16(r2);
|
||||||
n += 2;
|
n += 2;
|
||||||
|
|
||||||
case:
|
case:
|
||||||
|
if m+1 < n do break loop;
|
||||||
d[n] = u16(REPLACEMENT_CHAR);
|
d[n] = u16(REPLACEMENT_CHAR);
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
@@ -58,25 +56,23 @@ encode :: proc(d: []u16, s: []rune) -> int {
|
|||||||
|
|
||||||
|
|
||||||
encode_string :: proc(d: []u16, s: string) -> int {
|
encode_string :: proc(d: []u16, s: string) -> int {
|
||||||
n := utf8.rune_count_from_string(s);
|
n, m := 0, len(d);
|
||||||
for r in s do if r >= _surr_self do n += 1;
|
loop: for r in s {
|
||||||
|
|
||||||
max_n := min(len(d), n);
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
for r in s {
|
|
||||||
switch r {
|
switch r {
|
||||||
case 0.._surr1, _surr3 .. _surr_self:
|
case 0.._surr1, _surr3 .. _surr_self:
|
||||||
|
if m+1 < n do break loop;
|
||||||
d[n] = u16(r);
|
d[n] = u16(r);
|
||||||
n += 1;
|
n += 1;
|
||||||
|
|
||||||
case _surr_self .. MAX_RUNE:
|
case _surr_self .. MAX_RUNE:
|
||||||
|
if m+2 < n do break loop;
|
||||||
r1, r2 := encode_surrogate_pair(r);
|
r1, r2 := encode_surrogate_pair(r);
|
||||||
d[n] = u16(r1);
|
d[n] = u16(r1);
|
||||||
d[n+1] = u16(r2);
|
d[n+1] = u16(r2);
|
||||||
n += 2;
|
n += 2;
|
||||||
|
|
||||||
case:
|
case:
|
||||||
|
if m+1 < n do break loop;
|
||||||
d[n] = u16(REPLACEMENT_CHAR);
|
d[n] = u16(REPLACEMENT_CHAR);
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-8
@@ -265,7 +265,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): Check to see if the expression it to be aliases
|
// NOTE(bill): Check to see if the expression it to be aliases
|
||||||
#if 1
|
|
||||||
case Addressing_Builtin:
|
case Addressing_Builtin:
|
||||||
if (e->type != nullptr) {
|
if (e->type != nullptr) {
|
||||||
error(type_expr, "A constant alias of a built-in procedure may not have a type initializer");
|
error(type_expr, "A constant alias of a built-in procedure may not have a type initializer");
|
||||||
@@ -275,18 +274,16 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Addressing_ProcGroup: {
|
case Addressing_ProcGroup:
|
||||||
GB_ASSERT(operand.proc_group != nullptr);
|
GB_ASSERT(operand.proc_group != nullptr);
|
||||||
GB_ASSERT(operand.proc_group->kind == Entity_ProcGroup);
|
GB_ASSERT(operand.proc_group->kind == Entity_ProcGroup);
|
||||||
|
|
||||||
e->kind = Entity_ProcGroup;
|
e->kind = Entity_ProcGroup;
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
gb_memcopy(&e->ProcGroup, &operand.proc_group->ProcGroup, gb_size_of(e->ProcGroup));
|
gb_memmove(&e->ProcGroup, &operand.proc_group->ProcGroup, gb_size_of(e->ProcGroup));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
if (entity != nullptr) {
|
if (entity != nullptr) {
|
||||||
switch (entity->kind) {
|
switch (entity->kind) {
|
||||||
case Entity_Alias:
|
case Entity_Alias:
|
||||||
@@ -316,7 +313,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init != nullptr) {
|
if (init != nullptr) {
|
||||||
@@ -858,7 +854,6 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
|||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
check_proc_decl(c, e, d);
|
check_proc_decl(c, e, d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Entity_ProcGroup:
|
case Entity_ProcGroup:
|
||||||
check_proc_group_decl(c, e, d);
|
check_proc_group_decl(c, e, d);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+2
-4
@@ -267,6 +267,8 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb_mutex_lock(&c->mutex);
|
||||||
|
defer (gb_mutex_unlock(&c->mutex));
|
||||||
|
|
||||||
auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
|
auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
|
||||||
if (found_gen_procs) {
|
if (found_gen_procs) {
|
||||||
@@ -553,7 +555,6 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
if (is_type_array(dst)) {
|
if (is_type_array(dst)) {
|
||||||
Type *elem = base_array_type(dst);
|
Type *elem = base_array_type(dst);
|
||||||
i64 distance = check_distance_between_types(c, operand, elem);
|
i64 distance = check_distance_between_types(c, operand, elem);
|
||||||
@@ -561,7 +562,6 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
return distance + 6;
|
return distance + 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (is_type_any(dst)) {
|
if (is_type_any(dst)) {
|
||||||
if (!is_type_polymorphic(src)) {
|
if (!is_type_polymorphic(src)) {
|
||||||
@@ -2235,7 +2235,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
Type *elem = base_array_type(t);
|
Type *elem = base_array_type(t);
|
||||||
if (check_is_assignable_to(c, operand, elem)) {
|
if (check_is_assignable_to(c, operand, elem)) {
|
||||||
@@ -2248,7 +2247,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
case Type_Union:
|
case Type_Union:
|
||||||
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
|
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
|
||||||
|
|||||||
@@ -1682,6 +1682,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
|
Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
|
||||||
isize entity_count = 0;
|
isize entity_count = 0;
|
||||||
|
|
||||||
|
isize new_name_count = 0;
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names[i];
|
AstNode *name = vd->names[i];
|
||||||
Entity *entity = nullptr;
|
Entity *entity = nullptr;
|
||||||
@@ -1694,6 +1695,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
// NOTE(bill): Ignore assignments to '_'
|
// NOTE(bill): Ignore assignments to '_'
|
||||||
if (!is_blank_ident(str)) {
|
if (!is_blank_ident(str)) {
|
||||||
found = current_scope_lookup_entity(c->context.scope, str);
|
found = current_scope_lookup_entity(c->context.scope, str);
|
||||||
|
new_name_count += 1;
|
||||||
}
|
}
|
||||||
if (found == nullptr) {
|
if (found == nullptr) {
|
||||||
entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
|
entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
|
||||||
@@ -1721,6 +1723,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
entities[entity_count++] = entity;
|
entities[entity_count++] = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_name_count == 0) {
|
||||||
|
error(node, "No new declarations on the lhs");
|
||||||
|
}
|
||||||
|
|
||||||
Type *init_type = nullptr;
|
Type *init_type = nullptr;
|
||||||
if (vd->type != nullptr) {
|
if (vd->type != nullptr) {
|
||||||
init_type = check_type(c, vd->type, nullptr);
|
init_type = check_type(c, vd->type, nullptr);
|
||||||
|
|||||||
+12
-202
@@ -34,198 +34,6 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map<Entity *>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_struct_field_decl(Checker *c, AstNode *decl, Array<Entity *> *fields, Map<Entity *> *entity_map, AstNode *struct_node, String context, bool allow_default_values) {
|
|
||||||
GB_ASSERT(fields != nullptr);
|
|
||||||
if (decl->kind == AstNode_WhenStmt) {
|
|
||||||
ast_node(ws, WhenStmt, decl);
|
|
||||||
Operand operand = {Addressing_Invalid};
|
|
||||||
check_expr(c, &operand, ws->cond);
|
|
||||||
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
|
|
||||||
error(ws->cond, "Non-constant boolean 'when' condition");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
|
|
||||||
error(ws->cond, "Invalid body for 'when' statement");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (operand.value.kind == ExactValue_Bool &&
|
|
||||||
operand.value.value_bool) {
|
|
||||||
for_array(i, ws->body->BlockStmt.stmts) {
|
|
||||||
AstNode *stmt = ws->body->BlockStmt.stmts[i];
|
|
||||||
check_struct_field_decl(c, stmt, fields, entity_map, struct_node, context, allow_default_values);
|
|
||||||
}
|
|
||||||
} else if (ws->else_stmt) {
|
|
||||||
switch (ws->else_stmt->kind) {
|
|
||||||
case AstNode_BlockStmt:
|
|
||||||
for_array(i, ws->else_stmt->BlockStmt.stmts) {
|
|
||||||
AstNode *stmt = ws->else_stmt->BlockStmt.stmts[i];
|
|
||||||
check_struct_field_decl(c, stmt, fields, entity_map, struct_node, context, allow_default_values);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AstNode_WhenStmt:
|
|
||||||
check_struct_field_decl(c, ws->else_stmt, fields, entity_map, struct_node, context, allow_default_values);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decl->kind != AstNode_ValueDecl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ast_node(vd, ValueDecl, decl);
|
|
||||||
|
|
||||||
if (!vd->is_mutable) return;
|
|
||||||
|
|
||||||
bool is_using = vd->is_using;
|
|
||||||
|
|
||||||
if (is_using && vd->names.count > 1) {
|
|
||||||
error(vd->names[0], "Cannot apply 'using' to more than one of the same type");
|
|
||||||
is_using = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool arity_ok = check_arity_match(c, vd);
|
|
||||||
|
|
||||||
if (vd->values.count > 0 && !allow_default_values) {
|
|
||||||
error(vd->values[0], "Default values are not allowed within a %.*s", LIT(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Type *type = nullptr;
|
|
||||||
if (vd->type != nullptr) {
|
|
||||||
type = check_type(c, vd->type);
|
|
||||||
} else if (!allow_default_values) {
|
|
||||||
error(vd->names[0], "Expected a type for this field");
|
|
||||||
type = t_invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type != nullptr) {
|
|
||||||
if (is_type_empty_union(type)) {
|
|
||||||
error(vd->names[0], "An empty union cannot be used as a field type in %.*s", LIT(context));
|
|
||||||
type = t_invalid;
|
|
||||||
}
|
|
||||||
if (!c->context.allow_polymorphic_types && is_type_polymorphic(base_type(type))) {
|
|
||||||
error(vd->names[0], "Invalid use of a polymorphic type in %.*s", LIT(context));
|
|
||||||
type = t_invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<Operand> default_values = {};
|
|
||||||
defer (array_free(&default_values));
|
|
||||||
if (vd->values.count > 0 && allow_default_values) {
|
|
||||||
array_init(&default_values, heap_allocator(), 2*vd->values.count);
|
|
||||||
|
|
||||||
Type *type_hint = nullptr;
|
|
||||||
if (type != t_invalid && type != nullptr) {
|
|
||||||
type_hint = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_array(i, vd->values) {
|
|
||||||
AstNode *v = vd->values[i];
|
|
||||||
Operand o = {};
|
|
||||||
|
|
||||||
check_expr_base(c, &o, v, type_hint);
|
|
||||||
check_not_tuple(c, &o);
|
|
||||||
|
|
||||||
if (o.mode == Addressing_NoValue) {
|
|
||||||
error_operand_no_value(&o);
|
|
||||||
} else {
|
|
||||||
if (o.mode == Addressing_Value && o.type->kind == Type_Tuple) {
|
|
||||||
// NOTE(bill): Tuples are not first class thus never named
|
|
||||||
for_array(index, o.type->Tuple.variables) {
|
|
||||||
Operand single = {Addressing_Value};
|
|
||||||
single.type = o.type->Tuple.variables[index]->type;
|
|
||||||
single.expr = v;
|
|
||||||
array_add(&default_values, single);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
array_add(&default_values, o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
isize name_field_index = 0;
|
|
||||||
for_array(name_index, vd->names) {
|
|
||||||
AstNode *name = vd->names[name_index];
|
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token name_token = name->Ident.token;
|
|
||||||
|
|
||||||
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, cast(i32)fields->count);
|
|
||||||
e->identifier = name;
|
|
||||||
|
|
||||||
if (name_field_index < default_values.count) {
|
|
||||||
Operand a = default_values[name_field_index];
|
|
||||||
Operand b = default_values[name_field_index];
|
|
||||||
check_init_variable(c, e, &b, str_lit("struct field assignment"));
|
|
||||||
if (is_operand_nil(a)) {
|
|
||||||
e->Variable.default_is_nil = true;
|
|
||||||
} else if (is_operand_undef(a)) {
|
|
||||||
e->Variable.default_is_undef = true;
|
|
||||||
} else if (b.mode != Addressing_Constant) {
|
|
||||||
error(b.expr, "Default field value must be a constant");
|
|
||||||
} else if (is_type_any(e->type) || is_type_union(e->type)) {
|
|
||||||
gbString str = type_to_string(e->type);
|
|
||||||
error(b.expr, "A struct field of type '%s' cannot have a default value", str);
|
|
||||||
gb_string_free(str);
|
|
||||||
} else {
|
|
||||||
e->Variable.default_value = b.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
name_field_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
GB_ASSERT(e->type != nullptr);
|
|
||||||
GB_ASSERT(is_type_typed(e->type));
|
|
||||||
|
|
||||||
if (is_blank_ident(name_token)) {
|
|
||||||
array_add(fields, e);
|
|
||||||
} else {
|
|
||||||
HashKey key = hash_string(name_token.string);
|
|
||||||
Entity **found = map_get(entity_map, key);
|
|
||||||
if (found != nullptr) {
|
|
||||||
Entity *e = *found;
|
|
||||||
// NOTE(bill): Scope checking already checks the declaration but in many cases, this can happen so why not?
|
|
||||||
// This may be a little janky but it's not really that much of a problem
|
|
||||||
error(name_token, "'%.*s' is already declared in this type", LIT(name_token.string));
|
|
||||||
error(e->token, "\tpreviously declared");
|
|
||||||
} else {
|
|
||||||
map_set(entity_map, key, e);
|
|
||||||
array_add(fields, e);
|
|
||||||
add_entity(c, c->context.scope, name, e);
|
|
||||||
}
|
|
||||||
add_entity_use(c, name, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (is_using && fields->count > 0) {
|
|
||||||
Type *first_type = (*fields)[fields->count-1]->type;
|
|
||||||
Type *t = base_type(type_deref(first_type));
|
|
||||||
if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) &&
|
|
||||||
vd->names.count >= 1 &&
|
|
||||||
vd->names[0]->kind == AstNode_Ident) {
|
|
||||||
Token name_token = vd->names[0]->Ident.token;
|
|
||||||
gbString type_str = type_to_string(first_type);
|
|
||||||
error(name_token, "'using' cannot be applied to the field '%.*s' of type '%s'", LIT(name_token.string), type_str);
|
|
||||||
gb_string_free(type_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
populate_using_entity_map(c, struct_node, type, entity_map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns filled field_count
|
// Returns filled field_count
|
||||||
Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *> params,
|
Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *> params,
|
||||||
isize init_field_capacity, Type *named_type, String context) {
|
isize init_field_capacity, Type *named_type, String context) {
|
||||||
@@ -301,6 +109,10 @@ Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *>
|
|||||||
|
|
||||||
type = default_type(o.type);
|
type = default_type(o.type);
|
||||||
} else {
|
} else {
|
||||||
|
if (type_expr->kind == AstNode_Ident && type_expr->Ident.token.string == "Element") {
|
||||||
|
gb_printf_err("Element\n");
|
||||||
|
}
|
||||||
|
|
||||||
type = check_type(c, type_expr);
|
type = check_type(c, type_expr);
|
||||||
|
|
||||||
if (default_value != nullptr) {
|
if (default_value != nullptr) {
|
||||||
@@ -398,11 +210,6 @@ Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for_array(decl_index, params) {
|
|
||||||
// check_struct_field_decl(c, params[decl_index], &fields, &entity_map, node, context, context == "struct");
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,8 +295,10 @@ bool check_custom_align(Checker *c, AstNode *node, i64 *align_) {
|
|||||||
|
|
||||||
|
|
||||||
Entity *find_polymorphic_struct_entity(Checker *c, Type *original_type, isize param_count, Array<Operand> ordered_operands) {
|
Entity *find_polymorphic_struct_entity(Checker *c, Type *original_type, isize param_count, Array<Operand> ordered_operands) {
|
||||||
auto *found_gen_types = map_get(&c->info.gen_types, hash_pointer(original_type));
|
gb_mutex_lock(&c->mutex);
|
||||||
|
defer (gb_mutex_unlock(&c->mutex));
|
||||||
|
|
||||||
|
auto *found_gen_types = map_get(&c->info.gen_types, hash_pointer(original_type));
|
||||||
if (found_gen_types != nullptr) {
|
if (found_gen_types != nullptr) {
|
||||||
for_array(i, *found_gen_types) {
|
for_array(i, *found_gen_types) {
|
||||||
Entity *e = (*found_gen_types)[i];
|
Entity *e = (*found_gen_types)[i];
|
||||||
@@ -761,12 +570,15 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO(bill): Move this to the appropriate place
|
||||||
if (!struct_type->Struct.is_raw_union) {
|
if (!struct_type->Struct.is_raw_union) {
|
||||||
type_set_offsets(c->allocator, struct_type);
|
type_set_offsets(c->allocator, struct_type);
|
||||||
|
|
||||||
if (!struct_type->failure && !st->is_packed && !st->is_ordered) {
|
if (!struct_type->failure && !st->is_packed && !st->is_ordered) {
|
||||||
struct_type->failure = false;
|
struct_type->failure = false;
|
||||||
struct_type->Struct.are_offsets_set = false;
|
struct_type->Struct.are_offsets_set = false;
|
||||||
|
struct_type->Struct.are_offsets_being_processed = false;
|
||||||
gb_zero_item(&struct_type->Struct.offsets);
|
gb_zero_item(&struct_type->Struct.offsets);
|
||||||
// NOTE(bill): Reorder fields for reduced size/performance
|
// NOTE(bill): Reorder fields for reduced size/performance
|
||||||
|
|
||||||
@@ -791,7 +603,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
|
|||||||
|
|
||||||
type_set_offsets(c->allocator, struct_type);
|
type_set_offsets(c->allocator, struct_type);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (st->align != nullptr) {
|
if (st->align != nullptr) {
|
||||||
if (st->is_packed) {
|
if (st->is_packed) {
|
||||||
@@ -2195,9 +2007,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pt, PointerType, e);
|
case_ast_node(pt, PointerType, e);
|
||||||
Type *elem = check_type(c, pt->type);
|
*type = make_type_pointer(c->allocator, check_type(c, pt->type));
|
||||||
i64 esz = type_size_of(c->allocator, elem);
|
|
||||||
*type = make_type_pointer(c->allocator, elem);
|
|
||||||
return true;
|
return true;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+36
-1
@@ -464,6 +464,7 @@ struct CheckerInfo {
|
|||||||
struct Checker {
|
struct Checker {
|
||||||
Parser * parser;
|
Parser * parser;
|
||||||
CheckerInfo info;
|
CheckerInfo info;
|
||||||
|
gbMutex mutex;
|
||||||
|
|
||||||
AstFile * curr_ast_file;
|
AstFile * curr_ast_file;
|
||||||
Scope * global_scope;
|
Scope * global_scope;
|
||||||
@@ -792,8 +793,40 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GB_COMPARE_PROC(entity_variable_pos_cmp) {
|
||||||
|
Entity *x = *cast(Entity **)a;
|
||||||
|
Entity *y = *cast(Entity **)b;
|
||||||
|
|
||||||
|
return token_pos_cmp(x->token.pos, y->token.pos);
|
||||||
|
}
|
||||||
|
|
||||||
void check_scope_usage(Checker *c, Scope *scope) {
|
void check_scope_usage(Checker *c, Scope *scope) {
|
||||||
// TODO(bill): Use this?
|
// TODO(bill): Use this?
|
||||||
|
Array<Entity *> unused = {};
|
||||||
|
array_init(&unused, heap_allocator());
|
||||||
|
defer (array_free(&unused));
|
||||||
|
|
||||||
|
for_array(i, scope->elements.entries) {
|
||||||
|
Entity *e = scope->elements.entries[i].value;
|
||||||
|
if (e != nullptr && e->kind == Entity_Variable && (e->flags&EntityFlag_Used) == 0) {
|
||||||
|
array_add(&unused, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_sort_array(unused.data, unused.count, entity_variable_pos_cmp);
|
||||||
|
|
||||||
|
for_array(i, unused) {
|
||||||
|
Entity *e = unused[i];
|
||||||
|
error(e->token, "'%.*s' declared but not used", LIT(e->token.string));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Scope *child = scope->first_child;
|
||||||
|
child != nullptr;
|
||||||
|
child = child->next) {
|
||||||
|
if (!child->is_proc && !child->is_struct && !child->is_file) {
|
||||||
|
check_scope_usage(c, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -941,6 +974,7 @@ void init_checker(Checker *c, Parser *parser) {
|
|||||||
|
|
||||||
c->parser = parser;
|
c->parser = parser;
|
||||||
init_checker_info(&c->info);
|
init_checker_info(&c->info);
|
||||||
|
gb_mutex_init(&c->mutex);
|
||||||
|
|
||||||
array_init(&c->proc_stack, a);
|
array_init(&c->proc_stack, a);
|
||||||
map_init(&c->procs, a);
|
map_init(&c->procs, a);
|
||||||
@@ -973,6 +1007,8 @@ void init_checker(Checker *c, Parser *parser) {
|
|||||||
|
|
||||||
void destroy_checker(Checker *c) {
|
void destroy_checker(Checker *c) {
|
||||||
destroy_checker_info(&c->info);
|
destroy_checker_info(&c->info);
|
||||||
|
gb_mutex_destroy(&c->mutex);
|
||||||
|
|
||||||
destroy_scope(c->global_scope);
|
destroy_scope(c->global_scope);
|
||||||
array_free(&c->proc_stack);
|
array_free(&c->proc_stack);
|
||||||
map_destroy(&c->procs);
|
map_destroy(&c->procs);
|
||||||
@@ -3282,7 +3318,6 @@ void check_parsed_files(Checker *c) {
|
|||||||
bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0;
|
bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0;
|
||||||
bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
|
bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
|
||||||
|
|
||||||
|
|
||||||
if (bounds_check) {
|
if (bounds_check) {
|
||||||
c->context.stmt_state_flags |= StmtStateFlag_bounds_check;
|
c->context.stmt_state_flags |= StmtStateFlag_bounds_check;
|
||||||
c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check;
|
c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check;
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T
|
|||||||
entity->using_parent = parent;
|
entity->using_parent = parent;
|
||||||
entity->parent_proc_decl = parent->parent_proc_decl;
|
entity->parent_proc_decl = parent->parent_proc_decl;
|
||||||
entity->flags |= EntityFlag_Using;
|
entity->flags |= EntityFlag_Using;
|
||||||
|
entity->flags |= EntityFlag_Used;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-11
@@ -2093,7 +2093,6 @@ irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type *
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
if (is_type_array(ir_type(x))) {
|
if (is_type_array(ir_type(x))) {
|
||||||
ir_emit_comment(proc, str_lit("array.arith.begin"));
|
ir_emit_comment(proc, str_lit("array.arith.begin"));
|
||||||
// IMPORTANT TODO(bill): This is very wasteful with regards to stack memory
|
// IMPORTANT TODO(bill): This is very wasteful with regards to stack memory
|
||||||
@@ -2112,7 +2111,6 @@ irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type *
|
|||||||
return ir_emit_load(proc, res);
|
return ir_emit_load(proc, res);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return ir_emit(proc, ir_instr_unary_op(proc, op, x, type));
|
return ir_emit(proc, ir_instr_unary_op(proc, op, x, type));
|
||||||
}
|
}
|
||||||
@@ -2123,7 +2121,6 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
|||||||
Type *t_left = ir_type(left);
|
Type *t_left = ir_type(left);
|
||||||
Type *t_right = ir_type(right);
|
Type *t_right = ir_type(right);
|
||||||
|
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
if (is_type_array(t_left) || is_type_array(t_right)) {
|
if (is_type_array(t_left) || is_type_array(t_right)) {
|
||||||
ir_emit_comment(proc, str_lit("array.arith.begin"));
|
ir_emit_comment(proc, str_lit("array.arith.begin"));
|
||||||
// IMPORTANT TODO(bill): This is very wasteful with regards to stack memory
|
// IMPORTANT TODO(bill): This is very wasteful with regards to stack memory
|
||||||
@@ -2145,7 +2142,6 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
|||||||
ir_emit_comment(proc, str_lit("array.arith.end"));
|
ir_emit_comment(proc, str_lit("array.arith.end"));
|
||||||
return ir_emit_load(proc, res);
|
return ir_emit_load(proc, res);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (is_type_complex(t_left)) {
|
if (is_type_complex(t_left)) {
|
||||||
ir_emit_comment(proc, str_lit("complex.arith.begin"));
|
ir_emit_comment(proc, str_lit("complex.arith.begin"));
|
||||||
@@ -2404,7 +2400,6 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type *result = t_bool;
|
Type *result = t_bool;
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
if (is_type_array(a)) {
|
if (is_type_array(a)) {
|
||||||
ir_emit_comment(proc, str_lit("array.comp.begin"));
|
ir_emit_comment(proc, str_lit("array.comp.begin"));
|
||||||
defer (ir_emit_comment(proc, str_lit("array.comp.end")));
|
defer (ir_emit_comment(proc, str_lit("array.comp.end")));
|
||||||
@@ -2432,8 +2427,6 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
|||||||
return ir_emit_conv(proc, res, result);
|
return ir_emit_conv(proc, res, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (is_type_string(a)) {
|
if (is_type_string(a)) {
|
||||||
char *runtime_proc = nullptr;
|
char *runtime_proc = nullptr;
|
||||||
switch (op_kind) {
|
switch (op_kind) {
|
||||||
@@ -3188,7 +3181,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
return ir_emit_load(proc, slice);
|
return ir_emit_load(proc, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
if (is_type_array(dst)) {
|
if (is_type_array(dst)) {
|
||||||
Type *elem = dst->Array.elem;
|
Type *elem = dst->Array.elem;
|
||||||
irValue *e = ir_emit_conv(proc, value, elem);
|
irValue *e = ir_emit_conv(proc, value, elem);
|
||||||
@@ -3201,7 +3193,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
}
|
}
|
||||||
return ir_emit_load(proc, v);
|
return ir_emit_load(proc, v);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (is_type_any(dst)) {
|
if (is_type_any(dst)) {
|
||||||
irValue *result = ir_add_local_generated(proc, t_any);
|
irValue *result = ir_add_local_generated(proc, t_any);
|
||||||
@@ -4672,7 +4663,6 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tv.value.kind != ExactValue_Invalid) {
|
if (tv.value.kind != ExactValue_Invalid) {
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
// NOTE(bill): Edge case
|
// NOTE(bill): Edge case
|
||||||
if (tv.value.kind != ExactValue_Compound &&
|
if (tv.value.kind != ExactValue_Compound &&
|
||||||
is_type_array(tv.type)) {
|
is_type_array(tv.type)) {
|
||||||
@@ -4681,7 +4671,6 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
irValue *x = ir_add_module_constant(proc->module, elem, value);
|
irValue *x = ir_add_module_constant(proc->module, elem, value);
|
||||||
return ir_emit_conv(proc, x, tv.type);
|
return ir_emit_conv(proc, x, tv.type);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return ir_add_module_constant(proc->module, tv.type, tv.value);
|
return ir_add_module_constant(proc->module, tv.type, tv.value);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-24
@@ -1,7 +1,5 @@
|
|||||||
#define ALLOW_ARRAY_PROGRAMMING
|
|
||||||
// #define NO_ARRAY_BOUNDS_CHECK
|
// #define NO_ARRAY_BOUNDS_CHECK
|
||||||
|
|
||||||
|
|
||||||
#include "common.cpp"
|
#include "common.cpp"
|
||||||
#include "timings.cpp"
|
#include "timings.cpp"
|
||||||
#include "build_settings.cpp"
|
#include "build_settings.cpp"
|
||||||
@@ -248,6 +246,7 @@ bool parse_build_flags(Array<String> args) {
|
|||||||
add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String);
|
add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String);
|
||||||
|
|
||||||
|
|
||||||
|
GB_ASSERT(args.count >= 3);
|
||||||
Array<String> flag_args = args;
|
Array<String> flag_args = args;
|
||||||
flag_args.data += 3;
|
flag_args.data += 3;
|
||||||
flag_args.count -= 3;
|
flag_args.count -= 3;
|
||||||
@@ -296,29 +295,13 @@ bool parse_build_flags(Array<String> args) {
|
|||||||
switch (bf.param_kind) {
|
switch (bf.param_kind) {
|
||||||
default: ok = false; break;
|
default: ok = false; break;
|
||||||
case BuildFlagParam_Boolean: {
|
case BuildFlagParam_Boolean: {
|
||||||
if (param == "t") {
|
if (str_eq_ignore_case(param, str_lit("t")) ||
|
||||||
|
str_eq_ignore_case(param, str_lit("true")) ||
|
||||||
|
param == "1") {
|
||||||
value = exact_value_bool(true);
|
value = exact_value_bool(true);
|
||||||
} else if (param == "T") {
|
} else if (str_eq_ignore_case(param, str_lit("f")) ||
|
||||||
value = exact_value_bool(true);
|
str_eq_ignore_case(param, str_lit("false")) ||
|
||||||
} else if (param == "true") {
|
param == "0") {
|
||||||
value = exact_value_bool(true);
|
|
||||||
} else if (param == "TRUE") {
|
|
||||||
value = exact_value_bool(true);
|
|
||||||
} else if (param == "True") {
|
|
||||||
value = exact_value_bool(true);
|
|
||||||
} else if (param == "1") {
|
|
||||||
value = exact_value_bool(true);
|
|
||||||
} else if (param == "f") {
|
|
||||||
value = exact_value_bool(false);
|
|
||||||
} else if (param == "F") {
|
|
||||||
value = exact_value_bool(false);
|
|
||||||
} else if (param == "false") {
|
|
||||||
value = exact_value_bool(false);
|
|
||||||
} else if (param == "FALSE") {
|
|
||||||
value = exact_value_bool(false);
|
|
||||||
} else if (param == "False") {
|
|
||||||
value = exact_value_bool(false);
|
|
||||||
} else if (param == "0") {
|
|
||||||
value = exact_value_bool(false);
|
value = exact_value_bool(false);
|
||||||
} else {
|
} else {
|
||||||
gb_printf_err("Invalid flag parameter for '%.*s' = '%.*s'\n", LIT(name), LIT(param));
|
gb_printf_err("Invalid flag parameter for '%.*s' = '%.*s'\n", LIT(name), LIT(param));
|
||||||
|
|||||||
+4
-5
@@ -127,14 +127,12 @@ template <typename T> void multi_map_remove_all(Map<T> *h, HashKey key);
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
gb_inline void map_init(Map<T> *h, gbAllocator a, isize capacity) {
|
gb_inline void map_init(Map<T> *h, gbAllocator a, isize capacity) {
|
||||||
array_init(&h->hashes, a, capacity);
|
array_init(&h->hashes, a, capacity);
|
||||||
array_init(&h->entries, a, capacity);
|
array_init(&h->entries, a, capacity);}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
gb_inline void map_destroy(Map<T> *h) {
|
gb_inline void map_destroy(Map<T> *h) {
|
||||||
array_free(&h->entries);
|
array_free(&h->entries);
|
||||||
array_free(&h->hashes);
|
array_free(&h->hashes);}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
gb_internal isize map__add_entry(Map<T> *h, HashKey key) {
|
gb_internal isize map__add_entry(Map<T> *h, HashKey key) {
|
||||||
@@ -237,8 +235,9 @@ template <typename T>
|
|||||||
void map_set(Map<T> *h, HashKey key, T const &value) {
|
void map_set(Map<T> *h, HashKey key, T const &value) {
|
||||||
isize index;
|
isize index;
|
||||||
MapFindResult fr;
|
MapFindResult fr;
|
||||||
if (h->hashes.count == 0)
|
if (h->hashes.count == 0) {
|
||||||
map_grow(h);
|
map_grow(h);
|
||||||
|
}
|
||||||
fr = map__find(h, key);
|
fr = map__find(h, key);
|
||||||
if (fr.entry_index >= 0) {
|
if (fr.entry_index >= 0) {
|
||||||
index = fr.entry_index;
|
index = fr.entry_index;
|
||||||
|
|||||||
+2
-4
@@ -30,14 +30,12 @@ template <typename T> void ptr_set_rehash (PtrSet<T> *s, isize new_cou
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void ptr_set_init(PtrSet<T> *s, gbAllocator a, isize capacity) {
|
void ptr_set_init(PtrSet<T> *s, gbAllocator a, isize capacity) {
|
||||||
array_init(&s->hashes, a, capacity);
|
array_init(&s->hashes, a, capacity);
|
||||||
array_init(&s->entries, a, capacity);
|
array_init(&s->entries, a, capacity);}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ptr_set_destroy(PtrSet<T> *s) {
|
void ptr_set_destroy(PtrSet<T> *s) {
|
||||||
array_free(&s->hashes);
|
array_free(&s->hashes);
|
||||||
array_free(&s->entries);
|
array_free(&s->entries);}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
gb_internal isize ptr_set__add_entry(PtrSet<T> *s, T ptr) {
|
gb_internal isize ptr_set__add_entry(PtrSet<T> *s, T ptr) {
|
||||||
|
|||||||
+14
-10
@@ -659,11 +659,9 @@ bool is_type_numeric(Type *t) {
|
|||||||
return (t->Basic.flags & BasicFlag_Numeric) != 0;
|
return (t->Basic.flags & BasicFlag_Numeric) != 0;
|
||||||
}
|
}
|
||||||
// TODO(bill): Should this be here?
|
// TODO(bill): Should this be here?
|
||||||
#if defined(ALLOW_ARRAY_PROGRAMMING)
|
|
||||||
if (t->kind == Type_Array) {
|
if (t->kind == Type_Array) {
|
||||||
return is_type_numeric(t->Array.elem);
|
return is_type_numeric(t->Array.elem);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool is_type_string(Type *t) {
|
bool is_type_string(Type *t) {
|
||||||
@@ -1973,8 +1971,9 @@ Array<i64> type_set_offsets_of(gbAllocator allocator, Array<Entity *> fields, bo
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for_array(i, fields) {
|
for_array(i, fields) {
|
||||||
i64 align = gb_max(type_align_of(allocator, fields[i]->type), 1);
|
Type *t = fields[i]->type;
|
||||||
i64 size = gb_max(type_size_of(allocator, fields[i]->type), 0);
|
i64 align = gb_max(type_align_of(allocator, t), 1);
|
||||||
|
i64 size = gb_max(type_size_of(allocator, t), 0);
|
||||||
curr_offset = align_formula(curr_offset, align);
|
curr_offset = align_formula(curr_offset, align);
|
||||||
offsets[i] = curr_offset;
|
offsets[i] = curr_offset;
|
||||||
curr_offset += size;
|
curr_offset += size;
|
||||||
@@ -1989,6 +1988,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) {
|
|||||||
if (!t->Struct.are_offsets_set) {
|
if (!t->Struct.are_offsets_set) {
|
||||||
t->Struct.are_offsets_being_processed = true;
|
t->Struct.are_offsets_being_processed = true;
|
||||||
t->Struct.offsets = type_set_offsets_of(allocator, t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union);
|
t->Struct.offsets = type_set_offsets_of(allocator, t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union);
|
||||||
|
t->Struct.are_offsets_being_processed = false;
|
||||||
t->Struct.are_offsets_set = true;
|
t->Struct.are_offsets_set = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1996,6 +1996,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) {
|
|||||||
if (!t->Tuple.are_offsets_set) {
|
if (!t->Tuple.are_offsets_set) {
|
||||||
t->Struct.are_offsets_being_processed = true;
|
t->Struct.are_offsets_being_processed = true;
|
||||||
t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, false, false);
|
t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, false, false);
|
||||||
|
t->Struct.are_offsets_being_processed = false;
|
||||||
t->Tuple.are_offsets_set = true;
|
t->Tuple.are_offsets_set = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2037,6 +2038,9 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Type_Pointer:
|
||||||
|
return build_context.word_size;
|
||||||
|
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
i64 count, align, size, alignment;
|
i64 count, align, size, alignment;
|
||||||
count = t->Array.count;
|
count = t->Array.count;
|
||||||
@@ -2105,9 +2109,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
t->Union.tag_size = tag_size;
|
t->Union.tag_size = tag_size;
|
||||||
t->Union.variant_block_size = size - field_size;
|
t->Union.variant_block_size = size - field_size;
|
||||||
|
|
||||||
size += tag_size;
|
return align_formula(size + tag_size, align);
|
||||||
size = align_formula(size, align);
|
|
||||||
return size;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
@@ -2128,11 +2130,13 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
// TODO(bill): Is this how it should work?
|
// TODO(bill): Is this how it should work?
|
||||||
return align_formula(max, align);
|
return align_formula(max, align);
|
||||||
} else {
|
} else {
|
||||||
i64 count = t->Struct.fields.count;
|
i64 count = 0, size = 0, align = 0;
|
||||||
|
|
||||||
|
count = t->Struct.fields.count;
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
i64 align = type_align_of_internal(allocator, t, path);
|
align = type_align_of_internal(allocator, t, path);
|
||||||
if (path->failure) {
|
if (path->failure) {
|
||||||
return FAILURE_SIZE;
|
return FAILURE_SIZE;
|
||||||
}
|
}
|
||||||
@@ -2141,7 +2145,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
return FAILURE_SIZE;
|
return FAILURE_SIZE;
|
||||||
}
|
}
|
||||||
type_set_offsets(allocator, t);
|
type_set_offsets(allocator, t);
|
||||||
i64 size = t->Struct.offsets[count-1] + type_size_of_internal(allocator, t->Struct.fields[count-1]->type, path);
|
size = t->Struct.offsets[count-1] + type_size_of_internal(allocator, t->Struct.fields[count-1]->type, path);
|
||||||
return align_formula(size, align);
|
return align_formula(size, align);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
Reference in New Issue
Block a user