Sha256: 88b733887b6ef267b335289d9b006cd20c3eae7e43e03d0be160f7884fc20d80

Contents?: true

Size: 1.68 KB

Versions: 28

Compression:

Stored size: 1.68 KB

Contents

module Tracksperanto::ShakeGrammar
  # Will replay funcalls through to methods if such methods exist in the public insntance
  class Catcher < Lexer
    class At
      attr_accessor :at, :value
      include Comparable
      def initialize(a, v)
        @at, @value = a, v
      end
      
      def <=>(o)
        [@at, @value] <=> [o.at, o.value]
      end
      
      def inspect
        "(#{@value.inspect}@#{@at.inspect})"
      end
    end
    
    def push(atom)
      # Send primitive types to parent
      return super if !atom.is_a?(Array)
      return super if atom[0] != :funcall
      
      meth_for_shake_func, args = atom[1].downcase, atom[2..-1]
      if can_handle_meth?(meth_for_shake_func)
        super([:retval, exec_funcall(meth_for_shake_func, args)])
      else
        # This is a funcall we cannot perform, replace the return result of the funcall
        # with a token to signify that some unknown function's result would have been here
        super([:unknown_func])
      end
    end
    
    private
    
    def can_handle_meth?(m)
      # Ruby 1.9 - match on stringified methname
      @meths ||= self.class.public_instance_methods(false).map{|mn| mn.to_s }
      @meths.include?(m.to_s)
    end
    
    def exec_funcall(methname, args)
      ruby_args = args.map {|a| unwrap_atom(a) }
      send(methname, *ruby_args)
    end
    
    def unwrap_atom(atom)
      return atom unless atom.is_a?(Array)
      
      kind = atom.shift
      case kind
        when :arr
          atom[0].map{|e| unwrap_atom(e)}
        when :retval
          atom.shift
        when :value_at
          At.new(atom.shift, unwrap_atom(atom.shift))
        else
          :unknown
      end
    end

  end
end

Version data entries

28 entries across 28 versions & 1 rubygems

Version Path
tracksperanto-2.3.1 lib/import/shake_grammar/catcher.rb
tracksperanto-2.3.0 lib/import/shake_grammar/catcher.rb
tracksperanto-2.2.4 lib/import/shake_grammar/catcher.rb
tracksperanto-2.2.2 lib/import/shake_grammar/catcher.rb
tracksperanto-2.2.0 lib/import/shake_grammar/catcher.rb
tracksperanto-2.1.1 lib/import/shake_grammar/catcher.rb
tracksperanto-2.1.0 lib/import/shake_grammar/catcher.rb
tracksperanto-2.0.2 lib/import/shake_grammar/catcher.rb
tracksperanto-2.0.1 lib/import/shake_grammar/catcher.rb
tracksperanto-2.0.0 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.9 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.8 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.6 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.5 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.4 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.3 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.2 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.1 lib/import/shake_grammar/catcher.rb
tracksperanto-1.9.0 lib/import/shake_grammar/catcher.rb
tracksperanto-1.8.4 lib/import/shake_grammar/catcher.rb