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

Compromise Interface Redesign #25

Merged
merged 20 commits into from
Feb 29, 2024
Merged
31 changes: 9 additions & 22 deletions src/TermInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,6 @@ on `x` and must return a Symbol.
issym(x) = false
export issym

"""
exprhead(x)

If `x` is a term as defined by `istree(x)`, `exprhead(x)` must return a symbol,
corresponding to the head of the `Expr` most similar to the term `x`.
If `x` represents a function call, for example, the `exprhead` is `:call`.
If `x` represents an indexing operation, such as `arr[i]`, then `exprhead` is `:ref`.
Note that `exprhead` is different from `operation` and both functions should
be defined correctly in order to let other packages provide code generation
and pattern matching features.
"""
function exprhead end
export exprhead


"""
operation(x)

Expand All @@ -64,7 +49,6 @@ Get the arguments of `x`, must be defined if `istree(x)` is `true`.
function arguments end
export arguments


"""
unsorted_arguments(x::T)

Expand Down Expand Up @@ -106,18 +90,21 @@ function metadata(x, data)
error("Setting metadata on $x is not possible")
end


"""
similarterm(x, head, args, symtype=nothing; metadata=nothing, exprhead=:call)
similarterm(x, head, args, symtype=nothing; metadata=nothing)

Returns a term that is in the same closure of types as `typeof(x)`,
with `head` as the head and `args` as the arguments, `type` as the symtype
and `metadata` as the metadata. By default this will execute `head(args...)`.
`x` parameter can also be a `Type`. The `exprhead` keyword argument is useful
when manipulating `Expr`s.
`x` parameter can also be a `Type`. Implementers should define similarterm on the
type of `x` and not on `x` itself.
"""
function similarterm(x, head, args, symtype = nothing; metadata = nothing, exprhead = nothing)
head(args...)
function similarterm(x, head, args, symtype = nothing; metadata = nothing)
similarterm(typeof(x), head, args, symtype = symtype, metadata = metadata)
end

function similarterm(T::Type, head, args, symtype = nothing; metadata = nothing)
head(args...)
0x0f0f0f marked this conversation as resolved.
Show resolved Hide resolved
end

export similarterm
Expand Down
25 changes: 5 additions & 20 deletions src/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,10 @@
# Builtin Expr type.

istree(x::Expr) = true
exprhead(e::Expr) = e.head

operation(e::Expr) = expr_operation(e, Val{exprhead(e)}())
arguments(e::Expr) = expr_arguments(e, Val{exprhead(e)}())
operation(e::Expr) = e.head
arguments(e::Expr) = e.args

0x0f0f0f marked this conversation as resolved.
Show resolved Hide resolved
# See https://docs.julialang.org/en/v1/devdocs/ast/
expr_operation(e::Expr, ::Union{Val{:call},Val{:macrocall}}) = e.args[1]
expr_operation(e::Expr, ::Union{Val{:ref}}) = getindex
expr_operation(e::Expr, ::Val{T}) where {T} = T

expr_arguments(e::Expr, ::Union{Val{:call},Val{:macrocall}}) = e.args[2:end]
expr_arguments(e::Expr, _) = e.args


function similarterm(x::Expr, head, args, symtype = nothing; metadata = nothing, exprhead = exprhead(x))
expr_similarterm(head, args, Val{exprhead}())
end


expr_similarterm(head, args, ::Val{:call}) = Expr(:call, head, args...)
expr_similarterm(head, args, ::Val{:macrocall}) = Expr(:macrocall, head, args...) # discard linenumbernodes?
expr_similarterm(head, args, ::Val{eh}) where {eh} = Expr(eh, args...)
function similarterm(x::Expr, head, args, symtype = nothing; metadata = nothing)
Expr(head, args...)
end
11 changes: 4 additions & 7 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ using Test

@testset "Expr" begin
ex = :(f(a, b))
@test operation(ex) == :f
@test arguments(ex) == [:a, :b]
@test exprhead(ex) == :call
@test ex == similarterm(ex, :f, [:a, :b])
@test operation(ex) == :call
0x0f0f0f marked this conversation as resolved.
Show resolved Hide resolved
@test arguments(ex) == [:f, :a, :b]
@test ex == similarterm(ex, :call, [:f, :a, :b])

ex = :(arr[i, j])
@test operation(ex) == getindex
@test operation(ex) == :ref
@test arguments(ex) == [:arr, :i, :j]
@test exprhead(ex) == :ref
@test ex == similarterm(ex, :ref, [:arr, :i, :j]; exprhead = :ref)
@test ex == similarterm(ex, :ref, [:arr, :i, :j])
end
Loading