translate-c-2 array initializer expr

This commit is contained in:
Vexu 2019-12-14 10:41:00 +02:00
parent e4ca1f441b
commit a4ac6d15c4
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 120 additions and 10 deletions

View File

@ -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);
},

View File

@ -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",