From c30c93442b0350f2898e186403d9f4c3fa868c2a Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Sun, 10 Jan 2021 17:03:52 +0000 Subject: [PATCH] [Bootstrap] Update the printer functions to enhace the traceback visuals --- bootstrap/examples/hello-world.srn | 11 ++- bootstrap/pkg/ast/ast.go | 8 +-- bootstrap/pkg/core/call_stack.go | 24 ++++--- bootstrap/pkg/core/core.go | 6 +- bootstrap/pkg/core/errors.go | 14 ++-- bootstrap/pkg/core/parser.go | 6 +- bootstrap/pkg/core/printer.go | 103 ++++++++++++++++++----------- bootstrap/pkg/core/reader.go | 4 +- bootstrap/pkg/core/runtime.go | 2 +- 9 files changed, 105 insertions(+), 73 deletions(-) diff --git a/bootstrap/examples/hello-world.srn b/bootstrap/examples/hello-world.srn index 28483ec..01708b5 100644 --- a/bootstrap/examples/hello-world.srn +++ b/bootstrap/examples/hello-world.srn @@ -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"))) diff --git a/bootstrap/pkg/ast/ast.go b/bootstrap/pkg/ast/ast.go index 7c79f38..20e3de2 100644 --- a/bootstrap/pkg/ast/ast.go +++ b/bootstrap/pkg/ast/ast.go @@ -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, } } diff --git a/bootstrap/pkg/core/call_stack.go b/bootstrap/pkg/core/call_stack.go index 5490fa0..44c5280 100644 --- a/bootstrap/pkg/core/call_stack.go +++ b/bootstrap/pkg/core/call_stack.go @@ -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("", f.Fn, f.Count, f.Caller) + return fmt.Sprintf("", 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, } } diff --git a/bootstrap/pkg/core/core.go b/bootstrap/pkg/core/core.go index e007c47..de714ea 100644 --- a/bootstrap/pkg/core/core.go +++ b/bootstrap/pkg/core/core.go @@ -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) diff --git a/bootstrap/pkg/core/errors.go b/bootstrap/pkg/core/errors.go index 473e143..7d118d9 100644 --- a/bootstrap/pkg/core/errors.go +++ b/bootstrap/pkg/core/errors.go @@ -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{ diff --git a/bootstrap/pkg/core/parser.go b/bootstrap/pkg/core/parser.go index ac1362a..374c6f2 100644 --- a/bootstrap/pkg/core/parser.go +++ b/bootstrap/pkg/core/parser.go @@ -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 { diff --git a/bootstrap/pkg/core/printer.go b/bootstrap/pkg/core/printer.go index ecadfb9..436e7e8 100644 --- a/bootstrap/pkg/core/printer.go +++ b/bootstrap/pkg/core/printer.go @@ -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()) diff --git a/bootstrap/pkg/core/reader.go b/bootstrap/pkg/core/reader.go index 040ba88..3e9e217 100644 --- a/bootstrap/pkg/core/reader.go +++ b/bootstrap/pkg/core/reader.go @@ -18,6 +18,6 @@ along with this program. If not, see . 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) } diff --git a/bootstrap/pkg/core/runtime.go b/bootstrap/pkg/core/runtime.go index 3b1370d..e2998b6 100644 --- a/bootstrap/pkg/core/runtime.go +++ b/bootstrap/pkg/core/runtime.go @@ -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 }