[Bootstrap] Update the printer functions to enhace the traceback visuals
This commit is contained in:
parent
c2d4273319
commit
c30c93442b
|
@ -12,17 +12,14 @@
|
|||
(defmacro defn
|
||||
(name args &body)
|
||||
(list 'do
|
||||
(list 'def name (cons 'fn (cons args body)))
|
||||
(list 'a1 ~args)))
|
||||
|
||||
|
||||
|
||||
|
||||
(list 'def name (cons 'fn (list args body)))))
|
||||
|
||||
(defn pp (x y)
|
||||
(asd)
|
||||
(println x))
|
||||
|
||||
(macroexpand '(pp 33 22))
|
||||
(def main
|
||||
(fn (&args)
|
||||
(fn ()
|
||||
(pp "sam" 2)
|
||||
(hello-world "world")))
|
||||
|
|
|
@ -47,9 +47,9 @@ const (
|
|||
|
||||
type Source struct {
|
||||
Buffer *[]string
|
||||
// It can be the path to the source file or something like "*in*"
|
||||
// for standard in
|
||||
Path string
|
||||
|
||||
// The namespace name which this source is describing
|
||||
NS string
|
||||
LineIndex *[]int
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ func GetBuiltinSource() *Source {
|
|||
lineindex := []int{len(buf) - 1}
|
||||
builtinSource = &Source{
|
||||
Buffer: &buf,
|
||||
Path: "Builtin",
|
||||
NS: "Serene.builtins",
|
||||
LineIndex: &lineindex,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,12 @@ type ICallStack interface {
|
|||
|
||||
type Frame struct {
|
||||
// Number of recursive calls to this function
|
||||
Count uint
|
||||
Fn IFn
|
||||
Count uint
|
||||
|
||||
// Function to call
|
||||
Callee IFn
|
||||
|
||||
// Where is the call happening
|
||||
Caller IExpr
|
||||
}
|
||||
|
||||
|
@ -66,7 +70,7 @@ type CallStack struct {
|
|||
}
|
||||
|
||||
func (f *Frame) String() string {
|
||||
return fmt.Sprintf("<Frame: FN: %s, Count: %d Caller: \n%s\n>", f.Fn, f.Count, f.Caller)
|
||||
return fmt.Sprintf("<Frame: FN: %s, Count: %d Caller: \n%s\n>", f.Callee, f.Count, f.Caller)
|
||||
}
|
||||
|
||||
func (c *CallStack) Count() uint {
|
||||
|
@ -78,7 +82,7 @@ func (c *CallStack) GetCurrentFn() IFn {
|
|||
return nil
|
||||
}
|
||||
|
||||
return c.head.data.Fn
|
||||
return c.head.data.Callee
|
||||
}
|
||||
|
||||
func (c *CallStack) Push(caller IExpr, f IFn) IError {
|
||||
|
@ -98,7 +102,7 @@ func (c *CallStack) Push(caller IExpr, f IFn) IError {
|
|||
if c.head == nil {
|
||||
c.head = &CallStackItem{
|
||||
data: Frame{
|
||||
Fn: f,
|
||||
Callee: f,
|
||||
Caller: caller,
|
||||
Count: 0,
|
||||
},
|
||||
|
@ -109,14 +113,14 @@ func (c *CallStack) Push(caller IExpr, f IFn) IError {
|
|||
nodeData := &c.head.data
|
||||
|
||||
// If the same function was on top of the stack
|
||||
if nodeData.Fn == f && caller == nodeData.Caller {
|
||||
if nodeData.Callee == f && caller == nodeData.Caller {
|
||||
// TODO: expand the check here to support address and location as well
|
||||
nodeData.Count++
|
||||
} else {
|
||||
c.head = &CallStackItem{
|
||||
prev: c.head,
|
||||
data: Frame{
|
||||
Fn: f,
|
||||
Callee: f,
|
||||
Caller: caller,
|
||||
Count: 0,
|
||||
},
|
||||
|
@ -138,7 +142,7 @@ func (c *CallStack) Pop() *Frame {
|
|||
c.head = result.prev
|
||||
c.count--
|
||||
if c.debug {
|
||||
fmt.Printf("[Stack] <-- %s\n", result.data.Fn)
|
||||
fmt.Printf("[Stack] <-- %s\n", result.data.Callee)
|
||||
}
|
||||
return &result.data
|
||||
}
|
||||
|
@ -178,10 +182,10 @@ func MakeCallStack(debugMode bool) CallStack {
|
|||
}
|
||||
}
|
||||
|
||||
func MakeFrame(caller IExpr, f IFn, count uint) *Frame {
|
||||
func MakeFrame(rt *Runtime, caller IExpr, f IFn, count uint) *Frame {
|
||||
return &Frame{
|
||||
Count: count,
|
||||
Caller: caller,
|
||||
Fn: f,
|
||||
Callee: f,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ type mainRunner struct {
|
|||
}
|
||||
|
||||
func rep(rt *Runtime, line string) {
|
||||
ast, err := ReadString("*REPL*", line)
|
||||
ast, err := ReadString("serene.internal", line)
|
||||
|
||||
if err != nil {
|
||||
PrintError(rt, err)
|
||||
|
@ -118,7 +118,7 @@ func Run(flags map[string]bool, args []string) {
|
|||
}
|
||||
|
||||
rt := MakeRuntime([]string{cwd}, flags)
|
||||
rt.CreateNS("user", "RUN", true)
|
||||
rt.CreateNS("serene.internal", "RUN", true)
|
||||
|
||||
if len(args) == 0 {
|
||||
|
||||
|
@ -156,7 +156,7 @@ func Run(flags map[string]bool, args []string) {
|
|||
fmt.Println(buf.String())
|
||||
}
|
||||
|
||||
ast, err := ReadString("*INTERNAL*", buf.String())
|
||||
ast, err := ReadString("serene.internal", buf.String())
|
||||
|
||||
if err != nil {
|
||||
PrintError(rt, err)
|
||||
|
|
|
@ -135,14 +135,15 @@ func MakePlainError(msg string) IError {
|
|||
// MakeError creates an Error which points to the given IExpr `e` as
|
||||
// the root of the error.
|
||||
func MakeError(rt *Runtime, e IExpr, msg string) IError {
|
||||
frame := MakeFrame(e, rt.Stack.GetCurrentFn(), 1)
|
||||
trace := append(*rt.Stack.ToTraceBack(), frame)
|
||||
rt.Stack.Push(e, rt.Stack.GetCurrentFn())
|
||||
// frame := MakeFrame(e, rt.Stack.GetCurrentFn(), 1)
|
||||
// trace := append(*rt.Stack.ToTraceBack(), frame)
|
||||
|
||||
return &Error{
|
||||
Node: MakeNodeFromExpr(e),
|
||||
errtype: RuntimeError,
|
||||
msg: msg,
|
||||
trace: &trace,
|
||||
trace: rt.Stack.ToTraceBack(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,10 +156,11 @@ func MakeSyntaxErrorf(n Node, msg string, a ...interface{}) IError {
|
|||
}
|
||||
|
||||
func MakeSemanticError(rt *Runtime, e IExpr, errno errors.Errno, msg string) IError {
|
||||
currentFn := rt.Stack.GetCurrentFn()
|
||||
|
||||
//currentFn := rt.Stack.GetCurrentFn()
|
||||
rt.Stack.Push(e, rt.Stack.GetCurrentFn())
|
||||
frames := &[]*Frame{
|
||||
MakeFrame(e, currentFn, 1),
|
||||
//MakeFrame(e, currentFn, 1),
|
||||
rt.Stack.Pop(),
|
||||
}
|
||||
|
||||
return &Error{
|
||||
|
|
|
@ -170,7 +170,7 @@ func (sp *StringParser) GetLocation() int {
|
|||
func (sp *StringParser) GetSource() *ast.Source {
|
||||
return &ast.Source{
|
||||
Buffer: &sp.buffer,
|
||||
Path: sp.source,
|
||||
NS: sp.source,
|
||||
LineIndex: &sp.lineIndex,
|
||||
}
|
||||
}
|
||||
|
@ -610,13 +610,13 @@ loop:
|
|||
// just anbstraction for a ordered collection of expressions.
|
||||
// It doesn't have anything to do with the concept of blocks
|
||||
// from other programming languages.
|
||||
func ParseToAST(source string, input string) (*Block, IError) {
|
||||
func ParseToAST(ns string, input string) (*Block, IError) {
|
||||
|
||||
var ast Block
|
||||
parser := StringParser{
|
||||
buffer: strings.Split(input, ""),
|
||||
pos: 0,
|
||||
source: source,
|
||||
source: ns,
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
|
@ -87,7 +87,7 @@ func printError(rt *Runtime, err IError, stage int) {
|
|||
color.Yellow.Printf(
|
||||
"%d: At '%s':%d\n",
|
||||
stage,
|
||||
source.Path,
|
||||
source.NS,
|
||||
source.LineNumberFor(loc.GetStart()),
|
||||
)
|
||||
|
||||
|
@ -98,45 +98,74 @@ func printError(rt *Runtime, err IError, stage int) {
|
|||
|
||||
}
|
||||
|
||||
func frameCaption(traces *TraceBack, frameIndex int) string {
|
||||
if frameIndex >= len(*traces) || frameIndex < 0 {
|
||||
panic("Out of range index for the traceback array. It shouldn't happen!!!")
|
||||
}
|
||||
var prevFrame *Frame
|
||||
place := "*run*"
|
||||
frame := (*traces)[frameIndex]
|
||||
|
||||
loc := frame.Caller.GetLocation()
|
||||
source := loc.GetSource()
|
||||
|
||||
if frameIndex != 0 {
|
||||
prevFrame = (*traces)[frameIndex-1]
|
||||
place = prevFrame.Callee.GetName()
|
||||
}
|
||||
|
||||
return color.Yellow.Sprintf(
|
||||
"%d: In function '%s' at '%s':%d\n",
|
||||
frameIndex,
|
||||
place,
|
||||
source.NS,
|
||||
source.LineNumberFor(loc.GetStart()),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func frameSource(traces *TraceBack, frameIndex int) string {
|
||||
if frameIndex >= len(*traces) || frameIndex < 0 {
|
||||
panic("Out of range index for the traceback array. It shouldn't happen!!!")
|
||||
}
|
||||
|
||||
frame := (*traces)[frameIndex]
|
||||
caller := frame.Caller
|
||||
callerLoc := caller.GetLocation()
|
||||
callerSource := callerLoc.GetSource()
|
||||
|
||||
startline := callerSource.LineNumberFor(callerLoc.GetStart())
|
||||
|
||||
if startline > 0 {
|
||||
startline -= 1
|
||||
}
|
||||
|
||||
endline := callerSource.LineNumberFor(callerLoc.GetEnd()) + 1
|
||||
|
||||
var lines string
|
||||
for i := startline; i <= endline; i++ {
|
||||
fLoc := frame.Caller.GetLocation()
|
||||
|
||||
if fLoc.IsKnownLocaiton() {
|
||||
line := fLoc.GetSource().GetLine(i)
|
||||
if line != "----" {
|
||||
lines += fmt.Sprintf("%d:\t%s\n", i, line)
|
||||
}
|
||||
} else {
|
||||
lines += "Builtin\n"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
func printErrorWithTraceBack(rt *Runtime, err IError) {
|
||||
trace := err.GetStackTrace()
|
||||
|
||||
for i, t := range *trace {
|
||||
caller := t.Caller
|
||||
callerLoc := caller.GetLocation()
|
||||
callerSource := callerLoc.GetSource()
|
||||
|
||||
startline := callerSource.LineNumberFor(callerLoc.GetStart())
|
||||
|
||||
if startline > 0 {
|
||||
startline -= 1
|
||||
}
|
||||
|
||||
endline := callerSource.LineNumberFor(callerLoc.GetEnd()) + 1
|
||||
|
||||
var lines string
|
||||
for i := startline; i <= endline; i++ {
|
||||
fLoc := t.Caller.GetLocation()
|
||||
|
||||
if fLoc.IsKnownLocaiton() {
|
||||
line := fLoc.GetSource().GetLine(i)
|
||||
if line != "----" {
|
||||
lines += fmt.Sprintf("%d:\t%s\n", i, line)
|
||||
}
|
||||
} else {
|
||||
lines += "Builtin\n"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
color.Yellow.Printf(
|
||||
"%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)
|
||||
for i := range *trace {
|
||||
fmt.Print(frameCaption(trace, i))
|
||||
color.White.Printf(frameSource(trace, i))
|
||||
}
|
||||
loc := err.GetLocation()
|
||||
errTag := color.Red.Sprint(err.GetErrType().String())
|
||||
|
|
|
@ -18,6 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
package core
|
||||
|
||||
func ReadString(src string, input string) (*Block, IError) {
|
||||
return ParseToAST(src, input)
|
||||
func ReadString(ns string, input string) (*Block, IError) {
|
||||
return ParseToAST(ns, input)
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ func (r *Runtime) LoadNS(ns *Symbol) (*loadedForms, IError) {
|
|||
return nil, readError
|
||||
}
|
||||
|
||||
body, e := ReadString(possibleFile, string(data))
|
||||
body, e := ReadString(ns.GetName(), string(data))
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue