goby-lang / goby

Goby - Yet another programming language written in Go
MIT License
3.49k stars 171 forks source link

Bug: unstable argument with `String#to_*` and `Range#each` #532

Closed hachi8833 closed 6 years ago

hachi8833 commented 6 years ago

The following causes invalid ArgumentError:

def foo(k)
  b = "4".to_f
  (1..k).each do |x|
    puts b + x
  end
end

foo(10) 
#=> ArgumentError: Expect 0 argument. got=1
#=> from /Users/hachi8833/deve/goby_sandbox/47sandbox.gb:2
#=> from /Users/hachi8833/deve/goby_sandbox/47sandbox.gb:15

Same errors are occured if you change "4".to_f to "4".to_d or "4".to_i.

But it is strange that the following works:

def foo(k)
  b = "4".to_f # dummy comment
  (1..k).each do |x|
    puts b + x
  end
end

foo(10) #=> (works)
def foo(k)
  b = "4".to_f
  puts k
  (1..k).each do |x|
    puts b + x
  end
end

foo(10) #=> (works)
def foo(k)
  b = 4
  (1..k).each do |x|
    puts b + x
  end
end

foo(10) #=> (works)

Assumption

The following condition might be relevant:

  1. the method has one or more arguments
  2. the first line of the methods contains String#to_*
  3. the second line contains a Range object with the argument and #each like:
    • (k..10).each causes the error
    • (10..k).each causes the error
    • puts (k..10) or puts (10..k) do not cause the error
st0012 commented 6 years ago

I think this is because the parser has trouble parsing range type correctly (I guess it's related to the float parsing), and those #to_* should be fine. Can you not using range for now until I fix this?

Update: This is method parsing's issue, has nothing to do with float parsing

st0012 commented 6 years ago

@hachi8833 Should be fixed at #533, can you check if the test cases are right and sufficient?

hachi8833 commented 6 years ago

LGTM. Just adding some tests for the case:

        {`
        def foo(k)
          b = "4".to_i
          (1..k).each do |x|
            b += x
          end
          b
        end

        foo(2)
        `, 7},
        {`
        def foo(k)
          b = "4".to_i
          (k..10).each do |x|
            b += x
          end
          b
        end

        foo(2)
        `, 58},
        {`
        def four
          4
        end

        def foo(k)
          b = four
          (1..k).each do |x|
            b += x
          end
          b
        end

        foo(2)
        `, 7},
        {`
        def four
          4
        end

        def foo(k)
          b = four
          (k..10).each do |x|
            b += x
          end
          b
        end

        foo(2)
        `, 58},