require "./run.rb"
require "./graphviz.rb"
require "stringio"

# Tests for graphviz.rb (ast2viz / ir2viz), the program-diagram generator that powers
# the online interpreter (the same diagrams shown in the docs). The web drives these via
# run_and_do_io's ast_cb / ir_cb; here we call gen_graph directly, which fires the same
# callbacks but skips evaluation/printing, so infinite-output programs don't hang.
# (webmain.rb itself needs the ruby.wasm `js` runtime and can't run under MRI; this covers
# the pure-ruby graph logic it depends on.)

$fail = false
def expect(desc, ok)
  return if ok
  STDERR.puts "FAIL: #{desc}"
  $fail = true
end

def dots(src)
  ast_dot = ir_dot = nil
  gen_graph(src, StringIO.new(""),
    ast_cb: ->ast,inds{ ast_dot = ast2viz(ast, inds) },
    ir_cb:  ->ir2,inds{ ir_dot  = ir2viz(ir2, inds) })
  [ast_dot, ir_dot]
end

def well_formed(desc, dot)
  expect("#{desc}: nonempty", dot && !dot.empty?)
  expect("#{desc}: digraph wrapper", dot.start_with?("digraph {") && dot.rstrip.end_with?("}"))
  expect("#{desc}: balanced braces", dot.count("{") == dot.count("}"))
end

# arithmetic: postfix tree, output node marked, 2nd args use empty arrowheads
ast, ir = dots("5 2 1+*")
well_formed("arith ast", ast); well_formed("arith ir", ir)
expect("arith ast has op labels", ast.include?(%q{[label="+"]}) && ast.include?(%q{[label="*"]}))
expect("arith ast marks output node", ast =~ /\[shape=Msquare\] \[label="\*"\]/)
expect("arith ast has 2nd-arg arrowhead", ast.include?("[arrowhead=empty]"))
expect("arith ir uses long op names", ir.include?(%q{[label="add"]}) && ir.include?(%q{[label="mult"]}))
expect("arith ir colors ints", ir.include?('fontcolor="#ff6600"'))

# loop: infinite output, but we only build the graph. Exercises the loop back-edge
# (dashed), the MatchedEndBracket ">" label, and desugaring of iterate in the IR.
ast, ir = dots("0 iterate 1+ >")
well_formed("loop ast", ast); well_formed("loop ir", ir)
expect("loop ast shows loop op + end bracket", ast.include?(%q{[label="iterate"]}) && ast.include?(%q{[label=">"]}))
expect("loop ast has dashed back-edge", ast.include?("[style=dashed]"))
expect("loop ir desugars to cons/repeat", ir.include?(%q{[label="cons"]}) && ir.include?(%q{[label="repeat"]}))

# string: char coloring in the IR and an escaped string label in the AST
ast, ir = dots(%q{"abc"})
well_formed("str ast", ast); well_formed("str ir", ir)
expect("str ir colors chars", ir.include?('fontcolor="#005c99"'))
expect("str ast escapes string label", ast.include?('\"abc\"'))

exit 1 if $fail
puts "PASS graphviz tests"
