class Cauldron::Solution::Composite

Attributes

operators[R]

Public Class Methods

new(children) click to toggle source
# File lib/cauldron/solution/composite.rb, line 7
def initialize(children)
  raise StandardError.new('inital value should be an array') unless children.kind_of?(Array)      
  @operators = children
end

Public Instance Methods

add_first_statement(statement) click to toggle source
# File lib/cauldron/solution/composite.rb, line 168
def add_first_statement(statement)
  [:stmts_add, [:stmts_new], statement]
end
add_statement(statement, inner) click to toggle source
# File lib/cauldron/solution/composite.rb, line 172
def add_statement(statement, inner)
  [:stmts_add, inner, statement]
end
add_statement_at(statement, point) click to toggle source
# File lib/cauldron/solution/composite.rb, line 35
def add_statement_at(statement, point)
  if point.length == 2
    container = self.operators[0]
    #return self if container.length > 1 # TODO: Quick hack to get it working
    container << Tree::TreeNode.new('SASA', statement)
  elsif point.length == 1
    operators << Tree::TreeNode.new('SASA', statement)
  else
    raise StandardError.new('Have not written code: '+point.inspect)
  end
  self
end
clone_solution() click to toggle source
# File lib/cauldron/solution/composite.rb, line 27
def clone_solution
  #self.clone
  tree_operators = operators.collect do |node|
    Tree::TreeNode.new('x', node.content.clone_statement)
  end
  Composite.new(tree_operators)
end
end_points() click to toggle source
# File lib/cauldron/solution/composite.rb, line 17
def end_points
  results = []
  operators.each do |x|
    if x.content.branch?
      results << [0,x.children.length]
    end
  end
  results << [operators.length]
end
insert_tracking(params) click to toggle source
# File lib/cauldron/solution/composite.rb, line 48
def insert_tracking(params)
  scope = Cauldron::Scope.new(params.clone)

  # TODO Might be useful
  # trace = TracePoint.new(:call) do |tp|
  #   p [tp.lineno, tp.event, tp.raised_exception]
  # end

  
  # NEW: Implementation
  m = %Q{
    def function(#{params.join(',')})
      #{to_ruby(Cauldron::Scope.new(params.clone))}
    end
  }

  sexp = Ripper::SexpBuilder.new(m).parse
  rendered_code = Sorcerer.source(sexp, indent: true)
  caret = Cauldron::Caret.new

  rendered_code = Sorcerer.source(sexp, indent: true).gsub(/end/,"\nend").split("\n").reject(&:empty?).join("\n")

  # Generate tracking code with pending substitutions
  tracked_code = []
  rendered_code.each_line do |line|
    #if line.match /end\s+/
    if line.match /end/
      tracked_code << Sorcerer.source(Ripper::SexpBuilder.new(Cauldron::Tracer.substitue_tracking).parse) #Sorcerer.source(Cauldron::Tracer.substitue_tracking)
    end
    tracked_code << line
  end
  sexp = Ripper::SexpBuilder.new(tracked_code.join("\n")).parse       
  code_tracking  = Sorcerer.source(sexp, indent: true)
  code_tracking.split("\n")

  current_line = -1
  total_lines = 0
  new_tracked_code = []
  last_line = nil
  relative_line = 0
  placeholder = nil
  point = [0,0]
  current_depth = 0
  caret = Cauldron::Caret.new

  points = end_points

  code_tracking.split("\n").each do |line|

    if line.match /record/
      depth = (line.match(/^(\s+)/)[0].length / 2) -1
      if depth > current_depth
        relative_line = 0
      end
      current_depth = depth

      new_tracked_code << last_line
      new_tracked_code << Sorcerer.source(
                            Cauldron::Tracer.tracking(relative_line, depth, total_lines, points.shift)
                          )
      new_tracked_code << placeholder
    else
      total_lines += 1

      unless line['=']
        placeholder = "#{'placeholder_'+rand(10000000000).to_s}"
        last_line = "#{placeholder} = "+line
      end

      if last_line
        if !last_line.match(/\s+end/).nil? || !last_line.match(/function/).nil? # || last_line.match /function/
          last_line = nil
          placeholder = nil
        end
      end

      if line.match /end$/
        unless line.strip == 'end'
          line = line.gsub(/end$/,'')
        end
      end

      new_tracked_code << line
      current_line += 1
    end
    #total_lines += 1
  end

  # NOTE: Keep this to debug before conversion of S-EXP
  sexp = Ripper::SexpBuilder.new(new_tracked_code.join("\n")).parse
  
  Cauldron::Tracer.new(sexp)

end
record(example) click to toggle source
# File lib/cauldron/solution/composite.rb, line 12
def record(example)
  # TODO params passed twice - and example not used at all
  insert_tracking(example.params).process(example)
end
reset_and_track(caret) click to toggle source
# File lib/cauldron/solution/composite.rb, line 143
def reset_and_track(caret)
  caret.return_depth(0)
  Cauldron::Tracer.tracking(caret.line, caret.current_depth, caret.total_lines)
end
solution?(problems) click to toggle source
# File lib/cauldron/solution/composite.rb, line 176
def solution?(problems)
  o = Object.new
  m = %Q{
    def function(#{problems.variables.join(',')})
      #{to_ruby(problems.scope)}
    end
  }
  o.instance_eval(m)

  #o.function *problems.examples.first.arguments
  problems.all? do |example|
    o.function(*example.arguments) == example.response
  end

# TODO: Remove this resque - it is just a temp
rescue NoMethodError => e
  return false
rescue NameError => e
  return false
rescue TypeError => e
  return false
end
successful?(problem) click to toggle source

TODO Drop this method

# File lib/cauldron/solution/composite.rb, line 200
def successful?(problem)

  # # TODO track the parameters of the operator
  # operators.trace(problem)

  # # TODO For now just evalute the code
  # return true if problem[:arguments].first == problem[:response]
  # false

  pt = PryTester.new

  args = problem.arguments
  variables = problem.params #(0...args.length).collect {|x| 'var'+x.to_s}
  a = [
    'def function('+variables.join(',')+');'+self.to_ruby(variables)+"; end", 
    'function('+problem.arguments.collect {|x| to_programme(x) }.join(',')+')'
  ]
  
  res = pt.eval(
    ['def function('+variables.join(',')+');'+self.to_ruby(variables)+"; end", 'function('+problem.arguments.collect {|x| to_programme(x) }.join(',')+')']
  )

  problem.response == res
end
to_programme(value) click to toggle source
# File lib/cauldron/solution/composite.rb, line 225
def to_programme(value)
  if value.kind_of?(String)
    return %Q{'#{value}'}
  end
  value.to_s
end
to_ruby(scope) click to toggle source
# File lib/cauldron/solution/composite.rb, line 163
def to_ruby(scope)
  return '' if operators.empty?
  Sorcerer.source(to_sexp(scope))
end
to_sexp(scope=Cauldron::Scope.new) click to toggle source
# File lib/cauldron/solution/composite.rb, line 148
def to_sexp(scope=Cauldron::Scope.new)

  res = operators.collect do |operator|
    #begin
      operator.content.to_ruby(scope, operator.children)  
    # rescue NoMethodError => e
    #   binding.pry
    # end
    
  end.join("\n")

  sexp = Ripper::SexpBuilder.new(res).parse
  return sexp
end