Class: Predicator::Evaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/predicator/evaluator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(instructions, context_data = {}) ⇒ Evaluator

Returns a new instance of Evaluator.



5
6
7
8
9
10
# File 'lib/predicator/evaluator.rb', line 5

def initialize instructions, context_data={}
  @instructions = instructions
  @context = context_for context_data
  @stack = []
  @ip = 0
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



3
4
5
# File 'lib/predicator/evaluator.rb', line 3

def context
  @context
end

#instructionsObject (readonly)

Returns the value of attribute instructions.



3
4
5
# File 'lib/predicator/evaluator.rb', line 3

def instructions
  @instructions
end

#stackObject (readonly)

Returns the value of attribute stack.



3
4
5
# File 'lib/predicator/evaluator.rb', line 3

def stack
  @stack
end

Instance Method Details

#compare(comparison) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/predicator/evaluator.rb', line 66

def compare comparison
  right = stack.pop
  left = stack.pop
  if left.nil? || right.nil?
    stack.push false
  else
    stack.push send("compare_#{comparison}", left, right)
  end
end

#compare_BETWEENObject



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/predicator/evaluator.rb', line 96

def compare_BETWEEN
  max = stack.pop
  min = stack.pop
  val = stack.pop
  if max.nil? || min.nil? || val.nil?
    stack.push false
  else
    result = val.between? min, max
    stack.push result
  end
end

#compare_EQ(left, right) ⇒ Object



76
77
78
# File 'lib/predicator/evaluator.rb', line 76

def compare_EQ left, right
  left == right
end

#compare_GT(left, right) ⇒ Object



80
81
82
# File 'lib/predicator/evaluator.rb', line 80

def compare_GT left, right
  left > right
end

#compare_IN(left, right) ⇒ Object



88
89
90
# File 'lib/predicator/evaluator.rb', line 88

def compare_IN left, right
  right.include? left
end

#compare_LT(left, right) ⇒ Object



84
85
86
# File 'lib/predicator/evaluator.rb', line 84

def compare_LT left, right
  left < right
end

#compare_NOTIN(left, right) ⇒ Object



92
93
94
# File 'lib/predicator/evaluator.rb', line 92

def compare_NOTIN left, right
  !right.include? left
end

#context_for(context_data) ⇒ Object



12
13
14
15
# File 'lib/predicator/evaluator.rb', line 12

def context_for context_data
  return context_data unless context_data.kind_of? Hash
  Context.new context_data
end

#jump_if_false(offset) ⇒ Object



48
49
50
51
52
53
54
55
# File 'lib/predicator/evaluator.rb', line 48

def jump_if_false offset
  if stack[-1] == false
    adjusted_offset = offset - 1
    @ip += adjusted_offset
  else
    stack.pop
  end
end

#jump_if_true(offset) ⇒ Object



57
58
59
60
61
62
63
64
# File 'lib/predicator/evaluator.rb', line 57

def jump_if_true offset
  if stack[-1] == true
    adjusted_offset = offset - 1
    @ip += adjusted_offset
  else
    stack.pop
  end
end

#process(instruction) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/predicator/evaluator.rb', line 25

def process instruction
  case instruction.first
  when "not"
    stack.push !stack.pop
  when "jfalse"
    jump_if_false instruction.last
  when "jtrue"
    jump_if_true instruction.last
  when "lit", "array"
    stack.push instruction.last
  when "load"
    stack.push context[instruction.last]
  when "to_bool"
    stack.push !!stack.pop
  when "compare"
    if instruction.last == "BETWEEN"
      compare_BETWEEN
    else
      compare instruction.last
    end
  end
end

#resultObject



17
18
19
20
21
22
23
# File 'lib/predicator/evaluator.rb', line 17

def result
  while @ip < instructions.length
    process @instructions[@ip]
    @ip += 1
  end
  stack.pop
end