Commit d1ac1abd34

Andrew Kelley <superjoe30@gmail.com>
2016-01-28 00:30:52
parseh correctly handles C's void type
1 parent 75cab48
Changed files (3)
src/all_types.hpp
@@ -242,6 +242,7 @@ struct AstNodeReturnExpr {
 struct AstNodeVariableDeclaration {
     Buf symbol;
     bool is_const;
+    bool is_extern;
     VisibMod visib_mod;
     // one or both of type and expr will be non null
     AstNode *type;
src/main.cpp
@@ -170,12 +170,12 @@ static void print_indent(ParseHPrint *p) {
     }
 }
 
-static Buf *type_node_to_name(AstNode *type_node) {
-    if (type_node->type == NodeTypeSymbol) {
-        return &type_node->data.symbol_expr.symbol;
-    } else if (type_node->type == NodeTypePrefixOpExpr) {
-        PrefixOp op = type_node->data.prefix_op_expr.prefix_op;
-        const char *child_type_str = buf_ptr(type_node_to_name(type_node->data.prefix_op_expr.primary_expr));
+static Buf *node_to_buf(AstNode *node) {
+    if (node->type == NodeTypeSymbol) {
+        return &node->data.symbol_expr.symbol;
+    } else if (node->type == NodeTypePrefixOpExpr) {
+        PrefixOp op = node->data.prefix_op_expr.prefix_op;
+        const char *child_type_str = buf_ptr(node_to_buf(node->data.prefix_op_expr.primary_expr));
         if (op == PrefixOpAddressOf) {
             return buf_sprintf("&%s", child_type_str);
         } else if (op == PrefixOpConstAddressOf) {
@@ -242,6 +242,24 @@ static int parseh(const char *arg0, int argc, char **argv) {
         return EXIT_FAILURE;
     }
 
+    for (int var_i = 0; var_i < p->parse_h.var_list.length; var_i += 1) {
+        AstNode *var_decl = p->parse_h.var_list.at(var_i);
+        assert(var_decl->type == NodeTypeVariableDeclaration);
+        const char *pub_str = (var_decl->data.variable_declaration.visib_mod == VisibModPub) ? "pub " : "";
+        const char *extern_str = var_decl->data.variable_declaration.is_extern ? "extern " : "";
+        const char *var_name = buf_ptr(&var_decl->data.variable_declaration.symbol);
+        const char *const_or_var = var_decl->data.variable_declaration.is_const ? "const" : "var";
+        print_indent(p);
+        fprintf(p->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name);
+        if (var_decl->data.variable_declaration.type) {
+            fprintf(p->f, ": %s", buf_ptr(node_to_buf(var_decl->data.variable_declaration.type)));
+        }
+        if (var_decl->data.variable_declaration.expr) {
+            fprintf(p->f, " = %s", buf_ptr(node_to_buf(var_decl->data.variable_declaration.expr)));
+        }
+        fprintf(p->f, ";\n");
+    }
+
     for (int struct_i = 0; struct_i < p->parse_h.struct_list.length; struct_i += 1) {
         AstNode *struct_decl = p->parse_h.struct_list.at(struct_i);
         assert(struct_decl->type == NodeTypeStructDecl);
@@ -253,7 +271,7 @@ static int parseh(const char *arg0, int argc, char **argv) {
             AstNode *field_node = struct_decl->data.struct_decl.fields.at(field_i);
             assert(field_node->type == NodeTypeStructField);
             const char *field_name = buf_ptr(&field_node->data.struct_field.name);
-            Buf *type_name = type_node_to_name(field_node->data.struct_field.type);
+            Buf *type_name = node_to_buf(field_node->data.struct_field.type);
             print_indent(p);
             fprintf(p->f, "%s: %s,\n", field_name, buf_ptr(type_name));
         }
@@ -268,14 +286,15 @@ static int parseh(const char *arg0, int argc, char **argv) {
         print_indent(p);
         const char *fn_name = buf_ptr(&fn_proto->data.fn_proto.name);
         const char *pub_str = (fn_proto->data.fn_proto.visib_mod == VisibModPub) ? "pub " : "";
-        fprintf(p->f, "%sextern fn %s(", pub_str, fn_name);
+        const char *extern_str = fn_proto->data.fn_proto.is_extern ? "extern " : "";
+        fprintf(p->f, "%s%sfn %s(", pub_str, extern_str, fn_name);
         int arg_count = fn_proto->data.fn_proto.params.length;
         bool is_var_args = fn_proto->data.fn_proto.is_var_args;
         for (int arg_i = 0; arg_i < arg_count; arg_i += 1) {
             AstNode *param_decl = fn_proto->data.fn_proto.params.at(arg_i);
             assert(param_decl->type == NodeTypeParamDecl);
             const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);
-            Buf *arg_type = type_node_to_name(param_decl->data.param_decl.type);
+            Buf *arg_type = node_to_buf(param_decl->data.param_decl.type);
             const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
             fprintf(p->f, "%s%s: %s", noalias_str, arg_name, buf_ptr(arg_type));
             if (arg_i + 1 < arg_count || is_var_args) {
@@ -286,7 +305,7 @@ static int parseh(const char *arg0, int argc, char **argv) {
             fprintf(p->f, "...");
         }
         fprintf(p->f, ")");
-        Buf *return_type_name = type_node_to_name(fn_proto->data.fn_proto.return_type);
+        Buf *return_type_name = node_to_buf(fn_proto->data.fn_proto.return_type);
         if (!buf_eql_str(return_type_name, "void")) {
             fprintf(p->f, " -> %s", buf_ptr(return_type_name));
         }
src/parseh.cpp
@@ -20,7 +20,8 @@ using namespace clang;
 struct Context {
     ParseH *parse_h;
     bool warnings_on;
-    bool pub;
+    VisibMod visib_mod;
+    AstNode *c_void_decl_node;
 };
 
 static AstNode *type_node_from_qual_type(Context *c, QualType qt);
@@ -42,10 +43,33 @@ static const char *decl_name(const Decl *decl) {
     return (const char *)named_decl->getName().bytes_begin();
 }
 
+static AstNode *create_typedef_node(Context *c, const char *new_name, const char *target_name) {
+    AstNode *node = create_node(c, NodeTypeVariableDeclaration);
+    buf_init_from_str(&node->data.variable_declaration.symbol, new_name);
+    node->data.variable_declaration.is_const = true;
+    node->data.variable_declaration.visib_mod = c->visib_mod;
+    node->data.variable_declaration.expr = simple_type_node(c, target_name);
+    return node;
+}
+
+static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {
+    if (type_node->type == NodeTypeSymbol &&
+        buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))
+    {
+        if (!c->c_void_decl_node) {
+            c->c_void_decl_node = create_typedef_node(c, "c_void", "u8");
+            c->parse_h->var_list.append(c->c_void_decl_node);
+        }
+        return simple_type_node(c, "c_void");
+    } else {
+        return type_node;
+    }
+}
+
 static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
     AstNode *node = create_node(c, NodeTypePrefixOpExpr);
     node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf;
-    node->data.prefix_op_expr.primary_expr = type_node;
+    node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node);
     return node;
 }
 
@@ -187,7 +211,7 @@ static bool decl_visitor(void *context, const Decl *decl) {
                 const FunctionDecl *fn_decl = static_cast<const FunctionDecl*>(decl);
                 AstNode *node = create_node(c, NodeTypeFnProto);
                 node->data.fn_proto.is_extern = true;
-                node->data.fn_proto.visib_mod = c->pub ? VisibModPub : VisibModPrivate;
+                node->data.fn_proto.visib_mod = c->visib_mod;
                 node->data.fn_proto.is_var_args = fn_decl->isVariadic();
                 buf_init_from_str(&node->data.fn_proto.name, decl_name(decl));