parseh understands simple structs

This commit is contained in:
Andrew Kelley 2016-01-28 14:49:34 -07:00
parent a09b505558
commit 47c3a30310
2 changed files with 69 additions and 23 deletions

View File

@ -105,6 +105,18 @@ static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node)
return node;
}
static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *type_node) {
assert(type_node);
AstNode *node = create_node(c, NodeTypeStructField);
buf_init_from_str(&node->data.struct_field.name, name);
node->data.struct_field.directives = create_empty_directives(c);
node->data.struct_field.visib_mod = VisibModPub;
node->data.struct_field.type = type_node;
normalize_parent_ptrs(node);
return node;
}
static const char *decl_name(const Decl *decl) {
const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
return (const char *)named_decl->getName().bytes_begin();
@ -386,6 +398,11 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
add_typedef_node(c, type_name, make_qual_type_node(c, child_qt, typedef_decl));
}
static void add_alias(Context *c, const char *new_name, const char *target_name) {
AstNode *alias_node = create_var_decl_node(c, new_name, create_symbol_node(c, target_name));
c->aliases.append(alias_node);
}
static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
Buf bare_name = BUF_INIT;
buf_init_from_str(&bare_name, decl_name(enum_decl));
@ -403,9 +420,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
if (!enum_def) {
// this is a type that we can point to but that's it, same as `struct Foo;`.
add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name),
create_symbol_node(c, buf_ptr(type_name)));
c->aliases.append(alias_node);
add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name));
return;
}
@ -427,32 +442,29 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(type_name));
return;
}
AstNode *field_node = create_node(c, NodeTypeStructField);
Buf enum_val_name = BUF_INIT;
buf_init_from_str(&enum_val_name, decl_name(enum_const));
Buf field_name = BUF_INIT;
if (buf_starts_with_buf(&enum_val_name, &bare_name)) {
Buf *slice = buf_slice(&enum_val_name, buf_len(&bare_name), buf_len(&enum_val_name));
if (valid_symbol_starter(buf_ptr(slice)[0])) {
buf_init_from_buf(&field_node->data.struct_field.name, slice);
buf_init_from_buf(&field_name, slice);
} else {
buf_resize(&field_node->data.struct_field.name, 0);
buf_appendf(&field_node->data.struct_field.name, "_%s", buf_ptr(slice));
buf_resize(&field_name, 0);
buf_appendf(&field_name, "_%s", buf_ptr(slice));
}
} else {
buf_init_from_buf(&field_node->data.struct_field.name, &enum_val_name);
buf_init_from_buf(&field_name, &enum_val_name);
}
field_node->data.struct_field.directives = create_empty_directives(c);
field_node->data.struct_field.visib_mod = VisibModPub;
field_node->data.struct_field.type = create_symbol_node(c, "void");
normalize_parent_ptrs(field_node);
AstNode *field_node = create_struct_field_node(c, buf_ptr(&field_name), create_symbol_node(c, "void"));
node->data.struct_decl.fields.append(field_node);
// in C each enum value is in the global namespace. so we put them there too.
AstNode *field_access_node = create_field_access_node(c, buf_ptr(type_name),
buf_ptr(&field_node->data.struct_field.name));
buf_ptr(&field_name));
AstNode *var_node = create_var_decl_node(c, buf_ptr(&enum_val_name), field_access_node);
var_decls.append(var_node);
}
@ -469,9 +481,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
// make an alias without the "enum_" prefix. this will get emitted at the
// end if it doesn't conflict with anything else
AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name), create_symbol_node(c, buf_ptr(type_name)));
c->aliases.append(alias_node);
add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name));
}
static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
@ -490,15 +500,15 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
if (!record_def) {
// this is a type that we can point to but that's it, such as `struct Foo;`.
add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name),
create_symbol_node(c, buf_ptr(type_name)));
c->aliases.append(alias_node);
add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name));
return;
}
emit_warning(c, record_decl, "skipping record %s, TODO", buf_ptr(&bare_name));
if (!record_def->isStruct()) {
emit_warning(c, record_decl, "skipping record %s, not a struct", buf_ptr(&bare_name));
return;
}
/*
AstNode *node = create_node(c, NodeTypeStructDecl);
buf_init_from_buf(&node->data.struct_decl.name, type_name);
@ -506,9 +516,34 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
node->data.struct_decl.visib_mod = VisibModExport;
node->data.struct_decl.directives = create_empty_directives(c);
for (auto it = record_def->field_begin(),
it_end = record_def->field_end();
it != it_end; ++it)
{
const FieldDecl *field_decl = *it;
if (field_decl->isBitField()) {
emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(&bare_name));
return;
}
AstNode *type_node = make_qual_type_node(c, field_decl->getType(), field_decl);
if (!type_node) {
emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(&bare_name));
return;
}
AstNode *field_node = create_struct_field_node(c, decl_name(field_decl), type_node);
node->data.struct_decl.fields.append(field_node);
}
c->type_table.put(type_name, true);
normalize_parent_ptrs(node);
c->root->data.root.top_level_decls.append(node);
*/
// make an alias without the "struct_" prefix. this will get emitted at the
// end if it doesn't conflict with anything else
add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name));
}
static bool decl_visitor(void *context, const Decl *decl) {

View File

@ -1828,6 +1828,17 @@ pub const Foo = enum_Foo;)OUTPUT");
void foo(void *restrict bar, void *restrict);
)SOURCE", R"OUTPUT(pub const c_void = u8;
pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");
add_parseh_case("simple struct", R"SOURCE(
struct Foo {
int x;
char *y;
};
)SOURCE", R"OUTPUT(export struct struct_Foo {
x: c_int,
y: ?&u8,
}
pub const Foo = struct_Foo;)OUTPUT");
}
static void print_compiler_invocation(TestCase *test_case) {