myst-lang / myst

A structured, dynamic, general-purpose language.
http://myst-lang.org
MIT License
119 stars 17 forks source link

[RFC] Unclear error messages #197

Open Jens0512 opened 6 years ago

Jens0512 commented 6 years ago

Have this code:

before = Time.now
sleep(Random.rand())
after  = Time.now

STDOUT.puts("Before - Milliseconds: <(before.milliseconds)>")
STDOUT.puts("After  - Milliseconds: <(after.milliseconds)>" )

And see it run:

$ myst test.mt
Uncaught Exception: No variable or method `milliseconds` for 2018-06-08 16:52:57:Time

The error in this program is that the method aimed for is Time#millisecond, as there exists no Time#milliseconds (with a trailing s).

The error message makes it clear that there is no variable or method milliseconds, – but for 2018-06-08 16:52:57:Time? At least to me, it seems very unlikely that 2018-06-08 16:52:57:Time would have any variables or methods at all. My point is that I believe using to_s in this situation can be very unclear.

Something like this would be good:

Uncaught Exception: No variable or method `milliseconds` for `before` test.mt:4
faultyserver commented 6 years ago

I can agree with this. This style was taken from Ruby, which uses the format <instance>:<Class> when it outputs the receiver. In practice, this can lead to some really unwieldy output with objects that have a Scope that reaches the Kernel:

screen shot 2018-11-01 at 3 29 08 pm

(this is only part of the error output from a line that just reads assert(1).is_a(Object). The whole content of the Kernel ends up getting printed in the error message).

I think part of the need for Ruby's format comes from the fact that Ruby allows every object to act as a singleton, defining methods on the instance itself. Since Myst doesn't allow that, I don't think we need to follow the same format.

Getting the variable name for the missing value might be a little bit tricky, just because I don't think the interpreter has a way of knowing that at the point that the Call is looked up. It would be a worthwhile addition, though.

At least in the meantime (and probably in general), I would also recommend including the type of the receiving object in that output. I think that would help people quickly see if they just made a typo (e.g., "no method miseconds for variable before (of type Time)" quickly says "oh, i misspelled 'milliseconds'", vs "no method milliseconds for variable before (of type Object)" says "oh, why is before an Object here?").

tl;dr: I agree, but let's also add the type of the receiver to the output. I think your example should output something like:

Uncaught Exception: No variable or method `milliseconds` for `before` (of type `Time`) at test.mt:4
Jens0512 commented 6 years ago

Wow, that's quite some error-message. And I love having such specific targets!

Jens0512 commented 5 years ago

Or maybe instead of ... for `before` (of type `Time`) ..., we can do:

... for `before:Time` ...

or even:

... for `before (Time)` ..

The one suggested by you definitely is the clearest one though