Add Location type and support to ILocatable

This commit is contained in:
Sameer Rahmani 2020-11-23 12:30:02 +00:00
parent a2725ba412
commit 57714accfc
8 changed files with 54 additions and 16 deletions

View File

@ -32,10 +32,32 @@ const (
Block // Dont' mistake it with block from other programming languages Block // Dont' mistake it with block from other programming languages
) )
type Location struct {
start int
end int
source *[]string
knownLocation bool
}
type ILocatable interface { type ILocatable interface {
GetLocation() int GetLocation() Location
}
func MakeLocation(input *[]string, start int, end int) Location {
return Location{
source: input,
start: start,
end: end,
knownLocation: true,
}
} }
type ITypable interface { type ITypable interface {
GetType() NodeType GetType() NodeType
} }
func MakeUnknownLocation() Location {
return Location{
knownLocation: false,
}
}

View File

@ -49,11 +49,11 @@ func (b *Block) ToDebugStr() string {
return fmt.Sprintf("%#v", b) return fmt.Sprintf("%#v", b)
} }
func (b *Block) GetLocation() int { func (b *Block) GetLocation() ast.Location {
if len(b.body) > 0 { if len(b.body) > 0 {
return b.body[0].GetLocation() return b.body[0].GetLocation()
} }
return -1 return ast.MakeUnknownLocation()
} }
func (b *Block) ToSlice() []IExpr { func (b *Block) ToSlice() []IExpr {

View File

@ -90,7 +90,6 @@ func MakeFunction(scope IScope, params IColl, body *Block) *Function {
// MakeFnScope a new scope for the body of a function. It binds the `bindings` // MakeFnScope a new scope for the body of a function. It binds the `bindings`
// to the given `values`. // to the given `values`.
func MakeFnScope(parent IScope, bindings IColl, values IColl) (*Scope, error) { func MakeFnScope(parent IScope, bindings IColl, values IColl) (*Scope, error) {
fmt.Printf("%s %s\n", bindings, values)
scope := MakeScope(parent.(*Scope)) scope := MakeScope(parent.(*Scope))
// TODO: Implement destructuring // TODO: Implement destructuring

View File

@ -29,8 +29,8 @@ func (n NilType) GetType() ast.NodeType {
return ast.Nil return ast.Nil
} }
func (n NilType) GetLocation() int { func (n NilType) GetLocation() ast.Location {
return 0 return ast.MakeUnknownLocation()
} }
func (n NilType) String() string { func (n NilType) String() string {

View File

@ -28,8 +28,8 @@ func (n NothingType) GetType() ast.NodeType {
return ast.Nothing return ast.Nothing
} }
func (n NothingType) GetLocation() int { func (n NothingType) GetLocation() ast.Location {
return -1 return ast.MakeUnknownLocation()
} }
func (n NothingType) String() string { func (n NothingType) String() string {

View File

@ -32,6 +32,7 @@ type IParsable interface {
peek(skipWhitespace bool) *string peek(skipWhitespace bool) *string
back() back()
GetLocation() int GetLocation() int
Buffer() *[]string
} }
type StringParser struct { type StringParser struct {
@ -81,6 +82,10 @@ func (sp *StringParser) GetLocation() int {
return sp.pos return sp.pos
} }
func (sp *StringParser) Buffer() *[]string {
return &sp.buffer
}
// END: IParsable --- // END: IParsable ---
func contains(s []rune, c rune) bool { func contains(s []rune, c rune) bool {
@ -132,7 +137,8 @@ func readRawSymbol(parser IParsable) (IExpr, error) {
} }
// TODO: Add support for ns qualified symbols // TODO: Add support for ns qualified symbols
return MakeSymbol(symbol), nil node := MakeNode(parser.Buffer(), parser.GetLocation()-len(symbol), parser.GetLocation())
return MakeSymbol(node, symbol), nil
} }
func readNumber(parser IParsable, neg bool) (IExpr, error) { func readNumber(parser IParsable, neg bool) (IExpr, error) {
@ -252,8 +258,9 @@ func readQuotedExpr(parser IParsable) (IExpr, error) {
return nil, err return nil, err
} }
symNode := MakeNode(parser.Buffer(), parser.GetLocation(), parser.GetLocation())
return MakeList([]IExpr{ return MakeList([]IExpr{
MakeSymbol("quote"), MakeSymbol(symNode, "quote"),
expr, expr,
}), nil }), nil
} }
@ -269,13 +276,15 @@ func readUnquotedExpr(parser IParsable) (IExpr, error) {
var err error var err error
var expr IExpr var expr IExpr
node := MakeNode(parser.Buffer(), parser.GetLocation(), parser.GetLocation())
if *c == "@" { if *c == "@" {
parser.next(true) parser.next(true)
sym = MakeSymbol("unquote-splicing") sym = MakeSymbol(node, "unquote-splicing")
expr, err = readExpr(parser) expr, err = readExpr(parser)
} else { } else {
sym = MakeSymbol("unquote") sym = MakeSymbol(node, "unquote")
expr, err = readExpr(parser) expr, err = readExpr(parser)
} }
@ -292,8 +301,9 @@ func readQuasiquotedExpr(parser IParsable) (IExpr, error) {
return nil, err return nil, err
} }
node := MakeNode(parser.Buffer(), parser.GetLocation(), parser.GetLocation())
return MakeList([]IExpr{ return MakeList([]IExpr{
MakeSymbol("quasiquote"), MakeSymbol(node, "quasiquote"),
expr, expr,
}), nil }), nil
} }

View File

@ -52,8 +52,9 @@ func (s *Symbol) IsRestable() bool {
return strings.HasPrefix(s.name, "&") return strings.HasPrefix(s.name, "&")
} }
func MakeSymbol(s string) *Symbol { func MakeSymbol(n Node, s string) *Symbol {
return &Symbol{ return &Symbol{
Node: n,
name: s, name: s,
} }
} }

View File

@ -50,10 +50,16 @@ type IExpr interface {
// Node struct is simply representing a Node in the AST which provides the // Node struct is simply representing a Node in the AST which provides the
// functionalities required to trace the code based on the location. // functionalities required to trace the code based on the location.
type Node struct { type Node struct {
location int location ast.Location
} }
// GetLocation returns the location of the Node in the source input // GetLocation returns the location of the Node in the source input
func (n Node) GetLocation() int { func (n Node) GetLocation() ast.Location {
return n.location return n.location
} }
func MakeNode(input *[]string, start int, end int) Node {
return Node{
location: ast.MakeLocation(input, start, end),
}
}