[Bootstrap] Update the printer functions to enhace the traceback visuals

This commit is contained in:
Sameer Rahmani 2021-01-10 17:03:52 +00:00
parent c2d4273319
commit c30c93442b
9 changed files with 105 additions and 73 deletions

View File

@ -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")))

View File

@ -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,
}
}

View File

@ -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,
}
}

View File

@ -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)

View File

@ -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{

View File

@ -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 {

View File

@ -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())

View File

@ -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)
}

View File

@ -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
}