Newer
Older
#!/usr/bin/env bin/crystal --run
require "../../spec_helper"
describe "Code gen: macro" do
it "expands macro" do
run("macro foo; 1 + 2; end; foo").to_i.should eq(3)
end
it "expands macro with arguments" do
run(%(
macro foo(n)
{{n}} + 2
end
foo(1)
)).to_i.should eq(3)
end
it "expands macro that invokes another macro" do
run(%(
macro foo
def x
1 + 2
end
end
macro bar
foo
end
bar
x
)).to_i.should eq(3)
end
it "expands macro defined in class" do
foo
end
foo = Foo.new
foo.bar
end
it "expands macro defined in base class" do
end
class Foo
foo
end
foo = Foo.new
foo.bar
it "expands inline macro" do
run(%(
a = {{ 1 }}
a
)).to_i.should eq(1)
end
it "expands inline macro for" do
run(%(
a = 0
{% for i in [1, 2, 3] %}
{% end %}
a
)).to_i.should eq(6)
end
it "expands inline macro if (true)" do
run(%(
a = 0
{% if 1 == 1 %}
{% end %}
a
)).to_i.should eq(1)
end
it "expands inline macro if (false)" do
run(%(
a = 0
{% if 1 == 2 %}
{% end %}
it "finds macro in class" do
run(%(
class Foo
macro foo
1 + 2
end
def bar
foo
end
end
Foo.new.bar
)).to_i.should eq(3)
end
Ary Borenszweig
committed
it "expands def macro" do
run(%(
def bar_baz
1
end
def foo : Int32
Ary Borenszweig
committed
bar_{{ "baz".id }}
Ary Borenszweig
committed
end
foo
)).to_i.should eq(1)
end
it "expands def macro with var" do
run(%(
def foo : Int32
a = {{ 1 }}
end
foo
)).to_i.should eq(1)
end
Ary Borenszweig
committed
it "expands def macro with @instance_vars" do
run(%(
class Foo
def initialize(@x)
end
def to_s : String
{{ @instance_vars.first.stringify }}
end
end
foo = Foo.new(1)
foo.to_s
)).to_string.should eq("@x")
end
Ary Borenszweig
committed
it "expands def macro with @instance_vars with subclass" do
run(%(
class Reference
def to_s : String
{{ @instance_vars.last.stringify }}
end
end
class Foo
def initialize(@x)
end
end
class Bar < Foo
def initialize(@x, @y)
end
end
Bar.new(1, 2).to_s
)).to_string.should eq("@y")
end
it "expands def macro with @instance_vars with hierarchy" do
Ary Borenszweig
committed
run(%(
class Reference
def to_s : String
{{ @instance_vars.last.stringify }}
end
end
class Foo
def initialize(@x)
end
end
class Bar < Foo
def initialize(@x, @y)
end
end
(Bar.new(1, 2) || Foo.new(1)).to_s
)).to_string.should eq("@y")
end
Ary Borenszweig
committed
it "expands def macro with @class_name" do
Ary Borenszweig
committed
run(%(
class Foo
def initialize(@x)
end
def to_s : String
Ary Borenszweig
committed
{{@class_name}}
Ary Borenszweig
committed
end
end
foo = Foo.new(1)
foo.to_s
)).to_string.should eq("Foo")
end
it "expands macro and resolves type correctly" do
run(%(
class Foo
def foo : Int32
1
end
end
class Bar < Foo
Int32 = 2
end
Bar.new.foo
)).to_i.should eq(1)
end
Ary Borenszweig
committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
it "expands def macro with @class_name with hierarchy" do
run(%(
class Reference
def to_s : String
{{ @class_name }}
end
end
class Foo
end
class Bar < Foo
end
(Bar.new || Foo.new).to_s
)).to_string.should eq("Bar")
end
it "expands def macro with @class_name with hierarchy (2)" do
run(%(
class Reference
def to_s : String
{{ @class_name }}
end
end
class Foo
end
class Bar < Foo
end
(Foo.new || Bar.new).to_s
)).to_string.should eq("Foo")
end
Ary Borenszweig
committed
it "allows overriding macro definition when redefining base class" do
run(%(
class Foo
def inspect : String
Ary Borenszweig
committed
{{@class_name}}
Ary Borenszweig
committed
end
end
class Bar < Foo
end
class Foo
def inspect
"OH NO"
end
end
Bar.new.inspect
)).to_string.should eq("OH NO")
end
it "uses invocation context" do
run(%(
macro foo
def bar
Ary Borenszweig
committed
{{@class_name}}
end
end
class Foo
foo
end
Foo.new.bar
)).to_string.should eq("Foo")
end
it "allows macro with default arguments" do
run(%(
def bar
2
end
macro foo(x, y = :bar)
{{x}} + {{y.id}}
end
foo(1)
)).to_i.should eq(3)
end
it "expands def macro with instance var and method call (bug)" do
run(%(
struct Nil
def to_i
0
end
end
class Foo
def foo : Int32
name = 1
@name = name
end
end
Foo.new.foo.to_i
)).to_i.should eq(1)
end
Ary Borenszweig
committed
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
it "expands @class_name in hierarchy metaclass (1)" do
run(%(
class Class
def to_s : String
{{ @name }}
end
end
class Foo
end
class Bar < Foo
end
p = Pointer(Foo.class).malloc(1_u64)
p.value = Bar
p.value = Foo
p.value.to_s
)).to_string.should eq("Foo:Class")
end
it "expands @class_name in hierarchy metaclass (2)" do
run(%(
class Class
def to_s : String
{{ @name }}
end
end
class Foo
end
class Bar < Foo
end
p = Pointer(Foo.class).malloc(1_u64)
p.value = Foo
p.value = Bar
p.value.to_s
)).to_string.should eq("Bar:Class")
end
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
it "doesn't skip abstract classes when defining macro methods" do
run(%(
class Object
def foo : Int32
1
end
end
class Type
end
class ModuleType < Type
def foo
2
end
end
class Type1 < ModuleType
end
class Type2 < Type
end
t = Type1.new || Type2.new
t.foo
)).to_i.should eq(2)
end