Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save a tiny bit of memory by rearranging fields; also using the newer way to "unsafely" instantiate a slice: #150

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 19 additions & 39 deletions bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"math"
"reflect"
"regexp"
"runtime"
"strings"
Expand All @@ -18,7 +17,7 @@ import (
)

// maintain a map of read functions that can be called from C
var readFuncs = &readFuncsMap{funcs: make(map[int]ReadFunc)}
var readFuncs = &readFuncsMap{funcs: map[int]ReadFunc{}}

// Parse is a shortcut for parsing bytes of source code,
// returns root node
Expand All @@ -44,9 +43,9 @@ func ParseCtx(ctx context.Context, content []byte, lang *Language) (*Node, error

// Parser produces concrete syntax tree based on source code using Language
type Parser struct {
isClosed bool
c *C.TSParser
cancel *uintptr
isClosed bool
}

// NewParser creates new Parser
Expand Down Expand Up @@ -259,7 +258,7 @@ func (p *Parser) newTree(c *C.TSTree) *Tree {
base := &BaseTree{c: c}
runtime.SetFinalizer(base, (*BaseTree).Close)

newTree := &Tree{p: p, BaseTree: base, cache: make(map[C.TSNode]*Node)}
newTree := &Tree{p: p, BaseTree: base, cache: map[C.TSNode]*Node{}}
return newTree
}

Expand Down Expand Up @@ -698,16 +697,15 @@ func QueryErrorTypeToString(errorType QueryErrorType) string {
default:
return "unknown"
}

}

// QueryError - if there is an error in the query,
// then the Offset argument will be set to the byte offset of the error,
// and the Type argument will be set to a value that indicates the type of error.
type QueryError struct {
Offset uint32
Type QueryErrorType
Message string
Type QueryErrorType
Offset uint32
}

func (qe *QueryError) Error() string {
Expand Down Expand Up @@ -891,18 +889,13 @@ type QueryPredicateStep struct {

func (q *Query) PredicatesForPattern(patternIndex uint32) [][]QueryPredicateStep {
var (
length C.uint32_t
cPredicateSteps []C.TSQueryPredicateStep
predicateSteps []QueryPredicateStep
length C.uint32_t
predicateSteps []QueryPredicateStep
)

cPredicateStep := C.ts_query_predicates_for_pattern(q.c, C.uint32_t(patternIndex), &length)
cPredicateSteps := unsafe.Slice(cPredicateStep, int(length))

count := int(length)
slice := (*reflect.SliceHeader)((unsafe.Pointer(&cPredicateSteps)))
slice.Cap = count
slice.Len = count
slice.Data = uintptr(unsafe.Pointer(cPredicateStep))
for _, s := range cPredicateSteps {
stepType := QueryPredicateStepType(s._type)
valueId := uint32(s.value_id)
Expand Down Expand Up @@ -989,26 +982,23 @@ func (qc *QueryCursor) Close() {

// QueryCapture is a captured node by a query with an index
type QueryCapture struct {
Index uint32
Node *Node
Index uint32
}

// QueryMatch - you can then iterate over the matches.
type QueryMatch struct {
Captures []QueryCapture
ID uint32
PatternIndex uint16
Captures []QueryCapture
}

// NextMatch iterates over matches.
// This function will return (nil, false) when there are no more matches.
// Otherwise, it will populate the QueryMatch with data
// about which pattern matched and which nodes were captured.
func (qc *QueryCursor) NextMatch() (*QueryMatch, bool) {
var (
cqm C.TSQueryMatch
cqc []C.TSQueryCapture
)
var cqm C.TSQueryMatch

if ok := C.ts_query_cursor_next_match(qc.c, &cqm); !bool(ok) {
return nil, false
Expand All @@ -1019,15 +1009,11 @@ func (qc *QueryCursor) NextMatch() (*QueryMatch, bool) {
PatternIndex: uint16(cqm.pattern_index),
}

count := int(cqm.capture_count)
slice := (*reflect.SliceHeader)((unsafe.Pointer(&cqc)))
slice.Cap = count
slice.Len = count
slice.Data = uintptr(unsafe.Pointer(cqm.captures))
cqc := unsafe.Slice(cqm.captures, int(cqm.capture_count))
for _, c := range cqc {
idx := uint32(c.index)
node := qc.t.cachedNode(c.node)
qm.Captures = append(qm.Captures, QueryCapture{idx, node})
qm.Captures = append(qm.Captures, QueryCapture{Index: idx, Node: node})
}

return qm, true
Expand All @@ -1036,7 +1022,6 @@ func (qc *QueryCursor) NextMatch() (*QueryMatch, bool) {
func (qc *QueryCursor) NextCapture() (*QueryMatch, uint32, bool) {
var (
cqm C.TSQueryMatch
cqc []C.TSQueryCapture
captureIndex C.uint32_t
)

Expand All @@ -1049,15 +1034,11 @@ func (qc *QueryCursor) NextCapture() (*QueryMatch, uint32, bool) {
PatternIndex: uint16(cqm.pattern_index),
}

count := int(cqm.capture_count)
slice := (*reflect.SliceHeader)((unsafe.Pointer(&cqc)))
slice.Cap = count
slice.Len = count
slice.Data = uintptr(unsafe.Pointer(cqm.captures))
cqc := unsafe.Slice(cqm.captures, int(cqm.capture_count))
for _, c := range cqc {
idx := uint32(c.index)
node := qc.t.cachedNode(c.node)
qm.Captures = append(qm.Captures, QueryCapture{idx, node})
qm.Captures = append(qm.Captures, QueryCapture{Index: idx, Node: node})
}

return qm, uint32(captureIndex), true
Expand Down Expand Up @@ -1144,10 +1125,10 @@ func (qc *QueryCursor) FilterPredicates(m *QueryMatch, input []byte) *QueryMatch
}
}

if matchedAll == false {
// TODO: This is an ineffective break statement. Is it a bug or just superfluous?
if !matchedAll {
break
}

case "match?", "not-match?":
isPositive := operator == "match?"

Expand All @@ -1173,15 +1154,14 @@ func (qc *QueryCursor) FilterPredicates(m *QueryMatch, input []byte) *QueryMatch
}

return qm

}

// keeps callbacks for parser.parse method
type readFuncsMap struct {
sync.Mutex

funcs map[int]ReadFunc
count int

sync.Mutex
}

func (m *readFuncsMap) register(f ReadFunc) int {
Expand Down
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module github.com/smacker/go-tree-sitter

go 1.13
go 1.17

require github.com/stretchr/testify v1.7.4

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)