From 049a9bd62f0907caa8d2eca6337cd2542a5c7726 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 13 Dec 2023 12:49:37 -0500 Subject: [PATCH] [PRISM] Fix `compile_prism` when src is a file `compile_prism` can take a source and file (and other arguments) or a file as the source. `compile` checks if the source is a file and if it is converts it. `compile_prism` is now doing the same thing. On the Ruby side `compile` handles a file [here](https://github.com/ruby/ruby/blob/master/iseq.c#L1159-L1162). Before: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(26,21)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] name@0 0000 putstring "Prism" ( 25)[Li] 0002 setlocal name@0, 0 0005 putself ( 26)[Li] 0006 putobject "hello, " 0008 getlocal name@0, 0 0011 dup 0012 objtostring 0014 anytostring 0015 concatstrings 2 0017 send , nil 0020 leave hello, Prism "********* PRISM *************" ./test.rb:13:in `compile_prism': wrong argument type File (expected String) (TypeError) from ./test.rb:13:in `
' make: *** [run] Error 1 ``` After: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(26,21)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] name@0 0000 putstring "Prism" ( 25)[Li] 0002 setlocal name@0, 0 0005 putself ( 26)[Li] 0006 putobject "hello, " 0008 getlocal name@0, 0 0011 dup 0012 objtostring 0014 anytostring 0015 concatstrings 2 0017 send , nil 0020 leave "********* PRISM *************" == disasm: #@test_code.rb:24 (24,0)-(25,21)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] name@0 0000 putstring "Prism" ( 24)[Li] 0002 setlocal name@0, 0 0005 putself ( 25)[Li] 0006 putobject "hello, " 0008 getlocal name@0, 0 0011 dup 0012 objtostring 0014 anytostring 0015 concatstrings 2 0017 send , nil 0020 leave ( 24) ``` Fixes ruby/prism#1609 --- iseq.c | 14 +++++++++++++- test/ruby/test_iseq.rb | 11 +++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/iseq.c b/iseq.c index b68c230404..fa5f564fb3 100644 --- a/iseq.c +++ b/iseq.c @@ -1447,7 +1447,19 @@ iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self) pm_options_line_set(&options, start_line); pm_parser_t parser; - pm_parser_init(&parser, (const uint8_t *) RSTRING_PTR(src), RSTRING_LEN(src), &options); + + if (RB_TYPE_P(src, T_FILE)) { + FilePathValue(src); + file = rb_fstring(src); /* rb_io_t->pathv gets frozen anyways */ + + pm_string_t input; + pm_string_mapped_init(&input, RSTRING_PTR(file)); + + pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); + } + else { + pm_parser_init(&parser, (const uint8_t *) RSTRING_PTR(src), RSTRING_LEN(src), &options); + } rb_iseq_t *iseq = iseq_alloc(); iseqw_s_compile_prism_compile(&parser, opt, iseq, file, path, start_line); diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index f05d067ac2..b0896511d8 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -798,4 +798,15 @@ class TestISeq < Test::Unit::TestCase result = RubyVM::InstructionSequence.load_from_binary(iseq.to_binary).eval assert_equal expected, result, proc {sprintf("expected: %x, result: %x", expected, result)} end + + def test_compile_prism_with_file + Tempfile.create(%w"test_iseq .rb") do |f| + f.puts "name = 'Prism'; puts 'hello" + f.close + + assert_nothing_raised(SyntaxError) { + RubyVM::InstructionSequence.compile_prism(f.path) + } + end + end end