From 3e533d3d17e149e735ddb502319337e2778d46f7 Mon Sep 17 00:00:00 2001 From: Niklas Korsbo Date: Mon, 12 Apr 2021 16:54:09 +0200 Subject: [PATCH 1/2] Add refactor prototype overloading `show`. --- refactor_show_prototype.jl | 136 +++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 refactor_show_prototype.jl diff --git a/refactor_show_prototype.jl b/refactor_show_prototype.jl new file mode 100644 index 00000000..2b1c62bb --- /dev/null +++ b/refactor_show_prototype.jl @@ -0,0 +1,136 @@ +using Pkg +Pkg.activate(@__DIR__) +using Latexify +import Base: show +using SnoopCompile + + +const Lmime = MIME"text/latexify" +const lmime = MIME("text/latexify") + +const opdict = (; + :* => :Multiplication, + :/ => :Division, + :+ => :Addition, + :- => :Subtraction, + :^ => :Pow, +) +for T in values(opdict) + println(T) +end +abstract type AbstractLatexifyOperation end +for T in values(opdict) + @eval( + struct $(T){S} <: AbstractLatexifyOperation + args::S + end + ) +end + +const ops = (; (keys(opdict) .=> eval.(values(opdict)))...) +ops[:*]([:a, :b]) + +for op in pairs(ops) + println(op[1], op[2]) + @eval latexop(::Val{:call}, ::Val{$(QuoteNode(op[1]))}, args) = $(op[2])(args) +end + + +abstract type AbstractLatexifyEnvironment end +for T in [:Align, :Equation, :Inline, :Bracket, :Raw, :Table] + @eval( + struct $(T){S} <: AbstractLatexifyEnvironment + args::S + end + ) +end +Align(x, y) = Align(hcat(x, y)) + + + +latexop(ex::Expr) = latexop(Val(ex.head), Val(ex.args[1]), ex.args[2:end]) +latexop(x) = x +latexop(x...) = x +latexop(x::Matrix) = Align(x) +latexop(::Val{:align}, x) = Align(x) +latexop(::Val{:equation}, x) = Equation(x) +latexop(lhs::Vector, rhs::Vector) = Align(lhs, rhs) + +show(io::IO, ::MIME"text/latexify", x) = print(io, x) + +compare_precedence(a, b) = Base.operator_precedence(a) > Base.operator_precedence(b) +function show(io::IO, mime::MIME"text/latexify", x::Multiplication) + surround = compare_precedence(get(io, :precedence, :+), :*) + io = IOContext(io, :precedence=>:*) + surround ? write(io, "\\left( ") : nothing + show(io, mime, x.args[1]) + write(io, get(io, :multsign, " \\cdot ")) + show(io, mime, x.args[2]) + surround ? write(io, "\\right) ") : nothing +end + +function show(io::IO, mime::MIME"text/latexify", x::Addition) + surround = compare_precedence(get(io, :precedence, :+), :+) + io = IOContext(io, :precedence=>:+) + surround ? write(io, "\\left(") : nothing + for arg in x.args[1:end-1] + show(io, mime, arg) + write(io, " + ") + end + show(io, mime, x.args[end]) + surround ? write(io, "\\right)") : nothing +end + +function show(io::IO, mime::MIME"text/latexify", x::Division) + write(io, "\\frac{") + show(io, mime, x.args[1]) + write(io, "}{") + show(io, mime, x.args[2]) + write(io, "}") +end + +function show(io::IO, mime::MIME"text/latexify", x::Expr) + show(io, mime, latexop(x)) +end + + +function join_matrix(io, m, delim = " & ", eol="\\\\\n") + nrows, ncols = size(m) + mime = MIME("text/latexify") + for (i, row) in enumerate(eachrow(m)) + for x in row[1:end-1] + show(io, mime, x) + write(io, delim) + end + show(io, mime, row[end]) + i != nrows && write(io, eol) + end + return nothing +end + + +function show(io::IO, mime::MIME"text/latexify", x::Align) + write(io, "\\begin{align}\n") + # join_show(io, x.args, " &= ") + join_matrix(io, x.args, " &= ") + write(io, "\n\\end{align}") +end + + +function _latex(args...; kwargs...) + io = IOBuffer(; append=true) + _latex(io, args...; kwargs...) + String(take!(io)) +end +function _latex(io::IO, args...; kwargs...) + io = IOContext(io, kwargs...) + show(io, MIME("text/latexify"), latexop(args...)) + return nothing +end + +io = IOBuffer(; append=true) +@time _latex(:(x/y)) +tinf = @snoopi_deep _latex(io, [1 2; :(x/y) 3]) +@time read(io, String) +using ProfileView +ProfileView.view(flamegraph(tinf)) \ No newline at end of file From 1b3e25e369502b522a4fe9c89f846c645165698f Mon Sep 17 00:00:00 2001 From: Niklas Korsbo Date: Tue, 13 Apr 2021 10:49:33 +0200 Subject: [PATCH 2/2] Refine prototype. --- refactor_show_prototype.jl | 204 ++++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 94 deletions(-) diff --git a/refactor_show_prototype.jl b/refactor_show_prototype.jl index 2b1c62bb..f1e80589 100644 --- a/refactor_show_prototype.jl +++ b/refactor_show_prototype.jl @@ -1,136 +1,152 @@ -using Pkg -Pkg.activate(@__DIR__) -using Latexify +# using Pkg +# Pkg.activate(@__DIR__) +# using Latexify import Base: show -using SnoopCompile const Lmime = MIME"text/latexify" const lmime = MIME("text/latexify") -const opdict = (; - :* => :Multiplication, - :/ => :Division, - :+ => :Addition, - :- => :Subtraction, - :^ => :Pow, -) -for T in values(opdict) - println(T) -end -abstract type AbstractLatexifyOperation end -for T in values(opdict) - @eval( - struct $(T){S} <: AbstractLatexifyOperation - args::S - end - ) +function join_matrix(io, m, delim = " & ", eol="\\\\\n") + nrows, ncols = size(m) + mime = MIME("text/latexify") + for (i, row) in enumerate(eachrow(m)) + for x in row[1:end-1] + show(io, mime, x) + write(io, delim) + end + show(io, mime, row[end]) + i != nrows ? write(io, eol) : write(io, "\n") + end + return nothing end -const ops = (; (keys(opdict) .=> eval.(values(opdict)))...) -ops[:*]([:a, :b]) +compare_precedence(a, b) = Base.operator_precedence(a) > Base.operator_precedence(b) -for op in pairs(ops) - println(op[1], op[2]) - @eval latexop(::Val{:call}, ::Val{$(QuoteNode(op[1]))}, args) = $(op[2])(args) +struct Environment{T} + args end +Environment(s::Symbol, args) = Environment{Val{s}}(args) +# lalign(x::AbstractVector, y::AbstractVector) = hcat(x, y) -abstract type AbstractLatexifyEnvironment end -for T in [:Align, :Equation, :Inline, :Bracket, :Raw, :Table] - @eval( - struct $(T){S} <: AbstractLatexifyEnvironment - args::S - end - ) +## Default Environments +Environment(args) = Environment{Val{:inline}}(args) +Environment(args::AbstractMatrix) = Environment{Val{:equation}}(args) +Environment(arg1::AbstractVector, arg2::AbstractVector) = Environment{Val{:align}}(hcat(arg1, arg2)) + + + +struct Operation{Head, Op} + args end -Align(x, y) = Align(hcat(x, y)) +Operation(ex::Expr) = Operation{Val{head(ex)}, Val{op(ex)}}(args(ex)) +head(::Any) = nothing +op(::Any) = nothing +args(::Any) = nothing +head(ex::Expr) = ex.head +op(ex::Expr) = head(ex) ∈ [:call, :ref] ? ex.args[1] : nothing +args(ex::Expr) = isnothing(op(ex)) ? ex.args : ex.args[2:end] -latexop(ex::Expr) = latexop(Val(ex.head), Val(ex.args[1]), ex.args[2:end]) -latexop(x) = x -latexop(x...) = x -latexop(x::Matrix) = Align(x) -latexop(::Val{:align}, x) = Align(x) -latexop(::Val{:equation}, x) = Equation(x) -latexop(lhs::Vector, rhs::Vector) = Align(lhs, rhs) +head(::Environment) = nothing +op(::Environment) = nothing +args(x::Environment) = x.args -show(io::IO, ::MIME"text/latexify", x) = print(io, x) +val(::Val{T}) where T = T +val(T::DataType) = val(T()) +val(x) = x -compare_precedence(a, b) = Base.operator_precedence(a) > Base.operator_precedence(b) -function show(io::IO, mime::MIME"text/latexify", x::Multiplication) - surround = compare_precedence(get(io, :precedence, :+), :*) - io = IOContext(io, :precedence=>:*) - surround ? write(io, "\\left( ") : nothing - show(io, mime, x.args[1]) - write(io, get(io, :multsign, " \\cdot ")) - show(io, mime, x.args[2]) - surround ? write(io, "\\right) ") : nothing +head(::Operation{Head, Op}) where {Head, Op} = val(Head) +op(::Operation{Head, Op}) where {Head, Op} = val(Op) +args(x::Operation) = x.args + +######## Environments + +function show(io::IO, mime::Lmime, x::Environment{Val{:align}}) + write(io, "\\begin{align}\n") + join_matrix(io, args(x), " &= ") + write(io, "\\end{align}") +end + +function show(io::IO, mime::Lmime, x::Environment{Val{:inline}}) + write(io, "\$") + show(io, mime, args(x)) + write(io, "\$") +end + +function show(io::IO, mime::Lmime, x::Environment{Val{:equation}}) + write(io, "\\begin{equation}\n") + show(io, mime, args(x)) + write(io, "\n\\end{equation}") +end + +function show(io::IO, mime::Lmime, x::Environment{Val{:bracket}}) + write(io, "\\[") + show(io, mime, args(x)) + write(io, "\\]") end -function show(io::IO, mime::MIME"text/latexify", x::Addition) +######## Operations + +function show(io::IO, mime::Lmime, x::Operation{Val{:call}, Val{:+}}) surround = compare_precedence(get(io, :precedence, :+), :+) io = IOContext(io, :precedence=>:+) surround ? write(io, "\\left(") : nothing - for arg in x.args[1:end-1] + for arg in args(x)[1:end-1] show(io, mime, arg) - write(io, " + ") + write(io, " ++ ") end - show(io, mime, x.args[end]) + show(io, mime, args(x)[end]) surround ? write(io, "\\right)") : nothing end -function show(io::IO, mime::MIME"text/latexify", x::Division) +function show(io::IO, mime::Lmime, x::Operation{Val{:ref}, T}) where T + show(io, mime, op(x)) + write(io, "\\left[") + for arg in args(x)[1:end-1] + show(io, mime, arg) + write(io, ", ") + end + show(io, mime, args(x)[end]) + write(io, "\\right]") +end + +function show(io::IO, mime::MIME"text/latexify", x::Operation{Val{:call}, Val{:/}}) write(io, "\\frac{") - show(io, mime, x.args[1]) + show(io, mime, args(x)[1]) write(io, "}{") - show(io, mime, x.args[2]) + show(io, mime, args(x)[2]) write(io, "}") end -function show(io::IO, mime::MIME"text/latexify", x::Expr) - show(io, mime, latexop(x)) -end - - -function join_matrix(io, m, delim = " & ", eol="\\\\\n") - nrows, ncols = size(m) - mime = MIME("text/latexify") - for (i, row) in enumerate(eachrow(m)) - for x in row[1:end-1] - show(io, mime, x) - write(io, delim) - end - show(io, mime, row[end]) - i != nrows && write(io, eol) - end - return nothing -end - +###### Convenience +show(io::IO, mime::Lmime, ex::Expr) = show(io, mime, Operation(ex)) +show(io::IO, ::MIME"text/latexify", x) = print(io, x) -function show(io::IO, mime::MIME"text/latexify", x::Align) - write(io, "\\begin{align}\n") - # join_show(io, x.args, " &= ") - join_matrix(io, x.args, " &= ") - write(io, "\n\\end{align}") -end +using LaTeXStrings -function _latex(args...; kwargs...) +function latex(args...; kwargs...) io = IOBuffer(; append=true) - _latex(io, args...; kwargs...) - String(take!(io)) + latex(io, args...; kwargs...) + LaTeXString(String(take!(io))) end -function _latex(io::IO, args...; kwargs...) + +function latex(io::IO, args...; env=:auto, kwargs...) io = IOContext(io, kwargs...) - show(io, MIME("text/latexify"), latexop(args...)) + # envtype = env == :auto ? Environment(args...) : Environment(env, args) + envtype = Environment(args...) + show(io, MIME("text/latexify"), envtype) return nothing end -io = IOBuffer(; append=true) -@time _latex(:(x/y)) -tinf = @snoopi_deep _latex(io, [1 2; :(x/y) 3]) -@time read(io, String) -using ProfileView -ProfileView.view(flamegraph(tinf)) \ No newline at end of file +# using SnoopCompile +# tinf = @snoopi_deep _latex([:x, 2],[:(x/y), 1/2]) +# using ProfileView +# ProfileView.view(flamegraph(tinf)) + +@time latex([:x, 2],[:(x/y), 1/2]) +latex(:(x/y)) +