Skip to content

Instantly share code, notes, and snippets.

@oprypin
Last active August 24, 2016 23:02
Show Gist options
  • Save oprypin/b4f150b0d22e9e3ee2dff3bcf8ec8cb5 to your computer and use it in GitHub Desktop.
Save oprypin/b4f150b0d22e9e3ee2dff3bcf8ec8cb5 to your computer and use it in GitHub Desktop.
Power Assert 2
require "compiler/crystal/syntax"
class AssertToSVisitor < Crystal::ToSVisitor
getter locations = [] of Int32
def visit_any(node)
if node.class.name.ends_with? "Literal"
@str << node.to_s
return false
end
if (loc = node.location)
@str << "(__" << locations.size << "=("
locations << case node
when Crystal::Call
node.name_column_number
else
loc.column_number
end
end
super
end
def end_visit_any(node)
super
@str << "))"
end
end
src = ARGV[0].gsub('\n', ' ')
visitor = AssertToSVisitor.new(io = MemoryIO.new)
Crystal::Parser.parse(src).accept(visitor)
puts "unless #{io}"
puts " puts " + src.inspect
visitor.locations.each_with_index do |loc, i|
puts %{ puts "#{" " * (loc - 1)}^\#{__#{i}}"}
end
puts "end"
print "#" * 80
macro assert(expr)
{% puts o = run("./assert", expr) %}
{{ o }}
end
foo = "foo"
assert %{foo.index('o') == 1 + 2}
unless (__0=(((__1=((__2=(foo)).index('o')))) == ((__3=(1 + 2)))))
puts "foo.index('o') == 1 + 2"
puts " ^#{__0}"
puts " ^#{__1}"
puts "^#{__2}"
puts " ^#{__3}"
end
################################################################################
foo.index('o') == 1 + 2
^false
^1
^foo
^3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment