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

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

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

@ -4,30 +4,40 @@ import (
"go/ast"
)
type Class interface {
Name() string
String() string
AddMethod(*ast.FuncDecl)
}
var (
classDeclarations []*Class
classDeclarations []Class
isInMethod = false
currentReceiverName = ""
)
type Class struct {
Name string
type class struct {
name string
Struct *ast.StructType
methods []*ast.FuncDecl
}
func NewClass(className string) *Class {
return &Class{Name: className}
func NewClass(name string) *class {
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.methodImplementationsToString()
return
}
func (c *Class) classDefinitionToString() (code string) {
code = "class " + c.Name + " {"
func (c *class) classDefinitionToString() (code string) {
code = "class " + c.name + " {"
code += "public:\n"
code += c.structToString()
@ -39,19 +49,19 @@ func (c *Class) classDefinitionToString() (code string) {
code += "};\n"
return
}
func (c *Class) structToString() (code string) {
func (c *class) structToString() (code string) {
code += handleExpr(c.Struct)
code += "\n"
return
}
func (c *Class) methodDeclarationsToString() (code string) {
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) {
func (c *class) methodDeclarationToString(m *ast.FuncDecl) (code string) {
code += " "
code += handleFuncDeclType(m.Type)
code += " "
@ -62,7 +72,7 @@ func (c *Class) methodDeclarationToString(m *ast.FuncDecl) (code string) {
return
}
func (c *Class) methodImplementationsToString() (code string) {
func (c *class) methodImplementationsToString() (code string) {
for _, m := range c.methods {
code += c.methodImplementationToString(m)
}
@ -70,10 +80,10 @@ func (c *Class) methodImplementationsToString() (code string) {
return
}
func (c *Class) methodImplementationToString(m *ast.FuncDecl) (code string) {
func (c *class) methodImplementationToString(m *ast.FuncDecl) (code string) {
code += handleFuncDeclType(m.Type)
code += " "
code += c.Name + "::"
code += c.name + "::"
code += m.Name.String() + "("
code += handleFuncDeclParams(m.Type)
code += ") {"
@ -92,7 +102,7 @@ func (c *Class) methodImplementationToString(m *ast.FuncDecl) (code string) {
return
}
func (c *Class) AddMethod(m *ast.FuncDecl) {
func (c *class) AddMethod(m *ast.FuncDecl) {
c.methods = append(c.methods, m)
}
@ -101,9 +111,10 @@ func handleClass(name string, st *ast.StructType) string {
addClassFromStructType(name, st)
return ""
}
func addClassFromStructType(name string, s *ast.StructType) {
func addClassFromStructType(name string, s *ast.StructType) Class {
c := createClass(name)
c.Struct = s
return c
}
func handleMethodDeclaration(fd *ast.FuncDecl) string {
@ -112,7 +123,7 @@ func handleMethodDeclaration(fd *ast.FuncDecl) string {
return ""
}
func getOrCreateClassFromFuncDecl(fd *ast.FuncDecl) *Class {
func getOrCreateClassFromFuncDecl(fd *ast.FuncDecl) Class {
n := getClassNameFromReceiver(fd.Recv)
return getOrCreateClass(n)
}
@ -131,9 +142,9 @@ func getClassNameFromStarReceiver(expr ast.Expr) string {
return ""
}
func getOrCreateClass(className string) *Class {
func getOrCreateClass(className string) Class {
for _, c := range classDeclarations {
if c.Name == className {
if c.Name() == className {
return c
}
}
@ -141,13 +152,13 @@ func getOrCreateClass(className string) *Class {
return createClass(className)
}
func createClass(className string) *Class {
func createClass(className string) *class {
c := NewClass(className)
addClassDeclaration(c)
return c
}
func addClassDeclaration(c *Class) {
func addClassDeclaration(c Class) {
dlock.Lock()
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)
case *ast.StructType:
code += handleStructType(e)
case *ast.InterfaceType:
code += handleInterfaceType(e)
case *ast.ArrayType:
code += handleArray(e)
}
@ -54,7 +56,7 @@ func handleUnaryExpr(expr *ast.UnaryExpr) (code string) {
cl, ok := expr.X.(*ast.CompositeLit)
if ok {
code += "new "
code += handleIdentExpr(cl.Type)
code += handleIdentExpr(cl.Type.(*ast.Ident))
code += "()"
} else {
code += expr.Op.String()
@ -71,8 +73,8 @@ func handleBinaryExpr(expr ast.Expr) string {
return code
}
func handleCallExpr(expr *ast.CallExpr) string {
code := handleExpr(expr.Fun)
func handleCallExpr(expr *ast.CallExpr) (code string) {
code = handleExpr(expr.Fun)
code += "("
args := make([]string, 0)
for _, arg := range expr.Args {
@ -80,11 +82,10 @@ func handleCallExpr(expr *ast.CallExpr) string {
}
code += strings.Join(args, ",")
code += ")"
return code
return
}
func handleIdentExpr(expr ast.Expr) string {
ident := expr.(*ast.Ident)
func handleIdentExpr(ident *ast.Ident) string {
code := ""
switch ident.Name {
case "nil":

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

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