From 1be5add6c585fa8bfb57b37453b7c50b533fa325 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Tue, 13 Nov 2018 15:17:14 +0300 Subject: [PATCH] Proposal: find variables without pointer problem --- transpiler/functions.go | 117 +++++++++++++++++++++++++++++++++++++++ transpiler/transpiler.go | 6 ++ transpiler/unary.go | 18 ++++++ 3 files changed, 141 insertions(+) diff --git a/transpiler/functions.go b/transpiler/functions.go index 0801ad81..82fa078c 100644 --- a/transpiler/functions.go +++ b/transpiler/functions.go @@ -361,3 +361,120 @@ func transpileReturnStmt(n *ast.ReturnStmt, p *program.Program) ( Results: results, }, preStmts, postStmts, nil } + +// analyze function +func analyzeFunctionDec(n *ast.FunctionDecl, p *program.Program) (names []string) { + // create list of variables not pointer + var f func(ast.Node) + f = func(a ast.Node) { + switch v := a.(type) { + case *ast.VarDecl: + if types.IsPointer(v.Type) || types.IsFunction(v.Type) { + return + } + if !(types.IsCInteger(p, v.Type) || types.IsCFloat(p, v.Type)) { + return + } + names = append(names, v.Name) + default: + if a != nil { + for i := range a.Children() { + if a.Children() != nil { + f(a.Children()[i]) + } + } + } + } + } + f(n) + + if len(names) == 0 { + return + } + + // find all using + var excluder func(ast.Node, string) bool + + var unaryEx func(ast.Node, string) bool + unaryEx = func(a ast.Node, name string) bool { + switch v := a.(type) { + case *ast.UnaryOperator: + // `-UnaryOperator 0x32d53e8 'float *' prefix '&' + // `-DeclRefExpr 0x32d53c0 'float' lvalue Var 0x32d5298 'o' 'float' <<----- + if decl, ok := v.Children()[0].(*ast.DeclRefExpr); ok { + if decl.Name == name { + return true + } + } else { + return unaryEx(v.Children()[0], name) + } + + default: + if a != nil { + for i := range a.Children() { + if a.Children()[i] != nil { + if unaryEx(a.Children()[i], name) { + return true + } + } + } + } + } + return false + } + + excluder = func(a ast.Node, name string) bool { + switch v := a.(type) { + case *ast.VarDecl: + // VarDecl used oo 'float *' cinit + // `-UnaryOperator 0x32d53e8 'float *' prefix '&' + // `-DeclRefExpr 0x32d53c0 'float' lvalue Var 0x32d5298 'o' 'float' <<----- + if len(v.Children()) != 0 { + return unaryEx(v, name) + } + + case *ast.CallExpr: + // CallExpr 'double *' + // |-ImplicitCastExpr 'double *(*)(int *const *, double *)' + // | `-DeclRefExpr 'double *(int *const *, double *)' Function 0x30e9f38 'returner' ... + // |-ImplicitCastExpr 'int *const *' + // | `-IntegerLiteral 'int' 0 + // `-UnaryOperator 'double *' prefix '&' + // `-DeclRefExpr 'double' lvalue Var 0x30ed938 'fd' 'double' + if len(v.Children()) != 0 { + return unaryEx(v, name) + } + + case *ast.BinaryOperator: + // BinaryOperator 'int *' '=' + // |-DeclRefExpr 'int *' lvalue Var 0x294fbb0 'b' 'int *' + // `-UnaryOperator 'int *' prefix '&' + // `-DeclRefExpr 'int' lvalue Var 0x294fb00 'a' 'int' <<-- + if len(v.Children()) != 0 { + return unaryEx(v, name) + } + + default: + if a != nil { + for i := range a.Children() { + if a.Children()[i] != nil { + if excluder(a.Children()[i], name) { + return true + } + } + } + } + } + return false + } + + var correctNames []string + for i := range names { + if excluder(n, names[i]) { + continue + } + correctNames = append(correctNames, names[i]) + } + + return correctNames +} diff --git a/transpiler/transpiler.go b/transpiler/transpiler.go index 163e3543..08023d90 100644 --- a/transpiler/transpiler.go +++ b/transpiler/transpiler.go @@ -372,6 +372,8 @@ func transpileToStmt(node ast.Node, p *program.Program) ( return } +var VarNameNotPointer []string + func transpileToNode(node ast.Node, p *program.Program) ( decls []goast.Decl, err error) { defer func() { @@ -403,6 +405,10 @@ func transpileToNode(node ast.Node, p *program.Program) ( switch n := node.(type) { case *ast.FunctionDecl: + // analyze variables + VarNameNotPointer = analyzeFunctionDec(n, p) + + // transpile com := p.GetComments(node.Position()) decls, err = transpileFunctionDecl(n, p) if len(decls) > 0 { diff --git a/transpiler/unary.go b/transpiler/unary.go index 3e8b8f35..956d248b 100644 --- a/transpiler/unary.go +++ b/transpiler/unary.go @@ -265,6 +265,24 @@ func transpileUnaryOperatorAmpersant(n *ast.UnaryOperator, p *program.Program) ( return } + if decl, ok := n.Children()[0].(*ast.DeclRefExpr); ok { + var found bool + for i := range VarNameNotPointer { + if decl.Name == VarNameNotPointer[i] { + found = true + break + } + } + if found { + expr = &goast.UnaryExpr{ + Op: token.AND, // & + X: util.NewIdent(decl.Name), + } + eType = n.Type + return + } + } + p.AddImport("unsafe") expr = util.CreateSliceFromReference(resolvedType, expr)