# One program that appends to a string literal, run five ways. In Ruby 4.0 a
# literal is "chilled": still mutable, but flagged, with a warning ready to fire.
require "open3"
require "rbconfig"
require "tmpdir"

PROGRAM = <<~'RUBY'
  greeting = "hello"
  puts "  greeting.frozen?  #{greeting.frozen?}"
  begin
    greeting << ", world"
    puts "  after <<          #{greeting.inspect}"
  rescue FrozenError => e
    puts "  #{e.class}: #{e.message}"
  end
RUBY

def run(title, flags: [], magic: nil)
  Dir.mktmpdir do |dir|
    File.write(File.join(dir, "greet.rb"), [magic, PROGRAM].compact.join("\n"))
    out, err, _status = Open3.capture3(RbConfig.ruby, *flags, "greet.rb", chdir: dir)
    puts "$ #{title}"
    print out
    err.each_line { |line| puts "  stderr: #{line}" }
    puts
  end
end

run("ruby greet.rb")
run("ruby -W:deprecated greet.rb", flags: ["-W:deprecated"])
run("ruby --enable=frozen-string-literal greet.rb", flags: ["--enable=frozen-string-literal"])
run("ruby greet.rb    # line 1: # frozen_string_literal: true", magic: "# frozen_string_literal: true")
run("ruby -W:deprecated greet.rb    # line 1: # frozen_string_literal: false",
    flags: ["-W:deprecated"], magic: "# frozen_string_literal: false")

puts "Strings you are allowed to change, with no warning:"
puts "  (+\"hello\").frozen?            #{(+"hello").frozen?}"
puts "  \"hello\".dup.frozen?           #{"hello".dup.frozen?}"
puts "  String.new(\"hello\").frozen?   #{String.new("hello").frozen?}"
puts
puts "Strings that are shared on purpose:"
puts "  (-\"hello\").equal?(-(\"hel\" + \"lo\"))   #{(-"hello").equal?(-("hel" + "lo"))}"
puts "  :hello.name.equal?(:hello.name)       #{:hello.name.equal?(:hello.name)}"
puts "  :hello.to_s.equal?(:hello.to_s)       #{:hello.to_s.equal?(:hello.to_s)}"
