class PosxmlCompiler::Jump

Constants

INSTRUCTION_BREAK
INSTRUCTION_CALLFUNCTION
INSTRUCTION_ELSE
INSTRUCTION_FUNCTION
INSTRUCTION_FUNCTION_END
INSTRUCTION_IF
INSTRUCTION_IF_END
INSTRUCTION_WHILE
INSTRUCTION_WHILE_END

Attributes

instructions[R]
jumps[R]

Public Class Methods

new(instructions_array) click to toggle source
# File lib/posxml_compiler/jump.rb, line 17
def initialize(instructions_array)
  @instructions = instructions_array
  @jumps        = []
  self.parse
end

Public Instance Methods

parse() click to toggle source
# File lib/posxml_compiler/jump.rb, line 30
def parse
  instructions_indexed = self.instructions.each_with_index.to_a.reverse
  stack_function       = []
  stack_while          = []
  stack_if             = []

  # It's necessary parse the list of functions first because a functions can
  # be called from anywhere, already declared or not
  tree_function  = instructions_indexed.select do |instruction, index|
    instruction[:name] == INSTRUCTION_FUNCTION
  end.group_by do |instruction, index|
    instruction[:parameters]["name"][:original]
  end

  # instruction[:point] + 1 - Because of "\n"
  instructions_indexed.each do |instruction, index|
    case instruction[:name]
    when INSTRUCTION_FUNCTION_END
      stack_function << [index, instruction[:point]]
    when INSTRUCTION_FUNCTION
      reference, point = stack_function.pop
      @jumps << JumpPoint.new(self, INSTRUCTION_FUNCTION, index, reference, point)
    when INSTRUCTION_CALLFUNCTION
      reference, point = check_function_tree(tree_function, instruction)
      @jumps << JumpPoint.new(self, INSTRUCTION_CALLFUNCTION, index, reference, point)
    when INSTRUCTION_WHILE_END
      stack_while << [index, instruction[:point]]
    when INSTRUCTION_BREAK
      reference, point = stack_while.last
      raise PosxmlCompilerError.new("#{instruction[:line_number]}:While not found for <break") unless reference
      @jumps << JumpPoint.new(self, INSTRUCTION_BREAK, index, reference, point)
    when INSTRUCTION_WHILE
      reference, point = stack_while.pop
      @jumps << JumpPoint.new(self, INSTRUCTION_WHILE, index, reference, point)
      @jumps << JumpPoint.new(self, INSTRUCTION_WHILE_END, reference, index, instruction[:point] - 1)
    when INSTRUCTION_IF_END
      stack_if << [index, instruction[:point]]
    when INSTRUCTION_ELSE
      reference, point = stack_if.pop
      @jumps << JumpPoint.new(self, INSTRUCTION_ELSE, index, reference, point)
      stack_if << [index, instruction[:point], true]
    when INSTRUCTION_IF
      reference, point, is_else = stack_if.pop
      @jumps << JumpPoint.new(self, INSTRUCTION_IF, index, reference, point)
    end
  end
  # TODO add treatment for open/end statments
  check_addition
end
persist!() click to toggle source
# File lib/posxml_compiler/jump.rb, line 23
def persist!
  self.jumps.each do |jump|
    line = self.instructions[jump.persistence][:line]
    self.instructions[jump.persistence][:line] = line.insert(1, "#{jump.jump_value}\n")
  end
end

Private Instance Methods

check_addition() click to toggle source
# File lib/posxml_compiler/jump.rb, line 81
def check_addition
  self.jumps.each do |jump|
    jump.check_itself!
  end
end
check_function_tree(tree, instruction) click to toggle source
# File lib/posxml_compiler/jump.rb, line 87
def check_function_tree(tree, instruction)
  function_name    = instruction[:parameters]["name"][:original]
  line_number      = instruction[:line_number]
  unless function  = tree[function_name]
    raise PosxmlCompilerError.new("#{line_number}:Function #{function_name} not found") unless reference
  end
  function_indexed = tree[function_name][0]
  [function_indexed[1], function_indexed[0][:point]]
end