diff --git a/spec/compiler/codegen/block_spec.cr b/spec/compiler/codegen/block_spec.cr index 0a53dd4a14e3..fa88f4e32d5a 100644 --- a/spec/compiler/codegen/block_spec.cr +++ b/spec/compiler/codegen/block_spec.cr @@ -563,18 +563,27 @@ describe "Code gen: block" do class Bar < Foo end - $x : Int32? + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end struct Int def foo x = Foo.new x = Bar.new - x.do { $x = self } + x.do { Global.x = self } end end 123.foo - $x.to_i + Global.x.to_i ").to_i.should eq(123) end @@ -1220,12 +1229,21 @@ describe "Code gen: block" do it "codegens block bug with conditional next and unconditional break (3)" do run(%( - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo a = 1234 a = yield 1 - $x = a + Global.x = a a end @@ -1233,27 +1251,36 @@ describe "Code gen: block" do next x if 1 == 1 break 0 end - $x + Global.x )).to_i.should eq(1) end it "codegens block bug with conditional next and unconditional break (4)" do run(%( - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo bar(yield 1) end def bar(x) - $x = x + Global.x = x end foo do |x| next x if 1 == 1 break 0 end - $x + Global.x )).to_i.should eq(1) end diff --git a/spec/compiler/codegen/case_spec.cr b/spec/compiler/codegen/case_spec.cr index f9fe00bd6caf..87aeb8f9655a 100644 --- a/spec/compiler/codegen/case_spec.cr +++ b/spec/compiler/codegen/case_spec.cr @@ -34,10 +34,8 @@ describe "Code gen: case" do run(" require \"prelude\" - $a = 0 - def foo - $a += 1 + 1 end case foo diff --git a/spec/compiler/codegen/class_spec.cr b/spec/compiler/codegen/class_spec.cr index 6992f9022d6d..7b49d06bc4b6 100644 --- a/spec/compiler/codegen/class_spec.cr +++ b/spec/compiler/codegen/class_spec.cr @@ -434,10 +434,14 @@ describe "Code gen: class" do 1 end - $x = self.foo.as(Int32) + @@x = self.foo.as(Int32) + + def self.x + @@x + end end - $x + Foo.x )).to_i.should eq(1) end @@ -448,10 +452,14 @@ describe "Code gen: class" do 1 end - $x = self.as(Foo.class) + @@x = self.as(Foo.class) + + def self.x + @@x + end end - $x.foo + Foo.x.foo )).to_i.should eq(1) end diff --git a/spec/compiler/codegen/const_spec.cr b/spec/compiler/codegen/const_spec.cr index 9e6c38ca3532..e101009fc2fd 100644 --- a/spec/compiler/codegen/const_spec.cr +++ b/spec/compiler/codegen/const_spec.cr @@ -204,14 +204,6 @@ describe "Codegen: const" do ").to_i.should eq(3) end - it "works with const initialized after global variable" do - run(%( - $a = 1 - COCO = $a - COCO - )).to_i.should eq(1) - end - it "works with variable declared inside if" do run(%( FOO = begin @@ -327,31 +319,6 @@ describe "Codegen: const" do )).to_i.should eq(3) end - it "initializes const the moment it reaches it" do - run(%( - $x = 10 - FOO = begin - a = $x - a - end - w = FOO - z = FOO - z - )).to_i.should eq(10) - end - - it "initializes const when read" do - run(%( - $x = 10 - z = FOO - FOO = begin - a = $x - a - end - z - )).to_i.should eq(10) - end - it "initializes simple const" do run(%( FOO = 10 diff --git a/spec/compiler/codegen/double_splat_spec.cr b/spec/compiler/codegen/double_splat_spec.cr index 11dbfe6ae93c..5a6ebb7b5dba 100644 --- a/spec/compiler/codegen/double_splat_spec.cr +++ b/spec/compiler/codegen/double_splat_spec.cr @@ -100,11 +100,20 @@ describe "Codegen: double splat" do it "evaluates double splat argument just once (#2677)" do run(%( - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def data - $a += 1 - {x: $a, y: $a, z: $a} + Global.x += 1 + {x: Global.x, y: Global.x, z: Global.x} end def test(x, y, z) @@ -112,7 +121,7 @@ describe "Codegen: double splat" do test(**data) - $a + Global.x )).to_i.should eq(1) end end diff --git a/spec/compiler/codegen/exception_spec.cr b/spec/compiler/codegen/exception_spec.cr index d36c0a2ac995..f8281acc0e5a 100644 --- a/spec/compiler/codegen/exception_spec.cr +++ b/spec/compiler/codegen/exception_spec.cr @@ -45,20 +45,29 @@ describe "Code gen: exception" do run(%( require "prelude" - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo raise "foo" rescue - $x += 1 + Global.x += 1 return ensure - $x += 1 + Global.x += 1 end foo - $x + Global.x )).to_i.should eq(2) end @@ -764,14 +773,30 @@ describe "Code gen: exception" do run(%( require "prelude" - $a = 0 - $b = 0 + class Global + @@a = 0 + @@b = 0 + + def self.a=(@@a) + end + + def self.a + @@a + end + + def self.b=(@@b) + end + + def self.b + @@b + end + end def bar begin yield ensure - $a = 1 + Global.a = 1 end end @@ -779,10 +804,10 @@ describe "Code gen: exception" do while true break end - $b = $a + Global.b = Global.a end - $b + Global.b )).to_i.should eq(0) end @@ -844,24 +869,33 @@ describe "Code gen: exception" do run(%( require "prelude" - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo begin begin raise "foo" rescue - $a += 1 + Global.x += 1 return end ensure - $a += 1 + Global.x += 1 end end foo - $a + Global.x )).to_i.should eq(2) end @@ -890,13 +924,22 @@ describe "Code gen: exception" do run(%( require "prelude" - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo begin yield ensure - $a += 1 + Global.x += 1 end end @@ -906,13 +949,13 @@ describe "Code gen: exception" do return end ensure - $a += 1 + Global.x += 1 end end bar - $a + Global.x )).to_i.should eq(2) end @@ -948,15 +991,31 @@ describe "Code gen: exception" do run(%( require "prelude" - $a = 0 - $b = 0 + class Global + @@a = 0 + @@b = 0 + + def self.a=(@@a) + end + + def self.a + @@a + end + + def self.b=(@@b) + end + + def self.b + @@b + end + end def foo begin yield - $b = $a + Global.b = Global.a ensure - $a += 1 + Global.a += 1 end end @@ -965,14 +1024,14 @@ describe "Code gen: exception" do begin next ensure - $a += 1 + Global.a += 1 end end ensure - $a += 1 + Global.a += 1 end - $b + Global.b )).to_i.should eq(1) end @@ -1008,19 +1067,28 @@ describe "Code gen: exception" do run(%( require "prelude" - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo yield ensure - $a = 123 + Global.x = 123 end foo do break end - $a + Global.x )).to_i.should eq(123) end diff --git a/spec/compiler/codegen/generic_class_spec.cr b/spec/compiler/codegen/generic_class_spec.cr index e068617c1c75..5d112abd8bc4 100644 --- a/spec/compiler/codegen/generic_class_spec.cr +++ b/spec/compiler/codegen/generic_class_spec.cr @@ -156,11 +156,20 @@ describe "Code gen: generic class type" do it "invokes super in generic class (#2354)" do run(%( - $x = 1 + class Global + @@x = 1 + + def self.x=(@@x) + end + + def self.x + @@x + end + end class Foo def foo - $x = 2 + Global.x = 2 end end @@ -173,7 +182,7 @@ describe "Code gen: generic class type" do b = Bar(Int32).new b.foo - $x + Global.x )).to_i.should eq(2) end diff --git a/spec/compiler/codegen/global_spec.cr b/spec/compiler/codegen/global_spec.cr deleted file mode 100644 index 75bc5991e5d5..000000000000 --- a/spec/compiler/codegen/global_spec.cr +++ /dev/null @@ -1,77 +0,0 @@ -require "../../spec_helper" - -describe "Code gen: global" do - it "codegens global" do - run("$foo = 1; def foo; $foo = 2; end; foo; $foo").to_i.should eq(2) - end - - it "codegens global with union" do - run("$foo = 1; def foo; $foo = 2.5_f32; end; foo; $foo.to_f").to_f64.should eq(2.5) - end - - it "codegens global when not initialized" do - run(%( - struct Nil; def to_i; 0; end; end - $foo : Int32? - $foo.to_i - )).to_i.should eq(0) - end - - it "codegens global when not initialized" do - run(%( - struct Nil; def to_i; 0; end; end - - def foo - $foo = 2 if 1 == 2 - end - - foo - - $foo.to_i - )).to_i.should eq(0) - end - - it "declares and initializes" do - run(%( - $x : Int32 = 42 - $x : Int32 = 84 - $x - )).to_i.should eq(84) - end - - it "doesn't crash on global declaration (#2619)" do - run(%( - struct Foo - def initialize(@value : Int32) - end - - def value - @value - end - end - - $one : Foo = Foo.new(42) - - def foo - end - - $one.value - )).to_i.should eq(42) - end - - it "declares var as uninitialized and initializes it unsafely" do - run(%( - def bar - if 1 == 2 - $x - else - 10 - end - end - - $x = uninitialized Int32 - $x = bar - $x - )).to_i.should eq(10) - end -end diff --git a/spec/compiler/codegen/hooks_spec.cr b/spec/compiler/codegen/hooks_spec.cr index a325db84cdf6..89b51790b2ca 100644 --- a/spec/compiler/codegen/hooks_spec.cr +++ b/spec/compiler/codegen/hooks_spec.cr @@ -5,14 +5,18 @@ describe "Code gen: hooks" do run(" class Foo macro inherited - $x = 1 + @@x = 1 + + def self.x + @@x + end end end class Bar < Foo end - $x + Bar.x ").to_i.should eq(1) end @@ -20,7 +24,11 @@ describe "Code gen: hooks" do run(" module Foo macro included - $x = 1 + @@x = 1 + + def self.x + @@x + end end end @@ -28,7 +36,7 @@ describe "Code gen: hooks" do include Foo end - $x + Bar.x ").to_i.should eq(1) end @@ -36,7 +44,11 @@ describe "Code gen: hooks" do run(" module Foo macro extended - $x = 1 + @@x = 1 + + def self.x + @@x + end end end @@ -44,31 +56,51 @@ describe "Code gen: hooks" do extend Foo end - $x + Bar.x ").to_i.should eq(1) end it "does added method macro" do run(" - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end + class Foo macro method_added(d) - $x = 1 + Global.x = 1 end def foo; end end - $x + Global.x ").to_i.should eq(1) end it "does inherited macro recursively" do run(" - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end + class Foo macro inherited - $x += 1 + Global.x += 1 end end @@ -78,25 +110,38 @@ describe "Code gen: hooks" do class Baz < Bar end - $x + Global.x ").to_i.should eq(2) end it "does inherited macro before class body" do run(" - $x = 123 + class Global + @@x = 123 + + def self.x=(@@x) + end + + def self.x + @@x + end + end + class Foo macro inherited - $y : Int32 - $y = $x + @@y : Int32 = Global.x + + def self.y + @@y + end end end class Bar < Foo - $x += 1 + Global.x += 1 end - $y + Bar.y ").to_i.should eq(123) end end diff --git a/spec/compiler/codegen/macro_spec.cr b/spec/compiler/codegen/macro_spec.cr index fed591e89c17..af3a158767ae 100644 --- a/spec/compiler/codegen/macro_spec.cr +++ b/spec/compiler/codegen/macro_spec.cr @@ -820,24 +820,36 @@ describe "Code gen: macro" do run(%( require "prelude" - $x = [] of String + class Global + @@x = [] of String + @@runnables = [] of Runnable.class + + def self.x=(@@x) + end + + def self.x + @@x + end + + def self.runnables + @@runnables + end + end def run - $runnables.each &.run + Global.runnables.each &.run end class Runnable end - $runnables = [] of Runnable.class - class Runnable macro inherited - $runnables << self + Global.runnables << self end def self.run : Nil - $x << {{@type.name.stringify}} + Global.x << {{@type.name.stringify}} nil end end @@ -846,13 +858,13 @@ describe "Code gen: macro" do end run - $x.clear + Global.x.clear class RunnableTest < Test end run - $x.join(", ") + Global.x.join(", ") )).to_string.should eq("Test, RunnableTest") end diff --git a/spec/compiler/codegen/new_spec.cr b/spec/compiler/codegen/new_spec.cr index 18553542b224..47ecf05ea1dc 100644 --- a/spec/compiler/codegen/new_spec.cr +++ b/spec/compiler/codegen/new_spec.cr @@ -115,7 +115,16 @@ describe "Code gen: new" do it "oveloads new and initialize, 2 (#2489)" do run(%( - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end class Foo def initialize(@foo : Int32) @@ -124,34 +133,43 @@ describe "Code gen: new" do class Bar < Foo def self.new(foo : Int32) : self - $x = foo + 1 + Global.x = foo + 1 super end end Bar.new(5) - $x + Global.x )).to_i.should eq(6) end it "oveloads new and initialize, 3 (#2489)" do run(%( - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end class Foo def initialize(@foo : Int32) end def self.new(foo : Int32) : self - $x = foo + 1 + Global.x = foo + 1 previous_def end end Foo.new(5) - $x + Global.x )).to_i.should eq(6) end diff --git a/spec/compiler/codegen/pointer_spec.cr b/spec/compiler/codegen/pointer_spec.cr index 9475ac5a6725..e4022ce1f7b5 100644 --- a/spec/compiler/codegen/pointer_spec.cr +++ b/spec/compiler/codegen/pointer_spec.cr @@ -346,14 +346,6 @@ describe "Code gen: pointer" do )).to_i.should eq(2) end - it "does pointerof global variable" do - run(%( - $a = 1 - pointerof($a).value = 2 - $a - )).to_i.should eq(2) - end - it "does pointerof read variable" do run(%( class Foo diff --git a/spec/compiler/codegen/primitives_spec.cr b/spec/compiler/codegen/primitives_spec.cr index 35690c1d30b9..4363f366ca16 100644 --- a/spec/compiler/codegen/primitives_spec.cr +++ b/spec/compiler/codegen/primitives_spec.cr @@ -164,16 +164,25 @@ describe "Code gen: primitives" do it "doesn't optimize away call whose obj is not passed as self (#2226)" do run(%( - $x = 1 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo - $x = 2 + Global.x = 2 3 end foo.class.crystal_type_id - $x + Global.x )).to_i.should eq(2) end diff --git a/spec/compiler/codegen/proc_spec.cr b/spec/compiler/codegen/proc_spec.cr index 1996b6fb6b73..4bbae53f52b9 100644 --- a/spec/compiler/codegen/proc_spec.cr +++ b/spec/compiler/codegen/proc_spec.cr @@ -219,15 +219,24 @@ describe "Code gen: proc" do it "automatically casts proc that returns something to proc that returns void" do run(" - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def foo(x : ->) x.call end - foo ->{ $a = 1 } + foo ->{ Global.x = 1 } - $a + Global.x ").to_i.should eq(1) end @@ -664,15 +673,24 @@ describe "Code gen: proc" do end end - $x = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end Foo.add("foo") do |a| - $x = a.foo + Global.x = a.foo end Foo.call - $x + Global.x )).to_i.should eq(2) end diff --git a/spec/compiler/codegen/splat_spec.cr b/spec/compiler/codegen/splat_spec.cr index 4f2affd2329a..0d149a73fa69 100644 --- a/spec/compiler/codegen/splat_spec.cr +++ b/spec/compiler/codegen/splat_spec.cr @@ -145,11 +145,20 @@ describe "Code gen: splat" do it "evaluates splat argument just once (#2677)" do run(%( - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end def data - $a += 1 - {$a, $a, $a} + Global.x += 1 + {Global.x, Global.x, Global.x} end def test(x, y, z) @@ -158,7 +167,7 @@ describe "Code gen: splat" do v = test(*data) - $a + Global.x )).to_i.should eq(1) end end diff --git a/spec/compiler/codegen/struct_spec.cr b/spec/compiler/codegen/struct_spec.cr index 4945712cab94..c24c2843a341 100644 --- a/spec/compiler/codegen/struct_spec.cr +++ b/spec/compiler/codegen/struct_spec.cr @@ -201,11 +201,11 @@ describe "Code gen: struct" do FOO = Foo.new(1) if 1 == 2 - $foo = Foo.new(1) + foo = Foo.new(1) else - $foo = FOO + foo = FOO end - $foo.x + foo.x ").to_i.should eq(1) end diff --git a/spec/compiler/codegen/super_spec.cr b/spec/compiler/codegen/super_spec.cr index 0f26fbffb463..d70d59a9f849 100644 --- a/spec/compiler/codegen/super_spec.cr +++ b/spec/compiler/codegen/super_spec.cr @@ -328,14 +328,23 @@ describe "Codegen: super" do it "doesn't invoke super twice in inherited generic types (#942)" do run(%( - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end abstract class Foo end class Bar(T) < Foo def initialize - $a += 1 + Global.x += 1 super end end @@ -345,7 +354,7 @@ describe "Codegen: super" do Baz(Int8).new - $a + Global.x )).to_i.should eq(1) end @@ -354,17 +363,26 @@ describe "Codegen: super" do run(%( require "prelude" - $a = 0 + class Global + @@x = 0 + + def self.x=(@@x) + end + + def self.x + @@x + end + end class Base def self.foo - $a += 1 + Global.x += 1 end end class One < Base def self.foo - $a += 3 + Global.x += 3 super end end diff --git a/spec/compiler/codegen/thread_local_spec.cr b/spec/compiler/codegen/thread_local_spec.cr index 2a52f50f021a..90cf4f5517b4 100644 --- a/spec/compiler/codegen/thread_local_spec.cr +++ b/spec/compiler/codegen/thread_local_spec.cr @@ -1,29 +1,6 @@ require "../../spec_helper" describe "Codegen: thread local" do - it "works with global variables" do - run(%( - require "prelude" - - @[ThreadLocal] - $var = 123 - - Thread.new { $var = 456 }.join - - $var - )).to_i.should eq(123) - end - - it "works with global variable in main thread" do - run(%( - require "prelude" - - @[ThreadLocal] - $a = 123 - $a - )).to_i.should eq(123) - end - it "works with class variables" do run(%( require "prelude" diff --git a/spec/compiler/crystal/tools/playground_spec.cr b/spec/compiler/crystal/tools/playground_spec.cr index 22034ea3049b..9608c99c5a00 100644 --- a/spec/compiler/crystal/tools/playground_spec.cr +++ b/spec/compiler/crystal/tools/playground_spec.cr @@ -64,37 +64,33 @@ end describe Playground::AgentInstrumentorTransformer do it "instrument literals" do - assert_agent %(nil), %($p.i(1) { nil }) - assert_agent %(5), %($p.i(1) { 5 }) - assert_agent %(5.0), %($p.i(1) { 5.0 }) - assert_agent %("lorem"), %($p.i(1) { "lorem" }) - assert_agent %(true), %($p.i(1) { true }) - assert_agent %('c'), %($p.i(1) { 'c' }) - assert_agent %(:foo), %($p.i(1) { :foo }) - assert_agent %([1, 2]), %($p.i(1) { [1, 2] }) - assert_agent %(/a/), %($p.i(1) { /a/ }) + assert_agent %(nil), %(_p.i(1) { nil }) + assert_agent %(5), %(_p.i(1) { 5 }) + assert_agent %(5.0), %(_p.i(1) { 5.0 }) + assert_agent %("lorem"), %(_p.i(1) { "lorem" }) + assert_agent %(true), %(_p.i(1) { true }) + assert_agent %('c'), %(_p.i(1) { 'c' }) + assert_agent %(:foo), %(_p.i(1) { :foo }) + assert_agent %([1, 2]), %(_p.i(1) { [1, 2] }) + assert_agent %(/a/), %(_p.i(1) { /a/ }) end it "instrument literals with expression names" do - assert_agent %({1, 2}), %($p.i(1, ["1", "2"]) { {1, 2} }) - assert_agent %({x, x + y}), %($p.i(1, ["x", "x + y"]) { {x, x + y} }) - assert_agent %(a = {x, x + y}), %(a = $p.i(1, ["x", "x + y"]) { {x, x + y} }) + assert_agent %({1, 2}), %(_p.i(1, ["1", "2"]) { {1, 2} }) + assert_agent %({x, x + y}), %(_p.i(1, ["x", "x + y"]) { {x, x + y} }) + assert_agent %(a = {x, x + y}), %(a = _p.i(1, ["x", "x + y"]) { {x, x + y} }) end it "instrument single variables expressions" do - assert_agent %(x), %($p.i(1) { x }) - end - - it "instrument single global variables expressions" do - assert_agent %($x), %($p.i(1) { $x }) + assert_agent %(x), %(_p.i(1) { x }) end it "instrument string interpolations" do - assert_agent %("lorem \#{a} \#{b}"), %($p.i(1) { "lorem \#{a} \#{b}" }) + assert_agent %("lorem \#{a} \#{b}"), %(_p.i(1) { "lorem \#{a} \#{b}" }) end it "instrument assignments in the rhs" do - assert_agent %(a = 4), %(a = $p.i(1) { 4 }) + assert_agent %(a = 4), %(a = _p.i(1) { 4 }) end it "do not instrument constants assignments" do @@ -102,43 +98,43 @@ describe Playground::AgentInstrumentorTransformer do end it "instrument not expressions" do - assert_agent %(!true), %($p.i(1) { !true }) + assert_agent %(!true), %(_p.i(1) { !true }) end it "instrument binary expressions" do - assert_agent %(a && b), %($p.i(1) { a && b }) - assert_agent %(a || b), %($p.i(1) { a || b }) + assert_agent %(a && b), %(_p.i(1) { a && b }) + assert_agent %(a || b), %(_p.i(1) { a || b }) end it "instrument unary expressions" do - assert_agent %(pointerof(x)), %($p.i(1) { pointerof(x) }) + assert_agent %(pointerof(x)), %(_p.i(1) { pointerof(x) }) end it "instrument is_a? expressions" do - assert_agent %(x.is_a?(Foo)), %($p.i(1) { x.is_a?(Foo) }) + assert_agent %(x.is_a?(Foo)), %(_p.i(1) { x.is_a?(Foo) }) end it "instrument ivar with obj" do - assert_agent %(x.@foo), %($p.i(1) { x.@foo }) + assert_agent %(x.@foo), %(_p.i(1) { x.@foo }) end it "instrument multi assignments in the rhs" do - assert_agent %(a, b = t), %(a, b = $p.i(1) { t }) - assert_agent %(a, b = d, f), %(a, b = $p.i(1, ["d", "f"]) { {d, f} }) - assert_agent %(a, b = {d, f}), %(a, b = $p.i(1, ["d", "f"]) { {d, f} }) + assert_agent %(a, b = t), %(a, b = _p.i(1) { t }) + assert_agent %(a, b = d, f), %(a, b = _p.i(1, ["d", "f"]) { {d, f} }) + assert_agent %(a, b = {d, f}), %(a, b = _p.i(1, ["d", "f"]) { {d, f} }) end it "instrument puts with args" do - assert_agent %(puts 3), %(puts($p.i(1) { 3 })) - assert_agent %(puts a, 2, b), %(puts(*$p.i(1, ["a", "2", "b"]) { {a, 2, b} })) - assert_agent %(puts *{3}), %(puts(*$p.i(1, ["3"]) { {3} })) - assert_agent %(puts *{3,a}), %(puts(*$p.i(1, ["3", "a"]) { {3,a} })) + assert_agent %(puts 3), %(puts(_p.i(1) { 3 })) + assert_agent %(puts a, 2, b), %(puts(*_p.i(1, ["a", "2", "b"]) { {a, 2, b} })) + assert_agent %(puts *{3}), %(puts(*_p.i(1, ["3"]) { {3} })) + assert_agent %(puts *{3,a}), %(puts(*_p.i(1, ["3", "a"]) { {3,a} })) assert_agent_eq %(puts), %(puts) end it "instrument print with args" do - assert_agent %(print 3), %(print($p.i(1) { 3 })) - assert_agent %(print a, 2, b), %(print(*$p.i(1, ["a", "2", "b"]) { {a, 2, b} })) + assert_agent %(print 3), %(print(_p.i(1) { 3 })) + assert_agent %(print a, 2, b), %(print(*_p.i(1, ["a", "2", "b"]) { {a, 2, b} })) assert_agent_eq %(print), %(print) end @@ -148,7 +144,7 @@ describe Playground::AgentInstrumentorTransformer do 4 end), <<-CR def foo - $p.i(3) { 4 } + _p.i(3) { 4 } end CR end @@ -159,7 +155,7 @@ describe Playground::AgentInstrumentorTransformer do x end), <<-CR def foo(x) - $p.i(3) { x } + _p.i(3) { x } end CR end @@ -171,8 +167,8 @@ describe Playground::AgentInstrumentorTransformer do 6 end), <<-CR def foo - $p.i(3) { 2 } - $p.i(4) { 6 } + _p.i(3) { 2 } + _p.i(4) { 6 } end CR end @@ -183,7 +179,7 @@ describe Playground::AgentInstrumentorTransformer do return 4 end), <<-CR def foo - return $p.i(3) { 4 } + return _p.i(3) { 4 } end CR end @@ -204,14 +200,14 @@ describe Playground::AgentInstrumentorTransformer do end), <<-CR class Foo def initialize - @x = $p.i(4) { 3 }.as(typeof(3)) + @x = _p.i(4) { 3 }.as(typeof(3)) end def bar(x) - x = $p.i(7) { x + x } - $p.i(8) { x } + x = _p.i(7) { x + x } + _p.i(8) { x } end def self.bar(x, y) - $p.i(11) { x + y } + _p.i(11) { x + y } end end CR @@ -233,14 +229,14 @@ describe Playground::AgentInstrumentorTransformer do end), <<-CR class Foo def initialize - @x = $p.i(4) { 3 }.as(typeof(3)) - @@x = $p.i(5) { 4 }.as(typeof(4)) + @x = _p.i(4) { 3 }.as(typeof(3)) + @@x = _p.i(5) { 4 }.as(typeof(4)) end def bar - $p.i(8) { @x } + _p.i(8) { @x } end def self.bar - $p.i(11) { @@x } + _p.i(11) { @@x } end end CR @@ -258,7 +254,7 @@ describe Playground::AgentInstrumentorTransformer do def initialize(x, y) @x = x @y = y - @z = $p.i(4) { @x + @y }.as(typeof(@x + @y)) + @z = _p.i(4) { @x + @y }.as(typeof(@x + @y)) end end CR @@ -276,10 +272,10 @@ describe Playground::AgentInstrumentorTransformer do end), <<-CR class Foo private def bar - $p.i(4) { 1 } + _p.i(4) { 1 } end protected def self.bar - $p.i(7) { 2 } + _p.i(7) { 2 } end end CR @@ -308,7 +304,7 @@ describe Playground::AgentInstrumentorTransformer do class Bar class Foo def initialize - @x = $p.i(5) { 3 }.as(typeof(3)) + @x = _p.i(5) { 3 }.as(typeof(3)) end end end @@ -340,7 +336,7 @@ describe Playground::AgentInstrumentorTransformer do end end bar - $p.i(7) { foo } + _p.i(7) { foo } CR ) end @@ -372,7 +368,7 @@ describe Playground::AgentInstrumentorTransformer do include Bar def foo bar - $p.i(11) { 8 } + _p.i(11) { 8 } end end CR @@ -394,7 +390,7 @@ describe Playground::AgentInstrumentorTransformer do class Baz class Foo def initialize - @x = $p.i(6) { 3 }.as(typeof(3)) + @x = _p.i(6) { 3 }.as(typeof(3)) end end end @@ -411,9 +407,9 @@ describe Playground::AgentInstrumentorTransformer do end ), <<-CR if a - $p.i(3) { b } + _p.i(3) { b } else - $p.i(5) { c } + _p.i(5) { c } end CR end @@ -427,9 +423,9 @@ describe Playground::AgentInstrumentorTransformer do end ), <<-CR unless a - $p.i(3) { b } + _p.i(3) { b } else - $p.i(5) { c } + _p.i(5) { c } end CR end @@ -442,8 +438,8 @@ describe Playground::AgentInstrumentorTransformer do end ), <<-CR while a - $p.i(3) { b } - $p.i(4) { c } + _p.i(3) { b } + _p.i(4) { c } end CR end @@ -462,11 +458,11 @@ describe Playground::AgentInstrumentorTransformer do ), <<-CR case a when 0 - $p.i(4) { b } + _p.i(4) { b } when 1 - $p.i(6) { c } + _p.i(6) { c } else - $p.i(8) { d } + _p.i(8) { d } end CR end @@ -481,11 +477,11 @@ describe Playground::AgentInstrumentorTransformer do end ), <<-CR def foo(x) - yield $p.i(3) { x } + yield _p.i(3) { x } end - $p.i(5) do + _p.i(5) do foo do |a| - $p.i(6) { a } + _p.i(6) { a } end end CR @@ -503,9 +499,9 @@ describe Playground::AgentInstrumentorTransformer do def foo(x) yield x, 1 end - $p.i(5) do + _p.i(5) do foo do |a, i| - $p.i(6) { a } + _p.i(6) { a } end end CR @@ -521,15 +517,15 @@ describe Playground::AgentInstrumentorTransformer do baz { 'c' } end ), <<-CR - a = $p.i(2) do + a = _p.i(2) do foo do - $p.i(3) { 'a' } - $p.i(4) do + _p.i(3) { 'a' } + _p.i(4) do bar do - $p.i(5) { 'b' } + _p.i(5) { 'b' } end end - $p.i(7) do + _p.i(7) do baz do 'c' end @@ -540,7 +536,7 @@ describe Playground::AgentInstrumentorTransformer do end it "instrument typeof" do - assert_agent %(typeof(5)), %($p.i(1) { typeof(5) }) + assert_agent %(typeof(5)), %(_p.i(1) { typeof(5) }) end it "instrument exceptions" do @@ -563,21 +559,21 @@ describe Playground::AgentInstrumentorTransformer do end ), <<-CR begin - raise($p.i(3) { "The exception" }) + raise(_p.i(3) { "The exception" }) rescue ex : String - $p.i(5) { 1 } + _p.i(5) { 1 } rescue - $p.i(7) { 0 } + _p.i(7) { 0 } else - $p.i(9) { 2 } + _p.i(9) { 2 } ensure - $p.i(11) { 3 } + _p.i(11) { 3 } end def foo(x) begin - raise($p.i(14) { "Other" }) + raise(_p.i(14) { "Other" }) rescue - $p.i(16) { 0 } + _p.i(16) { 0 } end end CR diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index 9a4113a38f93..49eb733ad954 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -384,7 +384,6 @@ describe Crystal::Formatter do assert_format "@a", "@a" assert_format "@@a", "@@a" - assert_format "$a", "$a" assert_format "$~", "$~" assert_format "$~.bar", "$~.bar" assert_format "$~ = 1", "$~ = 1" diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 2d5667a7386e..6decb3298e21 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -107,7 +107,6 @@ describe "Parser" do it_parses "_ = 1", Assign.new(Underscore.new, 1.int32) it_parses "@foo/2", Call.new("@foo".instance_var, "/", 2.int32) it_parses "@@foo/2", Call.new("@@foo".class_var, "/", 2.int32) - it_parses "$foo/2", Call.new(Global.new("$foo"), "/", 2.int32) it_parses "1+2*3", Call.new(1.int32, "+", Call.new(2.int32, "*", 3.int32)) it_parses "!1", Not.new(1.int32) @@ -135,7 +134,6 @@ describe "Parser" do it_parses "@a, b = 1, 2", MultiAssign.new(["@a".instance_var, "b".var] of ASTNode, [1.int32, 2.int32] of ASTNode) it_parses "@@a, b = 1, 2", MultiAssign.new(["@@a".class_var, "b".var] of ASTNode, [1.int32, 2.int32] of ASTNode) - it_parses "$a, b = 1, 2", MultiAssign.new([Global.new("$a"), "b".var] of ASTNode, [1.int32, 2.int32] of ASTNode) it_parses "A, b = 1, 2", MultiAssign.new(["A".path, "b".var] of ASTNode, [1.int32, 2.int32] of ASTNode) assert_syntax_error "1 == 2, a = 4" @@ -725,7 +723,7 @@ describe "Parser" do it_parses "::A::B", Path.global(["A", "B"]) - it_parses "$foo", Global.new("$foo") + assert_syntax_error "$foo", "$global_variables are not supported, use @@class_variables instead" it_parses "macro foo;end", Macro.new("foo", [] of Arg, Expressions.new) it_parses "macro [];end", Macro.new("[]", [] of Arg, Expressions.new) @@ -831,8 +829,6 @@ describe "Parser" do it_parses "1.=~(2)", Call.new(1.int32, "=~", 2.int32) it_parses "def =~; end", Def.new("=~", [] of Arg) - it_parses "foo $a", Call.new(nil, "foo", Global.new("$a")) - it_parses "$~", Global.new("$~") it_parses "$~.foo", Call.new(Global.new("$~"), "foo") it_parses "$1", Call.new(Global.new("$~"), "[]", 1.int32) @@ -930,17 +926,14 @@ describe "Parser" do it_parses "@a : Foo", TypeDeclaration.new("@a".instance_var, "Foo".path) it_parses "@a : Foo | Int32", TypeDeclaration.new("@a".instance_var, Crystal::Union.new(["Foo".path, "Int32".path] of ASTNode)) it_parses "@@a : Foo", TypeDeclaration.new("@@a".class_var, "Foo".path) - it_parses "$x : Foo", TypeDeclaration.new(Global.new("$x"), "Foo".path) it_parses "a : Foo = 1", TypeDeclaration.new("a".var, "Foo".path, 1.int32) it_parses "@a : Foo = 1", TypeDeclaration.new("@a".instance_var, "Foo".path, 1.int32) it_parses "@@a : Foo = 1", TypeDeclaration.new("@@a".class_var, "Foo".path, 1.int32) - it_parses "$x : Foo = 1", TypeDeclaration.new(Global.new("$x"), "Foo".path, 1.int32) it_parses "a = uninitialized Foo; a", [UninitializedVar.new("a".var, "Foo".path), "a".var] it_parses "@a = uninitialized Foo", UninitializedVar.new("@a".instance_var, "Foo".path) it_parses "@@a = uninitialized Foo", UninitializedVar.new("@@a".class_var, "Foo".path) - it_parses "$a = uninitialized Foo", UninitializedVar.new(Global.new("$a"), "Foo".path) it_parses "()", NilLiteral.new it_parses "(1; 2; 3)", [1.int32, 2.int32, 3.int32] of ASTNode @@ -1459,7 +1452,6 @@ describe "Parser" do assert_end_location "@foo" assert_end_location "foo.@foo" assert_end_location "@@foo" - assert_end_location "$foo" assert_end_location "a && b" assert_end_location "a || b" assert_end_location "def foo; end" diff --git a/spec/compiler/semantic/array_spec.cr b/spec/compiler/semantic/array_spec.cr index 9d92c8b25468..aa6e35aa1efa 100644 --- a/spec/compiler/semantic/array_spec.cr +++ b/spec/compiler/semantic/array_spec.cr @@ -20,14 +20,4 @@ describe "Semantic: array" do it "types array literal size correctly" do assert_type("require \"prelude\"; [1].size") { int32 } end - - it "recalculates array literal type after element type changes" do - assert_type(%( - require "prelude" - $a = 1 - x = [$a] - $a = 1.1 - x - )) { array_of(union_of int32, float64) } - end end diff --git a/spec/compiler/semantic/block_spec.cr b/spec/compiler/semantic/block_spec.cr index bbea9b79f710..f506dfb22d96 100644 --- a/spec/compiler/semantic/block_spec.cr +++ b/spec/compiler/semantic/block_spec.cr @@ -935,24 +935,6 @@ describe "Block inference" do "can't use `yield` outside a method" end - it "rebinds yield -> block arguments" do - assert_type(%( - def foo(x) - buffer = Pointer(typeof(x)).malloc(1_u64) - yield buffer - end - - $a = 1 - x = nil - foo($a) do |buffer| - buffer.value = $a - x = buffer - end - $a = 1.1 - x - )) { nilable(pointer_of(union_of(int32, float64))) } - end - it "errors on recursive yield" do assert_error %( def foo diff --git a/spec/compiler/semantic/class_spec.cr b/spec/compiler/semantic/class_spec.cr index 2d93d25456bd..dbb7c6196f3e 100644 --- a/spec/compiler/semantic/class_spec.cr +++ b/spec/compiler/semantic/class_spec.cr @@ -705,10 +705,14 @@ describe "Semantic: class" do 1 end - $x = self.foo.as(Int32) + @@x = self.foo.as(Int32) + + def self.x + @@x + end end - $x + Foo.x )) { int32 } end diff --git a/spec/compiler/semantic/const_spec.cr b/spec/compiler/semantic/const_spec.cr index de44908e142b..828f87818462 100644 --- a/spec/compiler/semantic/const_spec.cr +++ b/spec/compiler/semantic/const_spec.cr @@ -197,20 +197,6 @@ describe "Semantic: const" do )) { types["LibC"].types["Foo"] } end - it "doesn't error if constant depends on a global var that is never initialized" do - assert_type(%( - A = foo - - $b : Nil - - def foo - $b - end - - A - )) { nil_type } - end - it "errors on dynamic constant assignment inside block" do assert_error %( def foo diff --git a/spec/compiler/semantic/did_you_mean_spec.cr b/spec/compiler/semantic/did_you_mean_spec.cr index 25b9d94942e1..4f0e67d7f467 100644 --- a/spec/compiler/semantic/did_you_mean_spec.cr +++ b/spec/compiler/semantic/did_you_mean_spec.cr @@ -227,13 +227,6 @@ describe "Semantic: did you mean" do "do you maybe have a typo in this 'intialize' method?" end - it "suggests for global variable" do - assert_error %( - $foobar = 1 - $fooobar - ), "did you mean $foobar" - end - it "suggests for class variable" do assert_error %( class Foo diff --git a/spec/compiler/semantic/global_spec.cr b/spec/compiler/semantic/global_spec.cr deleted file mode 100644 index 7be6aeadd160..000000000000 --- a/spec/compiler/semantic/global_spec.cr +++ /dev/null @@ -1,698 +0,0 @@ -require "../../spec_helper" - -describe "Global inference" do - it "infers type of global assign" do - node = parse "$foo = 1" - result = semantic node - mod, node = result.program, result.node.as(Assign) - - node.type.should eq(mod.int32) - node.target.type.should eq(mod.int32) - node.value.type.should eq(mod.int32) - end - - it "infers type of global assign with union" do - nodes = parse "$foo = 1; $foo = 'a'" - result = semantic nodes - mod, node = result.program, result.node.as(Expressions) - - node[0].as(Assign).target.type.should eq(mod.union_of(mod.int32, mod.char)) - node[1].as(Assign).target.type.should eq(mod.union_of(mod.int32, mod.char)) - end - - it "errors when reading undefined global variables" do - assert_error %( - $x - ), "Can't infer the type of global variable '$x'" - end - - it "errors when writing undefined global variables" do - assert_error %( - def foo - 1 - end - - $x = foo - ), "Can't infer the type of global variable '$x'" - end - - it "infers type from number literal" do - assert_type(%( - $x = 1 - $x - )) { int32 } - end - - it "infers type from char literal" do - assert_type(%( - $x = 'a' - $x - )) { char } - end - - it "infers type from bool literal" do - assert_type(%( - $x = true - $x - )) { bool } - end - - it "infers type from nil literal" do - assert_type(%( - $x = nil - $x - )) { nil_type } - end - - it "infers type from string literal" do - assert_type(%( - $x = "foo" - $x - )) { string } - end - - it "infers type from string interpolation" do - assert_type(%( - require "prelude" - - $x = "foo\#{1}" - $x - )) { string } - end - - it "infers type from symbol literal" do - assert_type(%( - $x = :foo - $x - )) { symbol } - end - - it "infers type from array literal with of" do - assert_type(%( - $x = [] of Int32 - $x - )) { array_of int32 } - end - - it "infers type from array literal with of (metaclass)" do - assert_type(%( - $x = [] of Int32.class - $x - )) { array_of int32.metaclass } - end - - it "infers type from array literal with of, inside another type" do - assert_type(%( - class Foo - class Bar - end - - $x = [] of Bar - end - - $x - )) { array_of types["Foo"].types["Bar"] } - end - - it "infers type from array literal from its literals" do - assert_type(%( - require "prelude" - - $x = [1, 'a'] - $x - )) { array_of union_of(int32, char) } - end - - it "infers type from hash literal with of" do - assert_type(%( - require "prelude" - - $x = {} of Int32 => String - $x - )) { hash_of(int32, string) } - end - - it "infers type from hash literal from elements" do - assert_type(%( - require "prelude" - - $x = {1 => "foo", 'a' => true} - $x - )) { hash_of(union_of(int32, char), union_of(string, bool)) } - end - - it "infers type from range literal" do - assert_type(%( - require "prelude" - - $x = 1..'a' - $x - )) { range_of(int32, char) } - end - - it "infers type from regex literal" do - assert_type(%( - require "prelude" - - $x = /foo/ - $x - )) { types["Regex"] } - end - - it "infers type from regex literal with interpolation" do - assert_type(%( - require "prelude" - - $x = /foo\#{1}/ - $x - )) { types["Regex"] } - end - - it "infers type from tuple literal" do - assert_type(%( - $x = {1, "foo"} - $x - )) { tuple_of([int32, string]) } - end - - it "infers type from named tuple literal" do - assert_type(%( - $x = {x: 1, y: "foo"} - $x - )) { named_tuple_of({"x": int32, "y": string}) } - end - - it "infers type from new expression" do - assert_type(%( - class Foo - end - - $x = Foo.new - $x - )) { types["Foo"] } - end - - it "doesn't infer from new if generic" do - assert_error %( - class Foo(T) - def self.new - a = 10 - a - end - end - - $x = Foo.new - $x - ), - "can't use Foo(T) as the type of global variable $x, use a more specific type" - end - - it "infers type from new expression of generic" do - assert_type(%( - class Foo(T) - end - - $x = Foo(Int32).new - $x - )) { generic_class "Foo", int32 } - end - - it "infers type from as" do - assert_type(%( - def foo - 1 - end - - $x = foo.as(Int32) - $x - )) { int32 } - end - - it "infers type from as?" do - assert_type(%( - def foo - 1 - end - - $x = foo.as?(Int32) - $x - )) { nilable int32 } - end - - it "infers type from static array type declaration" do - assert_type(%( - $x : Int8[3]? - $x - )) { nilable static_array_of(int8, 3) } - end - - it "infers type from argument restriction" do - assert_type(%( - class Foo - class Bar - end - - def foo(z : Bar) - $x = z - end - end - - $x - )) { nilable types["Foo"].types["Bar"] } - end - - it "infers type from argument default value" do - assert_type(%( - class Foo - class Bar - end - - def foo(z = Foo::Bar.new) - $x = z - end - end - - $x - )) { nilable types["Foo"].types["Bar"] } - end - - it "infers type from lib fun call" do - assert_type(%( - lib LibFoo - struct Bar - x : Int32 - end - - fun foo : Bar - end - - $x = LibFoo.foo - )) { types["LibFoo"].types["Bar"] } - end - - it "infers type from lib variable" do - assert_type(%( - lib LibFoo - struct Bar - x : Int32 - end - - $foo : Bar - end - - $x = LibFoo.foo - )) { types["LibFoo"].types["Bar"] } - end - - it "infers from ||" do - assert_type(%( - $x = 1 || true - )) { union_of(int32, bool) } - end - - it "infers from &&" do - assert_type(%( - $x = 1 && true - )) { union_of(int32, bool) } - end - - it "infers from ||=" do - assert_type(%( - def foo - $x ||= 1 - end - - $x - )) { nilable int32 } - end - - it "infers from ||= inside another assignment" do - assert_type(%( - def foo - x = $x ||= 1 - end - - $x - )) { nilable int32 } - end - - it "infers from if" do - assert_type(%( - $x = 1 == 2 ? 1 : true - )) { union_of(int32, bool) } - end - - it "infers from case" do - assert_type(%( - class Object - def ===(other) - self == other - end - end - - $x = case 1 - when 2 - 'a' - else - true - end - )) { union_of(char, bool) } - end - - it "infers from unless" do - assert_type(%( - $x = unless 1 == 2 - 1 - else - true - end - )) { union_of(int32, bool) } - end - - it "infers from begin" do - assert_type(%( - $x = begin - 1 - 'a' - end - )) { char } - end - - it "infers from assign (1)" do - assert_type(%( - $x = $y = 1 - $x - )) { int32 } - end - - it "infers from assign (2)" do - assert_type(%( - $x = $y = 1 - $y - )) { int32 } - end - - it "infers from new at top level" do - assert_type(%( - class Foo - $x = new - end - $x - )) { types["Foo"] } - end - - it "infers from block argument" do - assert_type(%( - def foo(&block : Int32 -> Int32) - $x = block - end - - $x - )) { nilable proc_of(int32, int32) } - end - - it "infers from block argument without restriction" do - assert_type(%( - def foo(&block) - $x = block - end - - $x - )) { nilable proc_of(void) } - end - - it "infers type from !" do - assert_type(%( - $x = !1 - $x - )) { bool } - end - - it "infers type from is_a?" do - assert_type(%( - $x = 1.is_a?(Int32) - $x - )) { bool } - end - - it "infers type from responds_to?" do - assert_type(%( - $x = 1.responds_to?(:foo) - $x - )) { bool } - end - - it "infers type from sizeof" do - assert_type(%( - $x = sizeof(Float64) - $x - )) { int32 } - end - - it "infers type from sizeof" do - assert_type(%( - class Foo - end - - $x = instance_sizeof(Foo) - $x - )) { int32 } - end - - it "infers type from path that is a type" do - assert_type(%( - class Foo; end - class Bar < Foo; end - - $x = Foo - $x - )) { types["Foo"].virtual_type!.metaclass } - end - - it "infers type from path that is a constant" do - assert_type(%( - CONST = 1 - - $x = CONST - $x - )) { int32 } - end - - it "doesn't infer from redefined method" do - assert_type(%( - def foo - $x = 1 - end - - def foo - $x = true - end - - $x - )) { nilable bool } - end - - it "infers from redefined method if calls previous_def" do - assert_type(%( - def foo - $x = 1 - end - - def foo - previous_def - end - - $x - )) { nilable int32 } - end - - it "infers type in multi assign (1)" do - assert_type(%( - $x, $y = 1, "foo" - $x - )) { int32 } - end - - it "infers type in multi assign (2)" do - assert_type(%( - $x, $y = 1, "foo" - $y - )) { string } - end - - it "infers type from enum member" do - assert_type(%( - enum Color - Red, Green, Blue - end - - $x = Color::Red - $x - )) { types["Color"] } - end - - it "errors if using typeof in type declaration" do - assert_error %( - $x : typeof(1) - $x - ), - "can't use 'typeof' here" - end - - it "doesn't error if using typeof for guessed variable (but doesn't guess)" do - assert_type(%( - class Foo(T) - end - - def foo - 1 - end - - $x = Foo(Int32).new - $x = Foo(typeof(foo)).new - $x - )) { generic_class "Foo", int32 } - end - - it "infers type of global reference" do - assert_type("$foo = 1; def foo; $foo = 'a'; end; foo; $foo") { union_of(int32, char) } - end - - it "infers type of write global variable when not previously assigned" do - assert_type("def foo; $foo = 1; end; foo; $foo") { nilable int32 } - end - - it "types constant depending on global (related to #708)" do - assert_type(%( - A = foo - - def foo - if a = $foo - a - else - $foo = 1 - end - end - - A - )) { int32 } - end - - it "declares global variable" do - assert_error %( - $x : Int32 - $x = true - ), - "global variable '$x' must be Int32, not Bool" - end - - it "declares global variable as metaclass" do - assert_type(%( - $x : Int32.class - $x = Int32 - $x - )) { int32.metaclass } - end - - it "declares global variable and reads it (nilable)" do - assert_error %( - $x : Int32 - $x - ), - "global variable '$x' is read here before it was initialized, rendering it nilable, but its type is Int32" - end - - it "declares global variable and reads it inside method" do - assert_error %( - $x : Int32 - - def foo - $x = 1 - end - - if 1 == 2 - foo - end - - $x - ), - "global variable '$x' must be Int32, not Nil" - end - - it "redefines global variable type" do - assert_type(%( - $x : Int32 - $x : Int32 | Float64 - $x = 1 - $x - )) { union_of int32, float64 } - end - - it "errors when typing a global variable inside a method" do - assert_error %( - def foo - $x : Int32 - end - - foo - ), - "declaring the type of a global variable must be done at the class level" - end - - it "errors on undefined constant" do - assert_error %( - $x = Bar.new - ), - "undefined constant Bar" - end - - it "infers in multiple assign for tuple type (1)" do - assert_type(%( - class Bar - def self.method : {Int32, Bool} - {1, true} - end - end - - $x, $y = Bar.method - $x - )) { int32 } - end - - it "expands global var with declaration (#2564)" do - assert_type(%( - $x : Bool = 1 <= 2 <= 3 - $x - )) { bool } - end - - it "errors when using Class (#2605)" do - assert_error %( - class Foo - def foo(klass : Class) - $class = klass - end - end - ), - "can't use Class as the type of global variable $class, use a more specific type" - end - - it "gives correct error when trying to use Int as a global variable type" do - assert_error %( - $x : Int - ), - "can't use Int as the type of a global variable yet, use a more specific type" - end - - it "declares uninitialized (#2935)" do - assert_type(%( - $x = uninitialized Int32 - - def foo - $x - end - - foo - )) { int32 } - end -end diff --git a/spec/compiler/semantic/hooks_spec.cr b/spec/compiler/semantic/hooks_spec.cr index 8dc8d3824c5d..263575b703d1 100644 --- a/spec/compiler/semantic/hooks_spec.cr +++ b/spec/compiler/semantic/hooks_spec.cr @@ -101,7 +101,11 @@ describe "Semantic: hooks" do assert_type(%( abstract class Foo macro inherited - $bar = new + @@bar = new + + def self.bar + @@bar + end end end @@ -114,7 +118,7 @@ describe "Semantic: hooks" do end end - $bar.name + Bar.bar.name )) { string } end diff --git a/spec/compiler/semantic/instance_var_spec.cr b/spec/compiler/semantic/instance_var_spec.cr index f90dc5611a8d..805662bdd5ac 100644 --- a/spec/compiler/semantic/instance_var_spec.cr +++ b/spec/compiler/semantic/instance_var_spec.cr @@ -449,7 +449,7 @@ describe "Semantic: instance var" do )) { int32 } end - it "infers type from literal" do + it "infers type from number literal" do assert_type(%( class Foo def initialize @@ -465,6 +465,785 @@ describe "Semantic: instance var" do )) { int32 } end + it "infers type from char literal" do + assert_type(%( + class Foo + def initialize + @x = 'a' + end + + def x + @x + end + end + + Foo.new.x + )) { char } + end + + it "infers type from bool literal" do + assert_type(%( + class Foo + def initialize + @x = true + end + + def x + @x + end + end + + Foo.new.x + )) { bool } + end + + it "infers type from string literal" do + assert_type(%( + class Foo + def initialize + @x = "hi" + end + + def x + @x + end + end + + Foo.new.x + )) { string } + end + + it "infers type from string interpolation" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = "foo\#{1}" + end + + def x + @x + end + end + + Foo.new.x + )) { string } + end + + it "infers type from symbol literal" do + assert_type(%( + class Foo + def initialize + @x = :hi + end + + def x + @x + end + end + + Foo.new.x + )) { symbol } + end + + it "infers type from array literal with of" do + assert_type(%( + class Foo + def initialize + @x = [] of Int32 + end + + def x + @x + end + end + + Foo.new.x + )) { array_of int32 } + end + + it "infers type from array literal with of metaclass" do + assert_type(%( + class Foo + def initialize + @x = [] of Int32.class + end + + def x + @x + end + end + + Foo.new.x + )) { array_of int32.metaclass } + end + + it "infers type from array literal from its literals" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = [1, 'a'] + end + + def x + @x + end + end + + Foo.new.x + )) { array_of union_of(int32, char) } + end + + it "infers type from hash literal with of" do + assert_type(%( + class Foo + def initialize + @x = {} of Int32 => String + end + + def x + @x + end + end + + Foo.new.x + )) { hash_of int32, string } + end + + it "infers type from hash literal from elements" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = {1 => "foo", 'a' => true} + end + + def x + @x + end + end + + Foo.new.x + )) { hash_of(union_of(int32, char), union_of(string, bool)) } + end + + it "infers type from range literal" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = 1..'a' + end + + def x + @x + end + end + + Foo.new.x + )) { range_of(int32, char) } + end + + it "infers type from regex literal" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = /foo/ + end + + def x + @x + end + end + + Foo.new.x + )) { types["Regex"] } + end + + it "infers type from regex literal with interpolation" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = /foo\#{1}/ + end + + def x + @x + end + end + + Foo.new.x + )) { types["Regex"] } + end + + it "infers type from tuple literal" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = {1, "foo"} + end + + def x + @x + end + end + + Foo.new.x + )) { tuple_of([int32, string]) } + end + + it "infers type from named tuple literal" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = {x: 1, y: "foo"} + end + + def x + @x + end + end + + Foo.new.x + )) { named_tuple_of({"x": int32, "y": string}) } + end + + it "infers type from new expression" do + assert_type(%( + class Bar + end + + class Foo + def initialize + @x = Bar.new + end + + def x + @x + end + end + + Foo.new.x + )) { types["Bar"] } + end + + it "infers type from as" do + assert_type(%( + class Foo + def initialize + @x = (1 + 2).as(Int32) + end + + def x + @x + end + end + + Foo.new.x + )) { int32 } + end + + it "infers type from as?" do + assert_type(%( + class Foo + def initialize + @x = (1 + 2).as?(Int32) + end + + def x + @x + end + end + + Foo.new.x + )) { nilable int32 } + end + + it "infers type from argument restriction" do + assert_type(%( + class Foo + def x=(@x : Int32) + end + + def x + @x + end + end + + Foo.new.x + )) { nilable int32 } + end + + it "infers type from argument default value" do + assert_type(%( + class Foo + def set(@x = 1) + end + + def x + @x + end + end + + Foo.new.x + )) { nilable int32 } + end + + it "infers type from lib fun call" do + assert_type(%( + lib LibFoo + struct Bar + x : Int32 + end + + fun foo : Bar + end + + class Foo + def initialize + @x = LibFoo.foo + end + + def x + @x + end + end + + Foo.new.x + )) { types["LibFoo"].types["Bar"] } + end + + it "infers type from lib variable" do + assert_type(%( + lib LibFoo + struct Bar + x : Int32 + end + + $foo : Bar + end + + class Foo + def initialize + @x = LibFoo.foo + end + + def x + @x + end + end + + Foo.new.x + )) { types["LibFoo"].types["Bar"] } + end + + it "infers type from ||" do + assert_type(%( + class Foo + def initialize + @x = 1 || true + end + + def x + @x + end + end + + Foo.new.x + )) { union_of(int32, bool) } + end + + it "infers type from &&" do + assert_type(%( + class Foo + def initialize + @x = 1 && true + end + + def x + @x + end + end + + Foo.new.x + )) { union_of(int32, bool) } + end + + it "infers type from ||=" do + assert_type(%( + class Foo + def x + @x ||= 1 + end + end + + Foo.new.@x + )) { nilable int32 } + end + + it "infers type from ||= inside another assignemnt" do + assert_type(%( + class Foo + def x + x = @x ||= 1 + end + end + + Foo.new.@x + )) { nilable int32 } + end + + it "infers type from if" do + assert_type(%( + class Foo + def initialize + @x = 1 == 1 ? 1 : true + end + + def x + @x + end + end + + Foo.new.x + )) { union_of(int32, bool) } + end + + it "infers type from case" do + assert_type(%( + require "prelude" + + class Foo + def initialize + @x = case 1 + when 2 + 'a' + else + true + end + end + + def x + @x + end + end + + Foo.new.x + )) { union_of(char, bool) } + end + + it "infers type from unless" do + assert_type(%( + class Foo + def initialize + @x = unless 1 == 1 + 1 + else + true + end + end + + def x + @x + end + end + + Foo.new.x + )) { union_of(int32, bool) } + end + + it "infers type from begin" do + assert_type(%( + class Foo + def initialize + @x = begin + 'a' + 1 + end + end + + def x + @x + end + end + + Foo.new.x + )) { int32 } + end + + it "infers type from assign (1)" do + assert_type(%( + class Foo + def initialize + @x = @y = 1 + end + + def x + @x + end + end + + Foo.new.x + )) { int32 } + end + + it "infers type from assign (2)" do + assert_type(%( + class Foo + def initialize + @x = @y = 1 + end + + def y + @y + end + end + + Foo.new.y + )) { int32 } + end + + it "infers type from block argument" do + assert_type(%( + class Foo + def set(&@x : Int32 -> Int32) + end + + def x + @x + end + end + + Foo.new.x + )) { nilable proc_of(int32, int32) } + end + + it "infers type from block argument without restriction" do + assert_type(%( + class Foo + def set(&@x) + end + + def x + @x + end + end + + Foo.new.x + )) { nilable proc_of(void) } + end + + it "infers type from !" do + assert_type(%( + class Foo + def initialize + @x = !1 + end + + def x + @x + end + end + + Foo.new.x + )) { bool } + end + + it "infers type from is_a?" do + assert_type(%( + class Foo + def initialize + @x = 1.is_a?(Char) + end + + def x + @x + end + end + + Foo.new.x + )) { bool } + end + + it "infers type from responds_to?" do + assert_type(%( + class Foo + def initialize + @x = 1.responds_to?(:foo) + end + + def x + @x + end + end + + Foo.new.x + )) { bool } + end + + it "infers type from sizeof" do + assert_type(%( + class Foo + def initialize + @x = sizeof(Int32) + end + + def x + @x + end + end + + Foo.new.x + )) { int32 } + end + + it "infers type from instance_sizeof" do + assert_type(%( + class Foo + def initialize + @x = instance_sizeof(Foo) + end + + def x + @x + end + end + + Foo.new.x + )) { int32 } + end + + it "infers type from path that is a type" do + assert_type(%( + class Bar; end + class Baz < Bar; end + + class Foo + def initialize + @x = Bar + end + + def x + @x + end + end + + Foo.new.x + )) { types["Bar"].virtual_type!.metaclass } + end + + it "infers type from path that is a constant" do + assert_type(%( + CONST = 1 + + class Foo + def initialize + @x = CONST + end + + def x + @x + end + end + + Foo.new.x + )) { int32 } + end + + it "doesn't infer type from redefined method" do + assert_type(%( + class Foo + def foo + @x = 1 + end + + def foo + @x = 'a' + end + + def x + @x + end + end + + Foo.new.x + )) { nilable char } + end + + it "infers type from redefined method if calls previous_def" do + assert_type(%( + class Foo + def foo + @x = 1 + end + + def foo + previous_def + @x = 'a' + end + + def x + @x + end + end + + Foo.new.x + )) { union_of(nil_type, int32, char) } + end + + it "infers type in multi assign" do + assert_type(%( + class Foo + def initialize + @x, @y = 1, 'a' + end + + def x + @x + end + + def y + @y + end + end + + {Foo.new.x, Foo.new.y} + )) { tuple_of([int32, char]) } + end + + it "infers type from enum member" do + assert_type(%( + enum Color + Red, Green, Blue + end + + class Foo + def initialize + @x = Color::Red + end + + def x + @x + end + end + + Foo.new.x + )) { types["Color"] } + end + it "infers type from two literals" do assert_type(%( class Foo diff --git a/spec/compiler/semantic/module_spec.cr b/spec/compiler/semantic/module_spec.cr index cdb52c0b6491..dfe08ba430e2 100644 --- a/spec/compiler/semantic/module_spec.cr +++ b/spec/compiler/semantic/module_spec.cr @@ -337,11 +337,15 @@ describe "Semantic: module" do module Foo class Bar; end - $x : Bar.class - $x = foo { Bar } + @@x : Bar.class + @@x = foo { Bar } + + def self.x + @@x + end end - $x + Foo.x ") { types["Foo"].types["Bar"].metaclass } end @@ -356,11 +360,15 @@ describe "Semantic: module" do 1 end - $x : Int32 - $x = foo { bar } + @@x : Int32 + @@x = foo { bar } + + def self.x + @@x + end end - $x + Foo.x ") { int32 } end diff --git a/spec/compiler/semantic/named_tuple_spec.cr b/spec/compiler/semantic/named_tuple_spec.cr index 0fdf2b9f1add..643453287af1 100644 --- a/spec/compiler/semantic/named_tuple_spec.cr +++ b/spec/compiler/semantic/named_tuple_spec.cr @@ -166,15 +166,6 @@ describe "Semantic: named tuples" do )) { named_tuple_of({"x": int32, "y": char}) } end - it "can assign two global var" do - assert_type(%( - $x = {name: "Foo", age: 20} - $y = {age: 40, name: "Bar"} - $x = $y - $x - )) { named_tuple_of({"name": string, "age": int32}) } - end - it "can assign to union of compatible named tuple" do assert_type(%( tup1 = {x: 1, y: "foo"} diff --git a/spec/compiler/semantic/proc_spec.cr b/spec/compiler/semantic/proc_spec.cr index 3d3ea16baea9..194f194369c6 100644 --- a/spec/compiler/semantic/proc_spec.cr +++ b/spec/compiler/semantic/proc_spec.cr @@ -105,9 +105,9 @@ describe "Semantic: proc" do it "binds proc literal to arguments and body" do assert_type(" - $x = 1 - f = -> { $x } - $x = 'a' + x = 1 + f = -> { x } + x = 'a' f ") { proc_of(union_of(int32, char)) } end diff --git a/src/compiler/crystal/semantic/class_vars_initializer_visitor.cr b/src/compiler/crystal/semantic/class_vars_initializer_visitor.cr index 23ee00f1f02e..a401221d6e18 100644 --- a/src/compiler/crystal/semantic/class_vars_initializer_visitor.cr +++ b/src/compiler/crystal/semantic/class_vars_initializer_visitor.cr @@ -67,7 +67,9 @@ module Crystal had_class_var = false end - node.accept main_visitor + main_visitor.pushing_type(owner.as(ModuleType)) do + node.accept main_visitor + end unless had_class_var main_visitor.undefined_class_variable(class_var, owner) diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 8bf9c6dc1330..221ae6be44bd 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -935,7 +935,7 @@ module Crystal when :SYMBOL node_and_next_token SymbolLiteral.new(@token.value.to_s) when :GLOBAL - new_node_check_type_declaration Global + raise "$global_variables are not supported, use @@class_variables instead" when :"$~", :"$?" location = @token.location var = Var.new(@token.to_s).at(location) diff --git a/src/compiler/crystal/tools/playground/agent_instrumentor_transformer.cr b/src/compiler/crystal/tools/playground/agent_instrumentor_transformer.cr index 0bb3b6b2b98e..1c451d66acd3 100644 --- a/src/compiler/crystal/tools/playground/agent_instrumentor_transformer.cr +++ b/src/compiler/crystal/tools/playground/agent_instrumentor_transformer.cr @@ -77,7 +77,7 @@ module Crystal if node.is_a?(TupleLiteral) args << ArrayLiteral.new(node.elements.map { |e| StringLiteral.new(e.to_s).as(ASTNode) }) end - call = Call.new(Global.new("$p"), "i", args, Block.new([] of Var, node.as(ASTNode))) + call = Call.new(Call.new(nil, "_p"), "i", args, Block.new([] of Var, node.as(ASTNode))) call = Cast.new(call, TypeOf.new([node.clone] of ASTNode)) if add_as_typeof call = Splat.new(call) if splat call diff --git a/src/compiler/crystal/tools/playground/server.cr b/src/compiler/crystal/tools/playground/server.cr index 95edaaad87de..ce3231d6bd7f 100644 --- a/src/compiler/crystal/tools/playground/server.cr +++ b/src/compiler/crystal/tools/playground/server.cr @@ -29,7 +29,18 @@ module Crystal::Playground prelude = %( require "compiler/crystal/tools/playground/agent" - $p = Crystal::Playground::Agent.new("ws://localhost:#{@port}/agent/#{@session_key}/#{tag}", #{tag}) + + class Crystal::Playground::Agent + @@instance = Crystal::Playground::Agent.new("ws://localhost:#{@port}/agent/#{@session_key}/#{tag}", #{tag}) + + def self.instance + @@instance + end + end + + def _p + Crystal::Playground::Agent.instance + end ) sources = [ @@ -352,7 +363,6 @@ module Crystal::Playground end class Server - $sockets = [] of HTTP::WebSocket @sessions = {} of Int32 => Session @sessions_key = 0 diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index 767d46158db2..1377c2dcd68b 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -106,7 +106,7 @@ module GC end def self.add_root(object : Reference) - roots = $roots ||= [] of Pointer(Void) + roots = @@roots ||= [] of Pointer(Void) roots << Pointer(Void).new(object.object_id) end diff --git a/src/reference.cr b/src/reference.cr index 1729f0955cd0..d5c391106dd0 100644 --- a/src/reference.cr +++ b/src/reference.cr @@ -76,12 +76,15 @@ class Reference nil end - # TODO: Boehm GC doesn't scan thread local vars, so we can't use it yet - # @[ThreadLocal] - $_exec_recursive : Hash({UInt64, Symbol}, Bool)? + # :nodoc: + module ExecRecursive + def self.hash + @@exec_recursive ||= {} of {UInt64, Symbol} => Bool + end + end private def exec_recursive(method) - hash = ($_exec_recursive ||= {} of {UInt64, Symbol} => Bool) + hash = ExecRecursive.hash key = {object_id, method} if hash[key]? false