class Class::DecisionTable

attr_accessor :member_range def member_num; member_range.first end

Public Class Methods

[](fh,class2result)
Alias for: new
new(fh,class2result) click to toggle source
# File lib/redparse/decisiontree.rb, line 158
def initialize(fh,class2result)
  @hierarchy=fh
  classes,ranges=fh.nonoverlapping_results_range_list(class2result)
  newme=[]
  classes.each_with_index{|k,i| newme.push k,ranges[i]}
  replace newme
end
Also aliased as: []

Public Instance Methods

c_ref_to(obj) click to toggle source
# File lib/redparse/decisiontree.rb, line 301
def c_ref_to(obj)
  @dont_delete_yet||=[]
  @dont_delete_yet << obj #keep a real ref around so that weak ref in inline c code
                        #keeps pointing to the right object.
  return "(VALUE)0x#{obj.object_id.to_s(16)}L"
end
compile() click to toggle source
# File lib/redparse/decisiontree.rb, line 331
def compile
  begin
    compile_to_c
  rescue Exception
    compile_to_ruby
  end
end
compile_to_c() click to toggle source
# File lib/redparse/decisiontree.rb, line 312
def compile_to_c
  huh "this prolly won't work cause inline c code has to be in an actual class"
  huh 'so,, need to rewrite as temporary class (module?) for the method to live in... then delegate to that'

  begin
  require 'rubygems'
  rescue Exception
  end
  require 'inline'

  class << self
    inline{|write| write.c %{ 
      static VALUE decide_from_classid(unsigned x){
        #{to_c}
      }
    } }
  end
end
compile_to_ruby() click to toggle source
# File lib/redparse/decisiontree.rb, line 308
def compile_to_ruby
  eval " def self.decide_from_classid(x)\n#{to_ruby}\n end"
end
decide(klass,member_ranges) click to toggle source
# File lib/redparse/decisiontree.rb, line 176
def decide(klass,member_ranges)
  decide_from_classid(member_ranges[klass])
end
decide_from_classid(x) click to toggle source
# File lib/redparse/decisiontree.rb, line 179
def decide_from_classid(x)
  huh broken
  if x.send op, val
    use=iftrue
  else
    use=iffalse
  end
  return use.decide_from_classid(x) if DecisionTree===use
  return use
end
inspect() click to toggle source
Calls superclass method
# File lib/redparse/decisiontree.rb, line 167
def inspect
  "Class::DecisionTable"+super
end
pretty_print(q) click to toggle source
# File lib/redparse/decisiontree.rb, line 170
def pretty_print(q)
  q.group(1, 'Class::DecisionTable[', ']') {
    q.seplist(self) {|v| q.pp v }
  }
end
ref_to(obj) click to toggle source
# File lib/redparse/decisiontree.rb, line 294
def ref_to obj
  @ruby_refs= defined?(@ruby_refs) ? @ruby_refs+1 : 1
  result="@ruby_ref_#{@ruby_refs}"
  instance_variable_set result, obj
  return result
end
to_c(low=0,high=self.size-1) click to toggle source
# File lib/redparse/decisiontree.rb, line 278
def to_c(low=0,high=self.size-1)
  #if downto a list of just 1 possibility
  #then return the corresponding result
  return "return "+c_ref_to(self[1+2*low]) if high==low 
  low<high or fail

  mid=((high+low+0.5)/2).to_i #midpoint of remaining list
  mid_class_id=self[2*mid].first
  "
     if (x<#{mid_class_id}) 
       #{to_c(low,mid-1)};
     else 
       #{to_c(mid,high)};
  "
end
to_ruby(low=0,high=results.size-1) click to toggle source

def self.overlapping_class_range_list(classes,member_ranges)

classes=sort_by_inheiritance(*classes)
return classes,classes.map{|k| member_ranges[k] }

end

def self.nonoverlapping_class_range_list(classes,member_ranges)

classes,ranges=overlapping_class_range_list(classes,member_ranges)

myclasses=[];myranges=[]
classes_index_stack=[]
classes.each_with_index{|k,i| 
  x=ranges[i].first
  if i>0 and ranges[i-1]===x #if overlaps previous range
    classes_index_stack.push i-1 #add to the stack of saved-up ranges
  else
    #pop off old superclasses that no longer apply to k,
    #adding regions for their last fragment as we go along
    until classes_index_stack.empty?
      current_range=ranges[classes_index_stack.last]
      break if current_range===x  
      ending=classes_index_stack.pop
      done_thru=myranges.last.last
      current_end=current_range.last
      unless done_thru==current_end
        myranges<<(done_thru+1..current_end)
        myclasses<<classes[ending]
      end
    end
  end

  #if a gap between (sub-?)classes, emit a fragment for the appropriate super (or default to nil)
  next_expected=myranges.last.last+1
  if next_expected!=x  #was:   (ranges[i].huh)
    myclasses<< (classes[classes_index_stack.last] unless classes_index_stack.empty?)
    myranges<<(next_expected..x-1)
  end

  #emit initial fragment for current class
  myclasses<<k
  myranges<<(x..[ranges[i+1].first-1,ranges[i].last].min)
}

return myclasses, myranges

end

def self.nonoverlapping_results_range_list(class2results,member_ranges)

classes=class2results.keys
classes,ranges=nonoverlapping_class_range_list(classes,member_ranges)
return classes.map{|k| class2results[k] }, ranges

end

# File lib/redparse/decisiontree.rb, line 261
def to_ruby(low=0,high=results.size-1)
  #if downto a list of just 1 possibility
  #then return the corresponding result
  return ref_to self[1+2*low] if high==low
  low<high or fail

  mid=((high+low+0.5)/2).to_i #midpoint of remaining list
  mid_class_id=self[2*mid].first
  "
     if (x<#{mid_class_id}) 
       #{to_ruby(low,mid-1)};
     else 
       #{to_ruby(mid,high)};
     end
  "
end