Сценарий: Интерфейс - это класс с виртуальными методами
Этот коммит содержится в:
родитель
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
Обычный файл
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
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче