module AutoC::Module::EntityContainer

@private

Constants

CAP

Attributes

name[R]
source_count[RW]
source_threshold[RW]

Public Class Methods

new(name, stateful: true) click to toggle source
# File lib/autoc/module.rb, line 55
def initialize(name, stateful: true)
  @name = name
  @stateful = stateful
end
render(name, **) { |m| ... } click to toggle source
# File lib/autoc/module.rb, line 93
def self.render(name, **, &code)
  m = self.new(name, **)
  yield(m) if block_given?
  m.render
end

Public Instance Methods

<<(entity) click to toggle source
# File lib/autoc/module.rb, line 19
def <<(entity)
  entities << entity
  self
end
digests(= @digests ||= State.new(self).read) click to toggle source
# File lib/autoc/module.rb, line 64
  def digests = @digests ||= State.new(self).read

  def render
    distribute_entities
    header.render
    sources.each(&:render)
    State.new(self).collect.write if stateful?
    self
  end

  def total_entities
    @total_entities ||= begin
      set = ::Set.new
      entities.each { |e| set.merge(e.total_references) }
      set
    end
  end

  private def distribute_entities
    header.entities.merge(total_entities)
    if source_count.nil?
      @source_count = source_threshold.nil? ? 1 : (total_entities.sum(&:complexity).to_f / source_threshold).ceil
    end
    total_entities.each do |e|
      sources.sort! { |lt, rt| lt.complexity <=> rt.complexity }
      sources.first << e
    end
  end

  def self.render(name, **, &code)
    m = self.new(name, **)
    yield(m) if block_given?
    m.render
  end

end
distribute_entities() click to toggle source
# File lib/autoc/module.rb, line 82
        def distribute_entities
  header.entities.merge(total_entities)
  if source_count.nil?
    @source_count = source_threshold.nil? ? 1 : (total_entities.sum(&:complexity).to_f / source_threshold).ceil
  end
  total_entities.each do |e|
    sources.sort! { |lt, rt| lt.complexity <=> rt.complexity }
    sources.first << e
  end
end
entities(= @entities ||= ::Set.new) click to toggle source
# File lib/autoc/module.rb, line 17
  def entities = @entities ||= ::Set.new

  def <<(entity)
    entities << entity
    self
  end

end
header(= @header ||= Header.new(self)) click to toggle source
# File lib/autoc/module.rb, line 60
  def header = @header ||= Header.new(self)

  def sources = @sources ||= (1..source_count).collect { |i| Source.new(self, i) }

  def digests = @digests ||= State.new(self).read

  def render
    distribute_entities
    header.render
    sources.each(&:render)
    State.new(self).collect.write if stateful?
    self
  end

  def total_entities
    @total_entities ||= begin
      set = ::Set.new
      entities.each { |e| set.merge(e.total_references) }
      set
    end
  end

  private def distribute_entities
    header.entities.merge(total_entities)
    if source_count.nil?
      @source_count = source_threshold.nil? ? 1 : (total_entities.sum(&:complexity).to_f / source_threshold).ceil
    end
    total_entities.each do |e|
      sources.sort! { |lt, rt| lt.complexity <=> rt.complexity }
      sources.first << e
    end
  end

  def self.render(name, **, &code)
    m = self.new(name, **)
    yield(m) if block_given?
    m.render
  end

end # Module


# @private
class Module::State < ::Hash

  attr_reader :module

  def file_name = "#{self.module.name}.state"

  def initialize(m)
    super
    @module = m
  end

  def collect
    self[self.module.header.file_name] = self.module.header.digest
    self.module.sources.each { |source| self[source.file_name] = source.digest }
    self
  end

  def read
    if self.module.stateful? && File.exist?(file_name)
      # It's OK not to have this file but if it exists it must have proper contents
      io = File.open(file_name, 'rt', chomp: true)
      begin
        hash = {}
        io.readlines.each do |x|
          raise 'improper state file format' if (/\s*([^\s]+)\s+\*(.*)/ =~ x).nil?
          hash[$2] = $1
        end
        update(hash)
      ensure
        io.close
      end
    end
    self
  end

  def write
    io = File.open(file_name, 'wt')
    begin
      begin
        each { |file_name, digest| io << "#{digest} *#{file_name}\n" }
      ensure
        io.close
      end
    rescue
      File.unlink(file_name) # Delete improperly rendered state file
      raise
    end
    self
  end

end # State


# @private
class Module::StreamFile < File

  def digest = @digest.hexdigest

  def initialize(*args, **kws)
    super(*args, **kws)
    @digest = Digest::MD5.new
  end

  def <<(data)
    super(data)
    @digest.update(data)
    self
  end

end # StreamFile


# @private
module Module::SmartRenderer

  # def render_contents(stream)

  attr_reader :digest

  def render
    io = stream
    _file_name = io.path # Memorize temporary file name
    begin
      begin
        render_contents(io)
        @digest = io.digest
      ensure
        io.close
      end
    rescue
      File.unlink(_file_name) # Remove improperly rendered temporary file
      raise
    else
      if !File.exist?(file_name) || self.module.digests[file_name] != digest
        File.rename(_file_name, file_name) # Rendered temporary has different digest - replace original permanent file with it
      else
        File.unlink(_file_name) # New temporary has the same digest as permanent - no need to replace the latter, delete the temporary instead
      end
    end
  end

end # SmartRenderer


class Module::Header

  include Module::EntityContainer

  include Module::SmartRenderer

  attr_reader :module

  def file_name = @file_name ||= "#{self.module.name}_auto.h"

  def tag = "#{self.module.name}_auto_h".upcase

  def initialize(m) = @module = m

private

  def render_contents(stream)
    render_prologue(stream)
    entities.to_a.sort.each { |e| e.interface.each { |x| stream << x } }
    render_epilogue(stream)
  end

  def render_prologue(stream)
    stream << %{
      #{Module::CAP}
      #ifndef #{tag}
      #define #{tag}
    }
  end

  def render_epilogue(stream)
    stream << %{
      #endif
    }
  end

  def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')

end # Header


class Module::Source

  include Module::EntityContainer

  include Module::SmartRenderer

  attr_reader :module

  attr_reader :complexity

  attr_reader :index

  def file_name = self.module.source_count < 2 ? "#{self.module.name}_auto.c" : "#{self.module.name}_auto#{index}.c"

  def initialize(m, index)
    @module = m
    @complexity = 0
    @index = index
  end

  def <<(entity)
    @complexity += entity.complexity unless entities.include?(entity)
    super
  end

private

  def render_contents(stream)
    render_prologue(stream)
    total_entities = ::Set.new
    entities.each { |e| total_entities.merge(e.total_references) }
    total_entities.to_a.sort.each { |e| e.forward_declarations.each { |x| stream << x } }
    entities.to_a.sort.each { |e| e.implementation.each { |x| stream << x } }
  end

  def render_prologue(stream)
    stream << %{
      #{Module::CAP}
      #include "#{self.module.header.file_name}"
    }
  end

  def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')

end # Source


module Entity

  include ::Comparable

  # A set of the entity's immediate references which, unlike dependencies, do not enforce the entities relative ordering
  def references = @references ||= ReferenceSet.new

  # Return the entire entity's reference set staring with self
  def total_references = @total_references ||= collect_references(::Set.new)

  # A set of the entity's immediate dependencies which enforce the entities relative ordering
  def dependencies = @dependencies ||= DependencySet.new(self)

  # Return the entire entity's dependency set staring with self
  def total_dependencies = @total_dependencies ||= collect_dependencies(::Set.new)

  protected def collect_references(set)
    unless set.include?(self)
      set << self
      references.each { |x| x.collect_references(set) }
    end
    set
  end

  protected def collect_dependencies(set)
    unless set.include?(self)
      set << self
      dependencies.each { |x| x.collect_dependencies(set) }
    end
    set
  end

  def <=>(other) = position <=> other.position

  # Compute the entity's relative position with respect to its dependencies
  def position = @position ||= begin
    p = 0
    # This code goes into infinite recursion on circular dependency
    # which must be resolved manually with Entity#references
    total_dependencies.each do |d|
      unless equal?(d)
        dp = d.position
        p = dp if p < dp # p <- max(p, dp)
      end
    end
    p + 1 # Arrange entity to follow all its dependencies
  end

  def complexity = forward_declarations.complexity + implementation.complexity # Interface part is not considered as it is shared across the sources

  def interface
    @interface ||= begin
      render_interface(stream = Module::Builder.new)
      stream
    end
  end

  def forward_declarations
    @forward_declarations ||= begin
      render_forward_declarations(stream = Module::Builder.new)
      stream
    end
  end

  def implementation
    @implementation ||= begin
      render_implementation(stream = Module::Builder.new)
      stream
    end
  end

private

  ### Overridable rendering methods

  def render_interface(stream) = nil

  def render_forward_declarations(stream) = nil

  def render_implementation(stream) = nil

end # Entity


Entity::ReferenceSet = ::Set


# @private
class Entity::DependencySet < ::Set

  def initialize(entity)
    super()
    @entity = entity
  end

  def <<(x)
    @entity.references << x # Each dependency is also registered as a reference
    super
  end

end # DependencySet


# Helper class to represent plain C side code block
class Code

  include Entity

  def initialize(interface: nil, implementation: nil, definitions: nil)
    @interface_ = interface
    @definitions_ = definitions
    @implementation_ = implementation
  end

  def inspect = "... <#{self.class}>"

private

  def render_interface(stream)
    stream << @interface_ unless @interface_.nil?
  end

  def render_implementation(stream)
    stream << @implementation_ unless @implementation_.nil?
  end

  def render_forward_declarations(stream)
    stream << @definitions_ unless @definitions_.nil?
  end

end # Code


render() click to toggle source
# File lib/autoc/module.rb, line 66
def render
  distribute_entities
  header.render
  sources.each(&:render)
  State.new(self).collect.write if stateful?
  self
end
sources(= @sources ||= (1..source_count).collect { |i| Source.new(self, i) }) click to toggle source
# File lib/autoc/module.rb, line 62
  def sources = @sources ||= (1..source_count).collect { |i| Source.new(self, i) }

  def digests = @digests ||= State.new(self).read

  def render
    distribute_entities
    header.render
    sources.each(&:render)
    State.new(self).collect.write if stateful?
    self
  end

  def total_entities
    @total_entities ||= begin
      set = ::Set.new
      entities.each { |e| set.merge(e.total_references) }
      set
    end
  end

  private def distribute_entities
    header.entities.merge(total_entities)
    if source_count.nil?
      @source_count = source_threshold.nil? ? 1 : (total_entities.sum(&:complexity).to_f / source_threshold).ceil
    end
    total_entities.each do |e|
      sources.sort! { |lt, rt| lt.complexity <=> rt.complexity }
      sources.first << e
    end
  end

  def self.render(name, **, &code)
    m = self.new(name, **)
    yield(m) if block_given?
    m.render
  end

end # Module


# @private
class Module::State < ::Hash

  attr_reader :module

  def file_name = "#{self.module.name}.state"

  def initialize(m)
    super
    @module = m
  end

  def collect
    self[self.module.header.file_name] = self.module.header.digest
    self.module.sources.each { |source| self[source.file_name] = source.digest }
    self
  end

  def read
    if self.module.stateful? && File.exist?(file_name)
      # It's OK not to have this file but if it exists it must have proper contents
      io = File.open(file_name, 'rt', chomp: true)
      begin
        hash = {}
        io.readlines.each do |x|
          raise 'improper state file format' if (/\s*([^\s]+)\s+\*(.*)/ =~ x).nil?
          hash[$2] = $1
        end
        update(hash)
      ensure
        io.close
      end
    end
    self
  end

  def write
    io = File.open(file_name, 'wt')
    begin
      begin
        each { |file_name, digest| io << "#{digest} *#{file_name}\n" }
      ensure
        io.close
      end
    rescue
      File.unlink(file_name) # Delete improperly rendered state file
      raise
    end
    self
  end

end # State


# @private
class Module::StreamFile < File

  def digest = @digest.hexdigest

  def initialize(*args, **kws)
    super(*args, **kws)
    @digest = Digest::MD5.new
  end

  def <<(data)
    super(data)
    @digest.update(data)
    self
  end

end # StreamFile


# @private
module Module::SmartRenderer

  # def render_contents(stream)

  attr_reader :digest

  def render
    io = stream
    _file_name = io.path # Memorize temporary file name
    begin
      begin
        render_contents(io)
        @digest = io.digest
      ensure
        io.close
      end
    rescue
      File.unlink(_file_name) # Remove improperly rendered temporary file
      raise
    else
      if !File.exist?(file_name) || self.module.digests[file_name] != digest
        File.rename(_file_name, file_name) # Rendered temporary has different digest - replace original permanent file with it
      else
        File.unlink(_file_name) # New temporary has the same digest as permanent - no need to replace the latter, delete the temporary instead
      end
    end
  end

end # SmartRenderer


class Module::Header

  include Module::EntityContainer

  include Module::SmartRenderer

  attr_reader :module

  def file_name = @file_name ||= "#{self.module.name}_auto.h"

  def tag = "#{self.module.name}_auto_h".upcase

  def initialize(m) = @module = m

private

  def render_contents(stream)
    render_prologue(stream)
    entities.to_a.sort.each { |e| e.interface.each { |x| stream << x } }
    render_epilogue(stream)
  end

  def render_prologue(stream)
    stream << %{
      #{Module::CAP}
      #ifndef #{tag}
      #define #{tag}
    }
  end

  def render_epilogue(stream)
    stream << %{
      #endif
    }
  end

  def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')

end # Header


class Module::Source

  include Module::EntityContainer

  include Module::SmartRenderer

  attr_reader :module

  attr_reader :complexity

  attr_reader :index

  def file_name = self.module.source_count < 2 ? "#{self.module.name}_auto.c" : "#{self.module.name}_auto#{index}.c"

  def initialize(m, index)
    @module = m
    @complexity = 0
    @index = index
  end

  def <<(entity)
    @complexity += entity.complexity unless entities.include?(entity)
    super
  end

private

  def render_contents(stream)
    render_prologue(stream)
    total_entities = ::Set.new
    entities.each { |e| total_entities.merge(e.total_references) }
    total_entities.to_a.sort.each { |e| e.forward_declarations.each { |x| stream << x } }
    entities.to_a.sort.each { |e| e.implementation.each { |x| stream << x } }
  end

  def render_prologue(stream)
    stream << %{
      #{Module::CAP}
      #include "#{self.module.header.file_name}"
    }
  end

  def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')

end # Source


module Entity

  include ::Comparable

  # A set of the entity's immediate references which, unlike dependencies, do not enforce the entities relative ordering
  def references = @references ||= ReferenceSet.new

  # Return the entire entity's reference set staring with self
  def total_references = @total_references ||= collect_references(::Set.new)

  # A set of the entity's immediate dependencies which enforce the entities relative ordering
  def dependencies = @dependencies ||= DependencySet.new(self)

  # Return the entire entity's dependency set staring with self
  def total_dependencies = @total_dependencies ||= collect_dependencies(::Set.new)

  protected def collect_references(set)
    unless set.include?(self)
      set << self
      references.each { |x| x.collect_references(set) }
    end
    set
  end

  protected def collect_dependencies(set)
    unless set.include?(self)
      set << self
      dependencies.each { |x| x.collect_dependencies(set) }
    end
    set
  end

  def <=>(other) = position <=> other.position

  # Compute the entity's relative position with respect to its dependencies
  def position = @position ||= begin
    p = 0
    # This code goes into infinite recursion on circular dependency
    # which must be resolved manually with Entity#references
    total_dependencies.each do |d|
      unless equal?(d)
        dp = d.position
        p = dp if p < dp # p <- max(p, dp)
      end
    end
    p + 1 # Arrange entity to follow all its dependencies
  end

  def complexity = forward_declarations.complexity + implementation.complexity # Interface part is not considered as it is shared across the sources

  def interface
    @interface ||= begin
      render_interface(stream = Module::Builder.new)
      stream
    end
  end

  def forward_declarations
    @forward_declarations ||= begin
      render_forward_declarations(stream = Module::Builder.new)
      stream
    end
  end

  def implementation
    @implementation ||= begin
      render_implementation(stream = Module::Builder.new)
      stream
    end
  end

private

  ### Overridable rendering methods

  def render_interface(stream) = nil

  def render_forward_declarations(stream) = nil

  def render_implementation(stream) = nil

end # Entity


Entity::ReferenceSet = ::Set


# @private
class Entity::DependencySet < ::Set

  def initialize(entity)
    super()
    @entity = entity
  end

  def <<(x)
    @entity.references << x # Each dependency is also registered as a reference
    super
  end

end # DependencySet


# Helper class to represent plain C side code block
class Code

  include Entity

  def initialize(interface: nil, implementation: nil, definitions: nil)
    @interface_ = interface
    @definitions_ = definitions
    @implementation_ = implementation
  end

  def inspect = "... <#{self.class}>"

private

  def render_interface(stream)
    stream << @interface_ unless @interface_.nil?
  end

  def render_implementation(stream)
    stream << @implementation_ unless @implementation_.nil?
  end

  def render_forward_declarations(stream)
    stream << @definitions_ unless @definitions_.nil?
  end

end # Code


# Helper class to inject a system-wide header into the C side interface part of the module
stateful?(= @stateful == true) click to toggle source
# File lib/autoc/module.rb, line 53
  def stateful? = @stateful == true

  def initialize(name, stateful: true)
    @name = name
    @stateful = stateful
  end

  def header = @header ||= Header.new(self)

  def sources = @sources ||= (1..source_count).collect { |i| Source.new(self, i) }

  def digests = @digests ||= State.new(self).read

  def render
    distribute_entities
    header.render
    sources.each(&:render)
    State.new(self).collect.write if stateful?
    self
  end

  def total_entities
    @total_entities ||= begin
      set = ::Set.new
      entities.each { |e| set.merge(e.total_references) }
      set
    end
  end

  private def distribute_entities
    header.entities.merge(total_entities)
    if source_count.nil?
      @source_count = source_threshold.nil? ? 1 : (total_entities.sum(&:complexity).to_f / source_threshold).ceil
    end
    total_entities.each do |e|
      sources.sort! { |lt, rt| lt.complexity <=> rt.complexity }
      sources.first << e
    end
  end

  def self.render(name, **, &code)
    m = self.new(name, **)
    yield(m) if block_given?
    m.render
  end

end # Module


# @private
class Module::State < ::Hash

  attr_reader :module

  def file_name = "#{self.module.name}.state"

  def initialize(m)
    super
    @module = m
  end

  def collect
    self[self.module.header.file_name] = self.module.header.digest
    self.module.sources.each { |source| self[source.file_name] = source.digest }
    self
  end

  def read
    if self.module.stateful? && File.exist?(file_name)
      # It's OK not to have this file but if it exists it must have proper contents
      io = File.open(file_name, 'rt', chomp: true)
      begin
        hash = {}
        io.readlines.each do |x|
          raise 'improper state file format' if (/\s*([^\s]+)\s+\*(.*)/ =~ x).nil?
          hash[$2] = $1
        end
        update(hash)
      ensure
        io.close
      end
    end
    self
  end

  def write
    io = File.open(file_name, 'wt')
    begin
      begin
        each { |file_name, digest| io << "#{digest} *#{file_name}\n" }
      ensure
        io.close
      end
    rescue
      File.unlink(file_name) # Delete improperly rendered state file
      raise
    end
    self
  end

end # State


# @private
class Module::StreamFile < File

  def digest = @digest.hexdigest

  def initialize(*args, **kws)
    super(*args, **kws)
    @digest = Digest::MD5.new
  end

  def <<(data)
    super(data)
    @digest.update(data)
    self
  end

end # StreamFile


# @private
module Module::SmartRenderer

  # def render_contents(stream)

  attr_reader :digest

  def render
    io = stream
    _file_name = io.path # Memorize temporary file name
    begin
      begin
        render_contents(io)
        @digest = io.digest
      ensure
        io.close
      end
    rescue
      File.unlink(_file_name) # Remove improperly rendered temporary file
      raise
    else
      if !File.exist?(file_name) || self.module.digests[file_name] != digest
        File.rename(_file_name, file_name) # Rendered temporary has different digest - replace original permanent file with it
      else
        File.unlink(_file_name) # New temporary has the same digest as permanent - no need to replace the latter, delete the temporary instead
      end
    end
  end

end # SmartRenderer


class Module::Header

  include Module::EntityContainer

  include Module::SmartRenderer

  attr_reader :module

  def file_name = @file_name ||= "#{self.module.name}_auto.h"

  def tag = "#{self.module.name}_auto_h".upcase

  def initialize(m) = @module = m

private

  def render_contents(stream)
    render_prologue(stream)
    entities.to_a.sort.each { |e| e.interface.each { |x| stream << x } }
    render_epilogue(stream)
  end

  def render_prologue(stream)
    stream << %{
      #{Module::CAP}
      #ifndef #{tag}
      #define #{tag}
    }
  end

  def render_epilogue(stream)
    stream << %{
      #endif
    }
  end

  def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')

end # Header


class Module::Source

  include Module::EntityContainer

  include Module::SmartRenderer

  attr_reader :module

  attr_reader :complexity

  attr_reader :index

  def file_name = self.module.source_count < 2 ? "#{self.module.name}_auto.c" : "#{self.module.name}_auto#{index}.c"

  def initialize(m, index)
    @module = m
    @complexity = 0
    @index = index
  end

  def <<(entity)
    @complexity += entity.complexity unless entities.include?(entity)
    super
  end

private

  def render_contents(stream)
    render_prologue(stream)
    total_entities = ::Set.new
    entities.each { |e| total_entities.merge(e.total_references) }
    total_entities.to_a.sort.each { |e| e.forward_declarations.each { |x| stream << x } }
    entities.to_a.sort.each { |e| e.implementation.each { |x| stream << x } }
  end

  def render_prologue(stream)
    stream << %{
      #{Module::CAP}
      #include "#{self.module.header.file_name}"
    }
  end

  def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')

end # Source


module Entity

  include ::Comparable

  # A set of the entity's immediate references which, unlike dependencies, do not enforce the entities relative ordering
  def references = @references ||= ReferenceSet.new

  # Return the entire entity's reference set staring with self
  def total_references = @total_references ||= collect_references(::Set.new)

  # A set of the entity's immediate dependencies which enforce the entities relative ordering
  def dependencies = @dependencies ||= DependencySet.new(self)

  # Return the entire entity's dependency set staring with self
  def total_dependencies = @total_dependencies ||= collect_dependencies(::Set.new)

  protected def collect_references(set)
    unless set.include?(self)
      set << self
      references.each { |x| x.collect_references(set) }
    end
    set
  end

  protected def collect_dependencies(set)
    unless set.include?(self)
      set << self
      dependencies.each { |x| x.collect_dependencies(set) }
    end
    set
  end

  def <=>(other) = position <=> other.position

  # Compute the entity's relative position with respect to its dependencies
  def position = @position ||= begin
    p = 0
    # This code goes into infinite recursion on circular dependency
    # which must be resolved manually with Entity#references
    total_dependencies.each do |d|
      unless equal?(d)
        dp = d.position
        p = dp if p < dp # p <- max(p, dp)
      end
    end
    p + 1 # Arrange entity to follow all its dependencies
  end

  def complexity = forward_declarations.complexity + implementation.complexity # Interface part is not considered as it is shared across the sources

  def interface
    @interface ||= begin
      render_interface(stream = Module::Builder.new)
      stream
    end
  end

  def forward_declarations
    @forward_declarations ||= begin
      render_forward_declarations(stream = Module::Builder.new)
      stream
    end
  end

  def implementation
    @implementation ||= begin
      render_implementation(stream = Module::Builder.new)
      stream
    end
  end

private

  ### Overridable rendering methods

  def render_interface(stream) = nil

  def render_forward_declarations(stream) = nil

  def render_implementation(stream) = nil

end # Entity


Entity::ReferenceSet = ::Set


# @private
class Entity::DependencySet < ::Set

  def initialize(entity)
    super()
    @entity = entity
  end

  def <<(x)
    @entity.references << x # Each dependency is also registered as a reference
    super
  end

end # DependencySet


# Helper class to represent plain C side code block
class Code

  include Entity

  def initialize(interface: nil, implementation: nil, definitions: nil)
    @interface_ = interface
    @definitions_ = definitions
    @implementation_ = implementation
  end

  def inspect = "... <#{self.class}>"

private

  def render_interface(stream)
    stream << @interface_ unless @interface_.nil?
  end

  def render_implementation(stream)
    stream << @implementation_ unless @implementation_.nil?
  end

  def render_forward_declarations(stream)
    stream << @definitions_ unless @definitions_.nil?
  end

end # Code
total_entities() click to toggle source
# File lib/autoc/module.rb, line 74
def total_entities
  @total_entities ||= begin
    set = ::Set.new
    entities.each { |e| set.merge(e.total_references) }
    set
  end
end