babl-json 0.5.6 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea8f407140ea61dc83be26fece70b85e47280b09
4
- data.tar.gz: d2503155b43b8ae0064d30808c30843c56b25702
3
+ metadata.gz: 3d16dfb585fb3f79b1242b92cd8ddf20663e8f18
4
+ data.tar.gz: 6fb4483228832e5d1016d92ef561c9dca4e34352
5
5
  SHA512:
6
- metadata.gz: 0725f1502d153f9de8dbd126dd3b5c03c9211c696b39a778aa756f9d8bc85f6db4fe10260bd39626edaf71b59d074af20b9af6aba49cba736e0eb72a70aca759
7
- data.tar.gz: 4e213c4de1d6bcd517e7b945b6eb3cd0004891c1356065a2c4716269f669b8fee63049897cbc4c4fc7be504ee8a6b02c209e3ba0a282fe1cd541331efaef2d9f
6
+ metadata.gz: 98ca371092e8bfdb4a49165439521aed3b7456bc350ae8908a700329f9da876133b91ae2c4adf982638f35a31a5d02efe1b540f647bd30f96699c745cf8a6d62
7
+ data.tar.gz: c30279d940b40fd1887a0e28b2885124bc1d84a2faac887dc667caf74ef2ef0dd92f4b4d67da443a3e08ab7197d4f3378003d692fbc3b1b5980a2b384d63168c
@@ -75,12 +75,12 @@ module Babl
75
75
 
76
76
  def template
77
77
  cached = @cached_template
78
- return cached.last if cached && config.using == cached.first
78
+ return cached.last if cached && [config.using].flatten == cached.first
79
79
  # Calling 'using' is a very inefficient operation, because
80
80
  # it creates a new class. We can avoid that cost most of the
81
81
  # time, assuming 'config.using' does not change often (typically
82
82
  # it should only change once at startup)
83
- modules = config.using.dup
83
+ modules = [config.using].flatten.dup
84
84
  template = Template.new.using(*modules)
85
85
  @cached_template = [modules, template]
86
86
  template
@@ -70,16 +70,12 @@ module Babl
70
70
  end
71
71
 
72
72
  def precompile(node)
73
- scope[node]
73
+ @scope[node]
74
74
  end
75
75
 
76
76
  def nest(context)
77
- self.class.new(context) { |node| scope[yield node] }
77
+ self.class.new(context) { |node| @scope[yield node] }
78
78
  end
79
-
80
- private
81
-
82
- attr_reader :scope
83
79
  end
84
80
  end
85
81
  end
@@ -17,33 +17,25 @@ module Babl
17
17
  end
18
18
 
19
19
  def compile(preloader: Rendering::NoopPreloader, pretty: true, optimize: true, lookup_context: nil)
20
- # Compute dependencies & schema on the non-simplified node tree in order
21
- # to catch all errors.
22
20
  tree = precompile(lookup_context: lookup_context)
21
+ tree = tree.optimize if optimize
23
22
  validate(tree)
24
23
 
25
- dependencies = tree.dependencies
26
- schema = tree.schema
27
-
28
- # Recompute dependencies & schema on the simplified tree before
29
- # exposing them to the user.
30
- if optimize
31
- tree = tree.optimize
32
- dependencies = tree.dependencies
33
- schema = tree.schema
34
- end
35
-
36
24
  Rendering::CompiledTemplate.with(
37
25
  preloader: preloader,
38
26
  pretty: pretty,
39
27
  node: tree,
40
- dependencies: dependencies,
41
- schema: schema
28
+ dependencies: tree.dependencies,
29
+ schema: tree.schema
42
30
  )
43
31
  end
44
32
 
33
+ def self.unscoped
34
+ @unscoped ||= new
35
+ end
36
+
45
37
  def unscoped
46
- self.class.new
38
+ self.class.unscoped
47
39
  end
48
40
 
49
41
  protected
@@ -48,11 +48,14 @@ module Babl
48
48
  def optimize_single
49
49
  return unless nodes.size == 1
50
50
  optimized = nodes.first.optimize
51
- case
52
- when FixedArray === optimized
53
- optimized
54
- when Constant === optimized
55
- optimized.value.nil? ? FixedArray::EMPTY : optimized
51
+
52
+ case optimized
53
+ when FixedArray then optimized
54
+ when Constant
55
+ case optimized.value
56
+ when ::Array then optimized
57
+ when ::NilClass then FixedArray::EMPTY
58
+ end
56
59
  end
57
60
  end
58
61
 
@@ -45,11 +45,14 @@ module Babl
45
45
  def optimize_single
46
46
  return unless nodes.size == 1
47
47
  optimized = nodes.first.optimize
48
- case
49
- when Object === optimized
50
- optimized
51
- when Constant === optimized
52
- optimized.value.nil? ? Object::EMPTY : optimized
48
+
49
+ case optimized
50
+ when Object then optimized
51
+ when Constant
52
+ case optimized.value
53
+ when ::Hash then optimized
54
+ when ::NilClass then Object::EMPTY
55
+ end
53
56
  end
54
57
  end
55
58
 
@@ -26,7 +26,7 @@ module Babl
26
26
 
27
27
  memoize def optimize
28
28
  optimized = node.optimize
29
- return optimized if Constant === optimized
29
+ return optimized if Constant === optimized || GotoPin === optimized
30
30
  return optimized.node if Parent === optimized
31
31
  return self if optimized.equal?(node)
32
32
  Nav.new(property, optimized)
@@ -21,7 +21,7 @@ module Babl
21
21
 
22
22
  memoize def optimize
23
23
  optimized = node.optimize
24
- return optimized if Constant === optimized
24
+ return optimized if Constant === optimized || GotoPin === optimized
25
25
  return self if optimized.equal?(node)
26
26
  Parent.new(optimized)
27
27
  end
@@ -22,17 +22,31 @@ module Babl
22
22
 
23
23
  memoize def optimize
24
24
  optimized = node.optimize
25
- return optimized if Constant === optimized
25
+ return optimized if Constant === optimized || GotoPin === optimized
26
26
  return optimized.node if Parent === optimized
27
+ return self if nodes.empty?
28
+
27
29
  optimized_nodes = nodes.map(&:optimize)
30
+
31
+ if optimized_nodes.all? { |n| Constant === n }
32
+ value = begin
33
+ block.call(*optimized_nodes.map(&:value))
34
+ rescue StandardError => e
35
+ raise Errors::InvalidTemplate, e.message, e.backtrace
36
+ end
37
+ constant_block = Utils::Proc.constant(value)
38
+ return With.new(optimized, Utils::Array::EMPTY, constant_block)
39
+ end
40
+
28
41
  return self if optimized.equal?(node) && optimized_nodes.each_with_index.all? { |n, idx| n.equal?(nodes[idx]) }
29
42
  With.new(optimized, optimized_nodes, block)
30
43
  end
31
44
 
32
45
  def render(frame)
33
- values = nodes.empty? ? nil : nodes.map { |n| n.render(frame) }
46
+ values = nodes.map { |n| n.render(frame) }
47
+
34
48
  value = begin
35
- nodes.empty? ? frame.object.instance_exec(&block) : block.call(*values)
49
+ block.call(*values)
36
50
  rescue StandardError => e
37
51
  raise Errors::RenderingError, "#{e.message}\n" + frame.formatted_stack(:__block__), e.backtrace
38
52
  end
@@ -10,7 +10,11 @@ module Babl
10
10
  def call(*args, &block)
11
11
  if block
12
12
  raise Errors::InvalidTemplate, 'call() expects no argument when a block is given' unless args.empty?
13
- return with(&block)
13
+
14
+ # The 'block' is wrapped by #selfify such that there is no implicit closure referencing the current
15
+ # template. Ideally, once a template has been compiled, all intermediate template objects should be
16
+ # garbage collectable.
17
+ return with(unscoped, &Utils::Proc.selfify(block))
14
18
  end
15
19
 
16
20
  raise Errors::InvalidTemplate, 'call() expects exactly 1 argument (unless block)' unless args.size == 1
@@ -3,10 +3,12 @@ module Babl
3
3
  module Operators
4
4
  module Extends
5
5
  module DSL
6
- def extends(partial_path, *args)
6
+ def extends(*partial_paths, extended_with)
7
7
  source {
8
- partial_template = partial(partial_path)
9
- args.empty? ? partial_template : merge(partial_template, *args)
8
+ merge(
9
+ *partial_paths.map { |path| partial(path) },
10
+ extended_with
11
+ )
10
12
  }
11
13
  end
12
14
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'babl/utils/array'
3
+ require 'babl/utils/dsl_proxy'
3
4
  require 'babl/utils/hash'
5
+ require 'babl/utils/proc'
4
6
  require 'babl/utils/ref'
5
7
  require 'babl/utils/value'
6
- require 'babl/utils/dsl_proxy'
@@ -4,16 +4,18 @@ module Babl
4
4
  class Hash
5
5
  EMPTY = {}.freeze
6
6
 
7
- def self.deep_merge(*hashes)
8
- filtered_hashes = hashes.reject(&:empty?)
9
- return EMPTY if filtered_hashes.empty?
10
- return filtered_hashes.first if filtered_hashes.size == 1
11
- filtered_hashes.reduce({}) { |out, hash| deep_merge_inplace(out, hash) }
12
- end
7
+ class << self
8
+ def deep_merge(*hashes)
9
+ filtered_hashes = hashes.reject(&:empty?)
10
+ return EMPTY if filtered_hashes.empty?
11
+ return filtered_hashes.first if filtered_hashes.size == 1
12
+ filtered_hashes.reduce({}) { |out, hash| deep_merge_inplace(out, hash) }
13
+ end
13
14
 
14
- def self.deep_merge_inplace(target, source)
15
- source.each { |k, v| target[k] = deep_merge_inplace(target[k] || {}, v) }
16
- target
15
+ def deep_merge_inplace(target, source)
16
+ source.each { |k, v| target[k] = deep_merge_inplace(target[k] || {}, v) }
17
+ target
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Babl
3
+ module Utils
4
+ class Proc
5
+ class << self
6
+ # Wrap a proc in a lambda, so that it is executed in the context of its first (and only) argument.
7
+ def selfify(proc)
8
+ ->(this) { this.instance_exec(&proc) }
9
+ end
10
+
11
+ # Create a lambda returning a constant.
12
+ def constant(value)
13
+ -> { value }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Babl
3
- VERSION = '0.5.6'
3
+ VERSION = '0.5.7'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: babl-json
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frederic Terrazzoni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-05 00:00:00.000000000 Z
11
+ date: 2018-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -195,6 +195,7 @@ files:
195
195
  - lib/babl/utils/array.rb
196
196
  - lib/babl/utils/dsl_proxy.rb
197
197
  - lib/babl/utils/hash.rb
198
+ - lib/babl/utils/proc.rb
198
199
  - lib/babl/utils/ref.rb
199
200
  - lib/babl/utils/value.rb
200
201
  - lib/babl/version.rb