Сценарий: Структура с методом

Этот коммит содержится в:
Softonik 2024-01-22 15:29:31 +03:00 коммит произвёл Nobody
родитель b6cb81fc11
коммит 5e7dec08df
6 изменённых файлов: 195 добавлений и 22 удалений

144
pkg/service/class.go Обычный файл
Просмотреть файл

@ -0,0 +1,144 @@
package service
import (
"go/ast"
)
var (
classDeclarations []*Class
)
type Class struct {
Name string
Struct *ast.StructType
methods []*ast.FuncDecl
}
func NewClass(className string) *Class {
return &Class{Name: className}
}
func (c *Class) String() (code string) {
code += c.classDefinitionToString()
code += c.methodImplementationsToString()
return
}
func (c *Class) classDefinitionToString() (code string) {
code = "class " + c.Name + " {"
code += "public:\n"
code += c.structToString()
code += "\n"
code += c.methodDeclarationsToString()
code += "\n"
code += "};\n"
return
}
func (c *Class) structToString() (code string) {
code += handleExpr(c.Struct)
code += "\n"
return
}
func (c *Class) methodDeclarationsToString() (code string) {
for _, m := range c.methods {
code += c.methodDeclarationToString(m)
}
code += "\n"
return
}
func (c *Class) methodDeclarationToString(m *ast.FuncDecl) (code string) {
code += " "
code += "void " + m.Name.String() + "();"
code += "\n"
return
}
func (c *Class) methodImplementationsToString() (code string) {
for _, m := range c.methods {
code += c.methodImplementationToString(m)
}
code += "\n"
return
}
func (c *Class) methodImplementationToString(m *ast.FuncDecl) (code string) {
code += "void "
code += c.Name + "::"
code += m.Name.String() + "("
code += ") {"
code += handleBlockStmt(m.Body)
code += "}"
code += "\n"
return
}
func (c *Class) AddMethod(m *ast.FuncDecl) {
c.methods = append(c.methods, m)
}
// Handlers
func handleClass(t *ast.TypeSpec) string {
st, ok := t.Type.(*ast.StructType)
if !ok {
return ""
}
addClassFromStructType(t.Name.String(), st)
return ""
}
func addClassFromStructType(name string, s *ast.StructType) {
c := createClass(name)
c.Struct = s
}
func handleMethodDeclaration(fd *ast.FuncDecl) string {
class := getOrCreateClassFromFuncDecl(fd)
class.AddMethod(fd)
return ""
}
func getOrCreateClassFromFuncDecl(fd *ast.FuncDecl) *Class {
n := getClassNameFromReceiver(fd.Recv)
return getOrCreateClass(n)
}
func getClassNameFromReceiver(recv *ast.FieldList) string {
for _, f := range recv.List {
return getClassNameFromStarReceiver(f.Type)
}
return ""
}
func getClassNameFromStarReceiver(expr ast.Expr) string {
switch e := expr.(type) {
case *ast.StarExpr:
return handleExpr(e.X)
}
return ""
}
func getOrCreateClass(className string) *Class {
for _, c := range classDeclarations {
if c.Name == className {
return c
}
}
return createClass(className)
}
func createClass(className string) *Class {
c := NewClass(className)
addClassDeclaration(c)
return c
}
func addClassDeclaration(c *Class) {
dlock.Lock()
defer dlock.Unlock()
classDeclarations = append(classDeclarations, c)
}

Просмотреть файл

@ -79,3 +79,26 @@ public:
std::string c,d,e;
};
```
@f
Сценарий: Структура с методом
* Исходник:
```
package test
type device struct {
a int
}
func (d *device) doSomething() {
}
```
* Результат:
```
class device {
public:
int a;
void doSomething();
};
void device::doSomething() {
}
```

Просмотреть файл

@ -7,6 +7,12 @@ import (
func handleFuncDecl(decl ast.Decl) string {
fd := decl.(*ast.FuncDecl)
if fd.Recv != nil {
return handleMethodDeclaration(fd)
}
return handleFunctionDeclaration(fd)
}
func handleFunctionDeclaration(fd *ast.FuncDecl) string {
if shouldSkipFunction(fd.Type) {
return ""
}

Просмотреть файл

@ -11,6 +11,7 @@ import (
"github.com/cucumber/godog/colors"
. "github.com/onsi/gomega"
gomega_format "github.com/onsi/gomega/format"
)
func InitializeScenario(ctx *godog.ScenarioContext) {
@ -47,6 +48,7 @@ func TestMain(t *testing.T) {
StopOnFailure: true,
TestingT: t,
}
gomega_format.CharactersAroundMismatchToInclude = 100
godog.BindCommandLineFlags("godog.", &opts)
godog.TestSuite{

Просмотреть файл

@ -86,6 +86,7 @@ func (s *defaultService) Start() error {
dst[i] = make(chan string, 1)
}
classDeclarations = nil
funcDeclarations = nil
helpersForDeclarations = nil
@ -103,6 +104,7 @@ func (s *defaultService) Start() error {
}
s.printIncludeHeaders()
s.printClassDeclarations()
s.printFunctionDeclarations()
s.printGoHelperDeclarations()
@ -128,6 +130,19 @@ func (s *defaultService) printIncludeHeaders() {
h := "#include <Arduino.h>\n\n"
s.out.Write([]byte(h))
}
func (s *defaultService) printClassDeclarations() {
dlock.Lock()
defer dlock.Unlock()
for _, c := range classDeclarations {
d := c.String()
s.out.Write([]byte(d + "\n"))
if s.header != nil {
s.header.Write([]byte(d + "\n"))
}
}
s.out.Write([]byte("\n"))
}
func (s *defaultService) printFunctionDeclarations() {
dlock.Lock()
defer dlock.Unlock()

Просмотреть файл

@ -4,31 +4,14 @@ import (
"go/ast"
)
func handleTypeSpec(spec ast.Spec) string {
func handleTypeSpec(spec ast.Spec) (code string) {
s := spec.(*ast.TypeSpec)
code := "class"
code += " "
code += s.Name.String()
code += " "
code += "{\n"
code += handleClass(s.Type)
// spew.Dump(s.TypeParams)
code += "};\n"
return code
handleClass(s)
return
}
func handleClass(e ast.Expr) string {
code := ""
code += "public:\n"
code += handleExpr(e)
// spew.Dump(e)
return code
}
func handleStructType(s *ast.StructType) string {
code := ""
code += handleFieldList(s.Fields)
return code
func handleStructType(s *ast.StructType) (code string) {
return handleFieldList(s.Fields)
}
func handleFieldList(l *ast.FieldList) string {