Class: AttrNameRewriter
- Inherits:
-
SexpProcessor
- Object
- SexpProcessor
- AttrNameRewriter
- Defined in:
- lib/bud/rewrite.rb
Overview
Rewrite named-column refs to positional refs
Instance Method Summary (collapse)
- - (Object) gather_collection_names(exp)
-
- (AttrNameRewriter) initialize(bud_instance)
constructor
:nodoc: all.
- - (Object) process_call(exp)
-
- (Object) process_iter(exp)
some icky special-case parsing to find mapping between collection names and iter vars.
Constructor Details
- (AttrNameRewriter) initialize(bud_instance)
:nodoc: all
456 457 458 459 460 461 462 463 |
# File 'lib/bud/rewrite.rb', line 456 def initialize(bud_instance) super() self.require_empty = false self.expected = Sexp @iterhash ||= {} @collnames = [] @bud_instance = bud_instance end |
Instance Method Details
- (Object) gather_collection_names(exp)
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/bud/rewrite.rb', line 514 def gather_collection_names(exp) # We expect a reference to a collection name to look like a function call # (nil receiver) with no arguments. if exp.sexp_type == :call and exp[1].nil? and exp.length == 3 @collnames << exp[2] elsif exp.sexp_type == :call and exp[2] == :rename namelit = exp[3] @collnames << namelit[1] elsif exp.sexp_type == :call and [:group, :argagg].include?(exp[2]) # For grouping and argagg expressions, only look at the receiver (the # collection we're grouping on); otherwise, we might mistakenly think some # of the arguments to the grouping operation are collection names. gather_collection_names(exp[1]) else exp.each { |e| gather_collection_names(e) if e.class <= Sexp } end end |
- (Object) process_call(exp)
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
# File 'lib/bud/rewrite.rb', line 532 def process_call(exp) call, recv, op, *args = exp if recv.class == Sexp and recv.sexp_type == :lvar and @iterhash[recv[1]] if @bud_instance.respond_to?(@iterhash[recv[1]]) if @bud_instance.send(@iterhash[recv[1]]).class <= Bud::BudCollection cols = @bud_instance.send(@iterhash[recv[1]]).cols if op != :[] and @bud_instance.send(@iterhash[recv[1]]).respond_to?(op) # if the op is an attribute name in the schema, col_idx is its index col_idx = cols.index(op) unless cols.nil? unless col_idx.nil? op = :[] args = [s(:lit, col_idx)] end end end return s(call, recv, op, *args) end end return s(call, process(recv), op, *(args.map{|a| process(a)})) end |
- (Object) process_iter(exp)
some icky special-case parsing to find mapping between collection names and iter vars
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
# File 'lib/bud/rewrite.rb', line 467 def process_iter(exp) if exp[1] and exp[1][0] == :call return exp unless exp[2] gather_collection_names(exp[1]) meth_name = exp[1][2] # now find iter vars and match up if exp[2][0] == :args and @collnames.size == 1 # single-table iter if @iterhash[exp[2][1]] raise Bud::CompileError, "redefinition of block variable \"#{exp[2][1]}\" not allowed" end # XXX: The BudChannel#payloads method assigns the correct schema to # tuples that pass through it (i.e., it omits the location specifier); # hence we don't want to apply the location rewrite to the code block # that is passed to payloads(). This is a dirty hack. unless meth_name == :payloads @iterhash[exp[2][1]] = @collnames[0] end elsif exp[2][0] == :args and not @collnames.empty? # join iter with lefts/rights case meth_name when :lefts @iterhash[exp[2][1]] = @collnames[0] when :rights @iterhash[exp[2][1]] = @collnames[1] when :reduce unless @collnames.length == 1 raise Bud::CompileError, "reduce should only have one associated collection, but has #{@collnames.inspect}" end @iterhash[exp[2][1]] = @collnames[0] else # join if @iterhash[exp[2][1]] raise Bud::CompileError, "redefinition of block variable \"#{exp[2][1]}\" not allowed" end @collnames.each_with_index do |c,i| next unless exp[2][i+1] @iterhash[exp[2][i+1]] = c end end end end (1..(exp.length-1)).each {|i| exp[i] = process(exp[i])} exp end |