Class: Opal::Nodes::HashNode

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

Constant Summary

Constants included from Helpers

Opal::Nodes::Helpers::BASIC_IDENTIFIER_RULES, Opal::Nodes::Helpers::ES3_RESERVED_WORD_EXCLUSIVE, Opal::Nodes::Helpers::ES51_RESERVED_WORD, Opal::Nodes::Helpers::IMMUTABLE_PROPS, Opal::Nodes::Helpers::PROTO_SPECIAL_METHODS, Opal::Nodes::Helpers::PROTO_SPECIAL_PROPS, Opal::Nodes::Helpers::RESERVED_FUNCTION_NAMES

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

#current_indent, #empty_line, #indent, #ivar, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #lvar_to_js, #mid_to_jsid, #property, #valid_ivar_name?, #valid_name?, #variable

Constructor Details

#initializeHashNode

Returns a new instance of HashNode



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

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

Instance Attribute Details

#has_kwsplatObject

Returns the value of attribute has_kwsplat



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

def has_kwsplat
  @has_kwsplat
end

#keysObject

Returns the value of attribute keys



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

def keys
  @keys
end

#valuesObject

Returns the value of attribute values



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

def values
  @values
end

Instance Method Details

#compileObject



54
55
56
57
58
59
60
61
62
63
64
# File 'opal/lib/opal/nodes/hash.rb', line 54

def compile
  extract_kv_pairs_and_kwsplats

  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.



103
104
105
106
107
108
109
110
111
112
# File 'opal/lib/opal/nodes/hash.rb', line 103

def compile_hash
  helper :hash

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

  wrap '$hash(', ')'
end

#compile_hash2Object

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



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'opal/lib/opal/nodes/hash.rb', line 116

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

  keys.size.times do |idx|
    key = keys[idx][1].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



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

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

#extract_kv_pairs_and_kwsplatsObject

Splits keys/values/kwsplats

hash like { **{ nested: 1 }, d: 2 } is represetned by sexp: (:hash, (:kwsplat, (:hash, (:sym, :nested), (:int, 1) ) ), (:sym, :d), (:int, 2), ) So k/v pairs and kwsplats can be mixed in any order.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'opal/lib/opal/nodes/hash.rb', line 32

def extract_kv_pairs_and_kwsplats
  found_key = false

  children.each do |obj|
    if obj.type == :kwsplat
      self.has_kwsplat = true
    elsif found_key
      values << obj
      found_key = false
    else
      keys << obj
      found_key = true
    end
  end

  [keys, values]
end

#simple_keys?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'opal/lib/opal/nodes/hash.rb', line 50

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