Сценарий: Интерфейс - это класс с виртуальными методами

Этот коммит содержится в:
Softonik 2024-02-12 00:48:18 +03:00 коммит произвёл Nobody
родитель 04c61b67a1
коммит 0516d8178a
5 изменённых файлов: 168 добавлений и 34 удалений

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

@ -4,30 +4,40 @@ import (
"go/ast" "go/ast"
) )
type Class interface {
Name() string
String() string
AddMethod(*ast.FuncDecl)
}
var ( var (
classDeclarations []*Class classDeclarations []Class
isInMethod = false isInMethod = false
currentReceiverName = "" currentReceiverName = ""
) )
type Class struct { type class struct {
Name string name string
Struct *ast.StructType Struct *ast.StructType
methods []*ast.FuncDecl methods []*ast.FuncDecl
} }
func NewClass(className string) *Class { func NewClass(name string) *class {
return &Class{Name: className} return &class{name: name}
} }
func (c *Class) String() (code string) { func (c *class) Name() string {
return c.name
}
func (c *class) String() (code string) {
code += c.classDefinitionToString() code += c.classDefinitionToString()
code += c.methodImplementationsToString() code += c.methodImplementationsToString()
return return
} }
func (c *Class) classDefinitionToString() (code string) { func (c *class) classDefinitionToString() (code string) {
code = "class " + c.Name + " {" code = "class " + c.name + " {"
code += "public:\n" code += "public:\n"
code += c.structToString() code += c.structToString()
@ -39,19 +49,19 @@ func (c *Class) classDefinitionToString() (code string) {
code += "};\n" code += "};\n"
return return
} }
func (c *Class) structToString() (code string) { func (c *class) structToString() (code string) {
code += handleExpr(c.Struct) code += handleExpr(c.Struct)
code += "\n" code += "\n"
return return
} }
func (c *Class) methodDeclarationsToString() (code string) { func (c *class) methodDeclarationsToString() (code string) {
for _, m := range c.methods { for _, m := range c.methods {
code += c.methodDeclarationToString(m) code += c.methodDeclarationToString(m)
} }
code += "\n" code += "\n"
return return
} }
func (c *Class) methodDeclarationToString(m *ast.FuncDecl) (code string) { func (c *class) methodDeclarationToString(m *ast.FuncDecl) (code string) {
code += " " code += " "
code += handleFuncDeclType(m.Type) code += handleFuncDeclType(m.Type)
code += " " code += " "
@ -62,7 +72,7 @@ func (c *Class) methodDeclarationToString(m *ast.FuncDecl) (code string) {
return return
} }
func (c *Class) methodImplementationsToString() (code string) { func (c *class) methodImplementationsToString() (code string) {
for _, m := range c.methods { for _, m := range c.methods {
code += c.methodImplementationToString(m) code += c.methodImplementationToString(m)
} }
@ -70,10 +80,10 @@ func (c *Class) methodImplementationsToString() (code string) {
return return
} }
func (c *Class) methodImplementationToString(m *ast.FuncDecl) (code string) { func (c *class) methodImplementationToString(m *ast.FuncDecl) (code string) {
code += handleFuncDeclType(m.Type) code += handleFuncDeclType(m.Type)
code += " " code += " "
code += c.Name + "::" code += c.name + "::"
code += m.Name.String() + "(" code += m.Name.String() + "("
code += handleFuncDeclParams(m.Type) code += handleFuncDeclParams(m.Type)
code += ") {" code += ") {"
@ -92,7 +102,7 @@ func (c *Class) methodImplementationToString(m *ast.FuncDecl) (code string) {
return return
} }
func (c *Class) AddMethod(m *ast.FuncDecl) { func (c *class) AddMethod(m *ast.FuncDecl) {
c.methods = append(c.methods, m) c.methods = append(c.methods, m)
} }
@ -101,9 +111,10 @@ func handleClass(name string, st *ast.StructType) string {
addClassFromStructType(name, st) addClassFromStructType(name, st)
return "" return ""
} }
func addClassFromStructType(name string, s *ast.StructType) { func addClassFromStructType(name string, s *ast.StructType) Class {
c := createClass(name) c := createClass(name)
c.Struct = s c.Struct = s
return c
} }
func handleMethodDeclaration(fd *ast.FuncDecl) string { func handleMethodDeclaration(fd *ast.FuncDecl) string {
@ -112,7 +123,7 @@ func handleMethodDeclaration(fd *ast.FuncDecl) string {
return "" return ""
} }
func getOrCreateClassFromFuncDecl(fd *ast.FuncDecl) *Class { func getOrCreateClassFromFuncDecl(fd *ast.FuncDecl) Class {
n := getClassNameFromReceiver(fd.Recv) n := getClassNameFromReceiver(fd.Recv)
return getOrCreateClass(n) return getOrCreateClass(n)
} }
@ -131,9 +142,9 @@ func getClassNameFromStarReceiver(expr ast.Expr) string {
return "" return ""
} }
func getOrCreateClass(className string) *Class { func getOrCreateClass(className string) Class {
for _, c := range classDeclarations { for _, c := range classDeclarations {
if c.Name == className { if c.Name() == className {
return c return c
} }
} }
@ -141,13 +152,13 @@ func getOrCreateClass(className string) *Class {
return createClass(className) return createClass(className)
} }
func createClass(className string) *Class { func createClass(className string) *class {
c := NewClass(className) c := NewClass(className)
addClassDeclaration(c) addClassDeclaration(c)
return c return c
} }
func addClassDeclaration(c *Class) { func addClassDeclaration(c Class) {
dlock.Lock() dlock.Lock()
defer dlock.Unlock() defer dlock.Unlock()

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

@ -0,0 +1,87 @@
package service
import (
"go/ast"
"strings"
)
type abstractClass struct {
name string
Interface *ast.InterfaceType
}
func NewAbstractClass(name string) *abstractClass {
return &abstractClass{name: name}
}
func (c *abstractClass) Name() string {
return c.name
}
func (c *abstractClass) String() (code string) {
code += c.abstractClassDefinitionToString()
return
}
func (c *abstractClass) abstractClassDefinitionToString() (code string) {
code = "class " + c.name + " {"
code += "public:\n"
code += c.methodDeclarationsToString()
code += "\n"
code += "};\n"
return
}
func (c *abstractClass) methodDeclarationsToString() (code string) {
for _, f := range c.Interface.Methods.List {
code += c.fieldDeclarationToString(f)
}
code += "\n"
return
}
func (c *abstractClass) fieldDeclarationToString(f *ast.Field) (code string) {
code += " virtual "
switch s := f.Type.(type) {
case *ast.FuncType:
code += handleFuncDeclType(s)
code += " "
code += handleIdentExpr(f.Names[0])
code += "("
code += handleAbstractFuncDeclParams(s)
code += ") = 0;"
}
return
}
func handleAbstractFuncDeclParams(t *ast.FuncType) (code string) {
if t.Params == nil || t.Params.List == nil {
return
}
values := make([]string, 0)
for _, field := range t.Params.List {
switch ft := field.Type.(type) {
case *ast.Ident:
t := handleIdentExpr(ft)
values = append(values, t)
}
}
code += strings.Join(values, ",")
return
}
func (c *abstractClass) AddMethod(m *ast.FuncDecl) {}
func handleClassAbstract(name string, it *ast.InterfaceType) string {
addAbstractClassFromStructType(name, it)
return ""
}
func addAbstractClassFromStructType(name string, it *ast.InterfaceType) Class {
c := createAbstractClass(name)
c.Interface = it
return c
}
func createAbstractClass(className string) *abstractClass {
c := NewAbstractClass(className)
addClassDeclaration(c)
return c
}

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

@ -25,6 +25,8 @@ func handleExpr(expr ast.Expr) string {
code += handleSelectorExpr(e) code += handleSelectorExpr(e)
case *ast.StructType: case *ast.StructType:
code += handleStructType(e) code += handleStructType(e)
case *ast.InterfaceType:
code += handleInterfaceType(e)
case *ast.ArrayType: case *ast.ArrayType:
code += handleArray(e) code += handleArray(e)
} }
@ -54,7 +56,7 @@ func handleUnaryExpr(expr *ast.UnaryExpr) (code string) {
cl, ok := expr.X.(*ast.CompositeLit) cl, ok := expr.X.(*ast.CompositeLit)
if ok { if ok {
code += "new " code += "new "
code += handleIdentExpr(cl.Type) code += handleIdentExpr(cl.Type.(*ast.Ident))
code += "()" code += "()"
} else { } else {
code += expr.Op.String() code += expr.Op.String()
@ -71,8 +73,8 @@ func handleBinaryExpr(expr ast.Expr) string {
return code return code
} }
func handleCallExpr(expr *ast.CallExpr) string { func handleCallExpr(expr *ast.CallExpr) (code string) {
code := handleExpr(expr.Fun) code = handleExpr(expr.Fun)
code += "(" code += "("
args := make([]string, 0) args := make([]string, 0)
for _, arg := range expr.Args { for _, arg := range expr.Args {
@ -80,11 +82,10 @@ func handleCallExpr(expr *ast.CallExpr) string {
} }
code += strings.Join(args, ",") code += strings.Join(args, ",")
code += ")" code += ")"
return code return
} }
func handleIdentExpr(expr ast.Expr) string { func handleIdentExpr(ident *ast.Ident) string {
ident := expr.(*ast.Ident)
code := "" code := ""
switch ident.Name { switch ident.Name {
case "nil": case "nil":

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

@ -25,6 +25,29 @@ type device struct {}
class device { class device {
public: public:
}; };
```
Сценарий: Интерфейс - это класс с виртуальными методами
* Исходник:
```
package test
type Device interface {
Name() string
String() string
Add(int)
Add2(int,float64)
}
```
* Результат:
```
class Device {
public:
virtual std::string Name() = 0;
virtual std::string String() = 0;
virtual void Add(int) = 0;
virtual void Add2(int,double) = 0;
};
``` ```
Сценарий: Структура с полем Сценарий: Структура с полем

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

@ -9,9 +9,11 @@ var (
) )
func handleTypeSpec(s *ast.TypeSpec) (code string) { func handleTypeSpec(s *ast.TypeSpec) (code string) {
st, ok := s.Type.(*ast.StructType) switch t := s.Type.(type) {
if ok { case *ast.StructType:
return handleClass(s.Name.String(), st) return handleClass(s.Name.String(), t)
case *ast.InterfaceType:
return handleClassAbstract(s.Name.String(), t)
} }
return handleType(s) return handleType(s)
@ -48,6 +50,10 @@ func handleStructType(s *ast.StructType) (code string) {
return handleFieldList(s.Fields) return handleFieldList(s.Fields)
} }
func handleInterfaceType(s *ast.InterfaceType) (code string) {
return handleFieldList(s.Methods)
}
func handleFieldList(l *ast.FieldList) string { func handleFieldList(l *ast.FieldList) string {
code := "" code := ""
for _, f := range l.List { for _, f := range l.List {
@ -56,10 +62,16 @@ func handleFieldList(l *ast.FieldList) string {
return code return code
} }
func handleField(f *ast.Field) string { func handleField(f *ast.Field) (code string) {
code := ""
code += " " code += " "
code += handleIdentExpr(f.Type)
switch t := f.Type.(type) {
case *ast.Ident:
code += handleIdentExpr(t)
case *ast.FuncType:
code += handleFuncDeclType(t)
}
code += " " code += " "
nado_zapyatuyu := false nado_zapyatuyu := false
for _, n := range f.Names { for _, n := range f.Names {
@ -70,5 +82,5 @@ func handleField(f *ast.Field) string {
nado_zapyatuyu = true nado_zapyatuyu = true
} }
code += ";\n" code += ";\n"
return code return
} }