ruby/test/yarp/compile_test.rb
Jemma Issroff cc7f765f2c [Feature #19741] Sync all files in yarp
This commit is the initial sync of all files from ruby/yarp
into ruby/ruby. Notably, it does the following:

* Sync all ruby/yarp/lib/ files to ruby/ruby/lib/yarp
* Sync all ruby/yarp/src/ files to ruby/ruby/yarp/
* Sync all ruby/yarp/test/ files to ruby/ruby/test/yarp
2023-06-21 11:25:39 -07:00

212 lines
5.4 KiB
Ruby

# frozen_string_literal: true
require "yarp_test_helper"
class CompileTest < Test::Unit::TestCase
def test_AliasNode
assert_compiles("alias foo bar")
end
def test_AndNode
assert_compiles("true && false")
end
def test_ArrayNode
assert_compiles("[]")
assert_compiles("[foo, bar, baz]")
end
def test_AssocNode
assert_compiles("{ foo: bar }")
end
def test_BlockNode
assert_compiles("foo { bar }")
end
def test_BlockNode_with_optionals
assert_compiles("foo { |x = 1| bar }")
end
def test_CallNode
assert_compiles("foo")
assert_compiles("foo(bar)")
end
def test_ClassVariableReadNode
assert_compiles("@@foo")
end
def test_ClassVariableWriteNode
assert_compiles("@@foo = 1")
end
def test_FalseNode
assert_compiles("false")
end
def test_GlobalVariableReadNode
assert_compiles("$foo")
end
def test_GlobalVariableWriteNode
assert_compiles("$foo = 1")
end
def test_HashNode
assert_compiles("{ foo: bar }")
end
def test_InstanceVariableReadNode
assert_compiles("@foo")
end
def test_InstanceVariableWriteNode
assert_compiles("@foo = 1")
end
def test_IntegerNode
assert_compiles("1")
assert_compiles("1_000")
end
def test_InterpolatedStringNode
assert_compiles("\"foo \#{bar} baz\"")
end
def test_LocalVariableWriteNode
assert_compiles("foo = 1")
end
def test_LocalVariableReadNode
assert_compiles("[foo = 1, foo]")
end
def test_NilNode
assert_compiles("nil")
end
def test_OrNode
assert_compiles("true || false")
end
def test_ParenthesesNode
assert_compiles("()")
end
def test_ProgramNode
assert_compiles("")
end
def test_RangeNode
assert_compiles("foo..bar")
assert_compiles("foo...bar")
assert_compiles("(foo..)")
assert_compiles("(foo...)")
assert_compiles("(..bar)")
assert_compiles("(...bar)")
end
def test_SelfNode
assert_compiles("self")
end
def test_StringNode
assert_compiles("\"foo\"")
end
def test_SymbolNode
assert_compiles(":foo")
end
def test_TrueNode
assert_compiles("true")
end
def test_UndefNode
assert_compiles("undef :foo, :bar, :baz")
end
def test_XStringNode
assert_compiles("`foo`")
end
private
def assert_compiles(source)
assert_equal_iseqs(rubyvm_compile(source), YARP.compile(source))
end
# Instruction sequences have 13 elements in their lists. We don't currently
# support all of the fields, so we can't compare the iseqs directly. Instead,
# we compare the elements that we do support.
def assert_equal_iseqs(expected, actual)
# The first element is the magic comment string.
assert_equal expected[0], actual[0]
# The next three elements are the major, minor, and patch version numbers.
# TODO: Insert this check once Ruby 3.3 is released, and the TruffleRuby
# GitHub workflow also checks against Ruby 3.3
# assert_equal expected[1...4], actual[1...4]
# The next element is a set of options for the iseq. It has lots of
# different information, some of which we support and some of which we
# don't.
assert_equal expected[4][:arg_size], actual[4][:arg_size], "Unexpected difference in arg_size"
assert_equal expected[4][:stack_max], actual[4][:stack_max], "Unexpected difference in stack_max"
assert_kind_of Integer, actual[4][:local_size]
assert_kind_of Integer, actual[4][:node_id]
assert_equal expected[4][:code_location].length, actual[4][:code_location].length, "Unexpected difference in code_location length"
assert_equal expected[4][:node_ids].length, actual[4][:node_ids].length, "Unexpected difference in node_ids length"
# Then we have the name of the iseq, the relative file path, the absolute
# file path, and the line number. We don't have this working quite yet.
assert_kind_of String, actual[5]
assert_kind_of String, actual[6]
assert_kind_of String, actual[7]
assert_kind_of Integer, actual[8]
# Next we have the type of the iseq.
assert_equal expected[9], actual[9]
# Next we have the list of local variables. We don't support this yet.
assert_kind_of Array, actual[10]
# Next we have the argument options. These are used in block and method
# iseqs to reflect how the arguments are passed.
assert_equal expected[11], actual[11], "Unexpected difference in argument options"
# Next we have the catch table entries. We don't have this working yet.
assert_kind_of Array, actual[12]
# Finally we have the actual instructions. We support some of this, but omit
# line numbers and some tracepoint events.
expected[13].each do |insn|
case insn
in [:send, opnds, expected_block] unless expected_block.nil?
actual[13].shift => [:send, ^(opnds), actual_block]
assert_equal_iseqs expected_block, actual_block
in Array | :RUBY_EVENT_B_CALL | :RUBY_EVENT_B_RETURN | /^label_\d+/
assert_equal insn, actual[13].shift
in Integer | /^RUBY_EVENT_/
# skip these for now
else
flunk "Unexpected instruction: #{insn.inspect}"
end
end
end
def rubyvm_compile(source)
options = {
peephole_optimization: false,
specialized_instruction: false,
operands_unification: false,
instructions_unification: false,
frozen_string_literal: false
}
RubyVM::InstructionSequence.compile(source, **options).to_a
end
end