class Predicator::Visitors::Instructions

Attributes

instructions[R]

Public Class Methods

new(instructions=[]) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 6
def initialize instructions=[]
  @instructions = instructions
  @label_locations = {}
end

Public Instance Methods

accept(ast) click to toggle source
Calls superclass method
# File lib/predicator/visitors/instructions.rb, line 11
def accept ast
  super
  update_jumps
  remove_labels
  @instructions
end

Private Instance Methods

add_typecast_to_instructions(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 144
def add_typecast_to_instructions node
  type = case node.right.type.to_s
         when /INT/  then "to_int"
         when /STR/  then "to_str"
         when /DATE/ then "to_date"
         end
  @instructions.push [type]
end
calculate_offset(from_idx, to_idx) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 172
def calculate_offset from_idx, to_idx
  offset = to_idx - from_idx
  num_labels = @instructions[from_idx...to_idx].count{ |i| i.first == "label" }
  offset - num_labels
end
jump_instruction(condition, node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 153
def jump_instruction condition, node
  ["j#{condition}", node.object_id.to_s]
end
label_instruction(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 157
def label_instruction node
  label = node.object_id.to_s
  @label_locations[label] = @instructions.size
  ["label", label]
end
remove_labels() click to toggle source
# File lib/predicator/visitors/instructions.rb, line 178
def remove_labels
  @instructions.delete_if{ |inst| inst.first == "label" }
end
terminal(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 140
def terminal node
  @instructions.push ["lit", node.symbol]
end
update_jumps() click to toggle source
# File lib/predicator/visitors/instructions.rb, line 163
def update_jumps
  @instructions.each_with_index do |inst, idx|
    next unless inst.first =~ /^j/
    label = inst.pop
    offset = calculate_offset idx, @label_locations[label]
    inst.push offset
  end
end
visit_AND(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 20
def visit_AND node
  visit node.left
  @instructions.push jump_instruction("false", node)
  visit node.right
  @instructions.push label_instruction(node)
end
visit_ARRAY(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 96
def visit_ARRAY node
  contents = node.left.map{ |item| item.left }
  @instructions.push ["array", contents]
end
visit_BETWEEN(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 60
def visit_BETWEEN node
  visit node.left
  add_typecast_to_instructions node
  visit node.middle
  visit node.right
  @instructions.push ["compare", "BETWEEN"]
end
visit_BLANK(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 130
def visit_BLANK node
  visit node.left
  @instructions.push ["blank"]
end
visit_BOOL(node) click to toggle source
Calls superclass method
# File lib/predicator/visitors/instructions.rb, line 105
def visit_BOOL node
  super
  @instructions.push ["to_bool"]
end
visit_DATE(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 110
def visit_DATE node
  @instructions.push ["lit", node.symbol]
  @instructions.push ["to_date"]
end
visit_DATEAGO(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 115
def visit_DATEAGO node
  visit node.left
  @instructions.push ["date_ago"]
end
visit_DATEFROMNOW(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 120
def visit_DATEFROMNOW node
  visit node.left
  @instructions.push ["date_from_now"]
end
visit_DURATION(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 125
def visit_DURATION node
  as_seconds = node.symbol.to_i * 24 * 60 * 60
  @instructions.push ["lit", as_seconds]
end
visit_EQ(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 39
def visit_EQ node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "EQ"]
end
visit_GT(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 46
def visit_GT node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "GT"]
end
visit_IN(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 68
def visit_IN node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "IN"]
end
visit_LT(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 53
def visit_LT node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "LT"]
end
visit_NOT(node) click to toggle source
Calls superclass method
# File lib/predicator/visitors/instructions.rb, line 34
def visit_NOT node
  super
  @instructions.push ["not"]
end
visit_NOTIN(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 75
def visit_NOTIN node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "NOTIN"]
end
visit_OR(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 27
def visit_OR node
  visit node.left
  @instructions.push jump_instruction("true", node)
  visit node.right
  @instructions.push label_instruction(node)
end
visit_PRESENT(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 135
def visit_PRESENT node
  visit node.left
  @instructions.push ["present"]
end
visit_STRENDSWITH(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 89
def visit_STRENDSWITH node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "ENDSWITH"]
end
visit_STRSTARTSWITH(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 82
def visit_STRSTARTSWITH node
  visit node.left
  add_typecast_to_instructions node
  visit node.right
  @instructions.push ["compare", "STARTSWITH"]
end
visit_VARIABLE(node) click to toggle source
# File lib/predicator/visitors/instructions.rb, line 101
def visit_VARIABLE node
  @instructions.push ["load", node.symbol]
end