Skip to content

Commit 86b55cd

Browse files
author
Randall C. O'Reilly
committed
gopy, gogi flags, generates class __init__ with SetTags properly for gogi mode. strings., copy() -> method calls
1 parent ee6b89f commit 86b55cd

File tree

6 files changed

+140
-39
lines changed

6 files changed

+140
-39
lines changed

README.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,17 @@ It is based on the Go `gofmt` command source code and the go `printer` package,
66

77
We have modified the `printer` code in the `pyprint` package to instead print out Python code.
88

9-
# TODO
10-
11-
* add gopy flag
12-
13-
* strings.Fields(x) -> x.split()
9+
The `-gopy` flag generates [GoPy](https:://github.com/go-python/gopy) specific Python code, including:
1410

15-
* class comments -> """
11+
* `nil` -> `go.nil`
12+
* `[]string{...}` -> `go.Slice_string([...])` etc for int, float64, float32
1613

17-
* switch -> ifs.. -- grab switch expr and put into each if
14+
The `-gogi` flag generates [GoGi](https:://github.com/goki/gi) specific Python code, including:
1815

19-
# gopy specific mode
16+
* struct tags generate: `self.SetTags()` call, for the `pygiv.ClassViewObj` class, which then provides an automatic GUI view with tag-based formatting of struct fields.
2017

21-
* replace []string() -> go.Slice_string etc
18+
# TODO
2219

23-
# Check
20+
* switch -> ifs.. -- grab switch expr and put into each if
2421

2522

format.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func format(
3636
if err != nil {
3737
return nil, err
3838
}
39-
pyfix := pyEdits(buf.Bytes(), true)
39+
pyfix := pyEdits(buf.Bytes())
4040
return pyfix, nil
4141
// return buf.Bytes(), nil
4242
}
@@ -82,7 +82,7 @@ func format(
8282
return nil, err
8383
}
8484

85-
pyfix := pyEdits(buf.Bytes(), true)
85+
pyfix := pyEdits(buf.Bytes())
8686

8787
out := sourceAdj(pyfix, cfg.Indent)
8888

gotopy.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,17 @@ var (
3838
simplifyAST = flag.Bool("s", false, "simplify code")
3939
doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
4040
allErrors = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)")
41+
gopyMode = flag.Bool("gopy", false, "support GoPy-specific Python code generation")
42+
gogiMode = flag.Bool("gogi", false, "support GoGi-specific Python code generation (implies gopy)")
4143

4244
// debugging
4345
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
4446
)
4547

4648
// Keep these in sync with go/format/format.go.
4749
const (
48-
tabWidth = 8
49-
printerMode = pyprint.UseSpaces | pyprint.TabIndent | printerNormalizeNumbers
50+
tabWidth = 8
51+
printerModeDef = pyprint.UseSpaces | pyprint.TabIndent | printerNormalizeNumbers
5052

5153
// printerNormalizeNumbers means to canonicalize number literal prefixes
5254
// and exponents while printing. See https://golang.org/doc/go1.13#gofmt.
@@ -56,10 +58,11 @@ const (
5658
)
5759

5860
var (
59-
fileSet = token.NewFileSet() // per process FileSet
60-
exitCode = 0
61-
rewrite func(*ast.File) *ast.File
62-
parserMode parser.Mode
61+
fileSet = token.NewFileSet() // per process FileSet
62+
exitCode = 0
63+
rewrite func(*ast.File) *ast.File
64+
parserMode parser.Mode
65+
printerMode = printerModeDef
6366
)
6467

6568
func report(err error) {
@@ -224,6 +227,14 @@ func gofmtMain() {
224227
return
225228
}
226229

230+
if *gopyMode {
231+
printerMode |= pyprint.GoPy
232+
}
233+
234+
if *gogiMode {
235+
printerMode |= pyprint.GoGi | pyprint.GoPy
236+
}
237+
227238
for i := 0; i < flag.NArg(); i++ {
228239
path := flag.Arg(i)
229240
switch dir, err := os.Stat(path); {

pyedits.go

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ package main
66

77
import (
88
"bytes"
9+
"fmt"
910
"strings"
11+
12+
"github.com/goki/gotopy/pyprint"
1013
)
1114

1215
// moveLines moves the st,ed region to 'to' line
@@ -26,11 +29,10 @@ func moveLines(lines *[][]byte, to, st, ed int) {
2629
// * moves python segments around, e.g., methods
2730
// into their proper classes
2831
// * fixes printf, slice other common code
29-
func pyEdits(src []byte, gopy bool) []byte {
32+
func pyEdits(src []byte) []byte {
3033
type sted struct {
3134
st, ed int
3235
}
33-
3436
classes := map[string]sted{}
3537

3638
nl := []byte("\n")
@@ -41,10 +43,14 @@ func pyEdits(src []byte, gopy bool) []byte {
4143
fmtSprintf := []byte("fmt.Sprintf(")
4244
prints := []byte("print")
4345
eqappend := []byte("= append(")
46+
elseif := []byte("else if")
47+
elif := []byte("elif")
4448
itoa := []byte("strconv.Itoa")
4549
float64p := []byte("float64(")
4650
float32p := []byte("float32(")
4751
floatp := []byte("float(")
52+
stringp := []byte("string(")
53+
strp := []byte("str(")
4854
slicestr := []byte("[]string(")
4955
sliceint := []byte("[]int(")
5056
slicefloat64 := []byte("[]float64(")
@@ -53,6 +59,8 @@ func pyEdits(src []byte, gopy bool) []byte {
5359
gosliceint := []byte("go.Slice_int([")
5460
goslicefloat64 := []byte("go.Slice_float64([")
5561
goslicefloat32 := []byte("go.Slice_float32([")
62+
stringsdot := []byte("strings.")
63+
copyp := []byte("copy(")
5664

5765
endclass := "EndClass: "
5866
method := "Method: "
@@ -66,6 +74,9 @@ func pyEdits(src []byte, gopy bool) []byte {
6674
lastComSt := -1
6775
lastComEd := -1
6876

77+
gopy := (printerMode&pyprint.GoPy != 0)
78+
// gogi := (printerMode&pyprint.GoGi != 0)
79+
6980
li := 0
7081
for {
7182
if li >= len(lines) {
@@ -86,6 +97,7 @@ func pyEdits(src []byte, gopy bool) []byte {
8697

8798
ln = bytes.Replace(ln, float64p, floatp, -1)
8899
ln = bytes.Replace(ln, float32p, floatp, -1)
100+
ln = bytes.Replace(ln, stringp, strp, -1)
89101
lines[li] = ln
90102

91103
switch {
@@ -154,25 +166,66 @@ func pyEdits(src []byte, gopy bool) []byte {
154166
nln = append(nln, []byte(".append(")...)
155167
nln = append(nln, ln[idx+len(eqappend)+comi+1:]...)
156168
lines[li] = nln
157-
case bytes.Contains(ln, slicestr):
169+
case bytes.Contains(ln, stringsdot):
170+
idx := bytes.Index(ln, stringsdot)
171+
pi := idx + len(stringsdot) + bytes.Index(ln[idx+len(stringsdot):], []byte("("))
172+
comi := bytes.Index(ln[pi:], []byte(","))
173+
nln := make([]byte, idx)
174+
copy(nln, ln[:idx])
175+
if comi < 0 {
176+
comi = bytes.Index(ln[pi:], []byte(")"))
177+
nln = append(nln, ln[pi+1:pi+comi]...)
178+
nln = append(nln, '.')
179+
meth := bytes.ToLower(ln[idx+len(stringsdot) : pi+1])
180+
fmt.Println(string(meth))
181+
if bytes.Equal(meth, []byte("fields(")) {
182+
meth = []byte("split(")
183+
}
184+
nln = append(nln, meth...)
185+
nln = append(nln, ln[pi+comi:]...)
186+
} else {
187+
nln = append(nln, ln[pi+1:pi+comi]...)
188+
nln = append(nln, '.')
189+
meth := bytes.ToLower(ln[idx+len(stringsdot) : pi+1])
190+
nln = append(nln, meth...)
191+
nln = append(nln, ln[pi+comi+1:]...)
192+
}
193+
lines[li] = nln
194+
case bytes.Contains(ln, copyp):
195+
idx := bytes.Index(ln, copyp)
196+
pi := idx + len(copyp) + bytes.Index(ln[idx+len(stringsdot):], []byte("("))
197+
comi := bytes.Index(ln[pi:], []byte(","))
198+
nln := make([]byte, idx)
199+
copy(nln, ln[:idx])
200+
nln = append(nln, ln[pi+1:pi+comi]...)
201+
nln = append(nln, '.')
202+
nln = append(nln, copyp...)
203+
nln = append(nln, ln[pi+comi+1:]...)
204+
lines[li] = nln
205+
case bytes.Contains(ln, itoa):
206+
ln = bytes.Replace(ln, itoa, []byte(`str`), -1)
207+
lines[li] = ln
208+
case bytes.Contains(ln, elseif):
209+
ln = bytes.Replace(ln, elseif, elif, -1)
210+
lines[li] = ln
211+
212+
// gopy cases
213+
case gopy && bytes.Contains(ln, slicestr):
158214
ln = bytes.Replace(ln, slicestr, goslicestr, -1)
159215
ln = bytes.Replace(ln, []byte(")"), []byte("])"), 1)
160216
lines[li] = ln
161-
case bytes.Contains(ln, sliceint):
217+
case gopy && bytes.Contains(ln, sliceint):
162218
ln = bytes.Replace(ln, sliceint, gosliceint, -1)
163219
ln = bytes.Replace(ln, []byte(")"), []byte("])"), 1)
164220
lines[li] = ln
165-
case bytes.Contains(ln, slicefloat64):
221+
case gopy && bytes.Contains(ln, slicefloat64):
166222
ln = bytes.Replace(ln, slicefloat64, goslicefloat64, -1)
167223
ln = bytes.Replace(ln, []byte(")"), []byte("])"), 1)
168224
lines[li] = ln
169-
case bytes.Contains(ln, slicefloat32):
225+
case gopy && bytes.Contains(ln, slicefloat32):
170226
ln = bytes.Replace(ln, slicefloat32, goslicefloat32, -1)
171227
ln = bytes.Replace(ln, []byte(")"), []byte("])"), 1)
172228
lines[li] = ln
173-
case bytes.Contains(ln, itoa):
174-
ln = bytes.Replace(ln, itoa, []byte(`str`), -1)
175-
lines[li] = ln
176229
}
177230
li++
178231
}

pyprint/nodes.go

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,17 @@ func (p *printer) setLineComment(text string) {
443443
p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}})
444444
}
445445

446+
func (p *printer) printFieldInit(fi ast.Expr) {
447+
switch fi.(type) {
448+
case *ast.Ident, *ast.SelectorExpr:
449+
p.expr(fi)
450+
p.print(token.LPAREN, token.RPAREN)
451+
default:
452+
p.expr(fi)
453+
// fmt.Printf("%T\n", fi)
454+
}
455+
}
456+
446457
func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
447458
lbrace := fields.Opening
448459
list := fields.List
@@ -496,6 +507,9 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
496507

497508
if isStruct {
498509
p.print("def __init__(self):", newline, indent)
510+
if p.Mode&GoGi != 0 {
511+
p.print("super(Sim, self).__init__()", newline)
512+
}
499513
sep := vtab
500514
if len(list) == 1 {
501515
sep = blank
@@ -512,8 +526,12 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
512526
if len(f.Names) > 0 {
513527
// named fields
514528
p.identList(f.Names, false)
515-
p.print(sep)
516-
p.expr(f.Type)
529+
p.print(sep, token.ASSIGN, sep)
530+
if se, ok := f.Type.(*ast.StarExpr); ok {
531+
p.printFieldInit(se.X)
532+
} else {
533+
p.printFieldInit(f.Type)
534+
}
517535
extraTabs = 1
518536
} else {
519537
// anonymous field
@@ -525,8 +543,16 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
525543
p.print(sep)
526544
}
527545
p.print(sep)
528-
p.print("# ")
529-
p.expr(f.Tag)
546+
if p.Mode&GoGi != 0 {
547+
p.print(newline, `self.SetTags("`+f.Names[0].Name+`", '`)
548+
tg := f.Tag.Value
549+
tg = strings.Replace(tg, "'", `\'`, -1)
550+
p.print(tg[1 : len(tg)-1]) // cut out ` `
551+
p.print(`')`)
552+
} else {
553+
p.print("# ")
554+
p.expr(f.Tag)
555+
}
530556
extraTabs = 0
531557
}
532558
if f.Comment != nil {
@@ -986,10 +1012,11 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
9861012
p.fieldList(x.Methods, false, x.Incomplete)
9871013

9881014
case *ast.MapType:
989-
p.print(token.MAP, token.LBRACK)
990-
p.expr(x.Key)
991-
p.print(token.RBRACK)
992-
p.expr(x.Value)
1015+
p.print(token.LBRACE, token.RBRACE)
1016+
// p.print(token.MAP, token.LBRACK)
1017+
// p.expr(x.Key)
1018+
// p.print(token.RBRACK)
1019+
// p.expr(x.Value)
9931020

9941021
case *ast.ChanType:
9951022
switch x.Dir {
@@ -1658,6 +1685,9 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
16581685
p.flush(p.pos, token.TYPE) // get rid of any comments
16591686
p.print("class", blank)
16601687
p.expr(s.Name)
1688+
if p.Mode&GoGi != 0 {
1689+
p.print("(pygiv.ClassViewObj):", newline)
1690+
}
16611691
// if n == 1 {
16621692
// p.print(blank)
16631693
// } else {
@@ -1666,8 +1696,10 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
16661696
if s.Assign.IsValid() {
16671697
p.print(token.ASSIGN, blank)
16681698
}
1669-
p.pyFuncComments(s.Doc) // neither s.Doc nor s.Comment work here
1699+
doc := p.comments[p.cindex-1]
1700+
p.pyFuncComments(doc) // neither s.Doc nor s.Comment work here
16701701
p.expr(s.Type)
1702+
p.print(newline)
16711703
p.print("<<<<EndClass: ")
16721704
p.expr(s.Name)
16731705
p.print(">>>>", newline)
@@ -1859,19 +1891,24 @@ func (p *printer) pyFuncComments(com *ast.CommentGroup) {
18591891
if com == nil || len(com.List) == 0 {
18601892
return
18611893
}
1894+
p.print("\t")
18621895
p.print(`"""`, newline)
18631896
for _, c := range com.List {
1897+
p.print("\t")
18641898
if len(c.Text) < 3 {
18651899
p.print(c.Text)
18661900
} else {
18671901
if c.Text[1] == '/' {
18681902
p.print(c.Text[3:])
1903+
} else if c.Text[0] == '#' {
1904+
p.print(c.Text[2:])
18691905
} else {
18701906
p.print(c.Text)
18711907
}
18721908
}
18731909
p.print(newline)
18741910
}
1911+
p.print("\t")
18751912
p.print(`"""`, newline)
18761913
}
18771914

@@ -1904,9 +1941,8 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
19041941
}
19051942
p.signature(d.Type.Params, d.Type.Results)
19061943
p.print(token.RPAREN)
1907-
p.print(token.COLON, newline, indent)
1944+
p.print(token.COLON, newline)
19081945
p.pyFuncComments(d.Doc)
1909-
p.print(unindent)
19101946
p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body)
19111947
if d.Recv != nil {
19121948
p.print(unindent)

pyprint/printer.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,9 @@ func (p *printer) print(args ...interface{}) {
10191019
case "false":
10201020
data = "False"
10211021
case "nil":
1022-
data = "go.nil" // todo: gopy mode
1022+
if p.Config.Mode&GoPy != 0 {
1023+
data = "go.nil"
1024+
}
10231025
}
10241026

10251027
p.writeString(next, data, isLit)
@@ -1293,6 +1295,8 @@ const (
12931295
TabIndent // use tabs for indentation independent of UseSpaces
12941296
UseSpaces // use spaces instead of tabs for alignment
12951297
SourcePos // emit //line directives to preserve original source positions
1298+
GoPy // support GoPy-specific Python code generation
1299+
GoGi // support GoGi-specific Python code generation
12961300
)
12971301

12981302
// The mode below is not included in printer's public API because

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy