{% skip_file if flag?(:without_interpreter) %} require "./spec_helper" describe Crystal::Repl::Interpreter do context "bugs" do it "doesn't pass self to top-level method" do interpret(<<-CRYSTAL).should eq(1) struct Int32 def foo(x) self end end def value 1 end module Moo def self.moo 1.foo(value) end end Moo.moo CRYSTAL end it "doesn't pass self to top-level method (FileNode)" do interpret(<<-CRYSTAL).should eq(1) enum Color Red Green Blue end class Object def should(expectation) self end end def eq(value) value end private def t(type : Color) type end other = 2 e = Color::Green.should eq(t :green) e.value CRYSTAL end it "breaks from current block, not from outer block" do interpret(<<-CRYSTAL).should eq(2) def twice # index: 1, block_caller: 0 yield yield end def bar # index: 4, block_caller: 3 yield end def foo # index: 3, block_caller: 2 bar do # index: 5, block_caller: 2 yield end end # index: 0 x = 0 twice do # index: 2 x += 1 foo do # index: 6 # parent frame has block_caller: 2, # that's where we have to go to break end end x CRYSTAL end it "doesn't incorrectly consider a non-closure as closure" do interpret(<<-CRYSTAL, prelude: "prelude").should eq("false") c = 0 ->{ c ->{}.closure? }.call CRYSTAL end it "doesn't override local variable value with block var with the same name" do interpret(<<-CRYSTAL).should eq(0) def block yield 1 end def block2 yield 10 end def foo block do |i| end i = 0 block2 do |x| i end end foo CRYSTAL end it "does leading zeros" do interpret(<<-CRYSTAL, prelude: "prelude").should eq("8") 0_i8.leading_zeros_count CRYSTAL end it "does multidispatch on virtual struct" do interpret(<<-CRYSTAL).should be_true abstract struct Base end struct Foo < Base @x : Int32 | Char def initialize @x = 0 end def foo @x.is_a?(Int32) end end struct Bar < Base def foo false end end address = Foo.new.as(Base) address.foo CRYSTAL end it "correctly puts virtual metaclass type in union" do interpret(<<-CRYSTAL).should eq("Bar") abstract struct Foo end struct Bar < Foo end struct Baz < Foo end class Class def name : String {{ @type.name.stringify }} end end foo = Bar.new.as(Foo) foo2 = foo || nil foo2.class.name CRYSTAL end it "does multidispatch on virtual struct union nil" do interpret(<<-CRYSTAL).should be_true abstract struct Foo @value = 1 end struct Bar < Foo end struct Baz < Foo end class Object def itself a = 1 self end end foo = Bar.new.as(Foo) bar = (foo || nil).itself bar.is_a?(Bar) CRYSTAL end it "handles self in inlined method with arguments (#16210)" do interpret(<<-CRYSTAL, prelude: "prelude").should eq(%("hello")) class Foo property x : String? def initialize(@x : String? = nil) end end foo = Foo.new("hello") foo.x.not_nil!("test") CRYSTAL end it "returns concrete type with typeof (#16377)" do interpret(<<-CRYSTAL, prelude: "prelude").should eq("true") class Foo end class Bar < Foo end foo = Bar.new.as(Foo) typeof(foo) == Foo CRYSTAL end it "looks up local vars in parent scopes after looking up local vars in current scope and closured scope (#15489)" do interpret(<<-CRYSTAL).should eq("parser") def capture(&block) block end def scoped(&) yield 1 end scoped do |parser| capture do parser end parser # Error: BUG: missing downcast_distinct from String to Int32 (Crystal::NonGenericClassType to Crystal::IntegerType) end parser = "parser" CRYSTAL end end end