Parent

Files

Protocol::MethodParser

Parse protocol method definition to derive a Message specification.

Attributes

args[R]

Returns the names of the arguments of the parsed method.

args[R]

Returns the names of the arguments of the parsed method.

arg_kinds[R]

Returns the kinds of the arguments of the parsed method.

arg_kinds[R]

Returns the names of the arguments of the parsed method.

arity[R]

Returns the arity of the parsed method.

arity[R]

Returns the arity of the parsed method.

Public Class Methods

new(modul, methodname, eigenclass = false) click to toggle source

Create a new MethodParser instance for method methodname of module modul. For eigenmethods set eigenclass to true, otherwise bad things will happen.

# File lib/protocol/method_parser/ruby_parser.rb, line 9
    def initialize(modul, methodname, eigenclass = false)
      super()
      @method = Module === modul ?
        modul.instance_method(methodname) :
        modul.method(methodname)
      @complex  = false
      @arity    = @method.arity
      if @method.respond_to?(:parameters)
        parameters = @method.parameters
        @args, @arg_kinds = parameters.map do |kind, name|
          case  kind
          when :req
            [ name, kind ]
          when :opt
            [ name, kind ]
          when :rest
            [ :"*#{name}", kind ]
          when :block
            [ :"&#{name}", kind ]
          end
        end.compact.transpose
      else
        raise NotImplementedError,
          "#{@method.class}#parameters as in ruby version >=1.9.2 is required"
      end
      @args         ||= []
      @arg_kinds    ||= []
      filename, lineno = @method.source_location
      if filename
        source = IO.readlines(filename)
        source = source[(lineno - 1)..-1].join
        current = 0
        tree = nil
        while current = source.index('end', current)
          current += 3
          begin
            tree = RubyParser.new.parse(source[0, current], filename)
            break
          rescue SyntaxError, Racc::ParseError
          end
        end
        ary = tree.to_a.flatten
        @complex = ary.flatten.any? { |node| [ :call, :fcall, :vcall ].include?(node) }
        if ary.index(:yield) and @arg_kinds.last != :block
          @args.push :'&block'
          @arg_kinds.push :block
        end
      end
    end
new(modul, methodname, eigenclass = false) click to toggle source

Create a new MethodParser instance for method methodname of module modul. For eigenmethods set eigenclass to true, otherwise bad things will happen.

# File lib/protocol/method_parser/parse_tree.rb, line 10
    def initialize(modul, methodname, eigenclass = false)
      super()
      @method = Module === modul ?
        modul.instance_method(methodname) :
        modul.method(methodname)
      self.strict = false
      self.auto_shift_type = true
      @complex      = false
      @first_defn   = true
      @first_block  = true
      @args         = []
      @arg_kinds    = []
      @arity        = @method.arity
      parsed = ParseTree.new.parse_tree_for_method(modul, methodname, eigenclass)
      process parsed
    end

Public Instance Methods

arg(i) click to toggle source

Returns the i-th argument (beginning with 0).

# File lib/protocol/method_parser/ruby_parser.rb, line 63
    def arg(i)
      @args[i]
    end
arg(i) click to toggle source

(Not documented)

# File lib/protocol/method_parser/parse_tree.rb, line 36
    def arg(i)
      @args[i]
    end
arg_kind(i) click to toggle source

(Not documented)

# File lib/protocol/method_parser/parse_tree.rb, line 43
    def arg_kind(i)
      @arg_kinds[i]
    end
arg_kind(i) click to toggle source

Returns the i-th kind of an argument (beginning with 0).

# File lib/protocol/method_parser/ruby_parser.rb, line 71
    def arg_kind(i)
      @arg_kinds[i]
    end
block_arg?() click to toggle source

Return true if a block argument was detected.

# File lib/protocol/method_parser/ruby_parser.rb, line 85
    def block_arg?
      @arg_kinds.last == :block
    end
block_arg?() click to toggle source

Return true if a block argument was detected.

# File lib/protocol/method_parser/parse_tree.rb, line 57
    def block_arg?
      @arg_kinds.last == :block
    end
complex?() click to toggle source

Return true if this protocol method is a complex method, which ought to be called for checking conformance to the protocol.

# File lib/protocol/method_parser/parse_tree.rb, line 52
    def complex?
      @complex
    end
complex?() click to toggle source

Return true if this protocol method is a complex method, which ought to be called for checking conformance to the protocol.

# File lib/protocol/method_parser/ruby_parser.rb, line 80
    def complex?
      @complex
    end
process(exp) click to toggle source

Process exp, but catch UnsupportedNodeError exceptions and ignore them.

# File lib/protocol/method_parser/parse_tree.rb, line 28
    def process(exp)
      super
    rescue UnsupportedNodeError => ignore
    end
process_args(exp) click to toggle source

Remember the argument names in exp in the args attribute.

# File lib/protocol/method_parser/parse_tree.rb, line 73
    def process_args(exp)
      @args.replace exp.select { |x| x.is_a? Symbol }
      @arg_kinds = @args.map { |a| a.to_s[0] == ?* ? :rest : :req }
      if block = exp.find { |x| x.is_a?(Array) and x.first == :block }
        lasgns = block[1..-1].transpose[1]
        i = args.size - 1
        @args.reverse_each do |a|
          exp.first
          l = lasgns.last
          if a == l
            @arg_kinds[i] = :opt
            lasgns.pop
          end
          i -= 1
        end
      end
      exp.clear
      s :dummy
    end
process_block(exp) click to toggle source

We only consider the first block in exp (can there be more than one?), and then try to figure out, if this is a complex method or not. Continue processing the exp tree after that.

# File lib/protocol/method_parser/parse_tree.rb, line 114
    def process_block(exp)
      if @first_block
        @first_block = false
        @complex = exp.flatten.any? { |e| [ :call, :fcall, :vcall ].include?(e) }
        exp.each { |e| process e }
      end
      exp.clear
      s :dummy
    end
process_block_arg(exp) click to toggle source

Remember if we encounter a block argument.

# File lib/protocol/method_parser/parse_tree.rb, line 94
    def process_block_arg(exp)
      @args.push :"&#{exp.first}"
      @arg_kinds.push :block
      exp.clear
      s :dummy
    end
process_defn(exp) click to toggle source

Only consider first the first defn, skip inner method definitions.

# File lib/protocol/method_parser/parse_tree.rb, line 62
    def process_defn(exp)
      if @first_defn
        @first_defn = false
        _name, scope = exp
        process scope
      end
      exp.clear
      s :dummy
    end
process_yield(exp) click to toggle source

Remember if we encounter a yield keyword.

# File lib/protocol/method_parser/parse_tree.rb, line 102
    def process_yield(exp)
      if @arg_kinds.last != :block
        @args.push :'&block'
        @arg_kinds.push :block
      end
      exp.clear
      s :dummy
    end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.