kiyonori-matsumoto/tcl-ruby

View on GitHub
lib/tcl/ruby/commands/basic.rb

Summary

Maintainability
A
25 mins
Test Coverage
module Tcl
  module Ruby
    class Interpreter
      private

      def ___set(var_name, value = nil)
        if (m = var_name.match(/(\w+)\((\S+?)\)/))
          ___array_set(m[1], "{#{m[2]}} {#{value}}") if value
          ___array_get(m[1], "{#{m[2]}}")
        else
          @variables[var_name] = value if value
          @variables[var_name]
        end
      end

      def ___expr(*arg)
        eval arg.join('')
      end

      def ___eval(*arg)
        raise(TclArgumentError, 'wrong number of arguments(0 for 1..)') if
        arg.empty?
        parse(___concat(*arg))
      end

      def ___if(*arg)
        arg.delete('then')
        arg.delete('else')
        arg.delete('elseif')
        while arg[1]
          r = eval(replace(arg[0]))
          return parse(arg[1]) if r && r != 0
          arg.shift(2)
        end
        return parse(arg[0]) if arg[0]
        nil
      end

      def ___for(start, tst, nxt, body)
        parse(start)
        catch(:break) do
          while eval(replace(tst))
            catch(:continue) do
              parse(body)
            end
            parse(nxt)
          end
        end
      end

      def ___foreach(*arg)
        varlist = []
        list = []
        while arg[2]
          varlist << parse(arg[0], true)
          list << parse(arg[1], true)
          arg.shift(2)
        end
        catch(:break) do
          while list.any?(&:any?)
            # assign variables
            varlist.each_with_index do |v, idx|
              v.each { |vv| @variables[vv] = list[idx].shift || '' }
            end
            catch(:continue) do
              parse(arg[0])
            end
          end
        end
      end

      def ___while(tst, body)
        catch(:break) do
          while eval(replace(tst))
            catch(:continue) do
              parse(body)
            end
          end
        end
      end

      def ___break
        throw :break
      end

      def ___continue
        throw :continue
      end

      def ___return(val = nil)
        throw(:return, val)
      end

      def ___incr(var_name, increment = 1)
        @variables[var_name] = ((@variables[var_name] || 0).to_i +
          increment.to_i).to_s
      end

      def ___format(str, *args)
        str % args
      end

      def ___proc(name, args, body)
        @proc[name] = [args, body]
      end

      def ___global(*arg)
        @variables[:___global] ||= []
        arg.each do |v|
          @variables[:___global] << v
          @variables[v] = @global[v] if @global
        end
      end
    end
  end
end