[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)
|
(fn (name)
|
||||||
(println "hello" name)))
|
(println "hello" name)))
|
||||||
|
|
||||||
|
(def a1
|
||||||
|
(fn (x y)
|
||||||
|
x))
|
||||||
|
|
||||||
(defmacro defn
|
(defmacro defn
|
||||||
(name args &body)
|
(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)
|
(defn pp (x y)
|
||||||
(println x))
|
(println x))
|
||||||
|
|
||||||
(def main
|
(def main
|
||||||
(fn (&args)
|
(fn (&args)
|
||||||
(pp "sam")
|
(pp "sam" 2)
|
||||||
(hello-world "world")))
|
(hello-world "world")))
|
||||||
|
|
|
@ -66,7 +66,7 @@ func (s *Source) GetLine(linenum int) string {
|
||||||
if linenum > 0 && linenum < len(lines) {
|
if linenum > 0 && linenum < len(lines) {
|
||||||
return lines[linenum-1]
|
return lines[linenum-1]
|
||||||
}
|
}
|
||||||
return "!!!"
|
return "----"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) LineNumberFor(pos int) int {
|
func (s *Source) LineNumberFor(pos int) int {
|
||||||
|
@ -96,13 +96,7 @@ func (s *Source) LineNumberFor(pos int) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
result := sort.Search(len(*s.LineIndex), func(i int) bool {
|
result := sort.SearchInts(*s.LineIndex, pos)
|
||||||
if i == 0 {
|
|
||||||
return pos < (*s.LineIndex)[i]
|
|
||||||
} else {
|
|
||||||
return (*s.LineIndex)[i-1] < pos && pos < (*s.LineIndex)[i]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// We've found something
|
// We've found something
|
||||||
if result > -1 {
|
if result > -1 {
|
||||||
|
@ -111,7 +105,6 @@ func (s *Source) LineNumberFor(pos int) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Location struct {
|
type Location struct {
|
||||||
|
|
|
@ -118,7 +118,7 @@ func Run(flags map[string]bool, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rt := MakeRuntime([]string{cwd}, flags)
|
rt := MakeRuntime([]string{cwd}, flags)
|
||||||
rt.CreateNS("user", "REPL", true)
|
rt.CreateNS("user", "RUN", true)
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|
||||||
|
@ -137,12 +137,8 @@ func Run(flags map[string]bool, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpl, e := template.New("run").Parse(
|
tmpl, e := template.New("run").Parse(
|
||||||
`(def run-main
|
`(require '({{.NS}} n))
|
||||||
(fn ()
|
(n/main {{.Args}})`,
|
||||||
(require '({{.NS}} n))
|
|
||||||
(n/main {{.Args}})))
|
|
||||||
|
|
||||||
(run-main)`,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
@ -160,7 +156,7 @@ func Run(flags map[string]bool, args []string) {
|
||||||
fmt.Println(buf.String())
|
fmt.Println(buf.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
ast, err := ReadString("*RUN*", buf.String())
|
ast, err := ReadString("*INTERNAL*", buf.String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
PrintError(rt, err)
|
PrintError(rt, err)
|
||||||
|
|
|
@ -49,6 +49,10 @@ const (
|
||||||
RuntimeError
|
RuntimeError
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (e ErrType) String() string {
|
||||||
|
return [...]string{"Syntax Error", "Semantic Error", "Runtime Error"}[e]
|
||||||
|
}
|
||||||
|
|
||||||
// IError defines the necessary functionality of the internal errors.
|
// IError defines the necessary functionality of the internal errors.
|
||||||
type IError interface {
|
type IError interface {
|
||||||
// In order to point to a specific point in the input
|
// 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 strings
|
||||||
// * Add the support for kewords
|
// * Add the support for kewords
|
||||||
// * Add a shortcut for the `deref` function like `@x` => `(deref x)`
|
// * 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 (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -325,6 +334,8 @@ func readNumber(parser IParsable, neg bool) (IExpr, IError) {
|
||||||
r := rune(char[0])
|
r := rune(char[0])
|
||||||
if unicode.IsDigit(r) {
|
if unicode.IsDigit(r) {
|
||||||
result = result + *c
|
result = result + *c
|
||||||
|
} else if isValidForSymbol(char) {
|
||||||
|
return nil, makeErrorAtPoint(parser, "Illegal token while scanning for a number.")
|
||||||
} else {
|
} else {
|
||||||
parser.back()
|
parser.back()
|
||||||
break
|
break
|
||||||
|
|
|
@ -64,12 +64,43 @@ func Println(rt *Runtime, ast ...IRepresentable) {
|
||||||
fmt.Println(toPrintableString(ast...))
|
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()
|
trace := err.GetStackTrace()
|
||||||
fmt.Println(err)
|
|
||||||
for i, t := range *trace {
|
for i, t := range *trace {
|
||||||
fmt.Println(*t)
|
|
||||||
caller := t.Caller
|
caller := t.Caller
|
||||||
callerLoc := caller.GetLocation()
|
callerLoc := caller.GetLocation()
|
||||||
callerSource := callerLoc.GetSource()
|
callerSource := callerLoc.GetSource()
|
||||||
|
@ -84,23 +115,36 @@ func PrintError(rt *Runtime, err IError) {
|
||||||
|
|
||||||
var lines string
|
var lines string
|
||||||
for i := startline; i <= endline; i++ {
|
for i := startline; i <= endline; i++ {
|
||||||
fmt.Println(">>>>>>>>>> ", err)
|
|
||||||
fLoc := t.Fn.GetLocation()
|
fLoc := t.Fn.GetLocation()
|
||||||
fmt.Println(">>>>>>>>>> ", fLoc, fLoc.GetSource())
|
line := fLoc.GetSource().GetLine(i)
|
||||||
|
if line != "----" {
|
||||||
lines += fmt.Sprintf("%d:\t%s\n", i, fLoc.GetSource().GetLine(i))
|
lines += fmt.Sprintf("%d:\t%s\n", i, line)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
color.Yellow.Printf(
|
color.Yellow.Printf(
|
||||||
"%d: In function '%s' at '%s'\n",
|
"%d: In function '%s' at '%s':%d\n",
|
||||||
i,
|
i,
|
||||||
t.Fn.GetName(),
|
t.Fn.GetName(),
|
||||||
callerLoc.GetSource().Path,
|
callerLoc.GetSource().Path,
|
||||||
|
callerSource.LineNumberFor(callerLoc.GetStart()),
|
||||||
)
|
)
|
||||||
color.White.Printf("%s\n", lines)
|
color.White.Printf("%s\n", lines)
|
||||||
}
|
}
|
||||||
loc := err.GetLocation()
|
loc := err.GetLocation()
|
||||||
|
errTag := color.Red.Sprint(err.GetErrType().String())
|
||||||
errTag := color.Red.Sprint("ERROR")
|
|
||||||
fmt.Printf("%s: %s\nAt: %d to %d\n", errTag, err.String(), loc.GetStart(), loc.GetEnd())
|
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