[Bootstrap] Add a basic PrintError function to print error messages with the traceback
This commit is contained in:
parent
9be27c124a
commit
e4001e3802
|
@ -5,14 +5,24 @@
|
|||
(fn (name)
|
||||
(println "hello" name)))
|
||||
|
||||
(def a1
|
||||
(fn (x y)
|
||||
x))
|
||||
|
||||
(defmacro defn
|
||||
(name args &body)
|
||||
(list 'def name (cons 'fn (cons args body))))
|
||||
(list 'do
|
||||
(list 'def name (cons 'fn (cons args body)))
|
||||
(list 'a1 ~args)))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(defn pp (x y)
|
||||
(println x))
|
||||
|
||||
(def main
|
||||
(fn (&args)
|
||||
(pp "sam")
|
||||
(pp "sam" 2)
|
||||
(hello-world "world")))
|
||||
|
|
|
@ -66,7 +66,7 @@ func (s *Source) GetLine(linenum int) string {
|
|||
if linenum > 0 && linenum < len(lines) {
|
||||
return lines[linenum-1]
|
||||
}
|
||||
return "!!!"
|
||||
return "----"
|
||||
}
|
||||
|
||||
func (s *Source) LineNumberFor(pos int) int {
|
||||
|
@ -96,13 +96,7 @@ func (s *Source) LineNumberFor(pos int) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
result := sort.Search(len(*s.LineIndex), func(i int) bool {
|
||||
if i == 0 {
|
||||
return pos < (*s.LineIndex)[i]
|
||||
} else {
|
||||
return (*s.LineIndex)[i-1] < pos && pos < (*s.LineIndex)[i]
|
||||
}
|
||||
})
|
||||
result := sort.SearchInts(*s.LineIndex, pos)
|
||||
|
||||
// We've found something
|
||||
if result > -1 {
|
||||
|
@ -111,7 +105,6 @@ func (s *Source) LineNumberFor(pos int) int {
|
|||
}
|
||||
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
type Location struct {
|
||||
|
|
|
@ -118,7 +118,7 @@ func Run(flags map[string]bool, args []string) {
|
|||
}
|
||||
|
||||
rt := MakeRuntime([]string{cwd}, flags)
|
||||
rt.CreateNS("user", "REPL", true)
|
||||
rt.CreateNS("user", "RUN", true)
|
||||
|
||||
if len(args) == 0 {
|
||||
|
||||
|
@ -137,12 +137,8 @@ func Run(flags map[string]bool, args []string) {
|
|||
}
|
||||
|
||||
tmpl, e := template.New("run").Parse(
|
||||
`(def run-main
|
||||
(fn ()
|
||||
(require '({{.NS}} n))
|
||||
(n/main {{.Args}})))
|
||||
|
||||
(run-main)`,
|
||||
`(require '({{.NS}} n))
|
||||
(n/main {{.Args}})`,
|
||||
)
|
||||
|
||||
if e != nil {
|
||||
|
@ -160,7 +156,7 @@ func Run(flags map[string]bool, args []string) {
|
|||
fmt.Println(buf.String())
|
||||
}
|
||||
|
||||
ast, err := ReadString("*RUN*", buf.String())
|
||||
ast, err := ReadString("*INTERNAL*", buf.String())
|
||||
|
||||
if err != nil {
|
||||
PrintError(rt, err)
|
||||
|
|
|
@ -49,6 +49,10 @@ const (
|
|||
RuntimeError
|
||||
)
|
||||
|
||||
func (e ErrType) String() string {
|
||||
return [...]string{"Syntax Error", "Semantic Error", "Runtime Error"}[e]
|
||||
}
|
||||
|
||||
// IError defines the necessary functionality of the internal errors.
|
||||
type IError interface {
|
||||
// In order to point to a specific point in the input
|
||||
|
|
|
@ -29,6 +29,15 @@ package core
|
|||
// * Add the support for strings
|
||||
// * Add the support for kewords
|
||||
// * Add a shortcut for the `deref` function like `@x` => `(deref x)`
|
||||
// * A line of comment at the end of a list definition causes a synxtax error.
|
||||
// We need to fix it. For example:
|
||||
// (asdb xyz
|
||||
// ;; problematic comment line
|
||||
// )
|
||||
// Will fails. The reason being we call `readExpr` in `readList` and in the
|
||||
// `readExpr` when we read a line of comment we jump to a label and try to
|
||||
// read another expr which in our case it would read the end of list and throw
|
||||
// and error
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
@ -325,6 +334,8 @@ func readNumber(parser IParsable, neg bool) (IExpr, IError) {
|
|||
r := rune(char[0])
|
||||
if unicode.IsDigit(r) {
|
||||
result = result + *c
|
||||
} else if isValidForSymbol(char) {
|
||||
return nil, makeErrorAtPoint(parser, "Illegal token while scanning for a number.")
|
||||
} else {
|
||||
parser.back()
|
||||
break
|
||||
|
|
|
@ -64,12 +64,43 @@ func Println(rt *Runtime, ast ...IRepresentable) {
|
|||
fmt.Println(toPrintableString(ast...))
|
||||
}
|
||||
|
||||
func PrintError(rt *Runtime, err IError) {
|
||||
func printError(rt *Runtime, err IError, stage int) {
|
||||
loc := err.GetLocation()
|
||||
source := loc.GetSource()
|
||||
|
||||
startline := source.LineNumberFor(loc.GetStart())
|
||||
|
||||
if startline > 0 {
|
||||
startline -= 1
|
||||
}
|
||||
|
||||
endline := source.LineNumberFor(loc.GetEnd()) + 1
|
||||
|
||||
var lines string
|
||||
for i := startline; i <= endline; i++ {
|
||||
line := source.GetLine(i)
|
||||
if line != "----" {
|
||||
lines += fmt.Sprintf("%d:\t%s\n", i, line)
|
||||
}
|
||||
}
|
||||
|
||||
color.Yellow.Printf(
|
||||
"%d: At '%s'\n",
|
||||
stage,
|
||||
source.Path,
|
||||
)
|
||||
|
||||
color.White.Printf("%s\n", lines)
|
||||
|
||||
errTag := color.Red.Sprint(err.GetErrType().String())
|
||||
fmt.Printf("%s: %s\nAt: %d to %d\n", errTag, err.String(), loc.GetStart(), loc.GetEnd())
|
||||
|
||||
}
|
||||
|
||||
func printErrorWithTraceBack(rt *Runtime, err IError) {
|
||||
trace := err.GetStackTrace()
|
||||
fmt.Println(err)
|
||||
|
||||
for i, t := range *trace {
|
||||
fmt.Println(*t)
|
||||
caller := t.Caller
|
||||
callerLoc := caller.GetLocation()
|
||||
callerSource := callerLoc.GetSource()
|
||||
|
@ -84,23 +115,36 @@ func PrintError(rt *Runtime, err IError) {
|
|||
|
||||
var lines string
|
||||
for i := startline; i <= endline; i++ {
|
||||
fmt.Println(">>>>>>>>>> ", err)
|
||||
fLoc := t.Fn.GetLocation()
|
||||
fmt.Println(">>>>>>>>>> ", fLoc, fLoc.GetSource())
|
||||
|
||||
lines += fmt.Sprintf("%d:\t%s\n", i, fLoc.GetSource().GetLine(i))
|
||||
line := fLoc.GetSource().GetLine(i)
|
||||
if line != "----" {
|
||||
lines += fmt.Sprintf("%d:\t%s\n", i, line)
|
||||
}
|
||||
}
|
||||
|
||||
color.Yellow.Printf(
|
||||
"%d: In function '%s' at '%s'\n",
|
||||
"%d: In function '%s' at '%s':%d\n",
|
||||
i,
|
||||
t.Fn.GetName(),
|
||||
callerLoc.GetSource().Path,
|
||||
callerSource.LineNumberFor(callerLoc.GetStart()),
|
||||
)
|
||||
color.White.Printf("%s\n", lines)
|
||||
}
|
||||
loc := err.GetLocation()
|
||||
|
||||
errTag := color.Red.Sprint("ERROR")
|
||||
errTag := color.Red.Sprint(err.GetErrType().String())
|
||||
fmt.Printf("%s: %s\nAt: %d to %d\n", errTag, err.String(), loc.GetStart(), loc.GetEnd())
|
||||
}
|
||||
|
||||
func PrintError(rt *Runtime, err IError) {
|
||||
switch err.GetErrType() {
|
||||
case SyntaxError, SemanticError:
|
||||
printError(rt, err, 0)
|
||||
return
|
||||
case RuntimeError:
|
||||
printErrorWithTraceBack(rt, err)
|
||||
return
|
||||
default:
|
||||
panic(fmt.Sprintf("Don't know about error type '%d'", err.GetErrType()))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue