Skip to content

Commit

Permalink
Support incrementing a MemberExpr that is is a pointer. Fixes #811 (#812
Browse files Browse the repository at this point in the history
)

For example, if a is a char **, now we can transpile ++*a.
  • Loading branch information
andybalholm authored and elliotchance committed Dec 4, 2018
1 parent 3fa7edc commit 39f4874
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
2 changes: 1 addition & 1 deletion noarch/stdio.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func Fopen(filePath, mode *byte) *File {
err = file.Truncate(0)
}
default:
panic(fmt.Sprintf("unsupported file mode: %s", mode))
panic(fmt.Sprintf("unsupported file mode: %s", m))
}

if err != nil {
Expand Down
23 changes: 22 additions & 1 deletion tests/operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ typedef unsigned char pcre_uchar;
#define PREP_A 0x0002
#define PREP_B 0x0010

void unusedInt(int n) {
;
}

int main()
{
plan(140);
plan(142);

int i = 10;
signed char j = 1;
Expand Down Expand Up @@ -371,6 +375,7 @@ int main()
}
{
int yy = 0;
unusedInt(yy);
if ((yy = simple_repeat(42)) > 3)
{
pass("ok")
Expand Down Expand Up @@ -505,6 +510,22 @@ int main()
flags &= ~(PREP_A|PREP_B);
is_eq(flags, 32);
}
diag("Increment pointer in struct");
{
struct aStruct {
char *a;
} v;
v.a = "Hello";
++v.a;
is_streq(v.a, "ello");
}
diag("Increment pointer via poiter");
{
char *s = "World";
char **p = &s;
++*p;
is_streq(s, "orld");
}

done_testing();
}
30 changes: 20 additions & 10 deletions transpiler/unary.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato
case token.DEC:
operator = token.SUB
}
var declRefExpr *ast.DeclRefExpr
declRefExpr, err = getSoleChildDeclRefExpr(n)
var e ast.Node
e, err = getSoleChildIncrementable(n)
if err != nil {
return
}

var left goast.Expr
var leftType string
var newPre, newPost []goast.Stmt
left, leftType, newPre, newPost, err = transpileToExpr(declRefExpr, p, false)
left, leftType, newPre, newPost, err = transpileToExpr(e, p, false)
if err != nil {
return
}
Expand All @@ -67,13 +67,8 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato

preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

var name string
name, err = getName(p, n.Children()[0])
if err != nil {
return
}
expr = &goast.BinaryExpr{
X: goast.NewIdent(name),
X: left,
Op: token.ASSIGN,
Y: expr,
}
Expand All @@ -85,7 +80,7 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato
}
expr = util.NewAnonymousFunction([]goast.Stmt{&goast.ExprStmt{
X: expr,
}}, nil, goast.NewIdent(name), lType)
}}, nil, left, lType)
}
return
}
Expand Down Expand Up @@ -133,6 +128,21 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato
}, p, exprIsStmt)
}

func getSoleChildIncrementable(n ast.Node) (result ast.Node, err error) {
children := n.Children()
if len(children) != 1 {
return nil, fmt.Errorf("expected one child node, got %d", len(children))
}
switch c := children[0].(type) {
case *ast.ParenExpr:
return getSoleChildIncrementable(c)
case *ast.DeclRefExpr, *ast.MemberExpr, *ast.UnaryOperator:
return c, nil
default:
return nil, fmt.Errorf("unsupported type %T", c)
}
}

func getSoleChildDeclRefExpr(n *ast.UnaryOperator) (result *ast.DeclRefExpr, err error) {
var inspect ast.Node = n
for {
Expand Down

0 comments on commit 39f4874

Please sign in to comment.