Skip to content

Commit fc5afbb

Browse files
committed
feat(sugar): support chain cmp, e.g. 1<x<3
1 parent c4d3cf0 commit fc5afbb

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

src/pylib/pysugar/stmt/chainCmp.nim

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
import std/macros
3+
from std/strutils import nimIdentNormalize, toLowerAscii
4+
5+
proc isOfComparisions(op: NimNode): bool =
6+
##[ "<" | ">" | "==" | ">=" | "<=" | "!="
7+
| "is" ["not"] | ["not"] "in"]##
8+
if not op.len == 0: return
9+
let sop = $op
10+
case sop.len
11+
of 1:
12+
sop[0] in {'<', '>'}
13+
of 2:
14+
sop in ["==", ">=", "<=", "!="] or
15+
sop[0] == 'i' and sop[1].toLowerAscii in {'s', 'n'} # is/in
16+
else:
17+
sop.nimIdentNormalize in ["is_not", "not_in"]
18+
19+
proc newInfix(op, l, r: NimNode): NimNode = nnkInfix.newTree(op, l, r)
20+
21+
proc expandChainImpl(resStmt: NimNode, cExp: NimNode): NimNode =
22+
let
23+
op = cExp[0]
24+
lhs = cExp[1]
25+
rhs = cExp[2]
26+
template shallChain: bool =
27+
lhs.len == 3 and op.isOfComparisions and lhs[0].isOfComparisions
28+
if shallChain:
29+
let med = lhs[2]
30+
if med.len != 0:
31+
let id = genSym(nskLet, "cmpMed")
32+
resStmt.add newLetStmt(id, med)
33+
lhs[2] = id
34+
nnkInfix.newTree(bindSym"and",
35+
expandChainImpl(resStmt, lhs),
36+
newInfix(op, lhs[2], rhs))
37+
else: # if isCmpOp: # but lhs is not
38+
cExp
39+
40+
proc expandChainImpl*(cExp: NimNode): NimNode =
41+
result = newStmtList()
42+
result.add expandChainImpl(result, cExp)
43+
44+
macro expandChain*(cExp): bool =
45+
expectKind cExp, nnkInfix
46+
expandChainImpl(cExp)
47+
48+
when isMainModule:
49+
template tCmp(m) =
50+
assert expandChain(1 < m <= 3)
51+
assert expandChain(1 < m > 2)
52+
tCmp 3
53+
var g = 0
54+
proc f(): int =
55+
g.inc
56+
3
57+
tCmp f()
58+
assert g == 2, $g

src/pylib/pysugar/stmt/exprRewrite.nim

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +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
7+
import ./frame, ./chainCmp
88

99
const CollectionSyms = CacheSeq"CollectionSyms"
1010
static:
@@ -153,17 +153,25 @@ proc toTuple(mparser; e): NimNode =
153153
for i in e:
154154
result.add mparser.toPyExpr i
155155

156-
proc rewriteEqualMinus(mparser; e; k=nnkAsgn): NimNode =
156+
proc tryRewriteEqualMinus(mparser; e; res: var NimNode; k=nnkAsgn): bool =
157157
## x==-1 -> x == -1
158158
## x=-1 -> x = -1
159159

160160
let lhs = mparser.toPyExpr e[1]
161161
template rhs: NimNode = newCall("-", mparser.toPyExpr e[2])
162+
template ret(n: NimNode) =
163+
res = n
164+
return true
162165
if e[0].eqIdent"=-":
163-
k.newTree lhs, rhs
166+
ret k.newTree(lhs, rhs)
164167
elif e[0].eqIdent"==-":
165-
newCall "==", lhs, rhs
166-
else: e
168+
ret newCall("==", lhs, rhs)
169+
170+
171+
proc rewriteInfix(mparser; e; k=nnkAsgn): NimNode =
172+
if mparser.tryRewriteEqualMinus(e, result, k=k):
173+
return
174+
result = expandChainImpl(e)
167175

168176
proc callToPyExpr*(mparser; e): NimNode
169177

@@ -182,7 +190,7 @@ template toPyExprImpl(mparser; atm: NimNode; toListCb; equalMinusAs=nnkAsgn): Ni
182190
of nnkPar:
183191
nnkPar.newTree mparser.toPyExpr atm[0]
184192
of nnkInfix:
185-
mparser.rewriteEqualMinus atm, equalMinusAs
193+
mparser.rewriteInfix atm, equalMinusAs
186194

187195
of nnkTripleStrLit,
188196
nnkStrLit, nnkRStrLit:

0 commit comments

Comments
 (0)