class Babl::Nodes::Concat

Public Instance Methods

dependencies() click to toggle source
# File lib/babl/nodes/concat.rb, line 9
        def dependencies
    Babl::Utils::Hash.deep_merge(nodes.map(&:dependencies))
end
optimize() click to toggle source
# File lib/babl/nodes/concat.rb, line 21
        def optimize
    optimize_empty ||
        optimize_single ||
        optimize_concatenated_arrays ||
        optimize_preconcat_constant ||
        self
end
pinned_dependencies() click to toggle source
# File lib/babl/nodes/concat.rb, line 13
        def pinned_dependencies
    Babl::Utils::Hash.deep_merge(nodes.map(&:pinned_dependencies))
end
render(frame) click to toggle source
# File lib/babl/nodes/concat.rb, line 29
def render(frame)
    out = []
    nodes.each { |node|
        values = node.render(frame)
        case values
        when ::NilClass then nil
        when ::Array then out.concat(values)
        else raise Errors::RenderingError, "Only arrays can be concatenated\n" + frame.formatted_stack
        end
    }
    out
end
schema() click to toggle source
# File lib/babl/nodes/concat.rb, line 17
        def schema
    nodes.map(&:schema).reduce(Schema::FixedArray::EMPTY) { |a, b| merge_doc(a, b) }
end

Private Instance Methods

constant_to_array(constant) click to toggle source
# File lib/babl/nodes/concat.rb, line 84
def constant_to_array(constant)
    case constant.schema
    when Schema::FixedArray
        FixedArray.new(constant.schema.items.each_with_index.map { |item, index|
            Constant.new(constant.value[index], item)
        })
    when Schema::Primitive::NULL
        FixedArray::EMPTY
    end
end
merge_doc(doc1, doc2) click to toggle source

Merging documentations from concatenated hashes is lossy, because neither JSON-Schema or our internal representation of arrays is able to model that.

# File lib/babl/nodes/concat.rb, line 97
def merge_doc(doc1, doc2)
    doc1 = Schema::FixedArray::EMPTY if doc1 == Schema::Primitive::NULL
    doc2 = Schema::FixedArray::EMPTY if doc2 == Schema::Primitive::NULL

    case
    when Schema::Anything === doc1 || Schema::Anything === doc2
        Schema::DynArray.new(Schema::Anything.instance)
    when Schema::FixedArray === doc1 && Schema::FixedArray === doc2
        Schema::FixedArray.new(doc1.items + doc2.items)
    when Schema::AnyOf === doc2
        Schema::AnyOf.canonicalized(doc2.choice_set.map { |c| merge_doc(doc1, c) })
    when Schema::AnyOf === doc1
        Schema::AnyOf.canonicalized(doc1.choice_set.map { |c| merge_doc(c, doc2) })
    when Schema::DynArray === doc1 && Schema::FixedArray === doc2
        Schema::DynArray.new(Schema::AnyOf.canonicalized([doc1.item] + doc2.items))
    when Schema::FixedArray === doc1 && Schema::DynArray === doc2
        Schema::DynArray.new(Schema::AnyOf.canonicalized(doc1.items + [doc2.item]))
    when Schema::DynArray === doc1 && Schema::DynArray === doc2
        Schema::DynArray.new(Schema::AnyOf.canonicalized([doc1.item, doc2.item]))
    else raise Errors::InvalidTemplate, 'Only arrays can be concatenated'
    end
end
optimize_concatenated_arrays() click to toggle source
# File lib/babl/nodes/concat.rb, line 63
def optimize_concatenated_arrays
    optimized_nodes = nodes.map(&:optimize)
    return if optimized_nodes == nodes

    Concat.new(optimized_nodes).optimize
end
optimize_empty() click to toggle source
# File lib/babl/nodes/concat.rb, line 44
def optimize_empty
    Constant.new(Utils::Array::EMPTY, Schema::FixedArray::EMPTY) if nodes.empty?
end
optimize_preconcat_constant() click to toggle source
# File lib/babl/nodes/concat.rb, line 70
def optimize_preconcat_constant
    nodes.each_cons(2).each_with_index do |(obj1, obj2), idx|
        obj1 = constant_to_array(obj1) if Constant === obj1
        obj2 = constant_to_array(obj2) if Constant === obj2
        next unless FixedArray === obj1 && FixedArray === obj2

        new_nodes = nodes.dup
        new_nodes[idx] = FixedArray.new(obj1.nodes + obj2.nodes)
        new_nodes[idx + 1] = nil
        return Concat.new(new_nodes.compact).optimize
    end
    nil
end
optimize_single() click to toggle source
# File lib/babl/nodes/concat.rb, line 48
def optimize_single
    return unless nodes.size == 1

    optimized = nodes.first.optimize

    case optimized
    when FixedArray then optimized
    when Constant
        case optimized.value
        when ::Array then optimized
        when ::NilClass then FixedArray::EMPTY
        end
    end
end