aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-09-23 15:18:02 -0400
committerAndrew Kelley <superjoe30@gmail.com>2016-09-23 15:18:02 -0400
commite06885d64e3569719e9479c7069da7ad426a70d3 (patch)
tree075258e85acce6c4d5fb3a29225fc0d97fabfb26 /src
parent9ec6a78f121c8f61c10ea02f6949f27b0228ba16 (diff)
downloadzig-e06885d64e3569719e9479c7069da7ad426a70d3.tar.gz
zig-e06885d64e3569719e9479c7069da7ad426a70d3.zip
enums support member functions
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp2
-rw-r--r--src/analyze.cpp97
-rw-r--r--src/codegen.cpp10
-rw-r--r--src/eval.cpp2
-rw-r--r--src/parseh.cpp4
5 files changed, 72 insertions, 43 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index d778145d37..99aa5ca471 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -924,7 +924,7 @@ struct TypeTableEntryError {
struct TypeTableEntryEnum {
AstNode *decl_node;
- uint32_t field_count;
+ uint32_t src_field_count;
uint32_t gen_field_count;
TypeEnumField *fields;
bool is_invalid; // true if any fields are invalid
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 5bcd7cc0ba..b3cf10737c 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1325,7 +1325,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
uint32_t field_count = decl_node->data.struct_decl.fields.length;
- enum_type->data.enumeration.field_count = field_count;
+ enum_type->data.enumeration.src_field_count = field_count;
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
@@ -2451,8 +2451,8 @@ static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *
return nullptr;
}
-static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
- for (uint32_t i = 0; i < enum_type->data.enumeration.field_count; i += 1) {
+static TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
+ for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
if (buf_eql_buf(type_enum_field->name, name)) {
return type_enum_field;
@@ -2467,7 +2467,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
{
assert(field_access_node->type == NodeTypeFieldAccessExpr);
- TypeEnumField *type_enum_field = get_enum_field(enum_type, field_name);
+ TypeEnumField *type_enum_field = find_enum_type_field(enum_type, field_name);
if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
}
@@ -2715,6 +2715,41 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
}
}
+static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call,
+ TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
+{
+ assert(node->type == NodeTypeFieldAccessExpr);
+ if (wrapped_in_fn_call && !is_slice(bare_struct_type)) {
+ BlockContext *container_block_context = get_container_block_context(bare_struct_type);
+ assert(container_block_context);
+ auto entry = container_block_context->decl_table.maybe_get(field_name);
+ AstNode *fn_decl_node = entry ? entry->value : nullptr;
+ if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) {
+ resolve_top_level_decl(g, fn_decl_node, false);
+ TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node);
+ if (tld->resolution == TldResolutionInvalid) {
+ return g->builtin_types.entry_invalid;
+ }
+
+ node->data.field_access_expr.is_member_fn = true;
+ FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
+ if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
+ return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false);
+ } else {
+ return resolve_expr_const_val_as_fn(g, node, fn_entry, false);
+ }
+ } else {
+ add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'",
+ buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
+ return g->builtin_types.entry_invalid;
+ }
+ } else {
+ add_node_error(g, node,
+ buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name)));
+ return g->builtin_types.entry_invalid;
+ }
+}
+
static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
@@ -2742,34 +2777,28 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);
if (node->data.field_access_expr.type_struct_field) {
return node->data.field_access_expr.type_struct_field->type_entry;
- } else if (wrapped_in_fn_call && !is_slice(bare_struct_type)) {
- BlockContext *container_block_context = get_container_block_context(bare_struct_type);
- assert(container_block_context);
- auto entry = container_block_context->decl_table.maybe_get(field_name);
- AstNode *fn_decl_node = entry ? entry->value : nullptr;
- if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) {
- resolve_top_level_decl(g, fn_decl_node, false);
- TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node);
- if (tld->resolution == TldResolutionInvalid) {
- return g->builtin_types.entry_invalid;
- }
+ } else {
+ return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name,
+ node, struct_type);
+ }
+ } else if (struct_type->id == TypeTableEntryIdEnum || (struct_type->id == TypeTableEntryIdPointer &&
+ struct_type->data.pointer.child_type->id == TypeTableEntryIdEnum))
+ {
+ TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdEnum) ?
+ struct_type : struct_type->data.pointer.child_type;
- node->data.field_access_expr.is_member_fn = true;
- FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
- if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
- return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false);
- } else {
- return resolve_expr_const_val_as_fn(g, node, fn_entry, false);
- }
- } else {
- add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'",
- buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
- return g->builtin_types.entry_invalid;
- }
+ if (!bare_struct_type->data.enumeration.complete) {
+ resolve_struct_type(g, bare_struct_type->data.enumeration.decl_node->owner, bare_struct_type);
+ }
+
+ node->data.field_access_expr.bare_struct_type = bare_struct_type;
+ node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_struct_type, field_name);
+
+ if (node->data.field_access_expr.type_enum_field) {
+ return node->data.field_access_expr.type_enum_field->type_entry;
} else {
- add_node_error(g, node,
- buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name)));
- return g->builtin_types.entry_invalid;
+ return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name,
+ node, struct_type);
}
} else if (struct_type->id == TypeTableEntryIdArray) {
if (buf_eql_str(field_name, "len")) {
@@ -5269,7 +5298,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
if (type_entry->id == TypeTableEntryIdInvalid) {
return type_entry;
} else if (type_entry->id == TypeTableEntryIdEnum) {
- uint64_t value_count = type_entry->data.enumeration.field_count;
+ uint64_t value_count = type_entry->data.enumeration.src_field_count;
return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
value_count, false);
} else {
@@ -6130,7 +6159,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
size_t *field_use_counts = nullptr;
HashMap<int, AstNode *, int_hash, int_eq> err_use_nodes = {};
if (expr_type->id == TypeTableEntryIdEnum) {
- field_use_counts = allocate<size_t>(expr_type->data.enumeration.field_count);
+ field_use_counts = allocate<size_t>(expr_type->data.enumeration.src_field_count);
} else if (expr_type->id == TypeTableEntryIdErrorUnion) {
err_use_nodes.init(10);
}
@@ -6168,7 +6197,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
if (expr_type->id == TypeTableEntryIdEnum) {
if (item_node->type == NodeTypeSymbol) {
Buf *field_name = item_node->data.symbol_expr.symbol;
- TypeEnumField *type_enum_field = get_enum_field(expr_type, field_name);
+ TypeEnumField *type_enum_field = find_enum_type_field(expr_type, field_name);
if (type_enum_field) {
item_node->data.symbol_expr.enum_field = type_enum_field;
if (!var_type) {
@@ -6300,7 +6329,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
}
if (expr_type->id == TypeTableEntryIdEnum && !else_prong) {
- for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) {
+ for (uint32_t i = 0; i < expr_type->data.enumeration.src_field_count; i += 1) {
if (field_use_counts[i] == 0) {
add_node_error(g, node,
buf_sprintf("enumeration value '%s' not handled in switch",
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 8c2d898ea1..44e29702d2 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4605,7 +4605,7 @@ static void define_builtin_types(CodeGen *g) {
entry->zero_bits = true; // only allowed at compile time
buf_init_from_str(&entry->name, "@OS");
uint32_t field_count = target_os_count();
- entry->data.enumeration.field_count = field_count;
+ entry->data.enumeration.src_field_count = field_count;
entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
for (uint32_t i = 0; i < field_count; i += 1) {
TypeEnumField *type_enum_field = &entry->data.enumeration.fields[i];
@@ -4631,7 +4631,7 @@ static void define_builtin_types(CodeGen *g) {
entry->zero_bits = true; // only allowed at compile time
buf_init_from_str(&entry->name, "@Arch");
uint32_t field_count = target_arch_count();
- entry->data.enumeration.field_count = field_count;
+ entry->data.enumeration.src_field_count = field_count;
entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
for (uint32_t i = 0; i < field_count; i += 1) {
TypeEnumField *type_enum_field = &entry->data.enumeration.fields[i];
@@ -4663,7 +4663,7 @@ static void define_builtin_types(CodeGen *g) {
entry->zero_bits = true; // only allowed at compile time
buf_init_from_str(&entry->name, "@Environ");
uint32_t field_count = target_environ_count();
- entry->data.enumeration.field_count = field_count;
+ entry->data.enumeration.src_field_count = field_count;
entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
for (uint32_t i = 0; i < field_count; i += 1) {
TypeEnumField *type_enum_field = &entry->data.enumeration.fields[i];
@@ -4690,7 +4690,7 @@ static void define_builtin_types(CodeGen *g) {
entry->zero_bits = true; // only allowed at compile time
buf_init_from_str(&entry->name, "@ObjectFormat");
uint32_t field_count = target_oformat_count();
- entry->data.enumeration.field_count = field_count;
+ entry->data.enumeration.src_field_count = field_count;
entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
for (uint32_t i = 0; i < field_count; i += 1) {
TypeEnumField *type_enum_field = &entry->data.enumeration.fields[i];
@@ -4716,7 +4716,7 @@ static void define_builtin_types(CodeGen *g) {
entry->deep_const = true;
buf_init_from_str(&entry->name, "AtomicOrder");
uint32_t field_count = 6;
- entry->data.enumeration.field_count = field_count;
+ entry->data.enumeration.src_field_count = field_count;
entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
entry->data.enumeration.fields[0].name = buf_create_from_str("Unordered");
entry->data.enumeration.fields[0].value = AtomicOrderUnordered;
diff --git a/src/eval.cpp b/src/eval.cpp
index 1ccf0225f4..c19e2ea234 100644
--- a/src/eval.cpp
+++ b/src/eval.cpp
@@ -683,7 +683,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
{
uint64_t value = other_val->data.x_bignum.data.x_uint;
assert(new_type->id == TypeTableEntryIdEnum);
- assert(value < new_type->data.enumeration.field_count);
+ assert(value < new_type->data.enumeration.src_field_count);
const_val->data.x_enum.tag = value;
const_val->data.x_enum.payload = NULL;
const_val->ok = true;
diff --git a/src/parseh.cpp b/src/parseh.cpp
index d3c964d3db..307129d4a0 100644
--- a/src/parseh.cpp
+++ b/src/parseh.cpp
@@ -870,7 +870,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
enum_type->data.enumeration.complete = true;
enum_type->data.enumeration.tag_type = tag_type_entry;
- enum_type->data.enumeration.field_count = field_count;
+ enum_type->data.enumeration.src_field_count = field_count;
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
@@ -977,7 +977,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
enum_node->data.struct_decl.top_level_decl.visib_mod = VisibModExport;
enum_node->data.struct_decl.type_entry = enum_type;
- for (uint32_t i = 0; i < enum_type->data.enumeration.field_count; i += 1) {
+ for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
AstNode *type_node = make_type_node(c, type_enum_field->type_entry);
AstNode *field_node = create_struct_field_node(c, buf_ptr(type_enum_field->name), type_node);