varsscope.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*
  2. * ECAL
  3. *
  4. * Copyright 2020 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package scope
  11. import (
  12. "bytes"
  13. "encoding/json"
  14. "fmt"
  15. "sort"
  16. "strconv"
  17. "strings"
  18. "sync"
  19. "devt.de/krotik/common/stringutil"
  20. "devt.de/krotik/ecal/parser"
  21. )
  22. /*
  23. varsScope models a scope for variables in ECAL.
  24. */
  25. type varsScope struct {
  26. name string // Name of the scope
  27. parent parser.Scope // Parent scope
  28. children []*varsScope // Children of this scope (only if tracking is enabled)
  29. storage map[string]interface{} // Storage for variables
  30. lock *sync.RWMutex // Lock for this scope
  31. }
  32. /*
  33. NewScope creates a new variable scope.
  34. */
  35. func NewScope(name string) parser.Scope {
  36. return NewScopeWithParent(name, nil)
  37. }
  38. /*
  39. NewScopeWithParent creates a new variable scope with a parent. This can be
  40. used to create scope structures without children links.
  41. */
  42. func NewScopeWithParent(name string, parent parser.Scope) parser.Scope {
  43. res := &varsScope{name, nil, nil, make(map[string]interface{}), &sync.RWMutex{}}
  44. SetParentOfScope(res, parent)
  45. return res
  46. }
  47. /*
  48. SetParentOfScope sets the parent of a given scope. This assumes that the given scope
  49. is a varsScope.
  50. */
  51. func SetParentOfScope(scope parser.Scope, parent parser.Scope) {
  52. if pvs, ok := parent.(*varsScope); ok {
  53. if vs, ok := scope.(*varsScope); ok {
  54. vs.lock.Lock()
  55. defer vs.lock.Unlock()
  56. pvs.lock.Lock()
  57. defer pvs.lock.Unlock()
  58. vs.parent = parent
  59. vs.lock = pvs.lock
  60. }
  61. }
  62. }
  63. /*
  64. NewChild creates a new child scope for variables. The new child scope is tracked
  65. by the parent scope. This means it should not be used for global scopes with
  66. many children.
  67. */
  68. func (s *varsScope) NewChild(name string) parser.Scope {
  69. s.lock.Lock()
  70. defer s.lock.Unlock()
  71. for _, c := range s.children {
  72. if c.name == name {
  73. return c
  74. }
  75. }
  76. child := NewScope(name).(*varsScope)
  77. child.parent = s
  78. child.lock = s.lock
  79. s.children = append(s.children, child)
  80. return child
  81. }
  82. /*
  83. Name returns the name of this scope.
  84. */
  85. func (s *varsScope) Name() string {
  86. return s.name
  87. }
  88. /*
  89. Clear clears this scope of all stored values. This will clear children scopes
  90. but not remove parent scopes.
  91. */
  92. func (s *varsScope) Clear() {
  93. s.children = nil
  94. s.storage = make(map[string]interface{})
  95. }
  96. /*
  97. Parent returns the parent scope or nil.
  98. */
  99. func (s *varsScope) Parent() parser.Scope {
  100. return s.parent
  101. }
  102. /*
  103. SetValue sets a new value for a variable.
  104. */
  105. func (s *varsScope) SetValue(varName string, varValue interface{}) error {
  106. s.lock.Lock()
  107. defer s.lock.Unlock()
  108. return s.setValue(varName, varValue)
  109. }
  110. /*
  111. setValue sets a new value for a variable.
  112. */
  113. func (s *varsScope) setValue(varName string, varValue interface{}) error {
  114. var err error
  115. // Check for dotted names which access a container structure
  116. if cFields := strings.Split(varName, "."); len(cFields) > 1 {
  117. // Get the container
  118. if container, ok, _ := s.getValue(cFields[0]); ok {
  119. if len(cFields) > 2 {
  120. var containerAccess func(fields []string)
  121. containerAccess = func(fields []string) {
  122. // Get inner container
  123. if mapContainer, ok := container.(map[interface{}]interface{}); ok {
  124. if container, ok = mapContainer[fields[0]]; !ok {
  125. err = fmt.Errorf("Container field %v does not exist",
  126. strings.Join(cFields[:len(cFields)-len(fields)+1], "."))
  127. }
  128. } else if listContainer, ok := container.([]interface{}); ok {
  129. var index int
  130. if index, err = strconv.Atoi(fmt.Sprint(fields[0])); err == nil {
  131. if index < 0 {
  132. // Handle negative numbers
  133. index = len(listContainer) + index
  134. }
  135. if index < len(listContainer) {
  136. container = listContainer[index]
  137. } else {
  138. err = fmt.Errorf("Out of bounds access to list %v with index: %v",
  139. strings.Join(cFields[:len(cFields)-len(fields)], "."), index)
  140. }
  141. } else {
  142. container = nil
  143. err = fmt.Errorf("List %v needs a number index not: %v",
  144. strings.Join(cFields[:len(cFields)-len(fields)], "."), fields[0])
  145. }
  146. } else {
  147. container = nil
  148. err = fmt.Errorf("Variable %v is not a container",
  149. strings.Join(cFields[:len(cFields)-len(fields)], "."))
  150. }
  151. if err == nil && len(fields) > 2 {
  152. containerAccess(fields[1:])
  153. }
  154. }
  155. containerAccess(cFields[1:])
  156. }
  157. if err == nil && container != nil {
  158. fieldIndex := cFields[len(cFields)-1]
  159. if mapContainer, ok := container.(map[interface{}]interface{}); ok {
  160. mapContainer[fieldIndex] = varValue
  161. } else if listContainer, ok := container.([]interface{}); ok {
  162. var index int
  163. if index, err = strconv.Atoi(fieldIndex); err == nil {
  164. if index < 0 {
  165. // Handle negative numbers
  166. index = len(listContainer) + index
  167. }
  168. if index < len(listContainer) {
  169. listContainer[index] = varValue
  170. } else {
  171. err = fmt.Errorf("Out of bounds access to list %v with index: %v",
  172. strings.Join(cFields[:len(cFields)-1], "."), index)
  173. }
  174. } else {
  175. err = fmt.Errorf("List %v needs a number index not: %v",
  176. strings.Join(cFields[:len(cFields)-1], "."), fieldIndex)
  177. }
  178. } else {
  179. err = fmt.Errorf("Variable %v is not a container",
  180. strings.Join(cFields[:len(cFields)-1], "."))
  181. }
  182. }
  183. } else {
  184. err = fmt.Errorf("Variable %v is not a container", cFields[0])
  185. }
  186. return err
  187. }
  188. // Check if the variable is already defined in a parent scope
  189. if vs := s.getScopeForVariable(varName); vs != nil {
  190. s = vs
  191. }
  192. // Set value newly in scope
  193. s.storage[varName] = varValue
  194. return err
  195. }
  196. /*
  197. getScopeForVariable returns the scope (this or a parent scope) which holds a
  198. given variable.
  199. */
  200. func (s *varsScope) getScopeForVariable(varName string) *varsScope {
  201. _, ok := s.storage[varName]
  202. if ok {
  203. return s
  204. } else if s.parent != nil {
  205. return s.parent.(*varsScope).getScopeForVariable(varName)
  206. }
  207. return nil
  208. }
  209. /*
  210. GetValue gets the current value of a variable.
  211. */
  212. func (s *varsScope) GetValue(varName string) (interface{}, bool, error) {
  213. s.lock.Lock()
  214. defer s.lock.Unlock()
  215. return s.getValue(varName)
  216. }
  217. /*
  218. getValue gets the current value of a variable.
  219. */
  220. func (s *varsScope) getValue(varName string) (interface{}, bool, error) {
  221. // Check for dotted names which access a container structure
  222. if cFields := strings.Split(varName, "."); len(cFields) > 1 {
  223. var err error
  224. var containerAccess func(fields []string, container interface{}) (interface{}, bool, error)
  225. // Get the container
  226. container, ok, _ := s.getValue(cFields[0])
  227. if !ok {
  228. return nil, ok, err
  229. }
  230. // Now look into the container and get the value
  231. containerAccess = func(fields []string, container interface{}) (interface{}, bool, error) {
  232. var retContainer interface{}
  233. if mapContainer, ok := container.(map[interface{}]interface{}); ok {
  234. var ok bool
  235. if index, err := strconv.Atoi(fmt.Sprint(fields[0])); err == nil {
  236. // Numbers are usually converted to float64
  237. retContainer, ok = mapContainer[float64(index)]
  238. }
  239. if !ok {
  240. retContainer = mapContainer[fields[0]]
  241. }
  242. } else if listContainer, ok := container.([]interface{}); ok {
  243. var index int
  244. if index, err = strconv.Atoi(fmt.Sprint(fields[0])); err == nil {
  245. if index < 0 {
  246. // Handle negative numbers
  247. index = len(listContainer) + index
  248. }
  249. if index < len(listContainer) {
  250. retContainer = listContainer[index]
  251. } else {
  252. err = fmt.Errorf("Out of bounds access to list %v with index: %v",
  253. strings.Join(cFields[:len(cFields)-len(fields)], "."), index)
  254. }
  255. } else {
  256. err = fmt.Errorf("List %v needs a number index not: %v",
  257. strings.Join(cFields[:len(cFields)-len(fields)], "."), fields[0])
  258. }
  259. } else {
  260. err = fmt.Errorf("Variable %v is not a container",
  261. strings.Join(cFields[:len(cFields)-len(fields)], "."))
  262. }
  263. if err == nil && len(fields) > 1 {
  264. return containerAccess(fields[1:], retContainer)
  265. }
  266. return retContainer, retContainer != nil, err
  267. }
  268. return containerAccess(cFields[1:], container)
  269. }
  270. if vs := s.getScopeForVariable(varName); vs != nil {
  271. ret := vs.storage[varName]
  272. return ret, true, nil
  273. }
  274. return nil, false, nil
  275. }
  276. /*
  277. String returns a string representation of this varsScope and all its
  278. parents.
  279. */
  280. func (s *varsScope) String() string {
  281. s.lock.RLock()
  282. defer s.lock.RUnlock()
  283. return s.scopeStringParents(s.scopeStringChildren())
  284. }
  285. /*
  286. ToJSONObject returns this ASTNode and all its children as a JSON object.
  287. */
  288. func (s *varsScope) ToJSONObject() map[string]interface{} {
  289. s.lock.RLock()
  290. defer s.lock.RUnlock()
  291. ret := make(map[string]interface{})
  292. for k, v := range s.storage {
  293. var value interface{}
  294. value = fmt.Sprintf("ComplexDataStructure: %#v", v)
  295. bytes, err := json.Marshal(v)
  296. if err != nil {
  297. bytes, err = json.Marshal(stringutil.ConvertToJSONMarshalableObject(v))
  298. }
  299. if err == nil {
  300. json.Unmarshal(bytes, &value)
  301. }
  302. ret[k] = value
  303. }
  304. return ret
  305. }
  306. /*
  307. scopeStringChildren returns a string representation of all children scopes.
  308. */
  309. func (s *varsScope) scopeStringChildren() string {
  310. var buf bytes.Buffer
  311. // Write the known child scopes
  312. for i, c := range s.children {
  313. buf.WriteString(c.scopeString(c.scopeStringChildren()))
  314. if i < len(s.children)-1 {
  315. buf.WriteString("\n")
  316. }
  317. }
  318. return buf.String()
  319. }
  320. /*
  321. scopeStringParents returns a string representation of this varsScope
  322. with initial children and all its parents.
  323. */
  324. func (s *varsScope) scopeStringParents(childrenString string) string {
  325. ss := s.scopeString(childrenString)
  326. if s.parent != nil {
  327. return s.parent.(*varsScope).scopeStringParents(ss)
  328. }
  329. return fmt.Sprint(ss)
  330. }
  331. /*
  332. scopeString returns a string representation of this varsScope.
  333. */
  334. func (s *varsScope) scopeString(childrenString string) string {
  335. buf := bytes.Buffer{}
  336. varList := []string{}
  337. buf.WriteString(fmt.Sprintf("%v {\n", s.name))
  338. for k := range s.storage {
  339. varList = append(varList, k)
  340. }
  341. sort.Strings(varList)
  342. for _, v := range varList {
  343. buf.WriteString(fmt.Sprintf(" %s (%T) : %v\n", v, s.storage[v],
  344. EvalToString(s.storage[v])))
  345. }
  346. if childrenString != "" {
  347. // Indent all
  348. buf.WriteString(" ")
  349. buf.WriteString(strings.Replace(childrenString, "\n", "\n ", -1))
  350. buf.WriteString("\n")
  351. }
  352. buf.WriteString("}")
  353. return buf.String()
  354. }