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

def compile
  if has_kwsplat
    compile_merge
  else
    compile_hash
  end
end

#compile_hashObject

Compiles a hash without kwsplats with simple or complex keys.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'opal/lib/opal/nodes/hash.rb', line 76

def compile_hash
  children.each_with_index do |pair, idx|
    key, value = pair.children
    push ', ' unless idx == 0
    if %i[sym str].include?(key.type)
      push "[#{key.children[0].to_s.inspect}", ', ', expr(value), ']'
    else
      push '[', expr(key), ', ', expr(value), ']'
    end
  end

  if keys.empty?
    push '(new Map())'
  elsif simple_keys?
    wrap '(new Map([', ']))'
  else
    helper :hash_rehash
    wrap '$hash_rehash(new Map([', ']))'
  end
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



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

def compile_merge
  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 int].include?(key.type) }
end