Implement diag.Diagable on MuIL AST nodes
This ensures that source context information flows automatically from MuIL AST nodes to the various diag-related functions.
This commit is contained in:
parent
3ff9e83f63
commit
2964bf6ad0
|
@ -4,8 +4,8 @@ package diag
|
|||
|
||||
// Pos represents a position in a file.
|
||||
type Pos struct {
|
||||
Ln int
|
||||
Col int
|
||||
Line int // a 1-based line number
|
||||
Column int // a 0-based column number
|
||||
}
|
||||
|
||||
// EmptyPos may be used when no position is needed.
|
||||
|
@ -13,19 +13,19 @@ var EmptyPos = Pos{0, 0}
|
|||
|
||||
// IsEmpty returns true if the Pos information is missing.
|
||||
func (pos Pos) IsEmpty() bool {
|
||||
return pos.Ln == 0 && pos.Col == 0
|
||||
return pos.Line == 0 && pos.Column == 0
|
||||
}
|
||||
|
||||
// Location represents a region spanning two positions in a file.
|
||||
type Location struct {
|
||||
From Pos
|
||||
To Pos
|
||||
Start Pos // a starting position.
|
||||
End *Pos // an ending position; if nil, represents a point.
|
||||
}
|
||||
|
||||
// EmptyLocation may be used when no position information is available.
|
||||
var EmptyLocation = Location{EmptyPos, EmptyPos}
|
||||
var EmptyLocation = Location{EmptyPos, nil}
|
||||
|
||||
// IsEmpty returns true if the Location information is missing.
|
||||
func (loc Location) IsEmpty() bool {
|
||||
return loc.From.IsEmpty() && loc.To.IsEmpty()
|
||||
return loc.Start.IsEmpty() && (loc.End == nil || loc.End.IsEmpty())
|
||||
}
|
||||
|
|
|
@ -114,9 +114,9 @@ func (d *defaultSink) Stringify(diag *Diag, prefix string, args ...interface{})
|
|||
|
||||
if diag.Loc != nil && !diag.Loc.IsEmpty() {
|
||||
buffer.WriteRune(':')
|
||||
buffer.WriteString(strconv.Itoa(diag.Loc.From.Ln))
|
||||
buffer.WriteString(strconv.Itoa(diag.Loc.Start.Line))
|
||||
buffer.WriteRune(':')
|
||||
buffer.WriteString(strconv.Itoa(diag.Loc.From.Col))
|
||||
buffer.WriteString(strconv.Itoa(diag.Loc.Start.Column))
|
||||
}
|
||||
buffer.WriteString(": ")
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"github.com/marapongo/mu/pkg/diag"
|
||||
"github.com/marapongo/mu/pkg/symbols"
|
||||
)
|
||||
|
||||
|
@ -30,10 +31,34 @@ type node struct {
|
|||
Loc *Location `json:"loc,omitempty"`
|
||||
}
|
||||
|
||||
var _ diag.Diagable = (*node)(nil)
|
||||
|
||||
func (node *node) nd() {}
|
||||
func (node *node) GetKind() NodeKind { return node.Kind }
|
||||
func (node *node) GetLoc() *Location { return node.Loc }
|
||||
|
||||
func (node *node) Where() (*diag.Document, *diag.Location) {
|
||||
// TODO: consider caching Document objects; allocating one per Node is wasteful.
|
||||
// TODO: for development scenarios, it would be really great to recover the original source file text for purposes
|
||||
// of the diag.Document part. Doing so would give nice error messages tied back to the original source code
|
||||
// for any errors associated with the AST. Absent that, we will simply return nil.
|
||||
if node.Loc == nil {
|
||||
return nil, nil
|
||||
} else {
|
||||
var doc *diag.Document
|
||||
if node.Loc.File != nil {
|
||||
doc = diag.NewDocument(*node.Loc.File)
|
||||
}
|
||||
var end *diag.Pos
|
||||
if node.Loc.End != nil {
|
||||
end = &diag.Pos{int(node.Loc.End.Line), int(node.Loc.End.Column)}
|
||||
}
|
||||
return doc, &diag.Location{
|
||||
diag.Pos{int(node.Loc.Start.Line), int(node.Loc.Start.Column)}, end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Identifier represents a simple string token associated with its source location context.
|
||||
type Identifier struct {
|
||||
node
|
||||
|
|
|
@ -11,6 +11,6 @@ type Location struct {
|
|||
|
||||
// Position consists of a 1-indexed `line` number and a 0-indexed `column` number.
|
||||
type Position struct {
|
||||
Line int64 `json:"line"` // >= 1
|
||||
Column int64 `json:"column"` // >= 0
|
||||
Line int64 `json:"line"` // a 1-based line number
|
||||
Column int64 `json:"column"` // a 0-based column number
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue