Commit fa1ea6062b

Andrew Kelley <superjoe30@gmail.com>
2016-01-27 11:11:51
parseh works for simple functions
1 parent 0278468
Changed files (2)
src/main.cpp
@@ -170,9 +170,19 @@ static void print_indent(ParseHPrint *p) {
     }
 }
 
-static const char *type_node_to_name(AstNode *type_node) {
-    assert(type_node->type == NodeTypeSymbol);
-    return buf_ptr(&type_node->data.symbol_expr.symbol);
+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;
+        if (op == PrefixOpAddressOf) {
+            return buf_sprintf("&%s", buf_ptr(type_node_to_name(type_node->data.prefix_op_expr.primary_expr)));
+        } else {
+            zig_unreachable();
+        }
+    } else {
+        zig_unreachable();
+    }
 }
 
 static int parseh(const char *arg0, int argc, char **argv) {
@@ -208,6 +218,11 @@ static int parseh(const char *arg0, int argc, char **argv) {
 
     clang_argv.append(in_file);
 
+    Buf *libc_include_path = buf_alloc();
+    os_path_join(buf_create_from_str(ZIG_LIBC_DIR), buf_create_from_str("include"), libc_include_path);
+    clang_argv.append("-isystem");
+    clang_argv.append(buf_ptr(libc_include_path));
+
     ParseHPrint parse_h_print = {{{0}}};
     ParseHPrint *p = &parse_h_print;
     p->f = stdout;
@@ -235,9 +250,9 @@ 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);
-            const char *type_name = type_node_to_name(field_node->data.struct_field.type);
+            Buf *type_name = type_node_to_name(field_node->data.struct_field.type);
             print_indent(p);
-            fprintf(p->f, "%s: %s,\n", field_name, type_name);
+            fprintf(p->f, "%s: %s,\n", field_name, buf_ptr(type_name));
         }
 
         p->cur_indent -= indent_size;
@@ -249,15 +264,17 @@ static int parseh(const char *arg0, int argc, char **argv) {
         assert(fn_proto->type == NodeTypeFnProto);
         print_indent(p);
         const char *fn_name = buf_ptr(&fn_proto->data.fn_proto.name);
-        fprintf(p->f, "extern fn %s(", fn_name);
+        const char *pub_str = (fn_proto->data.fn_proto.visib_mod == VisibModPub) ? "pub " : "";
+        fprintf(p->f, "%sextern fn %s(", pub_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);
-            const char *arg_type = type_node_to_name(param_decl->data.param_decl.type);
-            fprintf(p->f, "%s: %s", arg_name, arg_type);
+            Buf *arg_type = type_node_to_name(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) {
                 fprintf(p->f, ", ");
             }
@@ -266,9 +283,9 @@ static int parseh(const char *arg0, int argc, char **argv) {
             fprintf(p->f, "...");
         }
         fprintf(p->f, ")");
-        const char *return_type_name = type_node_to_name(fn_proto->data.fn_proto.return_type);
-        if (strcmp(return_type_name, "void") != 0) {
-            fprintf(p->f, " -> %s", return_type_name);
+        Buf *return_type_name = type_node_to_name(fn_proto->data.fn_proto.return_type);
+        if (!buf_eql_str(return_type_name, "void")) {
+            fprintf(p->f, " -> %s", buf_ptr(return_type_name));
         }
         fprintf(p->f, ";\n");
     }
src/parseh.cpp
@@ -19,12 +19,202 @@ using namespace clang;
 
 struct Context {
     ParseH *parse_h;
+    bool warnings_on;
+    bool pub;
 };
 
+static AstNode *type_node_from_qual_type(Context *c, QualType qt);
+
+static AstNode *create_node(Context *c, NodeType type) {
+    AstNode *node = allocate<AstNode>(1);
+    node->type = type;
+    return node;
+}
+
+static AstNode *simple_type_node(Context *c, const char *type_name) {
+    AstNode *node = create_node(c, NodeTypeSymbol);
+    buf_init_from_str(&node->data.symbol_expr.symbol, type_name);
+    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();
+}
+
+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;
+    return node;
+}
+
+static AstNode *type_node(Context *c, const Type *ty, bool is_const) {
+    switch (ty->getTypeClass()) {
+        case Type::Builtin:
+            {
+                const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
+                switch (builtin_ty->getKind()) {
+                    case BuiltinType::Void:
+                        return simple_type_node(c, "void");
+                    case BuiltinType::Bool:
+                        return simple_type_node(c, "bool");
+                    case BuiltinType::Char_U:
+                    case BuiltinType::UChar:
+                        return simple_type_node(c, "u8");
+                    case BuiltinType::Char_S:
+                    case BuiltinType::SChar:
+                        return simple_type_node(c, "i8");
+                    case BuiltinType::UShort:
+                        return simple_type_node(c, "c_ushort");
+                    case BuiltinType::UInt:
+                        return simple_type_node(c, "c_uint");
+                    case BuiltinType::ULong:
+                        return simple_type_node(c, "c_ulong");
+                    case BuiltinType::ULongLong:
+                        return simple_type_node(c, "c_ulonglong");
+                    case BuiltinType::Short:
+                        return simple_type_node(c, "c_short");
+                    case BuiltinType::Int:
+                        return simple_type_node(c, "c_int");
+                    case BuiltinType::Long:
+                        return simple_type_node(c, "c_long");
+                    case BuiltinType::LongLong:
+                        return simple_type_node(c, "c_longlong");
+                    case BuiltinType::Float:
+                        return simple_type_node(c, "f32");
+                    case BuiltinType::Double:
+                        return simple_type_node(c, "f64");
+                    case BuiltinType::LongDouble:
+                        return simple_type_node(c, "f128");
+                    case BuiltinType::WChar_U:
+                    case BuiltinType::Char16:
+                    case BuiltinType::Char32:
+                    case BuiltinType::UInt128:
+                    case BuiltinType::WChar_S:
+                    case BuiltinType::Int128:
+                    case BuiltinType::Half:
+                    case BuiltinType::NullPtr:
+                    case BuiltinType::ObjCId:
+                    case BuiltinType::ObjCClass:
+                    case BuiltinType::ObjCSel:
+                    case BuiltinType::OCLImage1d:
+                    case BuiltinType::OCLImage1dArray:
+                    case BuiltinType::OCLImage1dBuffer:
+                    case BuiltinType::OCLImage2d:
+                    case BuiltinType::OCLImage2dArray:
+                    case BuiltinType::OCLImage3d:
+                    case BuiltinType::OCLSampler:
+                    case BuiltinType::OCLEvent:
+                    case BuiltinType::Dependent:
+                    case BuiltinType::Overload:
+                    case BuiltinType::BoundMember:
+                    case BuiltinType::PseudoObject:
+                    case BuiltinType::UnknownAny:
+                    case BuiltinType::BuiltinFn:
+                    case BuiltinType::ARCUnbridgedCast:
+                        zig_panic("TODO - make error for these types");
+                }
+                break;
+            }
+        case Type::Pointer:
+            {
+                const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
+                AstNode *type_node = type_node_from_qual_type(c, pointer_ty->getPointeeType());
+                return pointer_to_type(c, type_node, is_const);
+            }
+        case Type::Typedef:
+        case Type::FunctionProto:
+        case Type::Record:
+        case Type::Enum:
+        case Type::BlockPointer:
+        case Type::LValueReference:
+        case Type::RValueReference:
+        case Type::MemberPointer:
+        case Type::ConstantArray:
+        case Type::IncompleteArray:
+        case Type::VariableArray:
+        case Type::DependentSizedArray:
+        case Type::DependentSizedExtVector:
+        case Type::Vector:
+        case Type::ExtVector:
+        case Type::FunctionNoProto:
+        case Type::UnresolvedUsing:
+        case Type::Paren:
+        case Type::Adjusted:
+        case Type::Decayed:
+        case Type::TypeOfExpr:
+        case Type::TypeOf:
+        case Type::Decltype:
+        case Type::UnaryTransform:
+        case Type::Elaborated:
+        case Type::Attributed:
+        case Type::TemplateTypeParm:
+        case Type::SubstTemplateTypeParm:
+        case Type::SubstTemplateTypeParmPack:
+        case Type::TemplateSpecialization:
+        case Type::Auto:
+        case Type::InjectedClassName:
+        case Type::DependentName:
+        case Type::DependentTemplateSpecialization:
+        case Type::PackExpansion:
+        case Type::ObjCObject:
+        case Type::ObjCInterface:
+        case Type::Complex:
+        case Type::ObjCObjectPointer:
+        case Type::Atomic:
+            zig_panic("TODO - make error for type: %s", ty->getTypeClassName());
+    }
+}
+
+static AstNode *type_node_from_qual_type(Context *c, QualType qt) {
+    bool is_const = qt.isConstQualified();
+    return type_node(c, qt.getTypePtr(), is_const);
+}
+
 static bool decl_visitor(void *context, const Decl *decl) {
-    //Context *c = (Context*)context;
+    Context *c = (Context*)context;
+
+    switch (decl->getKind()) {
+        case Decl::Function:
+            {
+                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.is_var_args = fn_decl->isVariadic();
+                buf_init_from_str(&node->data.fn_proto.name, decl_name(decl));
+
+                int arg_count = fn_decl->getNumParams();
+                for (int i = 0; i < arg_count; i += 1) {
+                    const ParmVarDecl *param = fn_decl->getParamDecl(i);
+                    AstNode *param_decl_node = create_node(c, NodeTypeParamDecl);
+                    const char *name = decl_name(param);
+                    if (strlen(name) == 0) {
+                        name = buf_ptr(buf_sprintf("arg%d", i));
+                    }
+                    buf_init_from_str(&param_decl_node->data.param_decl.name, name);
+                    QualType qt = param->getOriginalType();
+                    param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified();
+                    param_decl_node->data.param_decl.type = type_node_from_qual_type(c, qt);
+                    node->data.fn_proto.params.append(param_decl_node);
+                }
 
-    fprintf(stderr, "got top level decl\n");
+                if (fn_decl->isNoReturn()) {
+                    node->data.fn_proto.return_type = simple_type_node(c, "unreachable");
+                } else {
+                    node->data.fn_proto.return_type = type_node_from_qual_type(c, fn_decl->getReturnType());
+                }
+
+                c->parse_h->fn_list.append(node);
+
+                break;
+            }
+        default:
+            if (c->warnings_on) {
+                fprintf(stderr, "ignoring %s\n", decl->getDeclKindName());
+            }
+    }
 
     return true;
 }
@@ -46,7 +236,6 @@ int parse_h_buf(ParseH *parse_h, Buf *source, const char *libc_include_path) {
     os_delete_file(&tmp_file_path);
 
     return err;
-    // write to temp file, parse it, delete it
 }
 
 int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {
@@ -124,7 +313,7 @@ int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {
             }
             StringRef msg_str_ref = it->getMessage();
             FullSourceLoc fsl = it->getLocation();
-            FileID file_id = fsl.getManager().getFileID(fsl);
+            FileID file_id = fsl.getFileID();
             StringRef filename = fsl.getManager().getFilename(fsl);
             unsigned line = fsl.getSpellingLineNumber() - 1;
             unsigned column = fsl.getSpellingColumnNumber() - 1;