Module: Alf::Support

Extended by:
Support
Included in:
Support
Defined in:
lib/alf/support.rb,
lib/alf/support/tree.rb,
lib/alf/support/scope.rb,
lib/alf/support/coerce.rb,
lib/alf/support/config.rb,
lib/alf/support/registry.rb,
lib/alf/support/to_lispy.rb,
lib/alf/support/dot_utils.rb,
lib/alf/support/csv_utils.rb,
lib/alf/support/tuple_scope.rb,
lib/alf/support/ordered_set.rb,
lib/alf/support/miscellaneous.rb,
lib/alf/support/to_ruby_literal.rb

Overview

Provides tooling methods that are used here and there in Alf.

Defined Under Namespace

Modules: CSVUtils, DotUtils, OrderedSet, Registry Classes: Config, Scope, Tree, TupleScope

Constant Summary collapse

Coercions =

Defines all coercion rules, through Myrrha inheritance

Myrrha::Coerce.dup.append do |g|
  g.error_handler = lambda{|v,t,c|
    raise TypeError, "Unable to coerce `#{v.inspect}` to `#{t}`", caller
  }
  g.coercion String, Time,     lambda{|s,t| Time.parse(s) }
  g.coercion String, DateTime, lambda{|s,t| DateTime.parse(s) }
end
NOT_PROVIDED =
Object.new.freeze
ToLispy =

Myrrha rules for converting to ruby literals

Myrrha::coercions do |r|

  # Delegate to #to_lispy if it exists
  lispy_able = lambda{|v,rd| v.respond_to?(:to_lispy)}
  r.upon(lispy_able) do |v,rd|
    v.to_lispy
  end

  # Let's assume to to_ruby_literal will make the job
  r.fallback(Object) do |v, _|
    Support.to_ruby_literal(v) rescue v.inspect
  end

end
ToRubyLiteral =

Myrrha rules for converting to ruby literals

Myrrha::ToRubyLiteral.dup.append do |g|
  g.coercion(Time)    {|s,_| "Time.parse('#{s.iso8601}')"     }
  g.coercion(DateTime){|s,_| "DateTime.parse('#{s.iso8601}')" }
end

Instance Method Summary collapse

Instance Method Details

#class_name(clazz) ⇒ Symbol

Returns the unqualified name of a ruby class or module.

Example

class_name(Alf::Support) -> :Support

Parameters:

  • clazz (Class)

    a ruby class

Returns:

  • (Symbol)

    the unqualified name of the class as a Symbol


12
13
14
# File 'lib/alf/support/miscellaneous.rb', line 12

def class_name(clazz)
  /([A-Za-z0-9_]+)$/.match(clazz.name.to_s)[1].to_sym
end

#coerce(val, domain) ⇒ Object

Coerces a value to a particular domain.

Example:

Support.coerce("123", Integer) # => 123

Parameters:

  • val (Object)

    any value

  • domain (Class)

    a domain, represented by a ruby class

Returns:

  • (Object)

    an instance of `domain` resulting from the coercion

Raises:

  • (Myrrha::CoercionError)

    if something goes wrong


23
24
25
# File 'lib/alf/support/coerce.rb', line 23

def coerce(val, domain)
  Coercions.apply(val, domain)
end

#robust_compare(x, y) ⇒ Object

Compare `x` and `y` in a robust way, that is, by handling `nil` without failure.


61
62
63
64
65
66
# File 'lib/alf/support/miscellaneous.rb', line 61

def robust_compare(x, y)
  return 0  if x==y
  return -1 if x.nil?
  return 1  if y.nil?
  x.respond_to?(:<=>) ? (x <=> y) : (x.to_s <=> y.to_s)
end

#ruby_case(s) ⇒ String

Converts an unqualified class or module name to a ruby case method name.

Example

ruby_case(:Alf)  -> "alf"
ruby_case(:HelloWorld) -> "hello_world"

Parameters:

  • a (String or Symbol)

    class or module name

Returns:

  • (String)

    the class or module name in ruby_case


25
26
27
# File 'lib/alf/support/miscellaneous.rb', line 25

def ruby_case(s)
  s.to_s.gsub(/[A-Z]/){|x| "_#{x.downcase}"}[1..-1]
end

#rubycase_name(name) ⇒ Symbol

Converts `name` to a rubycase name, as a Symbol.

Example:

rubycase_name(Alf)        => :alf
rubycase_name(HelloWorld) => :hello_world

Parameters:

  • any (Object)

    object, typically a Class, Symbol or String

Returns:

  • (Symbol)

    a symbol capturing `name` in ruby-like casing


37
38
39
40
41
# File 'lib/alf/support/miscellaneous.rb', line 37

def rubycase_name(name)
  name = class_name(name) if name.is_a?(Module)
  name = ruby_case(name.to_s)
  name.to_sym
end

#symbolize_keys(tuple) ⇒ Tuple

Symbolizes all keys of `tuple`

Parameters:

  • tuple (Hash)

    a tuple, represented by a Hash

Returns:

  • (Tuple)

    the same tuple, with all keys as Symbols


47
48
49
# File 'lib/alf/support/miscellaneous.rb', line 47

def symbolize_keys(tuple)
  tuple.each_with_object({}){|(k,v),h| h[k.to_sym] = v}
end

#to_lispy(expr, default = NOT_PROVIDED) ⇒ String

Converts `value` to a lispy expression.

Example:

expr = Alf.examples.compile{
  project(:suppliers, [:name])
}
Support.to_lispy(expr)
# => project(:suppliers, [:name])

Parameters:

  • expr (Object)

    any ruby object denoting a lispy expression

Returns:

  • (String)

    a lispy expression for `value`


18
19
20
21
22
23
# File 'lib/alf/support/to_lispy.rb', line 18

def to_lispy(expr, default = NOT_PROVIDED)
  ToLispy.apply(expr)
rescue NotSupportedError
  raise if default == NOT_PROVIDED
  default
end

#to_ruby_literal(value) ⇒ String

Converts `value` to a ruby literal

This method is provided for code generation mechanisms used by Alf in various places (such as .rash files). The to_ruby_literal contract is such that the following invariant holds:

eval(to_ruby_literal(value)) == value

This contract is ensured by Myrrha::ToRubyLiteral for various ruby values. Myrrha delegates the job to `value.to_ruby_literal` provided this method exists. In such case, the implementation must be such that the invariant above is met.

In every case, an invocation to this method only makes sense provided that `value` denotes a pure value, with the obvious semantics (from TTM).

Parameters:

  • value (Object)

    any ruby object that denotes a pure value.

Returns:

  • (String)

    a ruby literal for `value`


22
23
24
# File 'lib/alf/support/to_ruby_literal.rb', line 22

def to_ruby_literal(value)
  ToRubyLiteral.apply(value)
end

#unsymbolize_keys(tuple) ⇒ Tuple

Unsymbolizes all keys of `tuple`

Parameters:

  • tuple (Hash)

    a tuple, represented by a Hash

Returns:

  • (Tuple)

    the same tuple, with all keys as Symbols


55
56
57
# File 'lib/alf/support/miscellaneous.rb', line 55

def unsymbolize_keys(tuple)
  tuple.each_with_object({}){|(k,v),h| h[k.to_s] = v}
end