go-translator/pkg/service/stmt.go

216 строки
4,1 КиБ
Go

package service
import (
"fmt"
"go/ast"
"go/token"
"strings"
"github.com/davecgh/go-spew/spew"
)
func handleBlockStmt(body *ast.BlockStmt) string {
code := ""
if body == nil {
return code
}
for _, stmt := range body.List {
code += handleStmt(stmt, false)
code += "\n"
}
return code
}
func handleStmt(stmt ast.Stmt, standaloneAssignment bool) string {
// println()
// spew.Dump(stmt)
code := ""
switch s := stmt.(type) {
case *ast.AssignStmt:
code += handleAssignStmt(s)
if !standaloneAssignment {
code += ";"
}
case *ast.IncDecStmt:
code += handleIncDecStmt(s)
if !standaloneAssignment {
code += ";"
}
case *ast.BranchStmt:
code += handleBranchStmt(s)
case *ast.CaseClause:
code += handleCaseClause(s)
case *ast.DeclStmt:
code += handleDeclStmt(s)
case *ast.GoStmt:
code += handleGoStmt(s)
case *ast.ExprStmt:
code += handleExprStmt(s)
code += ";"
case *ast.ForStmt:
code += handleForStmt(s)
case *ast.IfStmt:
code += handleIfStmt(s)
case *ast.SwitchStmt:
code += handleSwitchStmt(s)
case *ast.ReturnStmt:
code += handleReturnStmt(s)
default:
spew.Dump(stmt)
panic("handleStmt: unknown type")
}
return code
}
func handleAssignStmt(as *ast.AssignStmt) (code string) {
tkn, new := handleToken(as.Tok)
if new {
code += "auto "
}
code += handleAssignStmtExpr(as.Lhs)
code += tkn
code += handleAssignStmtExpr(as.Rhs)
return
}
func handleAssignStmtExpr(e []ast.Expr) string {
ops := make([]string, 0)
code := ""
for _, op := range e {
ops = append(ops, handleExpr(op))
}
code += strings.Join(ops, ",")
return code
}
func handleToken(t token.Token) (code string, new bool) {
st := t.String()
switch st {
case ":=":
return "=", true
}
return st, false
}
func handleIncDecStmt(as *ast.IncDecStmt) string {
code := handleExpr(as.X)
code += as.Tok.String()
return code
}
func handleBranchStmt(stmt *ast.BranchStmt) string {
return stmt.Tok.String() + ";"
}
func handleCaseClause(cc *ast.CaseClause) string {
code := "case "
clauses := make([]string, 0)
for _, clause := range cc.List {
clauses = append(clauses, handleExpr(clause))
}
code += strings.Join(clauses, ",")
code += ":"
for _, body := range cc.Body {
code += handleStmt(body, false)
}
return code
}
func handleDeclStmt(stmt *ast.DeclStmt) string {
code := ""
switch decl := stmt.Decl.(type) {
case *ast.GenDecl:
code += handleGenDecl(decl)
}
return code
}
func handleGoStmt(stmt *ast.GoStmt) string {
code := ""
switch f := stmt.Call.Fun.(type) {
case *ast.Ident:
go_helper := FunctionGoHelperPrefix + f.Name
addGoHelperDeclaration(f.Name)
code += `xTaskCreate(` + go_helper + `,"",1024,NULL,1,NULL);` + "\n"
}
return code
}
func addGoHelperDeclaration(f string) {
dlock.Lock()
defer dlock.Unlock()
helpersForDeclarations = append(helpersForDeclarations, f)
}
func handleExprStmt(stmt *ast.ExprStmt) string {
code := ""
switch x := stmt.X.(type) {
case *ast.CallExpr:
code += handleCallExpr(x)
}
return code
}
func handleForStmt(stmt *ast.ForStmt) string {
code := ""
is_while := false
if stmt.Init == nil && stmt.Post == nil {
is_while = true
code += "while"
} else {
code += "for"
}
code += "("
if !is_while {
code += handleStmt(stmt.Init, true)
code += ";"
}
if stmt.Cond != nil {
code += handleBinaryExpr(stmt.Cond)
} else {
code += "1"
}
if !is_while {
code += ";"
code += handleStmt(stmt.Post, true)
}
code += ") {\n"
code += handleBlockStmt(stmt.Body)
code += "}"
return code
}
func handleIfStmt(stmt *ast.IfStmt) string {
// println()
// spew.Dump(stmt)
cond := handleExpr(stmt.Cond)
body := handleBlockStmt(stmt.Body)
code := fmt.Sprintf("if (%s) {\n %s }\n", cond, body)
if stmt.Else != nil {
tail := handleBlockStmt(stmt.Else.(*ast.BlockStmt))
code += fmt.Sprintf(" else {\n %s }\n", tail)
}
return code
}
func handleSwitchStmt(stmt *ast.SwitchStmt) string {
code := "switch ("
code += handleExpr(stmt.Tag)
code += "){"
code += handleBlockStmt(stmt.Body)
code += "}"
return code
}
func handleReturnStmt(stmt *ast.ReturnStmt) string {
code := "return "
if len(stmt.Results) > 0 {
code += handleExpr(stmt.Results[0])
}
code += ";"
return code
}