Skip to content
This repository was archived by the owner on Sep 20, 2022. It is now read-only.

Commit 05158c4

Browse files
author
Nathan Smith
committed
switch to MacroTools
1 parent a348fcc commit 05158c4

File tree

4 files changed

+67
-63
lines changed

4 files changed

+67
-63
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@ Python generators are great, Julia is great. Why compromise?
55
```julia
66
julia> using PyGen
77

8-
julia> @pygen """
9-
function fibonacci()
8+
julia> @pygen function fibonacci()
109
n, m = 0, 1
1110
while true
12-
yield m
11+
yield(m)
1312
n, m = m, n + m
1413
end
1514
end
16-
"""
1715
fibonacci (generic function with 1 method)
1816

1917
julia> for i in fibonacci()
@@ -32,4 +30,4 @@ julia> for i in fibonacci()
3230
.
3331
```
3432

35-
Voila! Generators without all the ceremony!
33+
Voila! Generators without all the ceremony!

REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
julia 0.5
2+
MacroTools 0.3.0

src/PyGen.jl

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,71 @@
11
module PyGen
22

3-
export @pygen
4-
#=
5-
@pygen is a macro that allows for python like generator functions.
6-
The idea is that a function like this:
7-
8-
function f(args)
9-
...
10-
yield x
11-
...
12-
yield y
13-
...
14-
end
15-
16-
should become....
17-
18-
function f(args)
19-
function γ(c::Channel)
20-
...
21-
put!(c, x)
22-
...
23-
put!(c, y)
24-
...
25-
end
26-
return Channel(γ)
27-
end
28-
=#
29-
30-
const yregex = r"(yield .*)"
31-
32-
33-
function asput(str)
34-
# Convert "yield λ" to "put!(c, λ)
35-
λ = replace(str, "yield ", "")
36-
return "put!(c, )"
37-
end
38-
3+
using MacroTools
394

5+
export @pygen
406
"""
417
@pygen
428
439
Making julie walking a little *more* like python. Stick
4410
the @pygen macro in front of a function declaration and
4511
you can use `yield` statements to make a python style
46-
generator!
12+
generator!
13+
14+
## Examples
15+
16+
```julia
17+
julia> @pygen function fibonacci()
18+
n, m = 0, 1
19+
while true
20+
yield(m)
21+
n, m = m, n + m
22+
end
23+
end
24+
fibonacci (generic function with 1 method)
25+
26+
julia> for n in fibonacci()
27+
println(n)
28+
sleep(1)
29+
end
30+
1
31+
1
32+
2
33+
3
34+
5
35+
8
36+
13
37+
.
38+
.
39+
.
40+
```
4741
"""
4842
macro pygen(f)
49-
f′ = replace(f, yregex, asput)
50-
lines = f′ |> IOBuffer |> readlines
51-
ind = findfirst(x -> contains(x, "function"), lines)
52-
insert!(lines, ind + 1, "function γ(c::Channel)")
53-
push!(lines, "return Channel(γ)\nend")
54-
return join(lines, "\n") |> parse |> esc
43+
44+
# generate a new symbol for the channel name and
45+
# wrapper function
46+
c = gensym()
47+
η = gensym()
48+
49+
# yield(λ) → put!(c, λ)
50+
f′ = MacroTools.postwalk(f) do x
51+
@capture(x, yield(λ_)) || return x
52+
return :(put!($c, $λ))
53+
end
54+
55+
# Fetch the function name and args
56+
@capture(f′, function func_(args__) body_ end)
57+
58+
# wrap up the η function
59+
final = quote
60+
function $func($(args...))
61+
function ($c)
62+
$body
63+
end
64+
return Channel(c -> $η(c))
65+
end
66+
end
67+
68+
return esc(final)
5569
end
5670

5771
end

test/runtests.jl

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,27 @@ using PyGen
22
using Base.Test
33

44
# write your own tests here
5-
@test PyGen.asput("yield pi") == "put!(c, pi)"
6-
7-
@pygen "
8-
9-
function λ()
10-
yield 10
5+
@pygen function λ()
6+
yield(10)
117
end
12-
"
138

149
# Test for \n in first line issue
1510
@test isdefined() == true
1611

1712
# Test that the poodle function doesn't error out
18-
@pygen "
19-
function 🐩()
20-
yield \"🐩\"
13+
@pygen function 🐩()
14+
yield("🐩")
2115
end
22-
"
2316

2417
@test isdefined(:🐩) == true
2518

2619
# Test that one of these generators actually works
27-
@pygen """
28-
function squares(n)
20+
@pygen function squares(n)
2921
i = 0
3022
while i <= n
31-
yield i^2
23+
yield(i^2)
3224
i += 1
3325
end
3426
end
35-
"""
3627

3728
@test sum(squares(10)) == sum(i^2 for i in 1:10)

0 commit comments

Comments
 (0)