211 строки
4,1 КиБ
Go
211 строки
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 {
|
|
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 {
|
|
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
|
|
}
|