class AutoC::Value

@private

Attributes

type[R]

Public Class Methods

new(type, constant: false, reference: false) click to toggle source
# File lib/autoc/function.rb, line 26
def initialize(type, constant: false, reference: false)
  @type = type
  @constant = constant
  @reference = reference
end

Public Instance Methods

call(value) click to toggle source
# File lib/autoc/function.rb, line 39
def call(value)
  value = value.to_s
  if reference?
    # Manually collapse references &*xyz -> xyz for the sake of source code readability
    value[0] =='*' ? value[1..-1] : "&#{value}"
  else
    value
  end
end
constant?(= @constant == true) click to toggle source
# File lib/autoc/function.rb, line 22
  def constant? = @constant == true

  def reference? = @reference == true

  def initialize(type, constant: false, reference: false)
    @type = type
    @constant = constant
    @reference = reference
  end

  def to_s = signature

  def signature
    _ = reference? ? "#{type.signature}*" : type.signature
    constant? ? "const #{_}" : _
  end

  def call(value)
    value = value.to_s
    if reference?
      # Manually collapse references &*xyz -> xyz for the sake of source code readability
      value[0] =='*' ? value[1..-1] : "&#{value}"
    else
      value
    end
  end
end # Value


# @private
# Function parameter
class Parameter

  attr_reader :value

  attr_reader :name

  def initialize(value, name)
    @value = value.to_value
    @name = name.to_sym
  end

  def to_s = name.to_s

  def to_value_argument = value.reference? ? "*#{name}" : name

  def signature = value.signature

  def declaration = '%s %s' % [signature, name]

end # Parameter


# Standalone C side function
# The generated function is meant to be the C89-compliant
# NOTE: This function does not track parameter and result types as its dependencies
# This can be done manually by appending to #dependencies property with <<
class Function

  include Entity
  
  attr_reader :name

  attr_reader :result

  attr_reader :parameters

  attr_reader :visibility

  attr_writer :inline

  def initialize(result, name, parameters, inline: false, visibility: :public, constraint: true, variadic: false, abstract: false)
    @name = name.to_s
    @result = result
    @inline = inline
    @visibility = visibility
    @constraint = constraint
    @abstract = abstract
    @variadic = variadic
    @parameters = Parameters.new(self)
    if parameters.is_a?(Hash)
      parameters.each do |name, descriptor|
        x = Parameter.new(descriptor, name)
        @parameters[x.name] = x
      end
    else
      i = -1
      parameters.each do |descriptor|
        x = Parameter.new(descriptor, "_#{i+=1}")
        @parameters[x.name] = x
      end
    end
  end

  def inline_code(code)
    @inline = true
    code(code)
  end

  def external_code(code)
    @inline = false
    code(code)
  end

  def to_s = name

  def header(header) = @header = header

  def code(code) = @code = code

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

  def inline? = @inline == true

  def public? = @visibility == :public

  def private? = @visibility == :private

  def internal? = @visibility == :internal
  
  def abstract? = @abstract == true

  def variadic? = @variadic == true

  def live? = (@constraint.is_a?(Proc) ? @constraint.() : @constraint) == true
  
  def signature = '%s(%s)' % [result, (parameters.to_a.collect(&:signature) << (variadic? ? '...' : nil)).compact.join(',')]

  def prototype = '%s %s(%s)' % [result, name, (parameters.to_a.collect(&:declaration) << (variadic? ? '...' : nil)).compact.join(',')]

  def definition = '%s {%s}' % [prototype, @code]

  def parameter(name) = @values[name]

  def call(*arguments)
    xs = []
    ps = parameters.to_a
    (0...arguments.size).each do |i|
      a = arguments[i]
      v = a.is_a?(Parameter) ? a.to_value_argument : a
      xs << (i < ps.size ? ps[i].value.(v) : v)
    end
    '%s(%s)' % [name, xs.join(',')]
  end

  def configure(&block)
    instance_eval(&block)
    self
  end
  
  # This allows to call other functions with this function's individual parameters as arguments
  # A call to unknown method results in the method's name being emitted
  def method_missing(meth, *args) = parameters.has_key?(meth) ? parameters[meth] : meth

private

  # On function inlining in C: http://www.greenend.org.uk/rjk/tech/inline.html

  # static inline seems to be THE most portable way without resorting to preprocessor
  # but consider the possible code bloat it incurs

  def render_declaration_specifier(stream)
    # The inline specifier is not a part of C89 yet descent compilers do inlining at will
    # given the function definition is available at the function call
    stream << 'static ' if inline?
  end

  # Render the commentary block preceding the function declaration, both inline or external
  def render_function_header(stream)
    if public?
      stream << %{
        /* #{@header} */
      } unless @header.nil?
    else
      stream << Composite::PRIVATE
    end
  end

  # Render full function declaration statement including the commentary block
  # For inline functions this also renders a function body effectively making this also a function definition
  # The declaration comes into either public interface of forward declaration block depending on the function's visibility status
  def render_function_declaration(stream)
    render_function_header(stream) if @render_interface
    render_declaration_specifier(stream)
    if inline?
      render_function_definition(stream)
    else
      stream << prototype << ';'
    end
  end

  # Render function definition, both inline or extern
  # This code never gets into public interface
  def render_function_definition(stream)
    unless abstract?
      raise("missing function definition for #{name}()") if @code.nil?
      stream << definition
    end
  end

  # Render function's public interface
  # Render non-internal function declarations
  # @render_interface is used internally to distinguish header-time rendering from source-time rendering
  def render_interface(stream)
    @render_interface = true
    render_function_declaration(stream) if live? && (public? || private?)
  end

  # Render function's interface for non-public functions which should not appear in the public interface
  def render_forward_declarations(stream)
    @render_interface = false
    render_function_declaration(stream) if live? && !(public? || private?)
  end

  # Render non-inline function definition regardless of function's visibility status
  def render_implementation(stream)
    @render_interface = false
    render_function_definition(stream) if live? && !inline?
  end

end # Function


# @private
# Named parameter list for the function
class Function::Parameters < ::Hash
  def initialize(function)
    @function = function
    super()
  
reference?(= @reference == true) click to toggle source
# File lib/autoc/function.rb, line 24
  def reference? = @reference == true

  def initialize(type, constant: false, reference: false)
    @type = type
    @constant = constant
    @reference = reference
  end

  def to_s = signature

  def signature
    _ = reference? ? "#{type.signature}*" : type.signature
    constant? ? "const #{_}" : _
  end

  def call(value)
    value = value.to_s
    if reference?
      # Manually collapse references &*xyz -> xyz for the sake of source code readability
      value[0] =='*' ? value[1..-1] : "&#{value}"
    else
      value
    end
  end
end # Value


# @private
# Function parameter
class Parameter

  attr_reader :value

  attr_reader :name

  def initialize(value, name)
    @value = value.to_value
    @name = name.to_sym
  end

  def to_s = name.to_s

  def to_value_argument = value.reference? ? "*#{name}" : name

  def signature = value.signature

  def declaration = '%s %s' % [signature, name]

end # Parameter


# Standalone C side function
# The generated function is meant to be the C89-compliant
# NOTE: This function does not track parameter and result types as its dependencies
# This can be done manually by appending to #dependencies property with <<
class Function

  include Entity
  
  attr_reader :name

  attr_reader :result

  attr_reader :parameters

  attr_reader :visibility

  attr_writer :inline

  def initialize(result, name, parameters, inline: false, visibility: :public, constraint: true, variadic: false, abstract: false)
    @name = name.to_s
    @result = result
    @inline = inline
    @visibility = visibility
    @constraint = constraint
    @abstract = abstract
    @variadic = variadic
    @parameters = Parameters.new(self)
    if parameters.is_a?(Hash)
      parameters.each do |name, descriptor|
        x = Parameter.new(descriptor, name)
        @parameters[x.name] = x
      end
    else
      i = -1
      parameters.each do |descriptor|
        x = Parameter.new(descriptor, "_#{i+=1}")
        @parameters[x.name] = x
      end
    end
  end

  def inline_code(code)
    @inline = true
    code(code)
  end

  def external_code(code)
    @inline = false
    code(code)
  end

  def to_s = name

  def header(header) = @header = header

  def code(code) = @code = code

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

  def inline? = @inline == true

  def public? = @visibility == :public

  def private? = @visibility == :private

  def internal? = @visibility == :internal
  
  def abstract? = @abstract == true

  def variadic? = @variadic == true

  def live? = (@constraint.is_a?(Proc) ? @constraint.() : @constraint) == true
  
  def signature = '%s(%s)' % [result, (parameters.to_a.collect(&:signature) << (variadic? ? '...' : nil)).compact.join(',')]

  def prototype = '%s %s(%s)' % [result, name, (parameters.to_a.collect(&:declaration) << (variadic? ? '...' : nil)).compact.join(',')]

  def definition = '%s {%s}' % [prototype, @code]

  def parameter(name) = @values[name]

  def call(*arguments)
    xs = []
    ps = parameters.to_a
    (0...arguments.size).each do |i|
      a = arguments[i]
      v = a.is_a?(Parameter) ? a.to_value_argument : a
      xs << (i < ps.size ? ps[i].value.(v) : v)
    end
    '%s(%s)' % [name, xs.join(',')]
  end

  def configure(&block)
    instance_eval(&block)
    self
  end
  
  # This allows to call other functions with this function's individual parameters as arguments
  # A call to unknown method results in the method's name being emitted
  def method_missing(meth, *args) = parameters.has_key?(meth) ? parameters[meth] : meth

private

  # On function inlining in C: http://www.greenend.org.uk/rjk/tech/inline.html

  # static inline seems to be THE most portable way without resorting to preprocessor
  # but consider the possible code bloat it incurs

  def render_declaration_specifier(stream)
    # The inline specifier is not a part of C89 yet descent compilers do inlining at will
    # given the function definition is available at the function call
    stream << 'static ' if inline?
  end

  # Render the commentary block preceding the function declaration, both inline or external
  def render_function_header(stream)
    if public?
      stream << %{
        /* #{@header} */
      } unless @header.nil?
    else
      stream << Composite::PRIVATE
    end
  end

  # Render full function declaration statement including the commentary block
  # For inline functions this also renders a function body effectively making this also a function definition
  # The declaration comes into either public interface of forward declaration block depending on the function's visibility status
  def render_function_declaration(stream)
    render_function_header(stream) if @render_interface
    render_declaration_specifier(stream)
    if inline?
      render_function_definition(stream)
    else
      stream << prototype << ';'
    end
  end

  # Render function definition, both inline or extern
  # This code never gets into public interface
  def render_function_definition(stream)
    unless abstract?
      raise("missing function definition for #{name}()") if @code.nil?
      stream << definition
    end
  end

  # Render function's public interface
  # Render non-internal function declarations
  # @render_interface is used internally to distinguish header-time rendering from source-time rendering
  def render_interface(stream)
    @render_interface = true
    render_function_declaration(stream) if live? && (public? || private?)
  end

  # Render function's interface for non-public functions which should not appear in the public interface
  def render_forward_declarations(stream)
    @render_interface = false
    render_function_declaration(stream) if live? && !(public? || private?)
  end

  # Render non-inline function definition regardless of function's visibility status
  def render_implementation(stream)
    @render_interface = false
    render_function_definition(stream) if live? && !inline?
  end

end # Function


# @private
# Named parameter list for the function
class Function::Parameters < ::Hash
  def initialize(function)
    @function = function
    super()
  end
signature() click to toggle source
# File lib/autoc/function.rb, line 34
def signature
  _ = reference? ? "#{type.signature}*" : type.signature
  constant? ? "const #{_}" : _
end
to_s(= signature) click to toggle source
# File lib/autoc/function.rb, line 32
  def to_s = signature

  def signature
    _ = reference? ? "#{type.signature}*" : type.signature
    constant? ? "const #{_}" : _
  end

  def call(value)
    value = value.to_s
    if reference?
      # Manually collapse references &*xyz -> xyz for the sake of source code readability
      value[0] =='*' ? value[1..-1] : "&#{value}"
    else
      value
    end
  end
end
to_type(= type) click to toggle source
# File lib/autoc/function.rb, line 18
  def to_type = type

  def to_value = self

  def constant? = @constant == true

  def reference? = @reference == true

  def initialize(type, constant: false, reference: false)
    @type = type
    @constant = constant
    @reference = reference
  end

  def to_s = signature

  def signature
    _ = reference? ? "#{type.signature}*" : type.signature
    constant? ? "const #{_}" : _
  end

  def call(value)
    value = value.to_s
    if reference?
      # Manually collapse references &*xyz -> xyz for the sake of source code readability
      value[0] =='*' ? value[1..-1] : "&#{value}"
    else
      value
    end
  end
end # Value


# @private
# Function parameter
class Parameter

  attr_reader :value

  attr_reader :name

  def initialize(value, name)
    @value = value.to_value
    @name = name.to_sym
  end

  def to_s = name.to_s

  def to_value_argument = value.reference? ? "*#{name}" : name

  def signature = value.signature

  def declaration = '%s %s' % [signature, name]

end # Parameter


# Standalone C side function
# The generated function is meant to be the C89-compliant
# NOTE: This function does not track parameter and result types as its dependencies
# This can be done manually by appending to #dependencies property with <<
class Function

  include Entity
  
  attr_reader :name

  attr_reader :result

  attr_reader :parameters

  attr_reader :visibility

  attr_writer :inline

  def initialize(result, name, parameters, inline: false, visibility: :public, constraint: true, variadic: false, abstract: false)
    @name = name.to_s
    @result = result
    @inline = inline
    @visibility = visibility
    @constraint = constraint
    @abstract = abstract
    @variadic = variadic
    @parameters = Parameters.new(self)
    if parameters.is_a?(Hash)
      parameters.each do |name, descriptor|
        x = Parameter.new(descriptor, name)
        @parameters[x.name] = x
      end
    else
      i = -1
      parameters.each do |descriptor|
        x = Parameter.new(descriptor, "_#{i+=1}")
        @parameters[x.name] = x
      end
    end
  end

  def inline_code(code)
    @inline = true
    code(code)
  end

  def external_code(code)
    @inline = false
    code(code)
  end

  def to_s = name

  def header(header) = @header = header

  def code(code) = @code = code

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

  def inline? = @inline == true

  def public? = @visibility == :public

  def private? = @visibility == :private

  def internal? = @visibility == :internal
  
  def abstract? = @abstract == true

  def variadic? = @variadic == true

  def live? = (@constraint.is_a?(Proc) ? @constraint.() : @constraint) == true
  
  def signature = '%s(%s)' % [result, (parameters.to_a.collect(&:signature) << (variadic? ? '...' : nil)).compact.join(',')]

  def prototype = '%s %s(%s)' % [result, name, (parameters.to_a.collect(&:declaration) << (variadic? ? '...' : nil)).compact.join(',')]

  def definition = '%s {%s}' % [prototype, @code]

  def parameter(name) = @values[name]

  def call(*arguments)
    xs = []
    ps = parameters.to_a
    (0...arguments.size).each do |i|
      a = arguments[i]
      v = a.is_a?(Parameter) ? a.to_value_argument : a
      xs << (i < ps.size ? ps[i].value.(v) : v)
    end
    '%s(%s)' % [name, xs.join(',')]
  end

  def configure(&block)
    instance_eval(&block)
    self
  end
  
  # This allows to call other functions with this function's individual parameters as arguments
  # A call to unknown method results in the method's name being emitted
  def method_missing(meth, *args) = parameters.has_key?(meth) ? parameters[meth] : meth

private

  # On function inlining in C: http://www.greenend.org.uk/rjk/tech/inline.html

  # static inline seems to be THE most portable way without resorting to preprocessor
  # but consider the possible code bloat it incurs

  def render_declaration_specifier(stream)
    # The inline specifier is not a part of C89 yet descent compilers do inlining at will
    # given the function definition is available at the function call
    stream << 'static ' if inline?
  end

  # Render the commentary block preceding the function declaration, both inline or external
  def render_function_header(stream)
    if public?
      stream << %{
        /* #{@header} */
      } unless @header.nil?
    else
      stream << Composite::PRIVATE
    end
  end

  # Render full function declaration statement including the commentary block
  # For inline functions this also renders a function body effectively making this also a function definition
  # The declaration comes into either public interface of forward declaration block depending on the function's visibility status
  def render_function_declaration(stream)
    render_function_header(stream) if @render_interface
    render_declaration_specifier(stream)
    if inline?
      render_function_definition(stream)
    else
      stream << prototype << ';'
    end
  end

  # Render function definition, both inline or extern
  # This code never gets into public interface
  def render_function_definition(stream)
    unless abstract?
      raise("missing function definition for #{name}()") if @code.nil?
      stream << definition
    end
  end

  # Render function's public interface
  # Render non-internal function declarations
  # @render_interface is used internally to distinguish header-time rendering from source-time rendering
  def render_interface(stream)
    @render_interface = true
    render_function_declaration(stream) if live? && (public? || private?)
  end

  # Render function's interface for non-public functions which should not appear in the public interface
  def render_forward_declarations(stream)
    @render_interface = false
    render_function_declaration(stream) if live? && !(public? || private?)
  end

  # Render non-inline function definition regardless of function's visibility status
  def render_implementation(stream)
    @render_interface = false
    render_function_definition(stream) if live? && !inline?
  end

end # Function


# @private
# Named parameter list for the function
class Function::Parameters < ::Hash
  def initialize(function)
    @function = function
    super
to_value(= self) click to toggle source
# File lib/autoc/function.rb, line 20
  def to_value = self

  def constant? = @constant == true

  def reference? = @reference == true

  def initialize(type, constant: false, reference: false)
    @type = type
    @constant = constant
    @reference = reference
  end

  def to_s = signature

  def signature
    _ = reference? ? "#{type.signature}*" : type.signature
    constant? ? "const #{_}" : _
  end

  def call(value)
    value = value.to_s
    if reference?
      # Manually collapse references &*xyz -> xyz for the sake of source code readability
      value[0] =='*' ? value[1..-1] : "&#{value}"
    else
      value
    end
  end
end # Value


# @private
# Function parameter
class Parameter

  attr_reader :value

  attr_reader :name

  def initialize(value, name)
    @value = value.to_value
    @name = name.to_sym
  end

  def to_s = name.to_s

  def to_value_argument = value.reference? ? "*#{name}" : name

  def signature = value.signature

  def declaration = '%s %s' % [signature, name]

end # Parameter


# Standalone C side function
# The generated function is meant to be the C89-compliant
# NOTE: This function does not track parameter and result types as its dependencies
# This can be done manually by appending to #dependencies property with <<
class Function

  include Entity
  
  attr_reader :name

  attr_reader :result

  attr_reader :parameters

  attr_reader :visibility

  attr_writer :inline

  def initialize(result, name, parameters, inline: false, visibility: :public, constraint: true, variadic: false, abstract: false)
    @name = name.to_s
    @result = result
    @inline = inline
    @visibility = visibility
    @constraint = constraint
    @abstract = abstract
    @variadic = variadic
    @parameters = Parameters.new(self)
    if parameters.is_a?(Hash)
      parameters.each do |name, descriptor|
        x = Parameter.new(descriptor, name)
        @parameters[x.name] = x
      end
    else
      i = -1
      parameters.each do |descriptor|
        x = Parameter.new(descriptor, "_#{i+=1}")
        @parameters[x.name] = x
      end
    end
  end

  def inline_code(code)
    @inline = true
    code(code)
  end

  def external_code(code)
    @inline = false
    code(code)
  end

  def to_s = name

  def header(header) = @header = header

  def code(code) = @code = code

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

  def inline? = @inline == true

  def public? = @visibility == :public

  def private? = @visibility == :private

  def internal? = @visibility == :internal
  
  def abstract? = @abstract == true

  def variadic? = @variadic == true

  def live? = (@constraint.is_a?(Proc) ? @constraint.() : @constraint) == true
  
  def signature = '%s(%s)' % [result, (parameters.to_a.collect(&:signature) << (variadic? ? '...' : nil)).compact.join(',')]

  def prototype = '%s %s(%s)' % [result, name, (parameters.to_a.collect(&:declaration) << (variadic? ? '...' : nil)).compact.join(',')]

  def definition = '%s {%s}' % [prototype, @code]

  def parameter(name) = @values[name]

  def call(*arguments)
    xs = []
    ps = parameters.to_a
    (0...arguments.size).each do |i|
      a = arguments[i]
      v = a.is_a?(Parameter) ? a.to_value_argument : a
      xs << (i < ps.size ? ps[i].value.(v) : v)
    end
    '%s(%s)' % [name, xs.join(',')]
  end

  def configure(&block)
    instance_eval(&block)
    self
  end
  
  # This allows to call other functions with this function's individual parameters as arguments
  # A call to unknown method results in the method's name being emitted
  def method_missing(meth, *args) = parameters.has_key?(meth) ? parameters[meth] : meth

private

  # On function inlining in C: http://www.greenend.org.uk/rjk/tech/inline.html

  # static inline seems to be THE most portable way without resorting to preprocessor
  # but consider the possible code bloat it incurs

  def render_declaration_specifier(stream)
    # The inline specifier is not a part of C89 yet descent compilers do inlining at will
    # given the function definition is available at the function call
    stream << 'static ' if inline?
  end

  # Render the commentary block preceding the function declaration, both inline or external
  def render_function_header(stream)
    if public?
      stream << %{
        /* #{@header} */
      } unless @header.nil?
    else
      stream << Composite::PRIVATE
    end
  end

  # Render full function declaration statement including the commentary block
  # For inline functions this also renders a function body effectively making this also a function definition
  # The declaration comes into either public interface of forward declaration block depending on the function's visibility status
  def render_function_declaration(stream)
    render_function_header(stream) if @render_interface
    render_declaration_specifier(stream)
    if inline?
      render_function_definition(stream)
    else
      stream << prototype << ';'
    end
  end

  # Render function definition, both inline or extern
  # This code never gets into public interface
  def render_function_definition(stream)
    unless abstract?
      raise("missing function definition for #{name}()") if @code.nil?
      stream << definition
    end
  end

  # Render function's public interface
  # Render non-internal function declarations
  # @render_interface is used internally to distinguish header-time rendering from source-time rendering
  def render_interface(stream)
    @render_interface = true
    render_function_declaration(stream) if live? && (public? || private?)
  end

  # Render function's interface for non-public functions which should not appear in the public interface
  def render_forward_declarations(stream)
    @render_interface = false
    render_function_declaration(stream) if live? && !(public? || private?)
  end

  # Render non-inline function definition regardless of function's visibility status
  def render_implementation(stream)
    @render_interface = false
    render_function_definition(stream) if live? && !inline?
  end

end # Function


# @private
# Named parameter list for the function
class Function::Parameters < ::Hash
  def initialize(function)
    @function = function
    super()