helpers.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package interpreter
  11. import (
  12. "devt.de/krotik/common/datautil"
  13. "devt.de/krotik/eliasdb/eql/parser"
  14. "devt.de/krotik/eliasdb/graph/data"
  15. )
  16. // Not Implemented Runtime
  17. // =======================
  18. /*
  19. Special runtime for not implemented constructs.
  20. */
  21. type invalidRuntime struct {
  22. rtp *eqlRuntimeProvider
  23. node *parser.ASTNode
  24. }
  25. /*
  26. invalidRuntimeInst returns a new runtime component instance.
  27. */
  28. func invalidRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  29. return &invalidRuntime{rtp, node}
  30. }
  31. /*
  32. Validate this node and all its child nodes.
  33. */
  34. func (rt *invalidRuntime) Validate() error {
  35. return rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.node.Name, rt.node)
  36. }
  37. /*
  38. Eval evaluate this runtime component.
  39. */
  40. func (rt *invalidRuntime) Eval() (interface{}, error) {
  41. return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.node.Name, rt.node)
  42. }
  43. /*
  44. Evaluate the value as a condition component.
  45. */
  46. func (rt *invalidRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
  47. return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.node.Name, rt.node)
  48. }
  49. // Value Runtime
  50. // =============
  51. /*
  52. Runtime for values
  53. */
  54. type valueRuntime struct {
  55. rtp *eqlRuntimeProvider
  56. node *parser.ASTNode
  57. isNodeAttrValue bool
  58. isEdgeAttrValue bool
  59. nestedValuePath []string
  60. condVal string
  61. }
  62. /*
  63. valueRuntimeInst returns a new runtime component instance.
  64. */
  65. func valueRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  66. return &valueRuntime{rtp, node, false, false, nil, ""}
  67. }
  68. /*
  69. Validate this node and all its child nodes.
  70. */
  71. func (rt *valueRuntime) Validate() error {
  72. return nil
  73. }
  74. /*
  75. Eval evaluate this runtime component.
  76. */
  77. func (rt *valueRuntime) Eval() (interface{}, error) {
  78. return rt.node.Token.Val, nil
  79. }
  80. /*
  81. Evaluate the value as a condition component.
  82. */
  83. func (rt *valueRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
  84. // Check known constants
  85. if rt.node.Token.ID == parser.TokenAT {
  86. // Try to lookup a function
  87. funcName := rt.node.Children[0].Token.Val
  88. funcInst, ok := whereFunc[funcName]
  89. if !ok {
  90. return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct,
  91. "Unknown function: "+funcName, rt.node)
  92. }
  93. // Execute the function and return its result value
  94. return funcInst(rt.node, rt.rtp, node, edge)
  95. } else if rt.node.Token.ID == parser.TokenTRUE {
  96. return true, nil
  97. } else if rt.node.Token.ID == parser.TokenFALSE {
  98. return false, nil
  99. } else if rt.node.Token.ID == parser.TokenNULL {
  100. return nil, nil
  101. } else if rt.node.Name == parser.NodeLIST {
  102. // Collect items of a list
  103. var list []interface{}
  104. for _, item := range rt.node.Children {
  105. val, _ := item.Runtime.(CondRuntime).CondEval(node, edge)
  106. list = append(list, val)
  107. }
  108. return list, nil
  109. }
  110. // Check if this is describing a node or edge value
  111. var valRet interface{}
  112. if rt.isNodeAttrValue {
  113. // Check for nested values
  114. if rt.nestedValuePath != nil {
  115. if valMap, ok := node.Attr(rt.nestedValuePath[0]).(map[string]interface{}); ok {
  116. valRet, _ = datautil.GetNestedValue(valMap, rt.nestedValuePath[1:])
  117. }
  118. } else {
  119. valRet = node.Attr(rt.condVal)
  120. }
  121. return valRet, nil
  122. } else if rt.isEdgeAttrValue {
  123. if edge == nil {
  124. return nil, rt.rtp.newRuntimeError(ErrInvalidWhere,
  125. "No edge data available at this level", rt.node)
  126. }
  127. return edge.Attr(rt.condVal), nil
  128. }
  129. // Must be a constant value
  130. return rt.condVal, nil
  131. }