github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/transpiler/scope.go (about)

     1  // This file contains functions for transpiling scopes. A scope is zero or more
     2  // statements between a set of curly brackets.
     3  
     4  package transpiler
     5  
     6  import (
     7  	"fmt"
     8  	goast "go/ast"
     9  	"go/token"
    10  
    11  	"github.com/Konstantin8105/c4go/ast"
    12  	"github.com/Konstantin8105/c4go/program"
    13  )
    14  
    15  func transpileCompoundStmt(n *ast.CompoundStmt, p *program.Program) (
    16  	_ *goast.BlockStmt, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) {
    17  	stmts := []goast.Stmt{}
    18  
    19  	for _, x := range n.Children() {
    20  		// add '_ = '
    21  		var addPrefix bool
    22  		if impl, ok := x.(*ast.ImplicitCastExpr); ok && len(impl.Children()) == 1 {
    23  			if _, ok := impl.Children()[0].(*ast.ArraySubscriptExpr); ok {
    24  				addPrefix = true
    25  			}
    26  		}
    27  
    28  		var result []goast.Stmt
    29  		// Other cases
    30  		if parent, ok := x.(*ast.ParenExpr); ok {
    31  			x = parent.Children()[0]
    32  		}
    33  		result, err = transpileToStmts(x, p)
    34  		if err != nil {
    35  			return nil, nil, nil, err
    36  		}
    37  		if addPrefix && len(result) == 1 {
    38  			// goast.Print(token.NewFileSet(), result[0])
    39  			result[0] = &goast.AssignStmt{
    40  				Lhs: []goast.Expr{goast.NewIdent("_")},
    41  				Tok: token.ASSIGN,
    42  				Rhs: []goast.Expr{result[0].(*goast.ExprStmt).X},
    43  			}
    44  		}
    45  
    46  		if result != nil {
    47  			stmts = append(stmts, result...)
    48  		}
    49  
    50  	}
    51  
    52  	return &goast.BlockStmt{
    53  		List: stmts,
    54  	}, preStmts, postStmts, nil
    55  }
    56  
    57  func transpileToBlockStmt(node ast.Node, p *program.Program) (
    58  	*goast.BlockStmt, []goast.Stmt, []goast.Stmt, error) {
    59  	stmts, err := transpileToStmts(node, p)
    60  	if err != nil {
    61  		return nil, nil, nil, err
    62  	}
    63  
    64  	if len(stmts) == 1 {
    65  		if block, ok := stmts[0].(*goast.BlockStmt); ok {
    66  			return block, nil, nil, nil
    67  		}
    68  	}
    69  
    70  	if stmts == nil {
    71  		return nil, nil, nil, fmt.Errorf("stmts inside Block cannot be nil")
    72  	}
    73  
    74  	return &goast.BlockStmt{
    75  		List: stmts,
    76  	}, nil, nil, nil
    77  }