Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: find variables without pointer problem #253

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions transpiler/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 *)' <FunctionToPointerDecay>
// | `-DeclRefExpr 'double *(int *const *, double *)' Function 0x30e9f38 'returner' ...
// |-ImplicitCastExpr 'int *const *' <NullToPointer>
// | `-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
}
6 changes: 6 additions & 0 deletions transpiler/transpiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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 {
Expand Down
18 changes: 18 additions & 0 deletions transpiler/unary.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down