Commit c2666c48a4

Vexu <git@vexu.eu>
2019-12-18 21:57:53
translate-c-2 array access
1 parent cf7a5b7
Changed files (4)
src-self-hosted/c_tokenizer.zig
@@ -28,6 +28,8 @@ pub const CToken = struct {
         Comma,
         Fn,
         Arrow,
+        LBrace,
+        RBrace,
     };
 
     pub const NumLitSuffix = enum {
@@ -289,6 +291,14 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
                         result.id = .Comma;
                         state = .Done;
                     },
+                    '[' => {
+                        result.id = .LBrace;
+                        state = .Done;
+                    },
+                    ']' => {
+                        result.id = .RBrace;
+                        state = .Done;
+                    },
                     else => return error.TokenizingFailed,
                 }
             },
src-self-hosted/clang.zig
@@ -1102,3 +1102,6 @@ pub extern fn ZigClangMemberExpr_getBase(*const ZigClangMemberExpr) *const ZigCl
 pub extern fn ZigClangMemberExpr_isArrow(*const ZigClangMemberExpr) bool;
 pub extern fn ZigClangMemberExpr_getMemberDecl(*const ZigClangMemberExpr) *const ZigClangValueDecl;
 
+pub extern fn ZigClangArraySubscriptExpr_getBase(*const ZigClangArraySubscriptExpr) *const ZigClangExpr;
+pub extern fn ZigClangArraySubscriptExpr_getIdx(*const ZigClangArraySubscriptExpr) *const ZigClangExpr;
+
src-self-hosted/translate_c.zig
@@ -850,6 +850,7 @@ fn transStmt(
         .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used),
         .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used),
         .MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const ZigClangMemberExpr, stmt), result_used),
+        .ArraySubscriptExprClass => return transArrayAccess(rp, scope, @ptrCast(*const ZigClangArraySubscriptExpr, stmt), result_used),
         else => {
             return revertAndWarn(
                 rp,
@@ -1523,7 +1524,7 @@ fn transInitListExpr(
     var cat_tok: ast.TokenIndex = undefined;
     if (init_count != 0) {
         const dot_tok = try appendToken(rp.c, .Period, ".");
-        init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok);
+        init_node = try transCreateNodeContainerInitializer(rp.c, dot_tok);
         var i: c_uint = 0;
         while (i < init_count) : (i += 1) {
             const elem_expr = ZigClangInitListExpr_getInit(expr, i);
@@ -1538,7 +1539,7 @@ fn transInitListExpr(
     }
 
     const dot_tok = try appendToken(rp.c, .Period, ".");
-    var filler_init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok);
+    var filler_init_node = try transCreateNodeContainerInitializer(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));
     filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
@@ -1995,6 +1996,14 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE
     return maybeSuppressResult(rp, scope, result_used, node);
 }
 
+fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArraySubscriptExpr, result_used: ResultUsed) TransError!*ast.Node {
+    const container_node = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getBase(stmt), .used, .r_value);
+    const node = try transCreateNodeArrayAccess(rp.c, container_node);
+    node.op.ArrayAccess = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getIdx(stmt), .used, .r_value);
+    node.rtoken = try appendToken(rp.c, .RBrace, "]");
+    return maybeSuppressResult(rp, scope, result_used, &node.base);
+}
+
 fn transCPtrCast(
     rp: RestorePoint,
     loc: ZigClangSourceLocation,
@@ -2643,7 +2652,7 @@ fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node {
     return &node.base;
 }
 
-fn transCreateNodeArrayInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.Node.SuffixOp {
+fn transCreateNodeContainerInitializer(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{
@@ -2972,6 +2981,19 @@ fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
     return &node.base;
 }
 
+fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.SuffixOp {
+    _  = try appendToken(c, .LBrace, "[");
+    const node = try c.a().create(ast.Node.SuffixOp);
+    node.* = .{
+        .lhs = .{ .node = lhs },
+        .op = .{
+            .ArrayAccess = undefined,
+        },
+        .rtoken = undefined,
+    };
+    return node;
+}
+
 const RestorePoint = struct {
     c: *Context,
     token_index: ast.TokenIndex,
@@ -3869,26 +3891,14 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
             .Dot => {
                 const name_tok = it.next().?;
                 if (name_tok.id != .Identifier)
-                    return revertAndWarn(
-                        rp,
-                        error.ParseError,
-                        source_loc,
-                        "unable to translate C expr",
-                        .{},
-                    );
+                    return error.ParseError;
 
                 node = try transCreateNodeFieldAccess(rp.c, node, name_tok.bytes);
             },
             .Arrow => {
                 const name_tok = it.next().?;
                 if (name_tok.id != .Identifier)
-                    return revertAndWarn(
-                        rp,
-                        error.ParseError,
-                        source_loc,
-                        "unable to translate C expr",
-                        .{},
-                    );
+                    return error.ParseError;
 
                 const deref = try transCreateNodePtrDeref(rp.c, node);
                 node = try transCreateNodeFieldAccess(rp.c, deref, name_tok.bytes);
@@ -3929,6 +3939,14 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
                 };
                 node = &bitshift_node.base;
             },
+            .LBrace => {
+                const arr_node = try transCreateNodeArrayAccess(rp.c, node);
+                arr_node.op.ArrayAccess = try parseCPrimaryExpr(rp, it, source_loc, scope);
+                arr_node.rtoken = try appendToken(rp.c, .RBrace, "]");
+                node = &arr_node.base;
+                if (it.next().?.id != .RBrace)
+                    return error.ParseError;
+            },
             else => {
                 _ = it.prev();
                 return node;
test/translate_c.zig
@@ -1523,6 +1523,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub const ARROW = a.*.b;
     });
 
+    cases.add_2("array access",
+        \\#define ACCESS array[2]
+        \\int array[100] = {};
+        \\int foo(int index) {
+        \\    return array[index];
+        \\}
+    , &[_][]const u8{
+        \\pub export var array: [100]c_int = .{0} ** 100;
+        \\pub export fn foo(index: c_int) c_int {
+        \\    return array[index];
+        \\}
+    ,
+        \\pub const ACCESS = array[2];
+    });
+
     /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
 
     cases.addAllowWarnings("simple data types",
@@ -1731,18 +1746,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
-    cases.addC("array access",
-        \\int array[100];
-        \\int foo(int index) {
-        \\    return array[index];
-        \\}
-    , &[_][]const u8{
-        \\pub var array: [100]c_int = undefined;
-        \\pub export fn foo(index: c_int) c_int {
-        \\    return array[index];
-        \\}
-    });
-
     cases.addC("sizeof",
         \\#include <stddef.h>
         \\size_t size_of(void) {
@@ -2656,4 +2659,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    return foo.*.field;
         \\}
     });
+
+    cases.addC("array access",
+        \\int array[100];
+        \\int foo(int index) {
+        \\    return array[index];
+        \\}
+    , &[_][]const u8{
+        \\pub var array: [100]c_int = undefined;
+        \\pub export fn foo(index: c_int) c_int {
+        \\    return array[index];
+        \\}
+    });
 }