Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Implement REPL mode for Rewrite #42

Closed
wants to merge 13 commits into from
13 changes: 13 additions & 0 deletions Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,20 @@ git-tree-sha1 = "af883752c4935425a3ab30031a2069254c451b8b"
uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
version = "0.5.0"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[ReplMaker]]
deps = ["REPL", "Test", "Unicode"]
git-tree-sha1 = "e40e05e0dc94e12717fbc368a4977039ff472c83"
uuid = "b873ce64-0db9-51f5-a568-4457d8e49576"
version = "0.2.2"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

Expand All @@ -66,3 +76,6 @@ version = "0.1.0"
[[Test]]
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.1.0"
[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
DiffRules = "b552c78f-8df3-52c6-915a-8e097449b14b"
ReplMaker = "b873ce64-0db9-51f5-a568-4457d8e49576"
SpecialSets = "c6b63f46-9023-11e8-3b28-1f7d8c94880d"

[extras]
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ julia> normalize(@term(diff(sin(2*$x) - log($x+$y), $x)))
@term(2 * cos(2x) - 1 / (x + y))
```

## REPL Mode
Rewrite now exports a REPL mode which can be accessed by pressing the `=` key at an empty `julia>` prompt. Currently, this REPL mode simply takes code and wraps it with `@term` and `normalize`, ie.
```julia
@term> sin(θ)/cos(θ)
```
is equivalent to
```julia
julia> normalize(@term sin(θ)/cos(θ))
```


## Approach
*Rewrite.jl* uses matching, normalization, and completion, which will be elaborated in the next sections.
Expand Down
2 changes: 2 additions & 0 deletions src/Rewrite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ include("rules.jl")
include("completion/Completion.jl")
using .Completion

include("replmode.jl")

end # module
20 changes: 20 additions & 0 deletions src/replmode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using ReplMaker

if isdefined(Base, :active_repl)
initrepl(
prompt_text = "@term> ",
prompt_color = :cyan,
start_key = '=',
mode_name = "Rewrite_mode",
) do s
exs = [Meta.parse(i) for i in split(s, "with")]
if length(exs) == 1
:(normalize((@term $(exs[1]))))
elseif length(exs) == 2
:(normalize((@term $(exs[1])), $(exs[2])))
else
throw("Only one `with` statement allowed.")
end
end
end

2 changes: 2 additions & 0 deletions src/rule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,5 @@ end
normalize(t::Term, ::DiffRule) = t
vars(x::Variable) = [x]
vars(t::Term) = [map(vars, collect(t))...;]

normalize(t::Term, tup::Tuple) = normalize(t, tup...)
98 changes: 98 additions & 0 deletions test/replmode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using Test
Base.include(@__MODULE__, joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testhelpers", "FakePTYs.jl"))
import .FakePTYs: open_fake_pty

slave, master = open_fake_pty()

CTRL_C = '\x03'

function run_repl_test(test_script)
slave, master = open_fake_pty()
# Start a julia process
p = run(`$(Base.julia_cmd()) --history-file=no --startup-file=no`, slave, slave, slave; wait=false)

# Read until the prompt
readuntil(master, "julia>", keep=true)
done = false
repl_output_buffer = IOBuffer()

# A task that just keeps reading the output
@async begin
while true
done && break
write(repl_output_buffer, readavailable(master))
end
end

# Execute our "script"
for l in split(test_script, '\n'; keepempty=false)
write(master, l, '\n')
end

# Let the REPL exit
write(master, "exit()\n")
wait(p)
done = true

# Gather the output
repl_output = String(take!(repl_output_buffer))
return split(repl_output, '\n'; keepempty=false)
end


test_script1 = """
using Rewrite

=
1 + 1
"""*CTRL_C

test_script1p = """
using Rewrite

normalize(@term 1 + 1)
"""*CTRL_C

test_script2 = """
using Rewrite

=
1 + 1
"""*CTRL_C

out1 = run_repl_test(test_script1);
out1p = run_repl_test(test_script1p);

test_script2p = """
using Rewrite

normalize(@term 1 + 1)
"""*CTRL_C

out2 = run_repl_test(test_script2);
out2p = run_repl_test(test_script2p);


test_script3 = """
using Rewrite

=
cos(x)^2 + sin(x)^2
"""*CTRL_C

test_script3p = """
using Rewrite

normalize(@term cos(x)^2 + sin(x)^2)
"""*CTRL_C

out3 = run_repl_test(test_script3);
out3p = run_repl_test(test_script3p);

@testset "REPL Mode" begin
@test out1[end-7] == out1p[end-7]
println("Testing REPL...") # FIXME: avoids CI timeout
@test out2[end-7] == out2p[end-7]
println("Testing REPL...") # FIXME: avoids CI timeout
@test out3[end-7] == out3p[end-7]
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ using Test
include("patterns.jl")
include("rules.jl")
include("completion.jl")
include("replmode.jl")