RosettaCodeData/Task/Truth-table/Julia/truth-table-1.jl
2024-10-16 18:07:41 -07:00

43 lines
1.2 KiB
Julia

module TruthTable
using Printf
using MacroTools
isvariablename(::Any) = false
isvariablename(s::Symbol) = all(x -> isletter(x) || x == '_', string(s))
function table(expr)
if !isvariablename(expr) && !Meta.isexpr(expr, :call)
throw(ArgumentError("expr must be a boolean expression"))
end
exprstr = string(expr)
# Collect variable names
symset = Set{Symbol}()
MacroTools.prewalk(expr) do node
isvariablename(node) && push!(symset, node)
return node
end
symlist = collect(symset)
# Create assignment assertions + evaluate
blocks = Vector{Expr}(undef, 2 ^ length(symlist) + 1)
blocks[1] = quote
println(join(lpad.($(symlist), 6), " | "), " || ", $exprstr)
end
for (i, tup) in enumerate(Iterators.product(Iterators.repeated((false, true), length(symlist))...))
blocks[i + 1] = quote
let $(Expr(:(=), Expr(:tuple, symlist...), Expr(:tuple, tup...)))
println(join(lpad.($(Expr(:tuple, symlist...)), 6), " | "), " || ", lpad($expr, $(length(exprstr))))
end
end
end
return esc(Expr(:block, blocks...))
end
macro table(expr)
return table(expr)
end
end # module TruthTable