Commit a4ac6d15c4

Vexu <git@vexu.eu>
2019-12-14 09:41:00
translate-c-2 array initializer expr
1 parent e4ca1f4
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -498,7 +498,7 @@ fn transStmt(
     stmt: *const ZigClangStmt,
     result_used: ResultUsed,
     lrvalue: LRValue,
-) !TransResult {
+) TransError!TransResult {
     const sc = ZigClangStmt_getStmtClass(stmt);
     switch (sc) {
         .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used),
@@ -512,6 +512,7 @@ fn transStmt(
         .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
         .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
         .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
+        .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
         else => {
             return revertAndWarn(
                 rp,
@@ -856,6 +857,13 @@ fn transImplicitCastExpr(
         .LValueToRValue, .NoOp => {
             return transExpr(rp, scope, sub_expr, .used, .r_value);
         },
+        .NullToPointer => {
+            return TransResult{
+                .node = try transCreateNodeNullLiteral(rp.c),
+                .node_scope = scope,
+                .child_scope = scope,
+            };
+        },
         else => |kind| return revertAndWarn(
             rp,
             error.UnsupportedTranslation,
@@ -1040,21 +1048,33 @@ fn transInitListExpr(
     expr: *const ZigClangInitListExpr,
     used: ResultUsed,
 ) TransError!TransResult {
-    // TODO use anon literals once they work properly
     const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr));
     const qual_type = ZigClangQualType_getTypePtr(qt);
     const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr));
+    switch (ZigClangType_getTypeClass(qual_type)) {
+        .ConstantArray => {},
+        .Record, .Elaborated => {
+            return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO initListExpr for structs", .{});
+        },
+        else => {
+            const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));
+            return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{}'", .{type_name});
+        },
+    }
+
     const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type);
+    const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type);
     const child_qt = ZigClangArrayType_getElementType(arr_type);
     const init_count = ZigClangInitListExpr_getNumInits(expr);
-    const all_count = 200; //ZigClangArrayType_getSize(arr_type);
+    const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
+    const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize));
     const leftover_count = all_count - init_count;
 
     var init_node: *ast.Node.SuffixOp = undefined;
     var cat_tok: ast.TokenIndex = undefined;
     if (init_count != 0) {
-        var type_node = try transQualType(rp, qt, source_loc);
-        init_node = try transCreateNodeArrayInitializer(rp.c, type_node);
+        const dot_tok = try appendToken(rp.c, .Period, ".");
+        init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok);
         var i: c_uint = 0;
         while (i < init_count) : (i += 1) {
             const elem_expr = ZigClangInitListExpr_getInit(expr, i);
@@ -1072,8 +1092,8 @@ fn transInitListExpr(
         cat_tok = try appendToken(rp.c, .PlusPlus, "++");
     }
 
-    var filler_type_node = try transQualType(rp, qt, source_loc);
-    var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node);
+    const dot_tok = try appendToken(rp.c, .Period, ".");
+    var filler_init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok);
     const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr);
     try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node);
     filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
@@ -1116,6 +1136,58 @@ fn transInitListExpr(
     };
 }
 
+fn transImplicitValueInitExpr(
+    rp: RestorePoint,
+    scope: *Scope,
+    expr: *const ZigClangExpr,
+    used: ResultUsed,
+) TransError!TransResult {
+    const source_loc = ZigClangExpr_getBeginLoc(expr);
+    const qt = getExprQualType(rp.c, expr);
+    const ty = ZigClangQualType_getTypePtr(qt);
+    const node = switch (ZigClangType_getTypeClass(ty)) {
+        .Builtin => blk: {
+            const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
+            switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+                .Bool => {
+                    break :blk try transCreateNodeBoolLiteral(rp.c, false);
+                },
+                .Char_U,
+                .UChar,
+                .Char_S,
+                .Char8,
+                .SChar,
+                .UShort,
+                .UInt,
+                .ULong,
+                .ULongLong,
+                .Short,
+                .Int,
+                .Long,
+                .LongLong,
+                .UInt128,
+                .Int128,
+                .Float,
+                .Double,
+                .Float128,
+                .Float16,
+                .LongDouble,
+                => {
+                    break :blk try transCreateNodeInt(rp.c, 0);
+                },
+                else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
+            }
+        },
+        .Pointer => try transCreateNodeNullLiteral(rp.c),
+        else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}),
+    };
+    return TransResult{
+        .node = node,
+        .child_scope = scope,
+        .node_scope = scope,
+    };
+}
+
 fn findBlockScope(inner: *Scope) *Scope.Block {
     var scope = inner;
     while (true) : (scope = scope.parent orelse unreachable) {
@@ -1593,12 +1665,35 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
     return &node.base;
 }
 
-fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp {
+fn transCreateNodeNullLiteral(c: *Context) !*ast.Node {
+    const token = try appendToken(c, .Keyword_null, "null");
+    const node = try c.a().create(ast.Node.NullLiteral);
+    node.* = ast.Node.NullLiteral{
+        .base = ast.Node{ .id = .NullLiteral },
+        .token = token,
+    };
+    return &node.base;
+}
+
+fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node {
+    const token = if (value)
+        try appendToken(c, .Keyword_true, "true")
+    else
+        try appendToken(c, .Keyword_false, "false");
+    const node = try c.a().create(ast.Node.BoolLiteral);
+    node.* = ast.Node.BoolLiteral{
+        .base = ast.Node{ .id = .BoolLiteral },
+        .token = token,
+    };
+    return &node.base;
+}
+
+fn transCreateNodeArrayInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.Node.SuffixOp {
     _ = try appendToken(c, .LBrace, "{");
     const node = try c.a().create(ast.Node.SuffixOp);
     node.* = ast.Node.SuffixOp{
         .base = ast.Node{ .id = .SuffixOp },
-        .lhs = .{ .node = type_node },
+        .lhs = .{ .dot = dot_tok },
         .op = .{
             .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()),
         },
@@ -1753,7 +1848,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
             const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
 
             const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
-            // const typedef_name = rp.c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl))).?.value;
             const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
             return appendIdentifier(rp.c, typedef_name);
         },
test/translate_c.zig
@@ -252,6 +252,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo;
     });
 
+    cases.add_2("array initializer expr",
+        \\static void foo(void){
+        \\    char arr[10] ={1};
+        \\    char *arr1[10] ={0};
+        \\}
+    , &[_][]const u8{
+        \\pub fn foo() void {
+        \\    var arr: [10]u8 = .{
+        \\        @as(u8, 1),
+        \\    } ++ .{0} ** 9;
+        \\    var arr1: [10][*c]u8 = .{
+        \\        null,
+        \\    } ++ .{null} ** 9;
+        \\}
+    });
+
     /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
 
     cases.add_both("typedef of function in struct field",