Skip to content

Commit

Permalink
optimize interface link
Browse files Browse the repository at this point in the history
  • Loading branch information
chakravala committed Jun 9, 2017
1 parent 86c2381 commit 2852a59
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 32 deletions.
21 changes: 11 additions & 10 deletions src/Reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ if VERSION < v"0.5.0" # backwards compatability
end

function ReduceCheck(output) # check for REDUCE errors
contains(output,"***** ") && throw(ReduceError(output*"\n")); end
contains(output,"***** ") && throw(ReduceError(output)); end

const SOS = "[0-9]+: " # REDUCE terminal prompt
function Base.read(rs::PSL) # get result and strip prompts/EOT char
Expand All @@ -76,16 +76,16 @@ include("rexpr.jl") # load RExpr features

## io

export string, show, ResetReduce
export string, show
import Base: string, show

string(r::RExpr) = convert(Compat.String,r)
show(io::IO, r::RExpr) = print(io,convert(Compat.String,r))
Base.write(rs::PSL,r::RExpr) = write(rs,convert(Compat.String,r))

@compat function show(io::IO, ::MIME"text/plain", r::RExpr)
rcall(ra"on nat"); write(rs,r); output = join(split(read(rs),"\n")[1:end-1],'\n')
rcall(ra"off nat"); print(io,replace(output,Regex("\n"*SOS),"")); end
write(rs,"on nat"*r*"off nat"); output = join(split(read(rs),"\n")[2:end-1],'\n')
print(io,chomp(replace(output,Regex("\n"*SOS),""))); end

@compat function show(io::IO, ::MIME"text/latex", r::RExpr)
rcall(ra"on latex"); write(rs,r); rd = readsp(rs)
Expand All @@ -101,24 +101,25 @@ include("repl.jl") # load repl features
## Setup

"""
ResetReduce()
Reduce.Reset()
Kills the REDUCE process and starts a new instance.
## Examples
```julia
julia> ResetReduce()
julia> Reduce.Reset()
Reduce (Free PSL version, revision 4015), 5-May-2017 ...
```
"""
ResetReduce() = (kill(rs); LoadReduce())
__init__() = (LoadReduce(); atexit(() -> kill(rs)))
Reset() = (kill(rs); Load())
__init__() = (Load(); atexit(() -> kill(rs)))

# Server setup

function LoadReduce()
function Load()
global rs = PSL(); write(rs,"off nat") # disable nat mode
banner = readuntil(rs.output,EOT) |> String; readavailable(rs.output);
is_windows() && (banner = replace(banner,r"\r","")); ReduceCheck(banner)
!is_windows() && !(is_windows() && contains(dirname(@__FILE__),"appveyor")) && println(split(String(banner),'\n')[end-3])
!(is_windows() && contains(dirname(@__FILE__),"appveyor")) &&
println(split(String(banner),'\n')[end-3])
ra"load_package rlfi" |> rcall # load REDUCE's LaTeX package
if isdefined(Base,:active_repl) && isinteractive()
repl_init(Base.active_repl); end; end
Expand Down
2 changes: 1 addition & 1 deletion src/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function respond(repl, main)
input = subst("$(ans)", "%", input[1:end-1]) # substitute
input = string(input, tail); end # add the tail
if !isempty(strip(input))
try; global ans = RExpr(input[1:end-1]) |> rcall; REPL.reset(repl)
try; global ans = RExpr(input[1:end-1]); REPL.reset(repl)
if input[end] == ';'
REPL.print_response(repl, ans, nothing, true, Base.have_color)
else; REPL.print_response(repl, nothing, nothing, true, Base.have_color); end
Expand Down
48 changes: 29 additions & 19 deletions src/rexpr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# Copyright (C) 2017 Michael Reed

export RExpr, @ra_str, parse, rcall, convert, error, ReduceError, ==, getindex
import Base: parse, convert, error, ==, getindex
import Base: parse, convert, error, ==, getindex, *, split

type ReduceError <: Exception; errstr::Compat.String; end
Base.showerror(io::IO, err::ReduceError) = print(io,"Reduce:\n"*err.errstr)
Base.showerror(io::IO, err::ReduceError) = print(io,"Reduce:"*chomp(err.errstr))

const infix_ops = [:+, :-, :*, :/, :^]
isinfix(args) = args[1] in infix_ops && length(args) > 2
Expand All @@ -28,9 +28,17 @@ type RExpr <: Any
## Fields:
str :: Array{Compat.String,1}
"""
type RExpr; str::Array{Compat.String,1}; end
type RExpr; str::Array{Compat.String,1}; RExpr(r::Array{Compat.String,1}) = new(r)
RExpr(r::Array{SubString{String},1}) = new(convert(Array{Compat.String,1},r)); end
RExpr(str::Compat.String) = RExpr(push!(Array{Compat.String,1}(0),str))
RExpr(r::Any) = RExpr("$r")
macro ra_str(str); RExpr(str); end
*(x::RExpr,y::Compat.String) = RExpr(push!(deepcopy(x.str),y))
*(x::Compat.String,y::RExpr) = RExpr(unshift!(deepcopy(y.str),x))
*(x::RExpr,y::RExpr) = RExpr(vcat(x.str...,y.str...))
function split(r::RExpr); n = Array{Compat.String,1}(0)
for h 1:length(r.str); p = split(replace(r.str[h],r"\$",";"),';')
for t 1:length(p); push!(n,p[t]); end; end; return RExpr(n); end

const r_to_jl = Dict(
"i" => "im",
Expand All @@ -40,7 +48,8 @@ const r_to_jl = Dict(
const r_to_jl_utf = Dict(
"pi" => "π",
"golden_ratio" => "φ",
"**" => "^")
"**" => "^",
":=" => "=")

const jl_to_r = Dict(
"eu" => "e",
Expand All @@ -53,15 +62,16 @@ const jl_to_r_utf = Dict(
"π" => "pi",
"γ" => "euler_gamma",
"φ" => "golden_ratio",
"^" => "**")
"^" => "**",
"=" => ":=")

# convert substitution dictionary into SUB parameter string
function _syme(syme::Dict{String,String}); str = ""; for key in keys(syme)
str = str*"($key)=($(syme[key])),"; end; return str[1:end-1]; end

const symrjl = _syme(r_to_jl); const symjlr = _syme(jl_to_r)

_subst(syme::String,expr) = "sub({$syme},$expr)" |> RExpr |> rcall
const symrjl = _syme(r_to_jl); const reprjl = Dict(r_to_jl...,r_to_jl_utf...)
const symjlr = _syme(jl_to_r); const repjlr = Dict(jl_to_r...,jl_to_r_utf...)
# _subst(syme::String,expr) = "sub({$syme},$expr)" |> RExpr |> rcall

"""
RExpr(expr::Expr)
Expand All @@ -78,9 +88,8 @@ cos(---------------) + sinh(x)*i
function RExpr(expr::Expr)
str = unparse(expr)
for h 1:length(str)
for key keys(jl_to_r_utf)
str[h] = replace(str[h],key,jl_to_r_utf[key]); end;
str = [str[1:h-1]; (_subst(symjlr,str[h])).str; str[h+1:end]]; end
for key keys(repjlr)
str[h] = replace(str[h],key,repjlr[key]); end; end
return str |> RExpr; end

"""
Expand All @@ -93,17 +102,17 @@ julia> parse(ra\"sin(i*x)\")
```
"""
function parse(r::RExpr)
pexpr = Array{Any,1}(0); sexpr = Array{Compat.String,1}(0)
for h 1:length(r.str); sp = split(replace(r.str[h],r"\$",";"),';')
for str sp; push!(sexpr,_subst(symrjl,str).str...); end; end
pexpr = Array{Any,1}(0); sexpr = split(r).str
for h 1:length(sexpr)
for key in keys(r_to_jl_utf)
sexpr[h] = replace(sexpr[h],key,r_to_jl_utf[key]); end
for key in keys(reprjl)
sexpr[h] = replace(sexpr[h],key,reprjl[key]); end
push!(pexpr,parse(sexpr[h])); end
return length(pexpr) == 1 ? pexpr[1] : Expr(:block,pexpr...); end

convert(::Type{RExpr}, r::RExpr) = r
convert(::Type{Array{Compat.String,1}}, r::RExpr) = r.str
convert(::Type{Compat.String}, r::RExpr) = join(r.str,"; ")
convert(::Type{Expr}, r::RExpr) = parse(r)
convert{T}(::Type{T}, r::RExpr) = parse(r)
if VERSION < v"0.5.0"
convert(::Type{UTF8String}, r::RExpr) = UTF8String(r.str)
convert(::Type{ASCIIString}, r::RExpr) = ASCIIString(r.str)
Expand Down Expand Up @@ -135,6 +144,7 @@ julia> rcall(:(int(1/(1+x^2), x)))
"""
rcall{T}(expr::T) = convert(T, rcall(RExpr(expr)))

function ==(r::RExpr, s::RExpr)
return "if ($r) = ($s) then 1 else 0" |> rcall |> parse |> eval |> Bool; end
function ==(r::RExpr, s::RExpr); n = split(r).str; m = split(s).str
l=length(n); llength(m) && (return false); b = true; for j1:l
b &= "if($(n[j]))=($(m[j]))then 1 else 0"|>rcall|>parse|>eval|>Bool; end; return b; end
getindex(r::RExpr, i) = "$r($i)" |> rcall
9 changes: 7 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ using Base.Test
# write your own tests here
@test rcall(:((1+π)^2)) == convert(Expr,RExpr(rcall("(1+pi)**2")))
@test try; "1/0" |> rcall; false; catch; true; end
@test ResetReduce() == nothing
@test display(RExpr("(x+1)^3")) == nothing
@test Reduce.Reset() == nothing
@test display(RExpr("(x+i)^3")) == nothing; print('\n')
@test Reduce._syme(Reduce.r_to_jl) |> typeof == String
@test ra"x+2" == ra"2+x-1+1"
@test :((x+1+π)^2; int(1/(1+x^3),x)) |> RExpr |> parse |> typeof == Expr
@test !Base.process_exited(Reduce.rs)
@test string(ra"x+1") |> typeof == String
@test RExpr(:x) == ra"x"
@test RExpr(:x)*ra"x" == ra"x;x"
@test convert(RExpr,ra"x").str == convert(Array{Compat.String,1},ra"x")

0 comments on commit 2852a59

Please sign in to comment.