1# Examples taken from http://crystal-lang.org/docs/
2# Copyright 2012-2018 Manas Technology Solutions.
3# Updated on May 17th, 2018 by @faustinoaq.
4
5require "http/server"
6
7server = HTTP::Server.new(8080) do |context|
8  context.response.content_type = "text/plain"
9  context.response.print "Hello world! The time is #{Time.now}"
10end
11
12puts "Listening on http://0.0.0.0:8080"
13server.listen
14
15module HTTP
16  class RequestHandler
17  end
18end
19
20alias NumericValue = Float32 | Float64 | Int32 | Int64
21
22enum Time::DayOfWeek
23end
24
25class Greeting
26  class_property global_greeting = "Hello world"
27
28  @@default_greeting = "Hello world"
29
30  def initialize(@custom_greeting = nil)
31  end
32
33  def print_greeting
34    greeting = @custom_greeting || @@default_greeting
35    puts greeting
36  end
37end
38
39LUCKY_NUMBERS     = [3, 7, 11]
40DOCUMENTATION_URL = "http://crystal-lang.org/docs"
41
42module Scorecard
43  class Parser
44    def parse(score_text)
45      begin
46        score_text.scan(SCORE_PATTERN) do |match|
47          handle_match(match)
48        end
49      rescue err : ParseError
50        # handle error ...
51      end
52    end
53  end
54end
55
56module Money
57  CURRENCIES = {
58    "EUR" => 1.0,
59    "ARS" => 10.55,
60    "USD" => 1.12,
61    "JPY" => 134.15,
62  }
63
64  class Amount
65    getter :currency, :value
66
67    def initialize(@currency, @value)
68    end
69  end
70
71  class CurrencyConversion
72    def initialize(@amount, @target_currency)
73    end
74
75    def amount
76      # implement conversion ...
77    end
78  end
79end
80
81i = 0
82while i < 10
83  proc = ->(x : Int32) do
84    spawn do
85      puts(x)
86    end
87  end
88  proc.call(i)
89  i += 1
90end
91
92Fiber.yield
93
94# A buffered channel of capacity 2
95channel = Channel(Int32).new(2)
96
97spawn do
98  channel.send(1)
99  channel.send(2)
100  channel.send(3)
101end
102
1033.times do |i|
104  puts channel.receive
105end
106
107class MyDictionary(K, V)
108end
109
110MyBox.new(1)       # :: MyBox(Int32)
111MyBox.new("hello") # :: MyBox(String)
112
113module Moo(T)
114  def t
115    T
116  end
117end
118
119class Foo(U)
120  include Moo(U)
121
122  def initialize(@value : U)
123  end
124end
125
126foo = Foo.new(1)
127foo.t # Int32
128
129class Parent(T)
130end
131
132class Int32Child < Parent(Int32)
133end
134
135class GenericChild(T) < Parent(T)
136end
137
138class Person
139end
140
141a = 1
142ptr = pointerof(a)
143ptr[100_000] = 2 # undefined behaviour, probably a segmentation fault
144
145alias Int32OrString = Int32 | String
146
147alias Int32OrNil = Int32?
148
149alias Int32OrNil_ = Int32 | ::Nil
150
151alias Int32Ptr = Int32*
152
153alias Int32Ptr_ = Pointer(Int32)
154
155alias Int32_8 = Int32[8]
156
157alias Int32_8_ = StaticArray(Int32, 8)
158
159alias Int32StringTuple = {Int32, String}
160
161alias Int32StringTuple_ = Tuple(Int32, String)
162
163alias Int32ToString = Int32 -> String
164
165alias Int32ToString_ = Proc(Int32, String)
166
167alias ProcThatReturnsInt32 = -> Int32
168
169alias Int32AndCharToString = Int32, Char -> String
170
171alias ComplexProc = (Int32 -> Int32) -> String
172
173def foo(x : Int32)
174  "instance"
175end
176
177def foo(x : Int32.class)
178  "class"
179end
180
181foo 1     # "instance"
182foo Int32 # "class"
183
184class Parent
185end
186
187class Child1 < Parent
188end
189
190class Child2 < Parent
191end
192
193ary = [] of Parent.class
194ary << Child1
195ary << Child2
196
197# Same as not specifying a restriction, not very useful
198def foo(x : _)
199end
200
201# A bit more useful: any two arguments Proc that returns an Int32:
202def foo(x : _, _ -> Int32)
203end
204
205# alias SameAsInt32 = typeof(2)
206# alias Int32OrString_ = typeof(1, "a")
207
208class Person
209  def initialize(name)
210    @name = name
211    @age = 0
212  end
213
214  def name
215    @name
216  end
217
218  def age
219    @age
220  end
221end
222
223john = Person.new "John"
224peter = Person.new "Peter"
225
226john.name # => "John"
227john.age  # => 0
228
229peter.name # => "Peter"
230
231class Person
232  def self.new(name)
233    instance = Person.allocate
234    instance.initialize(name)
235    instance
236  end
237end
238
239if a.is_a?(String)
240  # here a is a String
241end
242
243if b.is_a?(Number)
244  # here b is a Number
245end
246
247a = some_condition ? 1 : "hello"
248# a : Int32 | String
249
250if a.is_a?(Number)
251  # a : Int32
252else
253  # a : String
254end
255
256if a.is_a?(String) && b.is_a?(Number)
257  # here a is a String and b is a Number
258end
259
260a.+(b)
261
262struct Vector2
263  getter x, y
264
265  def initialize(@x, @y)
266  end
267
268  def +(other)
269    Vector2.new(x + other.x, y + other.y)
270  end
271end
272
273v1 = Vector2.new(1, 2)
274v2 = Vector2.new(3, 4)
275v1 + v2 # => Vector2(@x=4, @y=6)
276
277struct Vector2
278  def -
279    Vector2.new(-x, -y)
280  end
281end
282
283v1 = Vector2.new(1, 2)
284-v1 # => Vector2(@x=-1, @y=-2)
285
286class MyArray
287  def [](index)
288    # ...
289  end
290
291  def [](index1, index2, index3)
292    # ...
293  end
294
295  def []=(index, value)
296    # ...
297  end
298end
299
300array = MyArray.new
301
302array[1]       # invokes the first method
303array[1, 2, 3] # invokes the second method
304array[1] = 2   # invokes the third method
305
306array.[](1)       # invokes the first method
307array.[](1, 2, 3) # invokes the second method
308array.[]=(1, 2)   # invokes the third method
309
310raise "OH NO!"
311raise Exception.new("Some error")
312
313class MyException < Exception
314end
315
316begin
317  raise MyException.new("OH NO!")
318rescue ex : MyException
319  puts "Rescued MyException: #{ex.message}"
320end
321
322begin
323  # ...
324rescue ex : MyException | MyOtherException
325  # only MyException or MyOtherException
326rescue
327  # any other kind of exception
328ensure
329  puts "Cleanup..."
330end
331
332def some_method
333  something_dangerous
334rescue
335  # execute if an exception is raised
336end
337
338array = [1, 2, 3]
339array[4]  # raises because of IndexError
340array[4]? # returns nil because of index out of bounds
341
342def some_proc(&block : Int32 -> Int32)
343  block
344end
345
346x = 0
347proc = ->(i : Int32) { x += i }
348proc = some_proc(&proc)
349proc.call(1)  # => 1
350proc.call(10) # => 11
351x             # => 11
352
353def add(x, y)
354  x + y
355end
356
357adder = ->add(Int32, Int32)
358adder.call(1, 2) # => 3
359
360module Curses
361  class Window
362  end
363end
364
365Curses::Window.new
366
367module ItemsSize
368  def size
369    items.size
370  end
371end
372
373class Items
374  include ItemsSize
375
376  def items
377    [1, 2, 3]
378  end
379end
380
381items = Items.new
382items.size # => 3
383
384module Base64
385  extend self
386
387  def encode64(string)
388    # ...
389  end
390
391  def decode64(string)
392    # ...
393  end
394end
395
396Base64.encode64 "hello" # => "aGVsbG8="
397
398if some_condition
399  a = 1
400else
401  a = "hello"
402end
403
404a_as_int = a.as(Int32)
405a_as_int.abs # works, compiler knows that a_as_int is Int32
406
407ptr = Pointer(Int32).malloc(1)
408ptr.as(Int8*) # :: Pointer(Int8)
409
410array = [1, 2, 3]
411
412# object_id returns the address of an object in memory,
413# so we create a pointer with that address
414ptr = Pointer(Void).new(array.object_id)
415
416# Now we cast that pointer to the same type, and
417# we should get the same value
418array2 = ptr.as(Array(Int32))
419array2.same?(array) # => true
420
421a = 1
422b = a.as(Int32 | Float64)
423b # :: Int32 | Float64
424
425ary = [1, 2, 3]
426
427# We want to create an array 1, 2, 3 of Int32 | Float64
428ary2 = ary.map { |x| x.as(Int32 | Float64) }
429
430ary2        # :: Array(Int32 | Float64)
431ary2 << 1.5 # OK
432
433class Person
434  def initialize(@name)
435  end
436
437  def name
438    @name
439  end
440end
441
442a = [] of Person
443x = a.map { |f| f.name } # Error: can't infer block return type
444
445a = [] of Person
446x = a.map { |f| f.name.as(String) } # OK
447
448Person.new "John"
449
450a = [] of Person
451x = a.map { |f| f.name } # OK
452
453loop do
454  do_something
455  break if some_condition
456end
457
458class Point
459  def initialize(@x, @y)
460  end
461end
462
463Point.new 1, 2
464
465# 2 x Int32 = 2 x 4 = 8
466instance_sizeof(Point) # => 12
467
468a = 1
469while a < 5
470  a += 1
471  if a == 3
472    next
473  end
474  puts a
475end
476
477# The above prints the numbers 2, 4 and 5
478
479lib C
480  # In C: double cos(double x)
481  fun cos(value : Float64) : Float64
482
483  fun getch : Int32
484
485  fun srand(seed : UInt32)
486
487  fun exit(status : Int32) : NoReturn
488
489  fun printf(format : UInt8*, ...) : Int32
490end
491
492C.cos(1.5) # => 0.0707372
493C.srand(1_u32)
494
495a = 1
496b = 2
497C.printf "%d + %d = %d\n", a, b, a + b
498
499lib LibSDL
500  fun init = SDL_Init(flags : UInt32) : Int32
501end
502
503lib LLVMIntrinsics
504  fun ceil_f32 = "llvm.ceil.f32"(value : Float32) : Float32
505end
506
507lib MyLib
508  fun my_fun(some_size : LibC::SizeT)
509end
510
511@[Link("pcre")]
512lib LibPCRE
513end
514
515lib C
516  {% if flag?(:x86_64) %}
517    alias SizeT = UInt64
518  {% else %}
519    alias SizeT = UInt32
520  {% end %}
521
522  fun memcmp(p1 : Void*, p2 : Void*, size : C::SizeT) : Int32
523end
524
525lib X
526  enum SomeEnum
527    Ten       = 10
528    Twenty    = 10 * 2
529    ThirtyTwo = 1 << 5
530  end
531end
532
533lib X
534  enum SomeEnum
535    A = 1_u32
536  end
537end
538
539X::SomeEnum::Zero # => 0_i8
540X::SomeEnum::Two  # => 2_i8
541
542lib X
543  fun callback(f : Int32 -> Int32)
544end
545
546f = ->(x : Int32) { x + 1 }
547X.callback(f)
548
549X.callback ->(x) { x + 1 }
550
551X.callback nil
552
553lib LibFoo
554  fun store_callback(callback : ->)
555  fun execute_callback
556end
557
558LibFoo.store_callback ->{ raise "OH NO!" }
559LibFoo.execute_callback
560
561lib LibFoo
562  fun store_callback(callback : ->)
563
564  @[Raises]
565  fun execute_callback
566end
567
568@[Link("pcre")]
569lib PCRE
570  INFO_CAPTURECOUNT = 2
571end
572
573PCRE::INFO_CAPTURECOUNT # => 2
574
575lib U
576  # In C:
577  #
578  #  union IntOrFloat {
579  #    int some_int;
580  #    double some_float;
581  #  };
582  union IntOrFloat
583    some_int : Int32
584    some_float : Float64
585  end
586end
587
588value = U::IntOrFloat.new
589
590value = uninitialized U::IntOrFlaot
591value.some_int # => some garbage value
592
593value = U::IntOrFloat.new
594value.some_int = 1
595value.some_int   # => 1
596value.some_float # => 4.94066e-324
597
598def change_it(value)
599  value.some_int = 1
600end
601
602value = U::IntOrFloat.new
603change_it value
604value.some_int # => 0
605
606lib C
607  # In C:
608  #
609  #  struct TimeZone {
610  #    int minutes_west;
611  #    int dst_time;
612  #  };
613  struct TimeZone
614    minutes_west : Int32
615    dst_time : Int32
616  end
617end
618
619lib C
620  # This is a forward declaration
621  struct Node
622  end
623
624  struct Node
625    node : Node*
626  end
627end
628
629tz = C::TimeZone.new
630
631tz = uninitialized C::TimeZone
632tz.minutes_west # => some garbage value
633
634tz = C::TimeZone.new
635tz.minutes_west = 1
636tz.minutes_west # => 1
637
638tz = C::TimeZone.new minutes_west: 1, dst_time: 2
639tz.minutes_west # => 1
640tz.dst_time     # => 2
641
642def change_it(tz)
643  tz.minutes_west = 1
644end
645
646tz = C::TimeZone.new
647change_it tz
648tz.minutes_west # => 0
649
650lib C
651  $errno : Int32
652end
653
654C.errno # => some value
655C.errno = 0
656C.errno # => 0
657
658lib C
659  @[ThreadLocal]
660  $errno : Int32
661end
662
663lib C
664  fun waitpid(pid : Int32, status_ptr : Int32*, options : Int32) : Int32
665end
666
667status_ptr = uninitialized Int32
668
669C.waitpid(pid, pointerof(status_ptr), options)
670
671C.waitpid(pid, out status_ptr, options)
672
673lib X
674  type CInt = Int32
675end
676
677{% if flag?(:x86_64) %}
678  # some specific code for 64 bits platforms
679{% else %}
680  # some specific code for non-64 bits platforms
681{% end %}
682
683{% if flag?(:linux) && flag?(:x86_64) %}
684  # some specific code for linux 64 bits
685{% end %}
686
687lib C
688  {% if flag?(:linux) && flag?(:x86_64) %}
689    struct SomeStruct
690      some_field : Int32
691    end
692  {% else %}
693    struct SomeStruct
694      some_field : Int64
695    end
696  {% end %}
697end
698
699# Assigns to a local variable
700local = 1
701
702# Assigns to a global property
703class Global
704  class_property global1 = 1
705  class_getter global2 = 2
706  class_setter global3 = 3
707
708  # Fails on nil
709  class_property! global4 = 4
710  class_getter! global5 = 5
711  class_setter! global6 = 6
712end
713
714class Testing
715  # Assigns to an instance variable
716  @instance = 2
717
718  # Assigns to a class variable
719  @@class = 3
720end
721
722local += 1 # same as: local = local + 1
723
724# The above is valid with these operators:
725# +, -, *, /, %, |, &, ^, **, <<, >>
726
727local ||= 1 # same as: local || (local = 1)
728local &&= 1 # same as: local && (local = 1)
729
730# A setter
731person.name=("John")
732
733# The above can be written as:
734person.name = "John"
735
736# An indexed assignment
737objects.[]=(2, 3)
738
739# The above can be written as:
740objects[2] = 3
741
742# Not assignment-related, but also syntax sugar:
743objects.[](2, 3)
744
745# The above can be written as:
746objects[2, 3]
747
748person.age += 1 # same as: person.age = person.age + 1
749
750person.name ||= "John" # same as: person.name || (person.name = "John")
751person.name &&= "John" # same as: person.name && (person.name = "John")
752
753objects[1] += 2 # same as: objects[1] = objects[1] + 2
754
755objects[1] ||= 2 # same as: objects[1]? || (objects[1] = 2)
756objects[1] &&= 2 # same as: objects[1]? && (objects[1] = 2)
757
758alias PInt32 = Pointer(Int32)
759
760ptr = PInt32.malloc(1) # : Pointer(Int32)
761
762alias RecArray = Array(Int32) | Array(RecArray)
763
764ary = [] of RecArray
765ary.push [1, 2, 3]
766ary.push ary
767ary # => [[1, 2, 3], [...]]
768
769module Json
770  alias Type = Nil |
771               Bool |
772               Int64 |
773               Float64 |
774               String |
775               Array(Type) |
776               Hash(String, Type)
777end
778
779a = 1
780if a > 0
781  a = 10
782end
783a # => 10
784
785b = 1
786if b > 2
787  b = 10
788else
789  b = 20
790end
791b # => 20
792
793if some_condition
794  do_something
795elsif some_other_condition
796  do_something_else
797else
798  do_that
799end
800
801a = 1
802if some_condition
803  a = "hello"
804else
805  a = true
806end
807# a : String | Bool
808
809b = 1
810if some_condition
811  b = "hello"
812end
813# b : Int32 | String
814
815if some_condition
816  c = 1
817else
818  c = "hello"
819end
820# c : Int32 | String
821
822if some_condition
823  d = 1
824end
825# d : Int32 | Nil
826
827a = 1
828if some_condition
829  a = "hello"
830  # a : String
831  a.size
832end
833# a : String | Int32
834
835if some_condition
836  e = 1
837else
838  e = "hello"
839  # e : String
840  return
841end
842# e : Int32
843
844enum Color : UInt8
845  Red        # 0
846  Green      # 1
847  Blue   = 5 # overwritten to 5
848  Yellow     # 6 (5 + 1)
849
850  def red?
851    self == Color::Red
852  end
853end
854
855Color::Red.value # :: UInt8
856
857@[Flags]
858enum IOMode
859  Read  # 1
860  Write # 2
861  Async # 4
862end
863
864IOMode::None.value # => 0
865IOMode::All.value  # => 7
866
867puts(Color::Red)                    # prints "Red"
868puts(IOMode::Write | IOMode::Async) # prints "Write, Async"
869
870puts Color.new(1) # => prints "Green"
871
872puts Color.new(10) # => prints "10"
873
874Color::Red.red?  # => true
875Color::Blue.red? # => false
876
877def paint(color : Color)
878  case color
879  when Color::Red
880    # ...
881  else
882    # Unusual, but still can happen
883    raise "unknown color: #{color}"
884  end
885end
886
887paint Color::Red
888
889def paint(color : Symbol)
890  case color
891  when :red
892    # ...
893  else
894    raise "unknown color: #{color}"
895  end
896end
897
898paint :red
899
900name = "Crystal"
901age = 1
902
903flower = "Tulip"
904# At this point 'flower' is a String
905
906flower = 1
907
908# At this point 'flower' is an Int32
909
910class Foo
911  def finalize
912    # Invoked when Foo is garbage-collected
913    puts "Bye bye from #{self}!"
914  end
915end
916
917# Prints "Bye bye ...!" for ever
918loop do
919  Foo.new
920end
921
922# Defines a method in the program
923def add(x, y)
924  x + y
925end
926
927# Invokes the add method in the program
928add(1, 2) # => 3
929
930def even?(num)
931  if num % 2 == 0
932    return true
933  end
934
935  return false
936end
937
938def add(x, y)
939  x + y
940end
941
942class Foo
943  def bar
944    # invokes the program's add method
945    add(1, 2)
946
947    # invokes Foo's baz method
948    baz(1, 2)
949  end
950
951  def baz(x, y)
952    x * y
953  end
954end
955
956def baz(x, y)
957  x + y
958end
959
960class Foo
961  def bar
962    baz(4, 2)   # => 2
963    ::baz(4, 2) # => 6
964  end
965
966  def baz(x, y)
967    x - y
968  end
969end
970
971x = 1
972
973def add(y)
974  x + y # error: undefined local variable or method 'x'
975end
976
977add(2)
978
979add 1, 2 # same as add(1, 2)
980
981class Counter
982  @@instances = 0
983
984  def initialize
985    @@instances += 1
986  end
987
988  def self.instances
989    @@instances
990  end
991end
992
993Counter.instances # => 0
994Counter.new
995Counter.new
996Counter.new
997Counter.instances # => 3
998
999class Counter
1000  def self.increment
1001    @@instances += 1
1002  end
1003end
1004
1005Counter.increment # Error: undefined method '+' for Nil
1006
1007class Parent
1008  @@counter = 0
1009end
1010
1011class Child < Parent
1012  def self.counter
1013    @@counter
1014  end
1015end
1016
1017Child.counter # => nil
1018
1019unless some_condition
1020  then_expression
1021else
1022  else_expression
1023end
1024
1025# Can also be written as a suffix
1026close_door unless door_closed?
1027
1028a = 1
1029b = typeof(a) # => Int32
1030
1031typeof(1, "a", 'a') # => (Int32 | String | Char)
1032
1033hash = {} of Int32 => String
1034another_hash = typeof(hash).new # :: Hash(Int32, String)
1035
1036class Array
1037  def self.elem_type(typ)
1038    if typ.is_a?(Array)
1039      elem_type(typ.first)
1040    else
1041      typ
1042    end
1043  end
1044end
1045
1046nest = [1, ["b", [:c, ['d']]]]
1047flat = Array(typeof(Array.elem_type(nest))).new
1048typeof(nest) # => Array(Int32 | Array(String | Array(Symbol | Array(Char))))
1049typeof(flat) # => Array(String | Int32 | Symbol | Char)
1050
1051a = 2 if some_condition
1052
1053x = 0
1054proc = ->{ x += 1; x }
1055proc.call # => 1
1056proc.call # => 2
1057x         # => 2
1058
1059def counter
1060  x = 0
1061  ->{ x += 1; x }
1062end
1063
1064proc = counter
1065proc.call # => 1
1066proc.call # => 2
1067
1068def foo
1069  yield
1070end
1071
1072x = 1
1073foo do
1074  x = "hello"
1075end
1076x # : Int32 | String
1077
1078x = 1
1079foo do
1080  x = "hello"
1081end
1082x # : Int32 | String
1083
1084x = 'a'
1085x # : Char
1086
1087def capture(&block)
1088  block
1089end
1090
1091x = 1
1092capture { x = "hello" }
1093
1094x = 'a'
1095x # : Int32 | String | Char
1096
1097def capture(&block)
1098  block
1099end
1100
1101x = 1
1102->{ x = "hello" }
1103
1104x = 'a'
1105x # : Int32 | String | Char
1106
1107abstract class Animal
1108  # Makes this animal talk
1109  abstract def talk
1110end
1111
1112class Dog < Animal
1113  def talk
1114    "Woof!"
1115  end
1116end
1117
1118class Cat < Animal
1119  def talk
1120    "Miau"
1121  end
1122end
1123
1124class Person
1125  getter pet
1126
1127  def initialize(@name, @pet)
1128  end
1129end
1130
1131john = Person.new "John", Dog.new
1132peter = Person.new "Peter", Cat.new
1133
1134john.pet.talk # => "Woof!"
1135
1136a = 1 > 2 ? 3 : 4
1137
1138# The above is the same as:
1139a = if 1 > 2
1140      3
1141    else
1142      4
1143    end
1144
1145def some_method : String
1146  "hello"
1147end
1148
1149PI = 3.14
1150
1151module Earth
1152  RADIUS = 6_371_000
1153end
1154
1155PI            # => 3.14
1156Earth::RADIUS # => 6_371_000
1157
1158TEN = begin
1159  a = 0
1160  while a < 10
1161    a += 1
1162  end
1163  a
1164end
1165
1166TEN # => 10
1167
1168class Person
1169  getter name
1170
1171  def initialize(@name)
1172    @age = 0
1173  end
1174end
1175
1176john = Person.new "John"
1177john.name      # => "John"
1178john.name.size # => 4
1179
1180one = Person.new 1
1181one.name     # => 1
1182one.name + 2 # => 3
1183
1184john = Person.new "John"
1185one = Person.new 1
1186
1187john = Person.new "John"
1188one = Person.new 1
1189
1190# Error: undefined method 'size' for Int32
1191john.name.size
1192
1193# Error: no overload matches 'String#+' with types Int32
1194john.name + 3
1195
1196john = Person.new "John"
1197john.name.size
1198one = Person.new 1
1199
1200class Person
1201  getter name
1202
1203  def initialize(@name)
1204    @age = 0
1205  end
1206
1207  def address
1208    @address
1209  end
1210
1211  def address=(@address)
1212  end
1213end
1214
1215john = Person.new "John"
1216john.address = "Argentina"
1217
1218# Error: undefined method 'size' for Nil
1219john.address.size
1220
1221class Person
1222  @age = 0
1223
1224  def initialize(@name)
1225  end
1226end
1227
1228class Person
1229  @age : Int32
1230
1231  def initialize(@name)
1232    @age = 0
1233  end
1234end
1235
1236a = if 2 > 1
1237      3
1238    else
1239      4
1240    end
1241a # => 3
1242
1243if 1 > 2
1244else
1245  3
1246end
1247
1248def twice(&block)
1249  yield
1250  yield
1251end
1252
1253twice() do
1254  puts "Hello!"
1255end
1256
1257twice do
1258  puts "Hello!"
1259end
1260
1261twice { puts "Hello!" }
1262
1263def twice
1264  yield 1
1265  yield 2
1266end
1267
1268twice do |i|
1269  puts "Got #{i}"
1270end
1271
1272twice { |i| puts "Got #{i}" }
1273
1274def many
1275  yield 1, 2, 3
1276end
1277
1278many do |x, y, z|
1279  puts x + y + z
1280end
1281
1282# Output: 6
1283
1284def many
1285  yield 1, 2, 3
1286end
1287
1288many do |x, y|
1289  puts x + y
1290end
1291
1292# Output: 3
1293
1294def twice
1295  yield
1296  yield
1297end
1298
1299twice do |i|
1300  puts i.inspect
1301end
1302
1303def some
1304  yield 1, 'a'
1305  yield true, "hello"
1306  yield 2
1307end
1308
1309some do |first, second|
1310  # first is Int32 | Bool
1311  # second is Char | String | Nil
1312end
1313
1314method do |argument|
1315  argument.some_method
1316end
1317
1318method(&.some_method)
1319
1320method &.some_method(arg1, arg2)
1321
1322method &.+(2)
1323method &.[index]
1324
1325def twice
1326  v1 = yield 1
1327  puts v1
1328
1329  v2 = yield 2
1330  puts v2
1331end
1332
1333twice do |i|
1334  i + 1
1335end
1336
1337ary = [1, 2, 3]
1338ary.map { |x| x + 1 }         # => [2, 3, 4]
1339ary.select { |x| x % 2 == 1 } # => [1, 3]
1340
1341def transform(value)
1342  yield value
1343end
1344
1345transform(1) { |x| x + 1 } # => 2
1346
1347def thrice
1348  puts "Before 1"
1349  yield 1
1350  puts "Before 2"
1351  yield 2
1352  puts "Before 3"
1353  yield 3
1354  puts "After 3"
1355end
1356
1357thrice do |i|
1358  if i == 2
1359    break
1360  end
1361end
1362
1363def twice
1364  yield 1
1365  yield 2
1366end
1367
1368twice { |i| i + 1 }         # => 3
1369twice { |i| break "hello" } # => "hello"
1370
1371value = twice do |i|
1372  if i == 1
1373    break "hello"
1374  end
1375  i + 1
1376end
1377value # :: Int32 | String
1378
1379values = twice { break 1, 2 }
1380values # => {1, 2}
1381
1382value = twice { break }
1383value # => nil
1384
1385def twice
1386  yield 1
1387  yield 2
1388end
1389
1390twice do |i|
1391  if i == 1
1392    puts "Skipping 1"
1393    next
1394  end
1395
1396  puts "Got #{i}"
1397end
1398
1399def twice
1400  v1 = yield 1
1401  puts v1
1402
1403  v2 = yield 2
1404  puts v2
1405end
1406
1407twice do |i|
1408  if i == 1
1409    next 10
1410  end
1411
1412  i + 1
1413end
1414
1415# Output
1416# 10
1417# 3
1418
1419class Foo
1420  def one
1421    1
1422  end
1423
1424  def yield_with_self
1425    with self yield
1426  end
1427
1428  def yield_normally
1429    yield
1430  end
1431end
1432
1433def one
1434  "one"
1435end
1436
1437Foo.new.yield_with_self { one } # => 1
1438Foo.new.yield_normally { one }  # => "one"
1439
1440def twice
1441  yield 1
1442  yield 2
1443end
1444
1445twice do |i|
1446  puts "Got: #{i}"
1447end
1448
1449i = 1
1450puts "Got: #{i}"
1451i = 2
1452puts "Got: #{i}"
1453
14543.times do |i|
1455  puts i
1456end
1457
1458struct Int
1459  def times
1460    i = 0
1461    while i < self
1462      yield i
1463      i += 1
1464    end
1465  end
1466end
1467
1468i = 0
1469while i < 3
1470  puts i
1471  i += 1
1472end
1473
1474class Person
1475  def initialize(@name)
1476  end
1477
1478  def greet
1479    puts "Hi, I'm #{@name}"
1480  end
1481end
1482
1483class Employee < Person
1484end
1485
1486employee = Employee.new "John"
1487employee.greet # "Hi, I'm John"
1488
1489class Person
1490  def initialize(@name)
1491  end
1492end
1493
1494class Employee < Person
1495  def initialize(@name, @company_name)
1496  end
1497end
1498
1499Employee.new "John", "Acme" # OK
1500Employee.new "Peter"        # Error: wrong number of arguments
1501# for 'Employee:Class#new' (1 for 2)
1502
1503class Person
1504  def greet(msg)
1505    puts "Hi, #{msg}"
1506  end
1507end
1508
1509class Employee < Person
1510  def greet(msg)
1511    puts "Hello, #{msg}"
1512  end
1513end
1514
1515p = Person.new
1516p.greet "everyone" # "Hi, everyone"
1517
1518e = Employee.new
1519e.greet "everyone" # "Hello, everyone"
1520
1521class Person
1522  def greet(msg)
1523    puts "Hi, #{msg}"
1524  end
1525end
1526
1527class Employee < Person
1528  def greet(msg : Int32)
1529    puts "Hi, this is a number: #{msg}"
1530  end
1531end
1532
1533e = Employee.new
1534e.greet "everyone" # "Hi, everyone"
1535
1536e.greet 1 # "Hi, this is a number: 1"
1537
1538class Person
1539  def greet(msg)
1540    puts "Hello, " # {msg}"
1541  end
1542end
1543
1544class Employee < Person
1545  def greet(msg)
1546    super # Same as: super(msg)
1547    super("another message")
1548  end
1549end
1550
1551def int_to_int(&block : Int32 -> Int32)
1552  block
1553end
1554
1555proc = int_to_int { |x| x + 1 }
1556proc.call(1) # => 2
1557
1558class Model
1559  def on_save(&block)
1560    @on_save_callback = block
1561  end
1562
1563  def save
1564    if callback = @on_save_callback
1565      callback.call
1566    end
1567  end
1568end
1569
1570model = Model.new
1571model.on_save { puts "Saved!" }
1572model.save # prints "Saved!"
1573
1574def some_proc(&block : Int32 ->)
1575  block
1576end
1577
1578proc = some_proc { |x| x + 1 }
1579proc.call(1) # void
1580
1581def some_proc(&block : Int32 -> _)
1582  block
1583end
1584
1585proc = some_proc { |x| x + 1 }
1586proc.call(1) # 2
1587
1588proc = some_proc { |x| x.to_s }
1589proc.call(1) # "1"
1590
1591macro update_x
1592  x = 1
1593end
1594
1595x = 0
1596update_x
1597x # => 1
1598
1599macro dont_update_x
1600  %x = 1
1601  puts %x
1602end
1603
1604x = 0
1605dont_update_x # outputs 1
1606x             # => 0
1607
1608macro fresh_vars_sample(*names)
1609  # First declare vars
1610  {% for name, index in names %}
1611    print "Declaring: ", "%name{index}", '\n'
1612    %name{index} = {{index}}
1613  {% end %}
1614
1615  # Then print them
1616  {% for name, index in names %}
1617    print "%name{index}: ", %name{index}, '\n'
1618  {% end %}
1619end
1620
1621fresh_vars_sample a, b, c
1622
1623# Sample output:
1624# Declaring: __temp_255
1625# Declaring: __temp_256
1626# Declaring: __temp_257
1627# __temp_255: 0
1628# __temp_256: 1
1629# __temp_257: 2
1630
1631class Object
1632  macro instance_vars_names
1633    def instance_vars_names : Array(String)
1634      {{ @type.instance_vars.map &.name.stringify }}
1635    end
1636  end
1637end
1638
1639class Person
1640  def initialize(@name, @age)
1641  end
1642end
1643
1644person = Person.new "John", 30
1645person.instance_vars_names # => ["name", "age"]
1646
1647class Object
1648  macro has_instance_var?(name)
1649    def has_instance_var?(name) : Bool
1650      # We cannot access name inside the macro expansion here,
1651      # instead we need to use the macro language to construct an array
1652      # and do the inclusion check at runtime.
1653      {{ @type.instance_vars.map &.name.stringify }}.includes? name
1654    end
1655  end
1656end
1657
1658person = Person.new "John", 30
1659person.has_instance_var?("name")     # => true
1660person.has_instance_var?("birthday") # => false
1661
1662class Parent
1663  macro inherited
1664    def {{@type.name.downcase.id}}
1665      1
1666    end
1667  end
1668end
1669
1670class Child < Parent
1671end
1672
1673Child.new.child # => 1
1674
1675macro method_missing(name, args, block)
1676  print "Got ", {{name.id.stringify}}, " with ", {{args.size}}, " arguments", '\n'
1677end
1678
1679foo          # Prints: Got foo with 0 arguments
1680bar 'a', 'b' # Prints: Got bar with 2 arguments
1681
1682sizeof(Int32) # => 4
1683sizeof(Int64) # => 8
1684
1685# On a 64 bits machine
1686sizeof(Pointer(Int32)) # => 8
1687sizeof(String)         # => 8
1688
1689a = 1
1690sizeof(typeof(a)) # => 4
1691
1692class Foo
1693  macro emphasize(value)
1694    "***#{ {{value}} }***"
1695  end
1696
1697  def yield_with_self
1698    with self yield
1699  end
1700end
1701
1702Foo.new.yield_with_self { emphasize(10) } # => "***10***"
1703
1704# This generates:
1705#
1706#     def :foo
1707#       1
1708#     end
1709define_method :foo, 1
1710
1711macro define_method(name, content)
1712  def {{name.id}}
1713    {{content}}
1714  end
1715end
1716
1717# This correctly generates:
1718#
1719#     def foo
1720#       1
1721#     end
1722define_method :foo, 1
1723
1724macro define_method(name, content)
1725  def {{name}}
1726    {% if content == 1 %}
1727      "one"
1728    {% else %}
1729      {{content}}
1730    {% end %}
1731  end
1732end
1733
1734define_method foo, 1
1735define_method bar, 2
1736
1737foo # => one
1738bar # => 2
1739
1740{% if env("TEST") %}
1741  puts "We are in test mode"
1742{% end %}
1743
1744macro define_dummy_methods(names)
1745  {% for name, index in names %}
1746    def {{name.id}}
1747      {{index}}
1748    end
1749  {% end %}
1750end
1751
1752define_dummy_methods [foo, bar, baz]
1753
1754foo # => 0
1755bar # => 1
1756baz # => 2
1757
1758macro define_dummy_methods(hash)
1759  {% for key, value in hash %}
1760    def {{key.id}}
1761      {{value}}
1762    end
1763  {% end %}
1764end
1765
1766define_dummy_methods({foo: 10, bar: 20})
1767foo # => 10
1768bar # => 20
1769
1770{% for name, index in ["foo", "bar", "baz"] %}
1771  def {{name.id}}
1772    {{index}}
1773  end
1774{% end %}
1775
1776foo # => 0
1777bar # => 1
1778baz # => 2
1779
1780macro define_dummy_methods(*names)
1781  {% for name, index in names %}
1782    def {{name.id}}
1783      {{index}}
1784    end
1785  {% end %}
1786end
1787
1788define_dummy_methods foo, bar, baz
1789
1790foo # => 0
1791bar # => 1
1792baz # => 2
1793
1794macro println(*values)
1795   print {{*values}}, '\n'
1796end
1797
1798println 1, 2, 3 # outputs 123\n
1799
1800VALUES = [1, 2, 3]
1801
1802{% for value in VALUES %}
1803  puts {{value}}
1804{% end %}
1805
1806until some_condition
1807  do_this
1808end
1809
1810# The above is the same as:
1811while !some_condition
1812  do_this
1813end
1814
1815a = some_condition ? nil : 3
1816# a is Int32 or Nil
1817
1818if a
1819  # Since the only way to get here is if a is truthy,
1820  # a can't be nil. So here a is Int32.
1821  a.abs
1822end
1823
1824if a = some_expression
1825  # here a is not nil
1826end
1827
1828if a && b
1829  # here both a and b are guaranteed not to be Nil
1830end
1831
1832if @a
1833  # here @a can be nil
1834end
1835
1836# First option: assign it to a variable
1837if a = @a
1838  # here a can't be nil
1839end
1840
1841# Second option: use `Object#try` found in the standard library
1842@a.try do |a|
1843  # here a can't be nil
1844end
1845
1846if method # first call to a method that can return Int32 or Nil
1847  # here we know that the first call did not return Nil
1848  method # second call can still return Int32 or Nil
1849end
1850
1851class Person
1852  def become_older(by = 1)
1853    @age += by
1854  end
1855end
1856
1857john = Person.new "John"
1858john.age # => 0
1859
1860john.become_older
1861john.age # => 1
1862
1863john.become_older 2
1864john.age # => 3
1865
1866john.become_older by: 5
1867
1868def some_method(x, y = 1, z = 2, w = 3)
1869  # do something...
1870end
1871
1872some_method 10                   # x = 10, y = 1, z = 2, w = 3
1873some_method 10, z: 10            # x = 10, y = 1, z = 10, w = 3
1874some_method 10, w: 1, y: 2, z: 3 # x = 10, y = 2, z = 3, w = 1
1875
1876case exp
1877when value1, value2
1878  do_something
1879when value3
1880  do_something_else
1881else
1882  do_another_thing
1883end
1884
1885case var
1886when String
1887  # var : String
1888  do_something
1889when Int32
1890  # var : Int32
1891  do_something_else
1892else
1893  # here var is neither a String nor an Int32
1894  do_another_thing
1895end
1896
1897case num
1898when .even?
1899  do_something
1900when .odd?
1901  do_something_else
1902end
1903
1904case
1905when cond1, cond2
1906  do_something
1907when cond3
1908  do_something_else
1909end
1910
1911a = 1
1912a.responds_to?(:abs)  # => true
1913a.responds_to?(:size) # => false
1914
1915foo_or_bar = /foo|bar/
1916heeello = /h(e+)llo/
1917integer = /\d+/
1918
1919r = /foo/imx
1920
1921slash = /\//
1922
1923r = %r(regex with slash: /)
1924
1925"hello world"
1926
1927"\"" # double quote
1928"\\" # backslash
1929"\e" # escape
1930"\f" # form feed
1931"\n" # newline
1932"\r" # carriage return
1933"\t" # tab
1934"\v" # vertical tab
1935
1936"\101" # == "A"
1937"\123" # == "S"
1938"\12"  # == "\n"
1939"\1"   # string with one character with code point 1
1940
1941"\u0041" # == "A"
1942
1943"\u{41}"    # == "A"
1944"\u{1F52E}" # == "��"
1945
1946"hello
1947      world" # same as "hello\n      world"
1948
1949"hello " \
1950"world, " \
1951"no newlines" # same as "hello world, no newlines"
1952
1953"hello \
1954     world, \
1955     no newlines" # same as "hello world, no newlines"
1956
1957# Supports double quotes and nested parenthesis
1958%(hello ("world")) # same as "hello (\"world\")"
1959
1960# Supports double quotes and nested brackets
1961%[hello ["world"]] # same as "hello [\"world\"]"
1962
1963# Supports double quotes and nested curlies
1964%{hello {"world"}} # same as "hello {\"world\"}"
1965
1966# Supports double quotes and nested angles
1967%<hello <"world">> # same as "hello <\"world\">"
1968
1969<<-XML
1970<parent>
1971  <child />
1972</parent>
1973XML
1974
1975# Same as "Hello\n  world"
1976<<-STRING
1977  Hello
1978    world
1979  STRING
1980
1981# Same as "  Hello\n    world"
1982<<-STRING
1983    Hello
1984      world
1985  STRING
1986
1987a = 1
1988b = 2
1989"sum = #{a + b}" # "sum = 3"
1990
19911.0     # Float64
19921.0_f32 # Float32
19931_f32   # Float32
1994
19951e10   # Float64
19961.5e10 # Float64
19971.5e-7 # Float64
1998
1999+1.3 # Float64
2000-0.5 # Float64
2001
20021_000_000.111_111 # better than 1000000.111111
2003
2004'a'
2005'z'
2006'0'
2007'_'
2008"あ"
2009
2010'\'' # single quote
2011'\\' # backslash
2012'\e' # escape
2013'\f' # form feed
2014'\n' # newline
2015'\r' # carriage return
2016'\t' # tab
2017'\v' # vertical tab
2018
2019"\101" # == 'A'
2020"\123" # == 'S'
2021"\12"  # == '\n'
2022"\1"   # code point 1
2023
2024'\u0041' # == 'A'
2025
2026'\u{41}'    # == 'A'
2027'\u{1F52E}' # == '��'
2028
2029{1 => 2, 3 => 4}   # Hash(Int32, Int32)
2030{1 => 2, 'a' => 3} # Hash(Int32 | Char, Int32)
2031
2032{} of Int32 => Int32 # same as Hash(Int32, Int32).new
2033
2034{key1: 'a', key2: 'b'} # Hash(Symbol, Char)
2035
2036{"key1": 'a', "key2": 'b'} # Hash(String, Char)
2037
2038MyType{"foo" => "bar"}
2039
2040tmp = MyType.new
2041tmp["foo"] = "bar"
2042tmp
2043
2044tmp = MyType(typeof("foo"), typeof("bar")).new
2045tmp["foo"] = "bar"
2046tmp
2047
2048MyType(String, String){"foo" => "bar"}
2049
2050:hello
2051:good_bye
2052
2053# With spaces and symbols
2054:"symbol with spaces"
2055
2056# Ending with question and exclamation marks
2057:question?
2058:exclamation!
2059
2060# For the operators
2061:+
2062:-
2063:*
2064:/
2065:==
2066:<
2067:<=
2068:>
2069:>=
2070:!
2071:!=
2072:=~
2073:!~
2074:&
2075:|
2076:^
2077:~
2078:**
2079:>>
2080:<<
2081:%
2082:[]
2083:[]?
2084:[]=
2085:<=>
2086:===
2087
2088x..y  # an inclusive range, in mathematics: [x, y]
2089x...y # an exclusive range, in mathematics: [x, y)
2090
2091# A proc without arguments
2092->{ 1 } # Proc(Int32)
2093
2094# A proc with one argument
2095->(x : Int32) { x.to_s } # Proc(Int32, String)
2096
2097# A proc with two arguments:
2098->(x : Int32, y : Int32) { x + y } # Proc(Int32, Int32, Int32)
2099
2100Proc(Int32, String).new { |x| x.to_s } # Proc(Int32, String)
2101
2102proc = ->(x : Int32, y : Int32) { x + y }
2103proc.call(1, 2) # => 3
2104
2105def one
2106  1
2107end
2108
2109proc = ->one
2110proc.call # => 1
2111
2112def plus_one(x)
2113  x + 1
2114end
2115
2116proc = ->plus_one(Int32)
2117proc.call(41) # => 42
2118
2119str = "hello"
2120proc = ->str.count(Char)
2121proc.call('e') # => 1
2122proc.call('l') # => 2
2123
2124tuple = {1, "hello", 'x'} # Tuple(Int32, String, Char)
2125tuple[0]                  # => 1       (Int32)
2126tuple[1]                  # => "hello" (String)
2127tuple[2]                  # => 'x'     (Char)
2128
2129[1, 2, 3]         # Array(Int32)
2130[1, "hello", 'x'] # Array(Int32 | String | Char)
2131
2132[] of Int32 # same as Array(Int32).new
2133
2134%w(one two three) # ["one", "two", "three"]
2135
2136%i(one two three) # [:one, :two, :three]
2137
2138MyType{1, 2, 3}
2139
2140tmp = MyType.new
2141tmp << 1
2142tmp << 2
2143tmp << 3
2144tmp
2145
2146tmp = MyType(typeof(1, 2, 3)).new
2147tmp << 1
2148tmp << 2
2149tmp << 3
2150tmp
2151
2152MyType(Int32 | String){1, 2, "foo"}
2153
2154nil
2155
21561 # Int32
2157
21581_i8  # Int8
21591_i16 # Int16
21601_i32 # Int32
21611_i64 # Int64
2162
21631_u8  # UInt8
21641_u16 # UInt16
21651_u32 # UInt32
21661_u64 # UInt64
2167
2168+10 # Int32
2169-20 # Int32
2170
21712147483648          # Int64
21729223372036854775808 # UInt64
2173
21741_000_000 # better than 1000000
2175
21760b1101 # == 13
2177
21780o123 # == 83
2179
21800xFE012D # == 16646445
21810xfe012d # == 16646445
2182
2183true  # A Bool that is true
2184false # A Bool that is false
2185
2186a = 1
2187
2188ptr = pointerof(a)
2189ptr.value = 2
2190
2191a # => 2
2192
2193class Point
2194  def initialize(@x, @y)
2195  end
2196
2197  def x
2198    @x
2199  end
2200
2201  def x_ptr
2202    pointerof(@x)
2203  end
2204end
2205
2206point = Point.new 1, 2
2207
2208ptr = point.x_ptr
2209ptr.value = 10
2210
2211point.x # => 10
2212
2213def add(x : Number, y : Number)
2214  x + y
2215end
2216
2217# Ok
2218add 1, 2 # Ok
2219
2220# Error: no overload matches 'add' with types Bool, Bool
2221add true, false
2222
2223def add(x, y)
2224  x + y
2225end
2226
2227add true, false
2228
2229# A class that has a + method but isn't a Number
2230class Six
2231  def +(other)
2232    6 + other
2233  end
2234end
2235
2236# add method without type restrictions
2237def add(x, y)
2238  x + y
2239end
2240
2241# OK
2242add Six.new, 10
2243
2244# add method with type restrictions
2245def restricted_add(x : Number, y : Number)
2246  x + y
2247end
2248
2249# Error: no overload matches 'restricted_add' with types Six, Int32
2250restricted_add Six.new, 10
2251
2252class Person
2253  def ==(other : self)
2254    other.name == name
2255  end
2256
2257  def ==(other)
2258    false
2259  end
2260end
2261
2262john = Person.new "John"
2263another_john = Person.new "John"
2264peter = Person.new "Peter"
2265
2266john == another_john # => true
2267john == peter        # => false (names differ)
2268john == 1            # => false (because 1 is not a Person)
2269
2270class Person
2271  def self.compare(p1 : self, p2 : self)
2272    p1.name == p2.name
2273  end
2274end
2275
2276john = Person.new "John"
2277peter = Person.new "Peter"
2278
2279Person.compare(john, peter) # OK
2280
2281def foo(x : Int32)
2282end
2283
2284foo 1       # OK
2285foo "hello" # Error
2286
2287def foo(x : Int32.class)
2288end
2289
2290foo Int32  # OK
2291foo String # Error
2292
2293def foo(x : Int32.class)
2294  puts "Got Int32"
2295end
2296
2297def foo(x : String.class)
2298  puts "Got String"
2299end
2300
2301foo Int32  # prints "Got Int32"
2302foo String # prints "Got String"
2303
2304def foo(*args : Int32)
2305end
2306
2307def foo(*args : String)
2308end
2309
2310foo 1, 2, 3       # OK, invokes first overload
2311foo "a", "b", "c" # OK, invokes second overload
2312foo 1, 2, "hello" # Error
2313foo()             # Error
2314
2315def foo
2316  # This is the empty-tuple case
2317end
2318
2319def foo(x : T)
2320  T
2321end
2322
2323foo(1)       # => Int32
2324foo("hello") # => String
2325
2326def foo(x : Array(T))
2327  T
2328end
2329
2330foo([1, 2])   # => Int32
2331foo([1, "a"]) # => (Int32 | String)
2332
2333def foo(x : T.class)
2334  Array(T)
2335end
2336
2337foo(Int32)  # => Array(Int32)
2338foo(String) # => Array(String)
2339
2340class Person
2341  # Increases age by one
2342  def become_older
2343    @age += 1
2344  end
2345
2346  # Increases age by the given number of years
2347  def become_older(years : Int32)
2348    @age += years
2349  end
2350
2351  # Increases age by the given number of years, as a String
2352  def become_older(years : String)
2353    @age += years.to_i
2354  end
2355
2356  # Yields the current age of this person and increases
2357  # its age by the value returned by the block
2358  def become_older
2359    @age += yield @age
2360  end
2361end
2362
2363person = Person.new "John"
2364
2365person.become_older
2366person.age # => 1
2367
2368person.become_older 5
2369person.age # => 6
2370
2371person.become_older "12"
2372person.age # => 18
2373
2374person.become_older do |current_age|
2375  current_age < 20 ? 10 : 30
2376end
2377person.age # => 28
2378
2379a = 1
2380a.is_a?(Int32)          # => true
2381a.is_a?(String)         # => false
2382a.is_a?(Number)         # => true
2383a.is_a?(Int32 | String) # => true
2384
2385# One for each thread
2386@[ThreadLocal]
2387values = [] of Int32
2388
2389@[AlwaysInline]
2390def foo
2391  1
2392end
2393
2394@[NoInline]
2395def foo
2396  1
2397end
2398
2399lib LibFoo
2400  @[CallConvention("X86_StdCall")]
2401  fun foo : Int32
2402end
2403
2404def sum(*elements)
2405  total = 0
2406  elements.each do |value|
2407    total += value
2408  end
2409  total
2410end
2411
2412# elements is Tuple(Int32, Int32, Int32, Float64)
2413sum 1, 2, 3, 4.5
2414
2415if a.responds_to?(:abs)
2416  # here a's type will be reduced to those responding to the 'abs' method
2417end
2418
2419a = some_condition ? 1 : "hello"
2420# a : Int32 | String
2421
2422if a.responds_to?(:abs)
2423  # here a will be Int32, since Int32#abs exists but String#abs doesn't
2424else
2425  # here a will be String
2426end
2427
2428if (a = @a).responds_to?(:abs)
2429  # here a is guaranteed to respond to `abs`
2430end
2431
2432def capture(&block)
2433  block
2434end
2435
2436def invoke(&block)
2437  block.call
2438end
2439
2440proc = capture { puts "Hello" }
2441invoke(&proc) # prints "Hello"
2442
2443def capture(&block)
2444  block
2445end
2446
2447def twice
2448  yield
2449  yield
2450end
2451
2452proc = capture { puts "Hello" }
2453twice &proc
2454
2455twice &->{ puts "Hello" }
2456
2457def say_hello
2458  puts "Hello"
2459end
2460
2461twice &->say_hello
2462
2463def foo
2464  yield 1
2465end
2466
2467def wrap_foo
2468  puts "Before foo"
2469  foo do |x|
2470    yield x
2471  end
2472  puts "After foo"
2473end
2474
2475wrap_foo do |i|
2476  puts i
2477end
2478
2479def foo
2480  yield 1
2481end
2482
2483def wrap_foo(&block : Int32 -> _)
2484  puts "Before foo"
2485  foo(&block)
2486  puts "After foo"
2487end
2488
2489wrap_foo do |i|
2490  puts i
2491end
2492
2493foo_forward do |i|
2494  break # error
2495end
2496
2497a = 2
2498while (a += 1) < 20
2499  if a == 10
2500    # goes to 'puts a'
2501    break
2502  end
2503end
2504puts a # => 10
2505
2506class Person
2507  private def say(message)
2508    puts message
2509  end
2510
2511  def say_hello
2512    say "hello"      # OK, no receiver
2513    self.say "hello" # Error, self is a receiver
2514
2515    other = Person.new "Other"
2516    other.say "hello" # Error, other is a receiver
2517  end
2518end
2519
2520class Employee < Person
2521  def say_bye
2522    say "bye" # OK
2523  end
2524end
2525
2526module Namespace
2527  class Foo
2528    protected def foo
2529      puts "Hello"
2530    end
2531  end
2532
2533  class Bar
2534    def bar
2535      # Works, because Foo and Bar are under Namespace
2536      Foo.new.foo
2537    end
2538  end
2539end
2540
2541Namespace::Bar.new.bar
2542
2543class Person
2544  protected def self.say(message)
2545    puts message
2546  end
2547
2548  def say_hello
2549    Person.say "hello"
2550  end
2551end
2552
2553buffer = uninitialized UInt8[256]
2554
2555foo = rand(5) > 1 ? 1 : nil
2556
2557foo.not_nil!.to_i
2558