Skip to content

class Crystal::LiteralExpander
inherits Reference

Class methods

.new(program : Program)

View source

Methods

#expand(node : ArrayLiteral)

Convert an array literal to creating an Array and storing the values:

From:

[] of T

To:

Array(T).new

From:

[1, 2, 3]

To:

Array(typeof(1, 2, 3)).new(3) do |buffer|
  buffer[0] = 1
  buffer[1] = 2
  buffer[2] = 3
  3
end
View source

#expand(node)

View source

#expand(node : ProcPointer)

Expand this:

->foo.bar(X, Y)

To this:

tmp = foo
->(x : X, y : Y) { tmp.bar(x, y) }

Expand this:

->Foo.bar(X, Y)

To this:

->(x : X, y : Y) { Foo.bar(x, y) }

Expand this:

->bar(X, Y)

To this:

->(x : X, y : Y) { bar(x, y) }

in case the implicit self is a class or a virtual class.

View source

#expand(node : MultiAssign)

Transform a multi assign into many assigns.

View source

#expand(node : Select)

View source

#expand(node : Case)

Convert a Case into a series of if ... elseif ... end:

From:

case foo
when bar, baz
  1
when bun
  2
else
  3
end

To:

temp = foo
if bar === temp || baz === temp
  1
elsif bun === temp
  2
else
  3
end

But, when the "when" has a constant name, it's transformed to is_a?:

From:

case foo
when Bar
  1
end

To:

temp = foo
if temp.is_a?(Bar)
  1
end

We also take care to expand multiple conds

From:

case {x, y}
when {1, 2}, {3, 4}
  3
end

To:

if (1 === x && y === 2) || (3 === x && 4 === y)
  3
end
View source

#expand(node : StringInterpolation)

Convert an interpolation to a call to String.interpolation

From:

"foo#{bar}baz#{qux}"

To:

String.interpolation("foo", bar, "baz", qux)
View source

#expand(node : RangeLiteral)

Transform a range literal into creating a Range object.

From:

1 .. 3

To:

Range.new(1, 3, true)

From:

1 ... 3

To:

Range.new(1, 3, false)

View source

#expand(node : Or)

Convert or to if

From:

a || b

To:

if temp = a
  temp
else
  b
end
View source

#expand(node : And)

Convert and to if:

From:

a && b

To:

if temp = a
  b
else
  temp
end
View source

#expand(node : RegexLiteral)

From:

/regex/flags

To:

if temp_var = $some_global
  temp_var
else
  $some_global = Regex.new("regex", Regex::Options.new(flags))
end

That is, cache the regex in a global variable.

Only do this for regex literals that don't contain interpolation.

If there's an interpolation, expand to: Regex.new(interpolation, flags)

View source

#expand(node : HashLiteral)

Convert a HashLiteral into creating a Hash and assigning keys and values:

From:

{} of K => V

To:

Hash(K, V).new

From:

{a => b, c => d}

To:

hash = Hash(typeof(a, c), typeof(b, d)).new
hash[a] = b
hash[c] = d
hash
View source

#expand_named(node : ArrayLiteral)

View source

#expand_named(node : HashLiteral)

View source

#new_temp_var

View source

#select_action_name(name)

View source

#transform_multi_assign_target(target, value)

View source

Macros

check_implicit_obj(type)

View source