Skip to content

Commit 3c6a762

Browse files
author
Randall C. O'Reilly
committed
almost as good as it can get for basic stuff..
1 parent 574dd43 commit 3c6a762

File tree

9 files changed

+2901
-60
lines changed

9 files changed

+2901
-60
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,14 @@ 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+
* imports
12+
13+
* class comments -> """
14+
15+
* basic repl is done -- need to repl % thing..
16+
* fmt.Sprintf -> "...." % (params, ...)
17+
* fmt.Printf -> print "..." % (params, ...)
18+
19+
* switch -> ifs.. -- grab switch expr and put into each if

gotopy_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ func TestRewrite(t *testing.T) {
149149
out = in[:len(in)-len(".input")] + ".golden"
150150
}
151151
runTest(t, in, out)
152-
if in != out {
153-
// Check idempotence.
154-
runTest(t, out, out)
155-
}
152+
// if in != out {
153+
// // Check idempotence.
154+
// runTest(t, out, out)
155+
// }
156156
}
157157
}

pymove.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ func pyMove(src []byte) []byte {
3535
class := []byte("class ")
3636
pymark := []byte("<<<<")
3737
pyend := []byte(">>>>")
38+
fmts := []byte("fmt.")
39+
fmtPrintf := []byte("fmt.Printf")
40+
fmtSprintf := []byte("fmt.Sprintf")
41+
prints := []byte("print")
3842
endclass := "EndClass: "
3943
method := "Method: "
4044
endmethod := "EndMethod"
@@ -106,11 +110,15 @@ func pyMove(src []byte) []byte {
106110
se, ok := classes[lastMeth]
107111
if ok {
108112
lines = append(lines[:li], lines[li+1:]...) // delete marker
109-
moveLines(&lines, se.ed, lastMethSt, li)
110-
classes[lastMeth] = sted{st: se.st, ed: se.ed + (li - lastMethSt)}
113+
moveLines(&lines, se.ed, lastMethSt, li+1) // extra blank
114+
classes[lastMeth] = sted{st: se.st, ed: se.ed + ((li + 1) - lastMethSt)}
111115
li -= 2
112116
}
113117
}
118+
case bytes.Contains(ln, fmts):
119+
ln = bytes.Replace(ln, fmtPrintf, prints, -1)
120+
ln = bytes.Replace(ln, fmtSprintf, []byte{}, -1)
121+
lines[li] = ln
114122
}
115123
li++
116124
}

pyprint/nodes.go

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
286286
// can align if possible.
287287
// (needsLinebreak is set if we started a new line before)
288288
p.expr(pair.Key)
289-
p.print(pair.Colon, token.COLON, vtab)
289+
p.print(pair.Colon, token.ASSIGN, vtab)
290290
p.expr(pair.Value)
291291
} else {
292292
p.expr0(x, depth)
@@ -369,7 +369,7 @@ func (p *printer) parameters(fields *ast.FieldList) {
369369
// by a linebreak call after a type, or in the next multi-line identList
370370
// will do the right thing.
371371
p.identList(par.Names, ws == indent)
372-
p.print(blank)
372+
// p.print(blank)
373373
}
374374
// parameter type
375375
// p.expr(stripParensAlways(par.Type))
@@ -785,7 +785,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
785785

786786
case *ast.KeyValueExpr:
787787
p.expr(x.Key)
788-
p.print(x.Colon, token.COLON, blank)
788+
p.print(x.Colon, token.ASSIGN, blank)
789789
p.expr(x.Value)
790790

791791
case *ast.StarExpr:
@@ -943,7 +943,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
943943
p.expr1(x.Type, token.HighestPrec, depth)
944944
}
945945
p.level++
946-
p.print(x.Lbrace, token.LBRACE)
946+
p.print(x.Lbrace, token.LPAREN)
947947
p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace, x.Incomplete)
948948
// do not insert extra line break following a /*-style comment
949949
// before the closing '}' as it might break the code if there
@@ -956,7 +956,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
956956
}
957957
// need the initial indent to print lone comments with
958958
// the proper level of indentation
959-
p.print(indent, unindent, mode, x.Rbrace, token.RBRACE, mode)
959+
p.print(indent, unindent, mode, x.Rbrace, token.RPAREN, mode)
960960
p.level--
961961

962962
case *ast.Ellipsis:
@@ -1148,7 +1148,7 @@ func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) {
11481148
func (p *printer) block(b *ast.BlockStmt, nindent int) {
11491149
p.print(b.Lbrace, token.COLON)
11501150
p.stmtList(b.List, nindent, true)
1151-
p.linebreak(p.lineFor(b.Rbrace), 1, ignore, true)
1151+
// p.linebreak(p.lineFor(b.Rbrace), 1, ignore, true)
11521152
p.print(b.Rbrace) // , token.RBRACE)
11531153
}
11541154

@@ -1224,9 +1224,10 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
12241224
}
12251225
}
12261226
}
1227-
if needsBlank {
1228-
p.print(blank)
1229-
}
1227+
_ = needsBlank
1228+
// if needsBlank {
1229+
// p.print(blank)
1230+
// }
12301231
}
12311232

12321233
// indentList reports whether an expression list would look better if it
@@ -1365,9 +1366,12 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
13651366
p.controlClause(false, s.Init, s.Cond, nil)
13661367
p.block(s.Body, 1)
13671368
if s.Else != nil {
1368-
p.print(token.ELSE, blank)
1369+
p.print(newline, token.ELSE)
13691370
switch s.Else.(type) {
1370-
case *ast.BlockStmt, *ast.IfStmt:
1371+
case *ast.BlockStmt:
1372+
p.stmt(s.Else, nextIsRBrace)
1373+
case *ast.IfStmt:
1374+
p.print(blank)
13711375
p.stmt(s.Else, nextIsRBrace)
13721376
default:
13731377
// This can only happen with an incorrectly
@@ -1390,8 +1394,8 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
13901394
p.stmtList(s.Body, 1, nextIsRBrace)
13911395

13921396
case *ast.SwitchStmt:
1393-
// p.print(token.SWITCH)
1394-
// p.controlClause(false, s.Init, s.Tag, nil)
1397+
p.print(token.SWITCH)
1398+
p.controlClause(false, s.Init, s.Tag, nil)
13951399
p.block(s.Body, 0)
13961400

13971401
case *ast.TypeSwitchStmt:
@@ -1428,7 +1432,20 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
14281432

14291433
case *ast.ForStmt:
14301434
p.print(token.FOR)
1431-
p.controlClause(true, s.Init, s.Cond, s.Post)
1435+
didRange := false
1436+
if x, ok := s.Cond.(*ast.BinaryExpr); ok {
1437+
if x.Op == token.LSS {
1438+
p.print(blank)
1439+
p.expr(x.X)
1440+
p.print(" in range", token.LPAREN)
1441+
p.expr(x.Y)
1442+
p.print(token.RPAREN)
1443+
didRange = true
1444+
}
1445+
}
1446+
if !didRange {
1447+
p.controlClause(true, s.Init, s.Cond, s.Post)
1448+
}
14321449
p.block(s.Body, 1)
14331450

14341451
case *ast.RangeStmt:
@@ -1441,9 +1458,10 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
14411458
p.print(s.Value.Pos(), token.COMMA, blank)
14421459
p.expr(s.Value)
14431460
}
1444-
p.print(blank, s.TokPos, s.Tok, blank)
1461+
// p.print(blank, s.TokPos, s.Tok, blank)
14451462
}
1446-
p.print(token.RANGE, blank)
1463+
// p.print(token.RANGE, blank)
1464+
p.print(blank, "in", blank)
14471465
p.expr(stripParens(s.X))
14481466
p.print(blank)
14491467
p.block(s.Body, 1)
@@ -1621,22 +1639,28 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
16211639
p.setComment(s.Comment)
16221640

16231641
case *ast.TypeSpec:
1624-
p.setComment(s.Doc)
1642+
// p.setComment(s.Doc)
1643+
if s.Doc != nil {
1644+
p.cindex++ // skip current comments
1645+
p.commentOffset = 0
1646+
}
1647+
p.flush(p.pos, token.TYPE) // get rid of any comments
16251648
p.print("class", blank)
16261649
p.expr(s.Name)
1627-
if n == 1 {
1628-
p.print(blank)
1629-
} else {
1630-
p.print(vtab)
1631-
}
1650+
// if n == 1 {
1651+
// p.print(blank)
1652+
// } else {
1653+
// p.print(vtab)
1654+
// }
16321655
if s.Assign.IsValid() {
16331656
p.print(token.ASSIGN, blank)
16341657
}
1658+
p.pyFuncComments(s.Doc) // neither s.Doc nor s.Comment work here
16351659
p.expr(s.Type)
16361660
p.print("<<<<EndClass: ")
16371661
p.expr(s.Name)
16381662
p.print(">>>>", newline)
1639-
p.setComment(s.Comment)
1663+
// p.setComment(s.Comment)
16401664

16411665
default:
16421666
panic("unreachable")
@@ -1842,19 +1866,19 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
18421866
// We have to save startCol only after emitting FUNC; otherwise it can be on a
18431867
// different line (all whitespace preceding the FUNC is emitted only when the
18441868
// FUNC is emitted).
1845-
// p.flush(p.pos, p.lastTok)
1846-
// p.comments = nil
1869+
if d.Doc != nil {
1870+
p.cindex++ // skip current comments
1871+
p.commentOffset = 0
1872+
}
18471873
if d.Recv != nil {
18481874
p.print("<<<<Method: ")
18491875
p.printMethRecvType(d.Recv.List[0].Type)
18501876
p.print(">>>>", newline)
18511877
// p.parameters(d.Recv) // method: print receiver
18521878
// p.print(blank)
18531879
p.print(indent)
1854-
} else {
1855-
p.commentOffset = 0
18561880
}
1857-
p.flush(p.pos, p.lastTok)
1881+
p.flush(p.pos, token.FUNC) // get rid of any comments
18581882
p.print("def", blank)
18591883
startCol := p.out.Column - len("def ")
18601884
p.expr(d.Name)
@@ -1873,8 +1897,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
18731897
p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body)
18741898
if d.Recv != nil {
18751899
p.print(unindent)
1876-
p.flush(p.pos, p.lastTok)
1877-
p.print("<<<<EndMethod>>>>", newline)
1900+
p.print(newline, "<<<<EndMethod>>>>", newline)
18781901
}
18791902
}
18801903

pyprint/printer.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,12 @@ func (p *printer) print(args ...interface{}) {
10131013
p.linePtr = nil
10141014
}
10151015

1016+
if data == "true" {
1017+
data = "True"
1018+
} else if data == "false" {
1019+
data = "False"
1020+
}
1021+
10161022
p.writeString(next, data, isLit)
10171023
p.impliedSemi = impliedSemi
10181024
}
@@ -1047,8 +1053,8 @@ func getDoc(n ast.Node) *ast.CommentGroup {
10471053
return n.Doc
10481054
case *ast.GenDecl:
10491055
return n.Doc
1050-
case *ast.FuncDecl:
1051-
return n.Doc
1056+
// case *ast.FuncDecl: // handled separately
1057+
// return n.Doc
10521058
case *ast.File:
10531059
return n.Doc
10541060
}
@@ -1120,6 +1126,7 @@ func (p *printer) printNode(node interface{}) error {
11201126
}
11211127
} else if n, ok := node.(*ast.File); ok {
11221128
// use ast.File comments, if any
1129+
// note: this seems to be typical source for a parsed .go file
11231130
p.comments = n.Comments
11241131
}
11251132

testdata/basic.golden

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,55 @@
11
package test
22

3-
GlobInt = 2
4-
GlobStr = "a string"
3+
GlobInt int = 2
4+
GlobStr = "a string"
5+
GlobBool = False
56

6-
class MyStru :
7+
class MyStru:
78
# A struct definition
89
def __init__(self):
910
# field desc
1011
self.A int
1112
self.B float32 # `desc:"field tag"`
1213
self.C string # `desc:"more tags"`
13-
14-
# MethOne does something
15-
def MethOne(st, arg1 ):
14+
def MethOne(st, arg1):
1615
"""
1716
MethOne does something
1817
"""
1918
rv = st.A
20-
for a = 0; a < 100; a++ :
19+
for _, a in SomeList :
2120
rv += a
21+
st.A = True
22+
23+
ano = MyStru(A= 22, B= 44.2, C= "happy")
2224

2325
return rv
24-
def MethTwo(st, arg1, arg2 , arg3 ):
26+
27+
def MethTwo(st, arg1, arg2, arg3):
2528
"""
2629
MethTwo does something
2730
it is pretty cool
2831
not really sure about that
2932
"""
3033
rv = st.A
31-
for a = 0; a < 100; a++ :
34+
for a in range(100):
3235
rv += a
33-
36+
switch rv:
37+
if 100:
38+
rv *= 2
39+
if 500:
40+
rv /= 5
3441
return rv
3542

43+
3644
# A global function
37-
def GlobFun(a, b ):
45+
def GlobFun(a, b):
3846
"""
3947
A global function
4048
"""
41-
if a > b and a == 0 or b == 0 :
49+
if a > b and a == 0 or b == 0:
4250
return a + b
43-
else if a == b :
51+
else if a == b:
4452
return a * b
45-
else :
53+
else:
4654
return a - b
4755

48-
49-
50-
51-
52-

0 commit comments

Comments
 (0)