Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No variable or method x for y, thrown after a potentially raising method is called #155

Closed
Jens0512 opened this issue Feb 11, 2018 · 5 comments
Labels
bug.interpreter A bug specifically relating to the interpreter source code bug Generic label for bugs. Every bug should have this tag in addition to the more specific bug tag
Milestone

Comments

@Jens0512
Copy link
Member

This is as minimal as I could get it:

def foo(a, b)
  bar(a) + (b * 2)
end

def bar(a)
  when a == 1
    return (a.to_s * 5)
  else
    raise "<(a)> must be 1!"
  end
end

STDOUT.puts(foo(1, 3))

This is expected to print "111116\n", but instead it raises the following error:

Uncaught Exception: No variable or method `b` for Kernel
  from `b` at .../example.mt:2:13
  from `+` at .../example.mt:2:3
  from `foo` at .../example.mt:13:13
  from `puts` at .../example.mt:13:8

This is where the error occurs:

def foo(a, b)
  bar(a) + (b * 2) # "No variable or method `b` for Kernel"
end
@faultyserver faultyserver added bug Generic label for bugs. Every bug should have this tag in addition to the more specific bug tag bug.interpreter A bug specifically relating to the interpreter source code labels Feb 11, 2018
@Jens0512
Copy link
Member Author

If you remove the raise ..., the error is not thrown

@faultyserver
Copy link
Member

I misread this issue the first few times and assumed there was a rescue on bar, so I was attributing the bug with how ExceptionHandler deals with popping scopes.

The fact that there isn't a rescue or ensure involved here is more confusing. A raise that doesn't get executed shouldn't have any effect on the surrounding code, and I'm really not sure how it could be leaking like this. Will definitely need to look more into it.

@faultyserver
Copy link
Member

Messed around with it a little bit and it looks like this is actually an issue with return. Here's a minimized example that raises the same error:

def bar(a)
  return a
end

def foo(a, b)
  bar(a)
  b
end

foo(1, 3)

Removing the explicit return from line 2 fixes the error. With that, this issue is probably happening in the Invocation struct, where invoke handles rescuing BreakException, NextException, and ReturnException.

@faultyserver
Copy link
Member

I think explicit returns/breaks might also have issues with restoring the correct value of self. This failed build occurred because an explicit return in IO#gets skipped popping a value from the self_stack: https://travis-ci.org/myst-lang/myst/builds/341175297

faultyserver added a commit to faultyserver/myst that referenced this issue Feb 13, 2018
…O#gets` issue.

The explicit return in `IO#gets` caused issues with the value of `self` (see myst-lang#155), so `raise/rescue` is used as a temporary workaround.

Also, the specs for File are a bit light, because there currently isn't a great way of mocking FileDescriptor input, nor accessing the Interpreter's `fd_pool` to check for opening/closing of files.
@faultyserver
Copy link
Member

Some more testing makes this look like an issue with scope_stack rather than self_stack. Still looking into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug.interpreter A bug specifically relating to the interpreter source code bug Generic label for bugs. Every bug should have this tag in addition to the more specific bug tag
Projects
None yet
Development

No branches or pull requests

2 participants