Skip to content

Commit 96f2c73

Browse files
committed
fix(py),feat(sugar): cls(xxx) is now supported over newCls(xxx); refact(exprRewrite): add mparser arg to toPyExpr
1 parent efe2627 commit 96f2c73

File tree

2 files changed

+97
-55
lines changed

2 files changed

+97
-55
lines changed

src/pylib/pysugar/stmt/exprRewrite.nim

Lines changed: 86 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import std/macrocache
44
from std/strutils import toLowerAscii, normalize
55
import ../../pystring/[strimpl, strprefix]
66
import ../../builtins/[list_decl, set, dict, pyslice]
7+
import ./frame
78

89
const CollectionSyms = CacheSeq"CollectionSyms"
910
static:
@@ -13,25 +14,26 @@ static:
1314
CollectionSyms.add bindSym"slice"
1415

1516
using e: NimNode
16-
proc toPyExpr*(atm: NimNode): NimNode
17+
using mparser: var PyAsgnRewriter
18+
proc toPyExpr*(mparser; atm: NimNode): NimNode
1719

1820
template newSlice(a, b: NimNode): NimNode =
1921
newCall(CollectionSyms[3], a, b)
2022

21-
proc colonToSlice(colonExpr: NimNode): NimNode =
23+
proc colonToSlice(mparser; colonExpr: NimNode): NimNode =
2224
## a:b -> slice(a,b)
23-
newSlice(colonExpr[0].toPyExpr, colonExpr[1].toPyExpr)
25+
newSlice(mparser.toPyExpr colonExpr[0], mparser.toPyExpr colonExpr[1])
2426

25-
proc rewriteSliceInBracket(bracketExpr: NimNode): NimNode =
27+
proc rewriteSliceInBracket(mparser; bracketExpr: NimNode): NimNode =
2628
result = bracketExpr.copyNimNode
27-
result.add bracketExpr[0].toPyExpr
29+
result.add mparser.toPyExpr bracketExpr[0]
2830
for i in 1..<bracketExpr.len:
2931
let ele = bracketExpr[i]
3032
result.add:
3133
let k = ele.kind
32-
if k == nnkExprColonExpr: colonToSlice ele
34+
if k == nnkExprColonExpr: mparser.colonToSlice ele
3335
elif k == nnkInfix and ele[0].eqIdent":-": # like `ls[1:-1]`
34-
newSlice(ele[1].toPyExpr, prefix(ele[2].toPyExpr, "-"))
36+
newSlice(mparser.toPyExpr ele[1], prefix(mparser.toPyExpr ele[2], "-"))
3537
else: ele
3638

3739
#[
@@ -75,14 +77,14 @@ func validStrLit(e: NimNode): bool =
7577
actStr.normalize == "fmt"
7678

7779

78-
proc rewriteStrLitCat(e: NimNode): NimNode =
80+
proc rewriteStrLitCat(mparser; e: NimNode): NimNode =
7981
if e.len != 2:
8082
return e
8183
let
8284
lhs = e[0]
8385
rhs = e[1]
8486
if not lhs.validStrLit: return e
85-
result = infix(lhs.toPyExpr, "&", rhs.toPyExpr)
87+
result = infix(mparser.toPyExpr lhs, "&", mparser.toPyExpr rhs)
8688

8789
func toStr(e): NimNode =
8890
result = nnkCallStrLit.newTree(bindSym"u", e)
@@ -94,12 +96,12 @@ template asisIfEmpty(e) =
9496
func getTypeof(e: NimNode): NimNode =
9597
newCall("typeof", e)
9698

97-
proc rewriteEachEle(e: NimNode; bracketNode = nnkBracket): NimNode =
99+
proc rewriteEachEle(mparser; e: NimNode; bracketNode = nnkBracket): NimNode =
98100
result = newNimNode bracketNode
99101
for i in e:
100-
result.add i.toPyExpr
102+
result.add mparser.toPyExpr i
101103

102-
template mapEleCall(
104+
template mapEleCall(mparser;
103105
initCall, e: NimNode;
104106
bracketNode = nnkBracket,
105107
): NimNode =
@@ -112,7 +114,7 @@ template mapEleCall(
112114
with original `PyTComplex` type (a.k.a. being regarded as a new type)
113115
]#
114116
e.asisIfEmpty
115-
let res = rewriteEachEle(e, bracketNode)
117+
let res = mparser.rewriteEachEle(e, bracketNode)
116118
let eleTyp = getTypeof res[0]
117119
newCall(
118120
nnkBracketExpr.newTree(
@@ -122,16 +124,16 @@ template mapEleCall(
122124
)
123125

124126

125-
proc toList(e): NimNode = mapEleCall(CollectionSyms[0], e)
126-
proc toSet (e): NimNode = mapEleCall(CollectionSyms[1], e)
127-
proc toDict(e): NimNode =
127+
proc toList(mparser; e): NimNode = mparser.mapEleCall(CollectionSyms[0], e)
128+
proc toSet (mparser; e): NimNode = mparser.mapEleCall(CollectionSyms[1], e)
129+
proc toDict(mparser; e): NimNode =
128130
e.asisIfEmpty
129131

130132
var eles = e.copyNimNode
131133
for i in e:
132134
var n = i.copyNimNode
133135
n.add i[0].toStr
134-
n.add i[1].toPyExpr
136+
n.add mparser.toPyExpr i[1]
135137
eles.add n
136138

137139
let
@@ -146,41 +148,41 @@ proc toDict(e): NimNode =
146148
eleValTyp
147149
), eles
148150
)
149-
proc toTuple(e): NimNode =
151+
proc toTuple(mparser; e): NimNode =
150152
result = newNimNode nnkTupleConstr
151153
for i in e:
152-
result.add i.toPyExpr
154+
result.add mparser.toPyExpr i
153155

154-
proc rewriteEqualMinus(e; k=nnkAsgn): NimNode =
156+
proc rewriteEqualMinus(mparser; e; k=nnkAsgn): NimNode =
155157
## x==-1 -> x == -1
156158
## x=-1 -> x = -1
157159

158-
let lhs = e[1].toPyExpr
159-
template rhs: NimNode = newCall("-", e[2].toPyExpr)
160+
let lhs = mparser.toPyExpr e[1]
161+
template rhs: NimNode = newCall("-", mparser.toPyExpr e[2])
160162
if e[0].eqIdent"=-":
161163
k.newTree lhs, rhs
162164
elif e[0].eqIdent"==-":
163165
newCall "==", lhs, rhs
164166
else: e
165167

166-
proc callToPyExpr*(e): NimNode
168+
proc callToPyExpr*(mparser; e): NimNode
167169

168-
template toPyExprImpl(atm: NimNode; toListCb; equalMinusAs=nnkAsgn): NimNode =
170+
template toPyExprImpl(mparser; atm: NimNode; toListCb; equalMinusAs=nnkAsgn): NimNode =
169171
case atm.kind
170172
of nnkExprEqExpr:
171-
nnkExprEqExpr.newTree(atm[0], atm[1].toPyExpr)
173+
nnkExprEqExpr.newTree(atm[0], mparser.toPyExpr atm[1])
172174
of nnkBracketExpr:
173-
rewriteSliceInBracket atm
175+
mparser.rewriteSliceInBracket atm
174176
of nnkCommand:
175-
rewriteStrLitCat atm
177+
mparser.rewriteStrLitCat atm
176178
of nnkCall:
177-
callToPyExpr atm
179+
mparser.callToPyExpr atm
178180
of nnkPrefix:
179-
nnkPrefix.newTree atm[0], atm[1].toPyExpr
181+
nnkPrefix.newTree atm[0], mparser.toPyExpr atm[1]
180182
of nnkPar:
181-
nnkPar.newTree atm[0].toPyExpr
183+
nnkPar.newTree mparser.toPyExpr atm[0]
182184
of nnkInfix:
183-
rewriteEqualMinus atm, equalMinusAs
185+
mparser.rewriteEqualMinus atm, equalMinusAs
184186

185187
of nnkTripleStrLit,
186188
nnkStrLit, nnkRStrLit:
@@ -189,22 +191,62 @@ template toPyExprImpl(atm: NimNode; toListCb; equalMinusAs=nnkAsgn): NimNode =
189191
# NOTE: f"xxx" does perform `translateEscape`
190192
# so we don't perform translation here
191193

192-
of nnkBracket: atm.toListCb
193-
of nnkCurly: atm.toSet
194-
of nnkTableConstr:atm.toDict
195-
of nnkTupleConstr:atm.toTuple
194+
of nnkBracket: mparser.toListCb atm
195+
of nnkCurly: mparser.toSet atm
196+
of nnkTableConstr:mparser.toDict atm
197+
of nnkTupleConstr:mparser.toTuple atm
196198
else:
197199
atm
198200

199-
proc toPyExpr*(atm: NimNode): NimNode = toPyExprImpl atm, toList
200-
proc toPyExprNoList*(atm: NimNode): NimNode = toPyExprImpl atm, rewriteEachEle
201+
proc toPyExpr*(mparser; atm: NimNode): NimNode = mparser.toPyExprImpl atm, toList
202+
proc toPyExprNoList*(mparser; atm: NimNode): NimNode = mparser.toPyExprImpl atm, rewriteEachEle
201203

202-
proc argInCallToPyExpr(atm: NimNode): NimNode =
204+
proc argInCallToPyExpr(mparser; atm: NimNode): NimNode =
203205
## f(x=-1) needs to be rewritten as Call(ExprEqExpr(Ident"x", -1))
204-
toPyExprImpl atm, toList, nnkExprEqExpr
205-
206-
proc callToPyExpr*(e): NimNode =
207-
result = e.copyNimNode
208-
for i in e:
209-
result.add i.argInCallToPyExpr
206+
mparser.toPyExprImpl atm, toList, nnkExprEqExpr
207+
208+
proc preNew(n: NimNode): NimNode =
209+
ident("new" & n.strVal)
210+
211+
proc callToPyExpr*(mparser; e): NimNode =
212+
## In addition, it will rewrite `cls(xxx)` to `newCls(xxx)`
213+
let callee = e[0]
214+
template addArg(addArgCb) =
215+
for i in 1..<e.len:
216+
let arg{.inject.} = mparser.argInCallToPyExpr e[i]
217+
addArgCb
218+
template retAfterAddOriCall =
219+
addArg:
220+
oriCall.add arg
221+
return oriCall
222+
223+
var
224+
newCls: NimNode
225+
oriCall = newCall callee
226+
case callee.kind
227+
of nnkIdent: newCls = callee.preNew
228+
of nnkDotExpr:
229+
if callee[1].len == 0:
230+
var lhs = callee[0]
231+
# in case `module.cls`
232+
newCls = newDotExpr(lhs, callee[1].preNew)
233+
while true:
234+
if lhs.len == 0:
235+
break
236+
elif lhs.kind != nnkDotExpr or lhs[1].kind != nnkIdent:
237+
retAfterAddOriCall
238+
lhs = lhs[0]
239+
else:
240+
retAfterAddOriCall
241+
else:
242+
retAfterAddOriCall
243+
var newClsCall = newCall newCls
244+
addArg:
245+
oriCall.add arg
246+
newClsCall.add arg
247+
result = quote do:
248+
when declared(`newCls`) and declared(`callee`) and compiles(`newClsCall`):
249+
`newClsCall`
250+
else:
251+
`oriCall`
210252

src/pylib/pysugar/stmt/tonim.nim

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ template parseBodyOnlyLast(ele): NimNode =
4747
var subStmt = newNimNode ele.kind
4848
let last = ele.len - 1
4949
for i in 0..<last:
50-
subStmt.add ele[i].toPyExpr
50+
subStmt.add mparser.toPyExpr ele[i]
5151
subStmt.add mparser.parsePyBody ele[last]
5252
subStmt
5353

@@ -67,7 +67,7 @@ proc parsePyStmt*(mparser; statement: NimNode): NimNode =
6767
for defs in statement:
6868
mparser.add $statement[0]
6969
var nDefs = defs.copyNimTree
70-
nDefs[^1] = nDefs[^1].toPyExpr
70+
nDefs[^1] = mparser.toPyExpr nDefs[^1]
7171
nStmt.add nDefs
7272
result.add nStmt
7373
of nnkAsgn:
@@ -82,16 +82,16 @@ proc parsePyStmt*(mparser; statement: NimNode): NimNode =
8282
let (varName, varValue) = (statement[0], statement[1])
8383
case varName.kind
8484
of nnkIdent:
85-
handleVar varName, varValue.toPyExpr
85+
handleVar varName, mparser.toPyExpr varValue
8686
of nnkTupleConstr:
8787
# no need to construct list if meeting `nnkBracket`
88-
unpackImplRec(data=varValue.toPyExprNoList,
88+
unpackImplRec(data=mparser.toPyExprNoList varValue,
8989
symbols=varName, res=result, receiver=handleVar)
9090
of nnkBracketExpr:
91-
result.add newAssignment(varName.toPyExpr, varValue.toPyExpr)
91+
result.add newAssignment(mparser.toPyExpr varName, mparser.toPyExpr varValue)
9292
else:
9393
# varName may be `nnkDotExpr`. e.g.`a.b=1`
94-
result.add statement.copyNimNode.add(varName, varValue.toPyExpr)
94+
result.add statement.copyNimNode.add(varName, mparser.toPyExpr varValue)
9595
of nnkCommand:
9696
let preCmd = $statement[0]
9797
case preCmd
@@ -131,7 +131,7 @@ proc parsePyStmt*(mparser; statement: NimNode): NimNode =
131131
cmd.add:
132132
if i.kind == nnkStmtList:
133133
mparser.parsePyBody i
134-
else: i.toPyExpr
134+
else: mparser.toPyExpr i
135135
result.add cmd
136136
of nnkRaiseStmt:
137137
result.add rewriteRaise statement
@@ -144,7 +144,7 @@ proc parsePyStmt*(mparser; statement: NimNode): NimNode =
144144
nStmt.add mparser.parsePyStmt e
145145
result.add nStmt
146146
of nnkReturnStmt, nnkDiscardStmt:
147-
result.add statement.copyNimNode.add(statement[0].toPyExpr)
147+
result.add statement.copyNimNode.add(mparser.toPyExpr statement[0])
148148
of nnkIfStmt, nnkWhenStmt:
149149
var nStmt = newNimNode statement.kind
150150
for branch in statement:
@@ -194,11 +194,11 @@ proc parsePyStmt*(mparser; statement: NimNode): NimNode =
194194
if statement[^1].kind == nnkStmtList:
195195
result.add parseBodyOnlyLast statement
196196
else:
197-
result.add statement.callToPyExpr
197+
result.add mparser.callToPyExpr statement
198198
of nnkForStmt, nnkWhileStmt:
199199
result.add parseBodyOnlyLast statement
200200
elif statement.len == 0:
201-
result.add statement.toPyExpr
201+
result.add mparser.toPyExpr statement
202202
else:
203203
# XXX: maybe no use
204204
var nStmt = newNimNode statement.kind
@@ -211,7 +211,7 @@ proc parsePyStmt*(mparser; statement: NimNode): NimNode =
211211
nStmt.add mparser.parsePyBody e
212212
of nnkOfBranch, nnkElifBranch, nnkElse, nnkForStmt:
213213
result.add parseBodyOnlyLast e
214-
else: nStmt.add e.toPyExpr
214+
else: nStmt.add mparser.toPyExpr e
215215
result.add nStmt
216216

217217

0 commit comments

Comments
 (0)