class
Crystal::LiteralExpander
Defined in:
compiler/crystal/semantic/literal_expander.crConstructors
Macro Summary
Instance Method Summary
- #complex_elem_temp_vars(elems : Array, &)
- #complex_elem_temp_vars(elems : Array(ASTNode))
-
#expand(node : ArrayLiteral)
Converts an array literal to creating an Array and storing the values:
-
#expand(node : HashLiteral)
Converts a hash literal into creating a Hash and assigning keys and values.
-
#expand(node : RegexLiteral)
From:
-
#expand(node : And)
Convert and to if:
-
#expand(node : Or)
Convert or to if
-
#expand(node : RangeLiteral)
Transform a range literal into creating a Range object.
-
#expand(node : StringInterpolation)
Convert an interpolation to a call to
String.interpolation -
#expand(node : Case)
Convert a Case into a series of if ...
-
#expand(node : Select)
Convert a
selectstatement into acasestatement based onChannel.select -
#expand(node : MultiAssign)
Transform a multi assign into many assigns.
-
#expand(node : ProcPointer)
Expand this:
- #expand(node)
-
#expand_named(node : ArrayLiteral, generic_type : ASTNode | Nil)
Converts an array-like literal to creating a container and storing the values:
-
#expand_named(node : HashLiteral, generic_type : ASTNode | Nil)
Converts a hash-like literal into creating a Hash and assigning keys and values:
- #new_temp_var(key = nil)
- #select_action_name(name)
- #transform_multi_assign_target(target, value)
- #typeof_exp(node : ArrayLiteral, temp_vars : Array(Var | Nil) | Nil = nil)
Instance methods inherited from class Reference
==(other : self)==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s
Constructor methods inherited from class Reference
new
new,
unsafe_construct(address : Pointer, *args, **opts) : self
unsafe_construct
Class methods inherited from class Reference
pre_initialize(address : Pointer)
pre_initialize
Instance methods inherited from class Object
! : Bool
!,
!=(other)
!=,
!~(other)
!~,
==(other)
==,
===(other : JSON::Any)===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as
Class methods inherited from class Object
from_json(string_or_io : String | IO, root : String)from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml
Macros inherited from class Object
class_getter(*names, &block)
class_getter,
class_getter!(*names)
class_getter!,
class_getter?(*names, &block)
class_getter?,
class_property(*names, &block)
class_property,
class_property!(*names)
class_property!,
class_property?(*names, &block)
class_property?,
class_setter(*names)
class_setter,
def_clone
def_clone,
def_equals(*fields)
def_equals,
def_equals_and_hash(*fields)
def_equals_and_hash,
def_hash(*fields)
def_hash,
delegate(*methods, to object)
delegate,
forward_missing_to(delegate)
forward_missing_to,
getter(*names, &block)
getter,
getter!(*names)
getter!,
getter?(*names, &block)
getter?,
property(*names, &block)
property,
property!(*names)
property!,
property?(*names, &block)
property?,
setter(*names)
setter
Constructor Detail
Macro Detail
Instance Method Detail
Converts an array literal to creating an Array and storing the values:
From:
[] of T
To:
Array(T).new
From:
[1, 2, 3]
To:
ary = ::Array(typeof(1, 2, 3)).unsafe_build(3)
buf = ary.to_unsafe
buf[0] = 1
buf[1] = 2
buf[2] = 3
ary
From:
[1, *exp2, *exp3, 4]
To:
temp1 = exp2
temp2 = exp3
ary = ::Array(typeof(1, ::Enumerable.element_type(temp1), ::Enumerable.element_type(temp2), 4)).new(2)
ary << 1
ary.concat(temp1)
ary.concat(temp2)
ary << 4
ary
Converts a hash literal into creating a Hash and assigning keys and values.
Equivalent to a hash-like literal using ::Hash.
From:
/regex/flags
To declaring a constant with this value (if not already declared):
Regex.new("regex", Regex::Options.new(flags))
and then reading from that constant. That is, we cache regex literals to avoid recompiling them all of the time.
Only do this for regex literals that don't contain interpolation. If there's an interpolation, expand to: Regex.new(interpolation, flags)
Convert and to if:
From:
a && b
To:
if temp = a
b
else
temp
end
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)
Convert an interpolation to a call to String.interpolation
From:
"foo#{bar}baz#{qux}"
To:
String.interpolation("foo", bar, "baz", qux)
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
Convert a select statement into a case statement based on Channel.select
From:
select
when foo then body
when x = bar then x.baz
end
To:
%index, %value = ::Channel.select({foo_select_action, bar_select_action})
case %index
when 0
body
when 1
x = value.as(typeof(foo))
x.baz
else
::raise("BUG: invalid select index")
end
If there's an else branch, use Channel.non_blocking_select.
From:
select
when foo then body
else qux
end
To:
%index, %value = ::Channel.non_blocking_select({foo_select_action})
case %index
when 0
body
else
qux
end
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.
Converts an array-like literal to creating a container and storing the values:
From:
T{1, 2, 3}
To:
ary = T.new
ary << 1
ary << 2
ary << 3
ary
From:
T{1, *exp2, *exp3, 4}
To:
ary = T.new
ary << 1
exp2.each { |v| ary << v }
exp3.each { |v| ary << v }
ary << 4
ary
If T is an uninstantiated generic type, injects a typeof with the
element types.
Converts a hash-like literal into creating a Hash and assigning keys and values:
From:
T{}
To:
T.new
From:
{} of K => V
To:
::Hash(K, V).new
From:
T{a => b, c => d}
To:
hash = T.new
hash[a] = b
hash[c] = d
hash
Or if T is an uninstantiated generic type:
hash = T(typeof(a, c), typeof(b, d)).new
hash[a] = b
hash[c] = d
hash