justinethier / cyclone

:cyclone: A brand-new compiler that allows practical application development using R7RS Scheme. We provide modern features and a stable system capable of generating fast native binaries.
http://justinethier.github.io/cyclone/
MIT License
825 stars 44 forks source link

Line numbers in call history / errors #353

Open justinethier opened 4 years ago

justinethier commented 4 years ago

It would be nice if compiler errors and/or call history traces could include line numbers. This would make debugging much easier though it is not a trivial change.

arthurmaciel commented 4 years ago

I estimate 70% of the time I spent writing cyclone-winds was trying to spot trivial errors. Most of time I used (display "I am here"), basically as a sexp-crafted version of printf() debugging :)

If I can contribute to it, please let me know.

justinethier commented 4 years ago

I would really like this feature but it would involve a lot of changes to the compiler pipeline. Basically, instead of passing Scheme S-expressions along we would want to pass an abstract syntax tree of records that contain additional information such as line number.

We have already started to do some of that for the later phases of the compiler to deal with compiler optimizations. With some planning this task may have a good plan of attack though it would be very large in scope as most of the compiler code would be affected.

justinethier commented 4 years ago

An alternative thought - how much information can the reader capture that can be used in further compiler passes (symbol locations, lambda info, etc) without having to rewrite everything?

arthurmaciel commented 4 years ago

A quick review of other implementations:

File test.scm:

1   (define a 1)
2   (define b 2)
3   (let ((a 3))
4     a)

5   (let (b)d ) ; **wrong**

Chibi

$ chibi-scheme test.scm
ERROR on line 1 of file test.scm: undefined variable: a
  called from <anonymous> on line 1076 of file /usr/local/lib/chibi/init-7.scm
  called from <anonymous> on line 230 of file /usr/local/lib/chibi/init-7.scm
  called from <anonymous> on line 640 of file /usr/local/lib/chibi/init-7.scm
Searching for modules exporting a ...  ;;; ***
  (libs a)

If I add (import (scheme base)) to test.scm and run again:

$ chibi-scheme test.scm
ERROR on line 6 of file test.scm: bad let syntax: (let (b) d)
  called from <anonymous> on line 1076 of file /usr/local/lib/chibi/init-7.scm
  called from <anonymous> on line 230 of file /usr/local/lib/chibi/init-7.scm
  called from <anonymous> on line 640 of file /usr/local/lib/chibi/init-7.scm

CHICKEN 5

$ chicken5 test.scm 

Syntax error: (test.scm:5) in `let' - pair expected

    (let (b) d)

    Expansion history:

    <syntax>      (##core#begin (let (b) d))
    <syntax>      (let (b) d)   <--

Chez

$ chez-scheme test.scm 
Chez Scheme Version 9.5.2
Copyright 1984-2019 Cisco Systems, Inc.

Exception: invalid syntax (let (b) d) at line 5, char 1 of test.scm

Gambit

$ gsc-gambit test.scm
*** ERROR IN "/usr/home/arthur/tmp/test.scm"@6.7 -- Ill-formed binding 

The "@5.7" reads to "at line 5 of 7".

Guile

$ guile test.scm 
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /usr/home/arthur/tmp/test.scm
;;; WARNING: compilation of /usr/home/arthur/tmp/test.scm failed:
;;; Syntax error:
;;; /usr/home/arthur/tmp/test.scm:5:0: let: bad let in form (let (b) d)
ice-9/boot-9.scm:222:17: In procedure map1:
Syntax error:
/usr/home/arthur/tmp/test.scm:5:0: let: bad let in form (let (b) d)
arthurmaciel commented 4 years ago

@justinethier, Cyclone Winds now have a library-index.scm automatically updated on push by its CI workflow.

The list is composed by package name, followed by the list of its libraries with their exports. I think this could be useful for generating hints to the user, when trying to use undefined variables/procedures/syntax.

Chibi already implements it as shown above on its first error (search for ;;; *** to find the specific line). I suppose something similar would be needed with cyclone internal libraries, so we would have a complete database of all exported definitions of the whole project. Maybe this feature could enabled/disabled by some flag for those who find it too polluting for error messages.

This is just a suggestion for the future.

justinethier commented 4 years ago

Building off of your examples, it should absolutely be possible to include line numbers for syntax errors, reported either directly by the reader or during the macro expansion phase.

It would be nice if we could preserve some line number information for later call history and/or variable/symbol error reporting. TBD

justinethier commented 4 years ago

The compiler is in a better place now and will output meaningful location information for all types of syntax errors.

Unfortunately the interpreter does not include location information for macro expansions, due to the environment override problem noted in issue #355

justinethier commented 4 years ago

Alright, both the compiler and interpreter report line number information now for syntax errors.

arthurmaciel commented 4 years ago

Amazing!! :)

justinethier commented 4 years ago

@arthurmaciel this just got merged back into the master branch. Please try it out if you have a chance and let me know what you think. I suspect there are still classes of errors that could use improvement. For example, undefined variable errors still just list the variables.

arthurmaciel commented 4 years ago

@justinethier, I tested here and it works perfectly! As long as I use cyclone for cyclone-winds development I will report any errors that could be improved. Cyclone is now better than ever! Thanks for that!

justinethier commented 4 years ago

@arthurmaciel No problem, please let me know if you run into other issues / inconveniences. I will leave this ticket open for now; I suspect there are other error messages that could be improved as well.

justinethier commented 4 years ago

Here is an error message without line numbers:

Compiler Error:
(loop$5$15 fp$1$12 r$27 (cons buf$6$16 lines$7$17))
Expected 2 arguments to loop$5$15 but received 3

In this case a named let was incorrectly passed an extra argument.