Class: Opal::Nodes::HashNode

Inherits:
Base
  • Object
show all
Defined in:
opal/lib/opal/nodes/hash.rb

Instance Attribute Summary collapse

Attributes inherited from Base

#compiler, #type

Instance Method Summary collapse

Methods inherited from Base

#add_gvar, #add_ivar, #add_local, #add_temp, #children, children, #class_variable_owner, #closest_module_node, #comments, #compile_to_fragments, #error, #expr, #expr?, #expr_or_nil, #fragment, handle, handlers, #has_rescue_else?, #helper, #in_ensure, #in_ensure?, #in_while?, #process, #push, #recv, #recv?, #s, #scope, #stmt, #stmt?, truthy_optimize?, #unshift, #while_loop, #with_temp, #wrap

Methods included from Helpers

#conditional_send, #current_indent, #empty_line, #indent, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #mid_to_jsid, #property, #valid_name?

Constructor Details

#initializeHashNode

Returns a new instance of HashNode



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'opal/lib/opal/nodes/hash.rb', line 11

def initialize(*)
  super
  @has_kwsplat = false
  @keys = []
  @values = []

  children.each do |child|
    case child.type
    when :kwsplat
      @has_kwsplat = true
    when :pair
      @keys << child.children[0]
      @values << child.children[1]
    end
  end
end

Instance Attribute Details

#has_kwsplatObject

Returns the value of attribute has_kwsplat



9
10
11
# File 'opal/lib/opal/nodes/hash.rb', line 9

def has_kwsplat
  @has_kwsplat
end

#keysObject

Returns the value of attribute keys



9
10
11
# File 'opal/lib/opal/nodes/hash.rb', line 9

def keys
  @keys
end

#valuesObject

Returns the value of attribute values



9
10
11
# File 'opal/lib/opal/nodes/hash.rb', line 9

def values
  @values
end

Instance Method Details

#compileObject



32
33
34
35
36
37
38
39
40
# File 'opal/lib/opal/nodes/hash.rb', line 32

def compile
  if has_kwsplat
    compile_merge
  elsif simple_keys?
    compile_hash2
  else
    compile_hash
  end
end

#compile_hashObject

Compiles a hash without kwsplats with complex keys.



79
80
81
82
83
84
85
86
87
88
89
# File 'opal/lib/opal/nodes/hash.rb', line 79

def compile_hash
  helper :hash

  children.each_with_index do |pair, idx|
    key, value = pair.children
    push ', ' unless idx == 0
    push expr(key), ', ', expr(value)
  end

  wrap '$hash(', ')'
end

#compile_hash2Object

Compiles a hash without kwsplats and containing only string/symbols as keys.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'opal/lib/opal/nodes/hash.rb', line 93

def compile_hash2
  hash_obj, hash_keys = {}, []
  helper :hash2

  keys.size.times do |idx|
    key = keys[idx].children[0].to_s.inspect
    hash_keys << key unless hash_obj.include? key
    hash_obj[key] = expr(values[idx])
  end

  hash_keys.each_with_index do |key, idx|
    push ', ' unless idx == 0
    push "#{key}: "
    push hash_obj[key]
  end

  wrap "$hash2([#{hash_keys.join ', '}], {", "})"
end

#compile_mergeObject

Compiles hashes containing kwsplats inside. hash like { *{ nested: 1 }, a: 1, *{ nested: 2} } should be compiled to { nested: 1}.merge(a: 1).merge(nested: 2) Each kwsplat overrides previosly defined keys Hash k/v pairs override previously defined kwsplat values



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'opal/lib/opal/nodes/hash.rb', line 48

def compile_merge
  helper :hash

  result, seq = [], []

  children.each do |child|
    if child.type == :kwsplat
      unless seq.empty?
        result << expr(s(:hash, *seq))
      end
      result << expr(child)
      seq = []
    else
      seq << child
    end
  end
  unless seq.empty?
    result << expr(s(:hash, *seq))
  end

  result.each_with_index do |fragment, idx|
    if idx == 0
      push fragment
    else
      push ".$merge(", fragment, ")"
    end
  end
end

#simple_keys?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'opal/lib/opal/nodes/hash.rb', line 28

def simple_keys?
  keys.all? { |key| [:sym, :str].include?(key.type) }
end