diff --git a/query/gremlin/build_iterator.go b/query/gremlin/build_iterator.go index 2a0b800..c2a9108 100644 --- a/query/gremlin/build_iterator.go +++ b/query/gremlin/build_iterator.go @@ -25,21 +25,15 @@ import ( "github.com/google/cayley/quad" ) -func getStrings(obj *otto.Object, field string) []string { - strings := make([]string, 0) - val, _ := obj.Get(field) - if !val.IsUndefined() { - export, _ := val.Export() - array := export.([]interface{}) - for _, arg := range array { - strings = append(strings, arg.(string)) - } +func propertiesOf(obj *otto.Object, name string) []string { + val, _ := obj.Get(name) + if val.IsUndefined() { + return nil } - return strings + export, _ := val.Export() + return export.([]string) } -func getStringArgs(obj *otto.Object) []string { return getStrings(obj, "string_args") } - func buildIteratorTree(obj *otto.Object, ts graph.TripleStore) graph.Iterator { if !isVertexChain(obj) { return iterator.NewNull() @@ -47,7 +41,7 @@ func buildIteratorTree(obj *otto.Object, ts graph.TripleStore) graph.Iterator { return buildIteratorTreeHelper(obj, ts, iterator.NewNull()) } -func makeListOfStringsFromArrayValue(obj *otto.Object) []string { +func stringsFrom(obj *otto.Object) []string { var output []string lengthValue, _ := obj.Get("length") length, _ := lengthValue.ToInteger() @@ -55,14 +49,10 @@ func makeListOfStringsFromArrayValue(obj *otto.Object) []string { for index := uint32(0); index < ulength; index += 1 { name := strconv.FormatInt(int64(index), 10) value, err := obj.Get(name) - if err != nil { + if err != nil || !value.IsString() { continue } - if !value.IsString() { - continue - } - s, _ := value.ToString() - output = append(output, s) + output = append(output, value.String()) } return output } @@ -87,7 +77,7 @@ func buildIteratorFromValue(val otto.Value, ts graph.TripleStore) graph.Iterator return buildIteratorTree(val.Object(), ts) case "Array": // Had better be an array of strings - strings := makeListOfStringsFromArrayValue(val.Object()) + strings := stringsFrom(val.Object()) it := ts.FixedIterator() for _, x := range strings { it.Add(ts.ValueOf(x)) @@ -101,8 +91,7 @@ func buildIteratorFromValue(val otto.Value, ts graph.TripleStore) graph.Iterator fallthrough case "String": it := ts.FixedIterator() - str, _ := val.ToString() - it.Add(ts.ValueOf(str)) + it.Add(ts.ValueOf(val.String())) return it default: glog.Errorln("Trying to handle unsupported Javascript value.") @@ -130,10 +119,9 @@ func buildInOutIterator(obj *otto.Object, ts graph.TripleStore, base graph.Itera var tags []string one, _ := argArray.Get("1") if one.IsString() { - s, _ := one.ToString() - tags = append(tags, s) + tags = append(tags, one.String()) } else if one.Class() == "Array" { - tags = makeListOfStringsFromArrayValue(one.Object()) + tags = stringsFrom(one.Object()) } for _, tag := range tags { predicateNodeIterator.Tagger().Add(tag) @@ -152,21 +140,19 @@ func buildInOutIterator(obj *otto.Object, ts graph.TripleStore, base graph.Itera } func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.Iterator) graph.Iterator { - var it graph.Iterator - it = base + var it graph.Iterator = base + // TODO: Better error handling - kindVal, _ := obj.Get("_gremlin_type") - stringArgs := getStringArgs(obj) var subIt graph.Iterator - prevVal, _ := obj.Get("_gremlin_prev") - if !prevVal.IsObject() { + if prev, _ := obj.Get("_gremlin_prev"); !prev.IsObject() { subIt = base } else { - subIt = buildIteratorTreeHelper(prevVal.Object(), ts, base) + subIt = buildIteratorTreeHelper(prev.Object(), ts, base) } - kind, _ := kindVal.ToString() - switch kind { + stringArgs := propertiesOf(obj, "string_args") + val, _ := obj.Get("_gremlin_type") + switch val.String() { case "vertex": if len(stringArgs) == 0 { it = ts.NodesAllIterator() diff --git a/query/gremlin/environ.go b/query/gremlin/environ.go index 7918a21..cdbbdb4 100644 --- a/query/gremlin/environ.go +++ b/query/gremlin/environ.go @@ -21,31 +21,25 @@ import ( "github.com/robertkrimen/otto" ) -func BuildEnviron(ses *Session) *otto.Otto { - env := otto.New() - setupGremlin(env, ses) - return env -} - -func concatStringArgs(call otto.FunctionCall) *[]interface{} { - outStrings := make([]interface{}, 0) +func argsOf(call otto.FunctionCall) []string { + var out []string for _, arg := range call.ArgumentList { if arg.IsString() { - outStrings = append(outStrings, arg.String()) + out = append(out, arg.String()) } if arg.IsObject() && arg.Class() == "Array" { obj, _ := arg.Export() for _, x := range obj.([]interface{}) { - outStrings = append(outStrings, x.(string)) + out = append(out, x.(string)) } } } - return &outStrings + return out } func isVertexChain(obj *otto.Object) bool { val, _ := obj.Get("_gremlin_type") - if x, _ := val.ToString(); x == "vertex" { + if val.String() == "vertex" { return true } val, _ = obj.Get("_gremlin_prev") @@ -55,8 +49,10 @@ func isVertexChain(obj *otto.Object) bool { return false } -func setupGremlin(env *otto.Otto, ses *Session) { +func (s *Session) setup(env *otto.Otto) *otto.Otto { graph, _ := env.Object("graph = {}") + env.Run("g = graph") + graph.Set("Vertex", func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, err := call.Otto.Object("out") @@ -65,31 +61,32 @@ func setupGremlin(env *otto.Otto, ses *Session) { return otto.TrueValue() } out.Set("_gremlin_type", "vertex") - outStrings := concatStringArgs(call) - if len(*outStrings) > 0 { - out.Set("string_args", *outStrings) + args := argsOf(call) + if len(args) > 0 { + out.Set("string_args", args) } - embedTraversals(env, ses, out) - embedFinals(env, ses, out) + s.embedTraversals(env, out) + s.embedFinals(env, out) return out.Value() }) + env.Run("graph.V = graph.Vertex") graph.Set("Morphism", func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", "morphism") - embedTraversals(env, ses, out) + s.embedTraversals(env, out) return out.Value() }) + env.Run("graph.M = graph.Morphism") + graph.Set("Emit", func(call otto.FunctionCall) otto.Value { value := call.Argument(0) if value.IsDefined() { - ses.SendResult(&Result{val: &value}) + s.SendResult(&Result{val: &value}) } return otto.NullValue() }) - env.Run("graph.V = graph.Vertex") - env.Run("graph.M = graph.Morphism") - env.Run("g = graph") + return env } diff --git a/query/gremlin/finals.go b/query/gremlin/finals.go index 6979e22..1e9f6ed 100644 --- a/query/gremlin/finals.go +++ b/query/gremlin/finals.go @@ -26,45 +26,45 @@ import ( const TopResultTag = "id" -func embedFinals(env *otto.Otto, ses *Session, obj *otto.Object) { - obj.Set("All", allFunc(env, ses, obj)) - obj.Set("GetLimit", limitFunc(env, ses, obj)) - obj.Set("ToArray", toArrayFunc(env, ses, obj, false)) - obj.Set("ToValue", toValueFunc(env, ses, obj, false)) - obj.Set("TagArray", toArrayFunc(env, ses, obj, true)) - obj.Set("TagValue", toValueFunc(env, ses, obj, true)) - obj.Set("Map", mapFunc(env, ses, obj)) - obj.Set("ForEach", mapFunc(env, ses, obj)) +func (s *Session) embedFinals(env *otto.Otto, obj *otto.Object) { + obj.Set("All", s.allFunc(env, obj)) + obj.Set("GetLimit", s.limitFunc(env, obj)) + obj.Set("ToArray", s.toArrayFunc(env, obj, false)) + obj.Set("ToValue", s.toValueFunc(env, obj, false)) + obj.Set("TagArray", s.toArrayFunc(env, obj, true)) + obj.Set("TagValue", s.toValueFunc(env, obj, true)) + obj.Set("Map", s.mapFunc(env, obj)) + obj.Set("ForEach", s.mapFunc(env, obj)) } -func allFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value { +func (s *Session) allFunc(env *otto.Otto, obj *otto.Object) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { - it := buildIteratorTree(obj, ses.ts) + it := buildIteratorTree(obj, s.ts) it.Tagger().Add(TopResultTag) - ses.limit = -1 - ses.count = 0 - runIteratorOnSession(it, ses) + s.limit = -1 + s.count = 0 + s.runIterator(it) return otto.NullValue() } } -func limitFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value { +func (s *Session) limitFunc(env *otto.Otto, obj *otto.Object) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) > 0 { limitVal, _ := call.Argument(0).ToInteger() - it := buildIteratorTree(obj, ses.ts) + it := buildIteratorTree(obj, s.ts) it.Tagger().Add(TopResultTag) - ses.limit = int(limitVal) - ses.count = 0 - runIteratorOnSession(it, ses) + s.limit = int(limitVal) + s.count = 0 + s.runIterator(it) } return otto.NullValue() } } -func toArrayFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value { +func (s *Session) toArrayFunc(env *otto.Otto, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { - it := buildIteratorTree(obj, ses.ts) + it := buildIteratorTree(obj, s.ts) it.Tagger().Add(TopResultTag) limit := -1 if len(call.ArgumentList) > 0 { @@ -74,10 +74,10 @@ func toArrayFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) var val otto.Value var err error if !withTags { - array := runIteratorToArrayNoTags(it, ses, limit) + array := s.runIteratorToArrayNoTags(it, limit) val, err = call.Otto.ToValue(array) } else { - array := runIteratorToArray(it, ses, limit) + array := s.runIteratorToArray(it, limit) val, err = call.Otto.ToValue(array) } @@ -89,21 +89,21 @@ func toArrayFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) } } -func toValueFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value { +func (s *Session) toValueFunc(env *otto.Otto, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { - it := buildIteratorTree(obj, ses.ts) + it := buildIteratorTree(obj, s.ts) it.Tagger().Add(TopResultTag) limit := 1 var val otto.Value var err error if !withTags { - array := runIteratorToArrayNoTags(it, ses, limit) + array := s.runIteratorToArrayNoTags(it, limit) if len(array) < 1 { return otto.NullValue() } val, err = call.Otto.ToValue(array[0]) } else { - array := runIteratorToArray(it, ses, limit) + array := s.runIteratorToArray(it, limit) if len(array) < 1 { return otto.NullValue() } @@ -119,9 +119,9 @@ func toValueFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) } } -func mapFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value { +func (s *Session) mapFunc(env *otto.Otto, obj *otto.Object) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { - it := buildIteratorTree(obj, ses.ts) + it := buildIteratorTree(obj, s.ts) it.Tagger().Add(TopResultTag) limit := -1 if len(call.ArgumentList) == 0 { @@ -132,26 +132,26 @@ func mapFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionC limitParsed, _ := call.Argument(0).ToInteger() limit = int(limitParsed) } - runIteratorWithCallback(it, ses, callback, call, limit) + s.runIteratorWithCallback(it, callback, call, limit) return otto.NullValue() } } -func tagsToValueMap(m map[string]graph.Value, ses *Session) map[string]string { +func (s *Session) tagsToValueMap(m map[string]graph.Value) map[string]string { outputMap := make(map[string]string) for k, v := range m { - outputMap[k] = ses.ts.NameOf(v) + outputMap[k] = s.ts.NameOf(v) } return outputMap } -func runIteratorToArray(it graph.Iterator, ses *Session, limit int) []map[string]string { +func (s *Session) runIteratorToArray(it graph.Iterator, limit int) []map[string]string { output := make([]map[string]string, 0) count := 0 it, _ = it.Optimize() for { select { - case <-ses.kill: + case <-s.kill: return nil default: } @@ -160,20 +160,20 @@ func runIteratorToArray(it graph.Iterator, ses *Session, limit int) []map[string } tags := make(map[string]graph.Value) it.TagResults(tags) - output = append(output, tagsToValueMap(tags, ses)) + output = append(output, s.tagsToValueMap(tags)) count++ if limit >= 0 && count >= limit { break } for it.NextPath() { select { - case <-ses.kill: + case <-s.kill: return nil default: } tags := make(map[string]graph.Value) it.TagResults(tags) - output = append(output, tagsToValueMap(tags, ses)) + output = append(output, s.tagsToValueMap(tags)) count++ if limit >= 0 && count >= limit { break @@ -184,20 +184,20 @@ func runIteratorToArray(it graph.Iterator, ses *Session, limit int) []map[string return output } -func runIteratorToArrayNoTags(it graph.Iterator, ses *Session, limit int) []string { +func (s *Session) runIteratorToArrayNoTags(it graph.Iterator, limit int) []string { output := make([]string, 0) count := 0 it, _ = it.Optimize() for { select { - case <-ses.kill: + case <-s.kill: return nil default: } if !graph.Next(it) { break } - output = append(output, ses.ts.NameOf(it.Result())) + output = append(output, s.ts.NameOf(it.Result())) count++ if limit >= 0 && count >= limit { break @@ -207,13 +207,13 @@ func runIteratorToArrayNoTags(it graph.Iterator, ses *Session, limit int) []stri return output } -func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Value, this otto.FunctionCall, limit int) { +func (s *Session) runIteratorWithCallback(it graph.Iterator, callback otto.Value, this otto.FunctionCall, limit int) { count := 0 it, _ = it.Optimize() glog.V(2).Infoln(it.DebugString(0)) for { select { - case <-ses.kill: + case <-s.kill: return default: } @@ -222,7 +222,7 @@ func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Valu } tags := make(map[string]graph.Value) it.TagResults(tags) - val, _ := this.Otto.ToValue(tagsToValueMap(tags, ses)) + val, _ := this.Otto.ToValue(s.tagsToValueMap(tags)) val, _ = callback.Call(this.This, val) count++ if limit >= 0 && count >= limit { @@ -230,13 +230,13 @@ func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Valu } for it.NextPath() { select { - case <-ses.kill: + case <-s.kill: return default: } tags := make(map[string]graph.Value) it.TagResults(tags) - val, _ := this.Otto.ToValue(tagsToValueMap(tags, ses)) + val, _ := this.Otto.ToValue(s.tagsToValueMap(tags)) val, _ = callback.Call(this.This, val) count++ if limit >= 0 && count >= limit { @@ -247,16 +247,16 @@ func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Valu it.Close() } -func runIteratorOnSession(it graph.Iterator, ses *Session) { - if ses.wantShape { - iterator.OutputQueryShapeForIterator(it, ses.ts, ses.shape) +func (s *Session) runIterator(it graph.Iterator) { + if s.wantShape { + iterator.OutputQueryShapeForIterator(it, s.ts, s.shape) return } it, _ = it.Optimize() glog.V(2).Infoln(it.DebugString(0)) for { select { - case <-ses.kill: + case <-s.kill: return default: } @@ -265,18 +265,18 @@ func runIteratorOnSession(it graph.Iterator, ses *Session) { } tags := make(map[string]graph.Value) it.TagResults(tags) - if !ses.SendResult(&Result{actualResults: &tags}) { + if !s.SendResult(&Result{actualResults: &tags}) { break } for it.NextPath() { select { - case <-ses.kill: + case <-s.kill: return default: } tags := make(map[string]graph.Value) it.TagResults(tags) - if !ses.SendResult(&Result{actualResults: &tags}) { + if !s.SendResult(&Result{actualResults: &tags}) { break } } diff --git a/query/gremlin/session.go b/query/gremlin/session.go index d1c84b5..30cd913 100644 --- a/query/gremlin/session.go +++ b/query/gremlin/session.go @@ -54,7 +54,7 @@ func NewSession(ts graph.TripleStore, timeout time.Duration, persist bool) *Sess limit: -1, timeout: timeout, } - g.env = BuildEnviron(&g) + g.env = g.setup(otto.New()) if persist { g.emptyEnv = g.env } diff --git a/query/gremlin/traversals.go b/query/gremlin/traversals.go index 32d4490..ff258dc 100644 --- a/query/gremlin/traversals.go +++ b/query/gremlin/traversals.go @@ -21,123 +21,122 @@ import ( "github.com/robertkrimen/otto" ) -func embedTraversals(env *otto.Otto, ses *Session, obj *otto.Object) { - obj.Set("In", gremlinFunc("in", obj, env, ses)) - obj.Set("Out", gremlinFunc("out", obj, env, ses)) - obj.Set("Is", gremlinFunc("is", obj, env, ses)) - obj.Set("Both", gremlinFunc("both", obj, env, ses)) - obj.Set("Follow", gremlinFunc("follow", obj, env, ses)) - obj.Set("FollowR", gremlinFollowR("followr", obj, env, ses)) - obj.Set("And", gremlinFunc("and", obj, env, ses)) - obj.Set("Intersect", gremlinFunc("and", obj, env, ses)) - obj.Set("Union", gremlinFunc("or", obj, env, ses)) - obj.Set("Or", gremlinFunc("or", obj, env, ses)) - obj.Set("Back", gremlinBack("back", obj, env, ses)) - obj.Set("Tag", gremlinFunc("tag", obj, env, ses)) - obj.Set("As", gremlinFunc("tag", obj, env, ses)) - obj.Set("Has", gremlinFunc("has", obj, env, ses)) - obj.Set("Save", gremlinFunc("save", obj, env, ses)) - obj.Set("SaveR", gremlinFunc("saver", obj, env, ses)) +func (s *Session) embedTraversals(env *otto.Otto, obj *otto.Object) { + obj.Set("In", gremlinFunc("in", obj, env, s)) + obj.Set("Out", gremlinFunc("out", obj, env, s)) + obj.Set("Is", gremlinFunc("is", obj, env, s)) + obj.Set("Both", gremlinFunc("both", obj, env, s)) + obj.Set("Follow", gremlinFunc("follow", obj, env, s)) + obj.Set("FollowR", gremlinFollowR("followr", obj, env, s)) + obj.Set("And", gremlinFunc("and", obj, env, s)) + obj.Set("Intersect", gremlinFunc("and", obj, env, s)) + obj.Set("Union", gremlinFunc("or", obj, env, s)) + obj.Set("Or", gremlinFunc("or", obj, env, s)) + obj.Set("Back", gremlinBack("back", obj, env, s)) + obj.Set("Tag", gremlinFunc("tag", obj, env, s)) + obj.Set("As", gremlinFunc("tag", obj, env, s)) + obj.Set("Has", gremlinFunc("has", obj, env, s)) + obj.Set("Save", gremlinFunc("save", obj, env, s)) + obj.Set("SaveR", gremlinFunc("saver", obj, env, s)) } -func gremlinFunc(kind string, prevObj *otto.Object, env *otto.Otto, ses *Session) func(otto.FunctionCall) otto.Value { +func gremlinFunc(kind string, prev *otto.Object, env *otto.Otto, ses *Session) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", kind) out.Set("_gremlin_values", call.ArgumentList) - out.Set("_gremlin_prev", prevObj) - outStrings := concatStringArgs(call) - if len(*outStrings) > 0 { - out.Set("string_args", *outStrings) + out.Set("_gremlin_prev", prev) + args := argsOf(call) + if len(args) > 0 { + out.Set("string_args", args) } - embedTraversals(env, ses, out) + ses.embedTraversals(env, out) if isVertexChain(call.This.Object()) { - embedFinals(env, ses, out) + ses.embedFinals(env, out) } return out.Value() } } -func gremlinBack(kind string, prevObj *otto.Object, env *otto.Otto, ses *Session) func(otto.FunctionCall) otto.Value { +func gremlinBack(kind string, prev *otto.Object, env *otto.Otto, ses *Session) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", kind) out.Set("_gremlin_values", call.ArgumentList) - outStrings := concatStringArgs(call) - if len(*outStrings) > 0 { - out.Set("string_args", *outStrings) + args := argsOf(call) + if len(args) > 0 { + out.Set("string_args", args) } var otherChain *otto.Object var thisObj *otto.Object - if len(*outStrings) != 0 { - otherChain, thisObj = reverseGremlinChainTo(call.Otto, prevObj, (*outStrings)[0].(string)) + if len(args) != 0 { + otherChain, thisObj = reverseGremlinChainTo(call.Otto, prev, args[0]) } else { - otherChain, thisObj = reverseGremlinChainTo(call.Otto, prevObj, "") + otherChain, thisObj = reverseGremlinChainTo(call.Otto, prev, "") } out.Set("_gremlin_prev", thisObj) out.Set("_gremlin_back_chain", otherChain) - embedTraversals(env, ses, out) + ses.embedTraversals(env, out) if isVertexChain(call.This.Object()) { - embedFinals(env, ses, out) + ses.embedFinals(env, out) } return out.Value() } } -func gremlinFollowR(kind string, prevObj *otto.Object, env *otto.Otto, ses *Session) func(otto.FunctionCall) otto.Value { +func gremlinFollowR(kind string, prev *otto.Object, env *otto.Otto, ses *Session) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", kind) out.Set("_gremlin_values", call.ArgumentList) - outStrings := concatStringArgs(call) - if len(*outStrings) > 0 { - out.Set("string_args", *outStrings) + args := argsOf(call) + if len(args) > 0 { + out.Set("string_args", args) } if len(call.ArgumentList) == 0 { - return prevObj.Value() + return prev.Value() } arg := call.Argument(0) if isVertexChain(arg.Object()) { - return prevObj.Value() + return prev.Value() } newChain, _ := reverseGremlinChainTo(call.Otto, arg.Object(), "") - out.Set("_gremlin_prev", prevObj) + out.Set("_gremlin_prev", prev) out.Set("_gremlin_followr", newChain) - embedTraversals(env, ses, out) + ses.embedTraversals(env, out) if isVertexChain(call.This.Object()) { - embedFinals(env, ses, out) + ses.embedFinals(env, out) } return out.Value() - } } -func reverseGremlinChainTo(env *otto.Otto, prevObj *otto.Object, tag string) (*otto.Object, *otto.Object) { +func reverseGremlinChainTo(env *otto.Otto, prev *otto.Object, tag string) (*otto.Object, *otto.Object) { env.Run("var _base_object = {}") base, err := env.Object("_base_object") if err != nil { glog.Error(err) return otto.NullValue().Object(), otto.NullValue().Object() } - if isVertexChain(prevObj) { + if isVertexChain(prev) { base.Set("_gremlin_type", "vertex") } else { base.Set("_gremlin_type", "morphism") } - return reverseGremlinChainHelper(env, prevObj, base, tag) + return reverseGremlinChainHelper(env, prev, base, tag) } func reverseGremlinChainHelper(env *otto.Otto, chain *otto.Object, newBase *otto.Object, tag string) (*otto.Object, *otto.Object) { kindVal, _ := chain.Get("_gremlin_type") - kind, _ := kindVal.ToString() + kind := kindVal.String() if tag != "" { if kind == "tag" { - tags := getStringArgs(chain) + tags := propertiesOf(chain, "string_args") for _, t := range tags { if t == tag { return newBase, chain @@ -174,8 +173,7 @@ func reverseGremlinChainHelper(env *otto.Otto, chain *otto.Object, newBase *otto func debugChain(obj *otto.Object) bool { val, _ := obj.Get("_gremlin_type") - x, _ := val.ToString() - glog.V(2).Infoln(x) + glog.V(2).Infoln(val) val, _ = obj.Get("_gremlin_prev") if val.IsObject() { return debugChain(val.Object())