Class: VirtualKeywords::RewrittenKeywords

Inherits:
Object
  • Object
show all
Defined in:
lib/virtual_keywords/rewritten_keywords.rb

Overview

Class holding the lambdas to call in place of keywords. Different classes can have their own set of “virtualized keywords”.

Instance Method Summary collapse

Constructor Details

#initialize(input) ⇒ RewrittenKeywords

Initialize a RewrittenKeywords

Arguments:

A Hash with the following key:
predicates_to_blocks: (Hash[Proc, Proc]) a hash mapping predicates that
    take ObjectAndKeywords and return true for matches to the lambdas
    that should be called in place of the keyword in the object's
    methods (optional, an empty Hash is the default).


23
24
25
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 23

def initialize(input)
  @predicates_to_blocks = input[:predicates_to_blocks] || {}
end

Instance Method Details

#call_and(caller_object, first, second) ⇒ Object

Call an “and” virtual block in place of an “and” expression.

Arguments:

caller_object: (Object) the object whose method this is being called in.
first: (Proc) The first operand of the "and", wrapped in a lambda.   
second: (Proc) The second operand of the "and", wrapped in a lambda.

Raises:

RewriteLambdaNotProvided if no "and" lambda is available.


114
115
116
117
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 114

def call_and(caller_object, first, second)
  and_lambda = lambda_or_raise(caller_object, :and)
  and_lambda.call(first, second)
end

#call_if(caller_object, condition, then_do, else_do) ⇒ Object

Call an if virtual block in place of an actual if expression. This function locates the lambda registered with the given object.

Arguments:

caller_object: (Object) the object whose method this is being called in.
condition: (Proc) The condition of the if statement, wrapped in a
    lambda.
then_do: (Proc) the lambda to execute if the condition is true (but
    the user-supplied block may do something else)
else_do: (Proc) the lambda to execute if the condition is false (but
    the user-supplied block may do something else)

Raises:

RewriteLambdaNotProvided if no "if" lambda is available.


100
101
102
103
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 100

def call_if(caller_object, condition, then_do, else_do)
  if_lambda = lambda_or_raise(caller_object, :if)
  if_lambda.call(condition, then_do, else_do)
end

#call_not(caller_object, value) ⇒ Object

Call a “not” virtual block in place of a “not” expression.

Arguments:

caller_object: (Object) the object whose method this is being called in.
value: (Proc) The operand of the not operator, which would normally be
    inverted.

Raises:

RewriteLambdaNotProvided if no "not" lambda is available.


177
178
179
180
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 177

def call_not(caller_object, value)
  not_lambda = lambda_or_raise(caller_object, :not)
  not_lambda.call value
end

#call_or(caller_object, first, second) ⇒ Object

Call an “or” virtual block in place of an “or” expression.

Arguments:

caller_object: (Object) the object whose method this is being called in.
first: (Proc) The first operand of the "or", wrapped in a lambda.   
second: (Proc) The second operand of the "or", wrapped in a lambda.

Raises:

RewriteLambdaNotProvided if no "or" lambda is available.


128
129
130
131
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 128

def call_or(caller_object, first, second)
  or_lambda = lambda_or_raise(caller_object, :or)
  or_lambda.call(first, second)
end

#call_until(caller_object, condition, body) ⇒ Object

Call an “until” virtual block in place of an “until” expression. Unlike unless, until IS a node in the AST (it doesn’t turn into while not) For now, I’m passing this inconsistency through to the client. A later modification of this gem may fold while and until into one thing for consistency.

Arguments:

caller_object: (Object) the object whose method this is being called in.
condition: (Proc) The condition of the until expression.
body: (Proc) The body of the until expression (which is normally
    executed repeatedly)

Raises:

RewriteLambdaNotProvided if no "until" lambda is available.


163
164
165
166
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 163

def call_until(caller_object, condition, body)
  until_lambda = lambda_or_raise(caller_object, :until)
  until_lambda.call(condition, body)
end

#call_while(caller_object, condition, body) ⇒ Object

Call a “while” virtual block in place of a “while” expression.

Arguments:

caller_object: (Object) the object whose method this is being called in.
condition: (Proc) The condition of the while expression.
body: (Proc) The body of the while expression (which is normally
    executed repeatedly)

Raises:

RewriteLambdaNotProvided if no "while" lambda is available.


143
144
145
146
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 143

def call_while(caller_object, condition, body)
  while_lambda = lambda_or_raise(caller_object, :while)
  while_lambda.call(condition, body)
end

#lambda_or_raise(caller_object, keyword) ⇒ Object

Get the virtual lambda to call for the given input, or raise an exception if it’s not there.

Arguments:

caller_object: (Object) the object part of the ObjectAndKeyword
keyword: (Symbol) they keyword part of the ObjectAndKeyword

Returns:

The lambda to call for that object's keyword, if the object and keyword
matched any of the predicates.

Raises:

RewriteLambdaNotProvided if no predicate returns true for
ObjectAndKeyword.


71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 71

def lambda_or_raise(caller_object, keyword)
  object_and_keyword = ObjectAndKeyword.new(caller_object, keyword)
  matching = @predicates_to_blocks.keys.find { |predicate|
    predicate.call object_and_keyword
  }

  if matching.nil?
    raise RewriteLambdaNotProvided, 'A rewrite was requested for ' +
        "#{caller_object}'s #{keyword} expressions, but there's no" +
        'lambda for it.'
  end

  @predicates_to_blocks[matching]
end

#register_lambda_for_class(klass, keyword, a_lambda) ⇒ Object

Register a lambda to be called for all objects created from a class. The predicate will match for all objects that are initialized with the class (but not if they are from subclasses)

Arguments:

klass: (Class) the class whose objects will have their methods
       virtualized.
keyword: (Symbol) the keyword that will be virtualized
a_lambda: (Proc) The lambda to be called in place of the keyword.


50
51
52
53
54
55
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 50

def register_lambda_for_class(klass, keyword, a_lambda)
  predicate = lambda { |input|
    input.object.instance_of?(klass) and input.keyword == keyword
  }
  @predicates_to_blocks[predicate] = a_lambda
end

#register_lambda_for_object(object, keyword, a_lambda) ⇒ Object

Register (save) a lambda to be called for a specific object.

Arguments:

object: (Object) the object whose methods will have their keyword
        virtualized.
keyword: (Symbol) the keyword that will be virtualized
a_lambda: (Proc) The lambda to be called in place of the keyword.


34
35
36
37
38
39
# File 'lib/virtual_keywords/rewritten_keywords.rb', line 34

def register_lambda_for_object(object, keyword, a_lambda)
  predicate = lambda { |input|
    input.object == object and input.keyword == keyword
  }
  @predicates_to_blocks[predicate] = a_lambda
end