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, #sexp, #type

Attributes included from Closure::NodeSupport

#closure

Instance Method Summary collapse

Methods inherited from Base

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

Methods included from Closure::NodeSupport

#closure_is?, #compile_catcher, #generate_thrower, #generate_thrower_without_catcher, #in_closure, #pop_closure, #push_closure, #select_closure, #thrower

Methods included from Helpers

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

Constructor Details

#initializeHashNode

Returns a new instance of HashNode.



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

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.



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

def has_kwsplat
  @has_kwsplat
end

#keysObject

Returns the value of attribute keys.



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

def keys
  @keys
end

#valuesObject

Returns the value of attribute values.



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

def values
  @values
end

Instance Method Details

#compileObject



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

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.



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

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.



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

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



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
76
# File 'opal/lib/opal/nodes/hash.rb', line 49

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)


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

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