Skip to content

Commit e8a3e99

Browse files
committed
Show more descriptive errors (with location tip)
This should make errors a whole lot easier to diagnose. Previously, no position information was ever available. Although tracing the code emitted from macros isn't yet supported, this helps pinpoint stuff like illegal identifiers.
1 parent f0e72cc commit e8a3e99

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

src/cli.ls

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ spawn = (require \child_process).spawn
44
esl = require \./index
55
require! <[ fs path nopt ]>
66

7+
{ InvalidAstError } = require \esvalid
8+
79
print-version = ->
810
try
911
console.log (require \../package.json .version)
@@ -64,7 +66,38 @@ compiler-opts = {}
6466
if parsed-options.transform
6567
compiler-opts.transform-macros = that .map require
6668

67-
compile-and-show = -> console.log esl it, compiler-opts
69+
compile-and-show = (code) ->
70+
code .= to-string!
71+
try
72+
console.log esl code, compiler-opts
73+
catch err
74+
if err instanceof InvalidAstError
75+
console.error "[Error]" err.message
76+
point-at-problem code, err.node
77+
else throw err
78+
79+
# Use the node's location data (if present) to show the lines on which the
80+
# problem occurred.
81+
point-at-problem = (input, problematic-node) ->
82+
{ location } = problematic-node
83+
switch typeof! location
84+
| \String =>
85+
stringified-node = JSON.stringify do
86+
problematic-node
87+
(k, v) -> if k is \location then undefined else v
88+
console.error " #stringified-node"
89+
console.error " [ #location ]"
90+
| \Object =>
91+
{ start, end } = location
92+
line = input
93+
.split "\n"
94+
.slice (start.line - 1), end.line
95+
.join "\n"
96+
underline = " " * (start.offset - 1) +
97+
"^" * (end.offset - start.offset)
98+
console.error " " + line
99+
console.error " " + underline
100+
| _ => throw Error "Internal error: unexpected location type"
68101

69102
if target-path
70103
e, esl-code <- fs.read-file target-path, encoding : \utf8
@@ -91,6 +124,13 @@ else
91124
# NOTE: will fail on older nodejs due to paren wrapping logic; see
92125
# SO http://stackoverflow.com/questions/19182057/node-js-repl-funny-behavior-with-custom-eval-function
93126
# GH https://github.com/nodejs/node-v0.x-archive/commit/9ef9a9dee54a464a46739b14e8a348bec673c5a5
94-
stateful-compiler cmd
95-
|> vm.run-in-this-context
96-
|> callback null, _
127+
try
128+
stateful-compiler cmd
129+
|> vm.run-in-this-context
130+
|> callback null, _
131+
catch err
132+
if err instanceof InvalidAstError
133+
console.error "[Error]" err.message
134+
point-at-problem cmd, err.node
135+
callback null
136+
else throw err

src/import-macro.ls

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ compilerify-macro = (env, func) ->
118118

119119
errors = ast-errors sm-ast
120120
if errors
121-
console.error "AST error at" sm-ast
122-
throw Error errors.0
121+
throw errors.0
123122

124123
sm-ast
125124

src/translate.ls

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ module.exports = (root-env, ast, options={}) ->
3131
err = errors program-ast
3232
if err.length
3333
first-error = err.0
34-
console.error "[Error] #{first-error.message}\n\
35-
Node: #{JSON.stringify first-error.node}"
3634
throw first-error
3735
else
3836
return program-ast

0 commit comments

Comments
 (0)