Added QueryResult and patched bugs

QueryResult now stores result items and position data, which aligns more
strongly with the rest of the library features than a plain
[]interface[}.  The design of the parser_test unittest was revised to
use array/map/scalar serialization (like match_test), since Go 1.3
redesigned maps to randomly order their keys. Since naive comparisons of
map data is now no longer possible, the unittest now sorts map
keys:value combinations.

* Patched a bug where getPosition("") was returning an invalid Position
* Revised parser_test to use serialization for comparisons for Go 1.3
diff --git a/jpath/match.go b/jpath/match.go
index c517157..bdc3db5 100644
--- a/jpath/match.go
+++ b/jpath/match.go
@@ -28,7 +28,7 @@
 }
 
 func (f *terminatingFn) Call(node interface{}, ctx *queryContext) {
-	ctx.appendResult(node)
+	ctx.result.appendResult(node)
 }
 
 // shim to ease functor writing
diff --git a/jpath/parser_test.go b/jpath/parser_test.go
index ec05f07..61908de 100644
--- a/jpath/parser_test.go
+++ b/jpath/parser_test.go
@@ -4,8 +4,55 @@
 	"fmt"
 	. "github.com/pelletier/go-toml"
 	"testing"
+  "sort"
+  "strings"
 )
 
+func valueString(root interface{}) string {
+  result := "" //fmt.Sprintf("%T:", root)
+	switch node := root.(type) {
+	case []interface{}:
+    items := []string{}
+    for _, v := range node {
+      items = append(items, valueString(v))
+    }
+    sort.Strings(items)
+    result = "[" + strings.Join(items, ", ") + "]"
+	case *TomlTree:
+    // workaround for unreliable map key ordering
+    items := []string{}
+    for _, k := range node.Keys() {
+      v := node.GetPath([]string{k})
+      items = append(items, k + ":" + valueString(v))
+    }
+    sort.Strings(items)
+    result = "{" + strings.Join(items, ", ") + "}"
+	case map[string]interface{}:
+    // workaround for unreliable map key ordering
+    items := []string{}
+    for k, v := range node {
+      items = append(items, k + ":" + valueString(v))
+    }
+    sort.Strings(items)
+    result = "{" + strings.Join(items, ", ") + "}"
+	case int64:
+    result += fmt.Sprintf("%d", node)
+  case string:
+    result += "'" + node + "'"
+  }
+  return result
+}
+
+func assertValue(t *testing.T, result, ref interface{}) {
+  pathStr := valueString(result)
+  refStr := valueString(ref)
+  if pathStr != refStr {
+    t.Errorf("values do not match")
+		t.Log("test:", pathStr)
+		t.Log("ref: ", refStr)
+  }
+}
+
 func assertQuery(t *testing.T, toml, query string, ref []interface{}) {
 	tree, err := Load(toml)
 	if err != nil {
@@ -13,59 +60,9 @@
 		return
 	}
 	results := Compile(query).Execute(tree)
-	assertValue(t, results, ref, "(("+query+")) -> ")
+	assertValue(t, results.Values(), ref)
 }
 
-func assertValue(t *testing.T, result, ref interface{}, location string) {
-	switch node := ref.(type) {
-	case []interface{}:
-		if resultNode, ok := result.([]interface{}); !ok {
-			t.Errorf("{%s} result value not of type %T: %T",
-				location, node, resultNode)
-		} else {
-			if len(node) != len(resultNode) {
-				t.Errorf("{%s} lengths do not match: %v vs %v",
-					location, node, resultNode)
-			} else {
-				for i, v := range node {
-					assertValue(t, resultNode[i], v, fmt.Sprintf("%s[%d]", location, i))
-				}
-			}
-		}
-	case map[string]interface{}:
-		if resultNode, ok := result.(*TomlTree); !ok {
-			t.Errorf("{%s} result value not of type %T: %T",
-				location, node, resultNode)
-		} else {
-			for k, v := range node {
-				assertValue(t, resultNode.GetPath([]string{k}), v, location+"."+k)
-			}
-		}
-	case int64:
-		if resultNode, ok := result.(int64); !ok {
-			t.Errorf("{%s} result value not of type %T: %T",
-				location, node, resultNode)
-		} else {
-			if node != resultNode {
-				t.Errorf("{%s} result value does not match", location)
-			}
-		}
-	case string:
-		if resultNode, ok := result.(string); !ok {
-			t.Errorf("{%s} result value not of type %T: %T",
-				location, node, resultNode)
-		} else {
-			if node != resultNode {
-				t.Errorf("{%s} result value does not match", location)
-			}
-		}
-	default:
-		if fmt.Sprintf("%v", node) != fmt.Sprintf("%v", ref) {
-			t.Errorf("{%s} result value does not match: %v != %v",
-				location, node, ref)
-		}
-	}
-}
 
 func TestQueryRoot(t *testing.T) {
 	assertQuery(t,
diff --git a/jpath/query.go b/jpath/query.go
index 3bf306c..3435515 100644
--- a/jpath/query.go
+++ b/jpath/query.go
@@ -1,21 +1,44 @@
 package jpath
 
 import (
-	_ "github.com/pelletier/go-toml"
+	. "github.com/pelletier/go-toml"
 )
 
 type nodeFilterFn func(node interface{}) bool
 type nodeFn func(node interface{}) interface{}
 
-// runtime context for executing query paths
-type queryContext struct {
-	filters *map[string]nodeFilterFn
-	scripts *map[string]nodeFn
-	results []interface{}
+type QueryResult struct {
+	items []interface{}
+  positions []Position
 }
 
-func (c *queryContext) appendResult(value interface{}) {
-	c.results = append(c.results, value)
+// TODO: modify after merging with rest of lib
+func (r *QueryResult) appendResult(node interface{}) {
+  r.items = append(r.items, node)
+  switch castNode := node.(type) {
+  case *TomlTree:
+    r.positions = append(r.positions, castNode.GetPosition(""))
+    //r.positions = append(r.positions, castNode.position)
+  //case *tomlValue:
+    //r.positions = append(r.positions, castNode.position)
+  default:
+    r.positions = append(r.positions, Position{})
+  }
+}
+
+func (r *QueryResult) Values() []interface{} {
+  return r.items
+}
+
+func (r *QueryResult) Positions() []Position {
+  return r.positions
+}
+
+// runtime context for executing query paths
+type queryContext struct {
+  result *QueryResult
+	filters *map[string]nodeFilterFn
+	scripts *map[string]nodeFn
 }
 
 // generic path functor interface
@@ -56,17 +79,22 @@
 	return parse(flow)
 }
 
-func (q *Query) Execute(node interface{}) interface{} {
+func (q *Query) Execute(tree *TomlTree) *QueryResult {
+  result := &QueryResult {
+    items: []interface{}{},
+    positions: []Position{},
+  }
 	if q.root == nil {
-		return []interface{}{node} // identity query for no predicates
-	}
-	ctx := &queryContext{
-		filters: q.filters,
-		scripts: q.scripts,
-		results: []interface{}{},
-	}
-	q.root.Call(node, ctx)
-	return ctx.results
+    result.appendResult(tree)
+	} else {
+    ctx := &queryContext{
+      result: result,
+      filters: q.filters,
+      scripts: q.scripts,
+    }
+    q.root.Call(tree, ctx)
+  }
+	return result
 }
 
 func (q *Query) SetFilter(name string, fn nodeFilterFn) {
diff --git a/parser.go b/parser.go
index c9f42a3..dcab890 100644
--- a/parser.go
+++ b/parser.go
@@ -70,9 +70,6 @@
 func parseStart(p *parser) parserStateFn {
 	tok := p.peek()
 
-	// prime position data with root tree instance
-	p.tree.position = tok.Position
-
 	// end of stream, parsing is finished
 	if tok == nil {
 		return nil
@@ -279,6 +276,7 @@
 
 func parse(flow chan token) *TomlTree {
 	result := newTomlTree()
+  result.position = Position{1,1}
 	parser := &parser{
 		flow:          flow,
 		tree:          result,
diff --git a/parser_test.go b/parser_test.go
index 761a181..10ac6d7 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -396,6 +396,7 @@
 	assertPosition(t,
 		"[foo]\nbar=42\nbaz=69",
 		map[string]Position{
+      "":        Position{1, 1},
 			"foo":     Position{1, 1},
 			"foo.bar": Position{2, 1},
 			"foo.baz": Position{3, 1},
@@ -406,6 +407,7 @@
 	assertPosition(t,
 		"  [foo]\n  bar=42\n  baz=69",
 		map[string]Position{
+      "":        Position{1, 1},
 			"foo":     Position{1, 3},
 			"foo.bar": Position{2, 3},
 			"foo.baz": Position{3, 3},
@@ -416,20 +418,9 @@
 	assertPosition(t,
 		"[[foo]]\nbar=42\nbaz=69",
 		map[string]Position{
+      "":        Position{1, 1},
 			"foo":     Position{1, 1},
 			"foo.bar": Position{2, 1},
 			"foo.baz": Position{3, 1},
 		})
 }
-
-func TestDocumentPositionsEmptyPath(t *testing.T) {
-	text := "[foo]\nbar=42\nbaz=69"
-	tree, err := Load(text)
-	if err != nil {
-		t.Errorf("Error loading document text: `%v`", text)
-		t.Errorf("Error: %v", err)
-	}
-	if pos := tree.GetPosition(""); !pos.Invalid() {
-		t.Errorf("Valid position was returned for empty path")
-	}
-}
diff --git a/toml.go b/toml.go
index 7cd74b0..678959a 100644
--- a/toml.go
+++ b/toml.go
@@ -28,7 +28,7 @@
 func newTomlTree() *TomlTree {
 	return &TomlTree{
 		values:   make(map[string]interface{}),
-		position: Position{0, 0},
+		position: Position{},
 	}
 }
 
@@ -103,7 +103,7 @@
 // GetPosition returns the position of the given key.
 func (t *TomlTree) GetPosition(key string) Position {
 	if key == "" {
-		return Position{0, 0}
+		return t.position
 	}
 	return t.GetPositionPath(strings.Split(key, "."))
 }