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