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