varsscope.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. SetLocalValue sets a new value for a local variable.
  112. */
  113. func (s *varsScope) SetLocalValue(varName string, varValue interface{}) error {
  114. s.lock.Lock()
  115. defer s.lock.Unlock()
  116. // Ensure the variable exists in the local scope
  117. localVarName := strings.Split(varName, ".")[0]
  118. s.storage[localVarName] = nil
  119. return s.setValue(varName, varValue)
  120. }
  121. /*
  122. setValue sets a new value for a variable.
  123. */
  124. func (s *varsScope) setValue(varName string, varValue interface{}) error {
  125. var err error
  126. // Check for dotted names which access a container structure
  127. if cFields := strings.Split(varName, "."); len(cFields) > 1 {
  128. // Get the container
  129. if container, ok, _ := s.getValue(cFields[0]); ok {
  130. if len(cFields) > 2 {
  131. container, err = s.containerAccess(container, cFields, cFields[1:])
  132. }
  133. if err == nil && container != nil {
  134. fieldIndex := cFields[len(cFields)-1]
  135. if mapContainer, ok := container.(map[interface{}]interface{}); ok {
  136. mapContainer[fieldIndex] = varValue
  137. } else if listContainer, ok := container.([]interface{}); ok {
  138. var index int
  139. if index, err = strconv.Atoi(fieldIndex); err == nil {
  140. if index < 0 {
  141. // Handle negative numbers
  142. index = len(listContainer) + index
  143. }
  144. if index < len(listContainer) {
  145. listContainer[index] = varValue
  146. } else {
  147. err = fmt.Errorf("Out of bounds access to list %v with index: %v",
  148. strings.Join(cFields[:len(cFields)-1], "."), index)
  149. }
  150. } else {
  151. err = fmt.Errorf("List %v needs a number index not: %v",
  152. strings.Join(cFields[:len(cFields)-1], "."), fieldIndex)
  153. }
  154. } else {
  155. err = fmt.Errorf("Variable %v is not a container",
  156. strings.Join(cFields[:len(cFields)-1], "."))
  157. }
  158. }
  159. } else {
  160. err = fmt.Errorf("Variable %v is not a container", cFields[0])
  161. }
  162. return err
  163. }
  164. // Check if the variable is already defined in a parent scope
  165. if vs := s.getScopeForVariable(varName); vs != nil {
  166. s = vs
  167. }
  168. // Set value newly in scope
  169. s.storage[varName] = varValue
  170. return err
  171. }
  172. /*
  173. containerAccess recursively accesses a field in a container structure.
  174. */
  175. func (s *varsScope) containerAccess(container interface{}, cFields []string, fields []string) (interface{}, error) {
  176. var err error
  177. // Get inner container
  178. if mapContainer, ok := container.(map[interface{}]interface{}); ok {
  179. if container, ok = mapContainer[fields[0]]; !ok {
  180. err = fmt.Errorf("Container field %v does not exist",
  181. strings.Join(cFields[:len(cFields)-len(fields)+1], "."))
  182. }
  183. } else if listContainer, ok := container.([]interface{}); ok {
  184. var index int
  185. if index, err = strconv.Atoi(fmt.Sprint(fields[0])); err == nil {
  186. if index < 0 {
  187. // Handle negative numbers
  188. index = len(listContainer) + index
  189. }
  190. if index < len(listContainer) {
  191. container = listContainer[index]
  192. } else {
  193. err = fmt.Errorf("Out of bounds access to list %v with index: %v",
  194. strings.Join(cFields[:len(cFields)-len(fields)], "."), index)
  195. }
  196. } else {
  197. container = nil
  198. err = fmt.Errorf("List %v needs a number index not: %v",
  199. strings.Join(cFields[:len(cFields)-len(fields)], "."), fields[0])
  200. }
  201. } else {
  202. container = nil
  203. err = fmt.Errorf("Variable %v is not a container",
  204. strings.Join(cFields[:len(cFields)-len(fields)], "."))
  205. }
  206. if err == nil && len(fields) > 2 {
  207. container, err = s.containerAccess(container, cFields, fields[1:])
  208. }
  209. return container, err
  210. }
  211. /*
  212. getScopeForVariable returns the scope (this or a parent scope) which holds a
  213. given variable.
  214. */
  215. func (s *varsScope) getScopeForVariable(varName string) *varsScope {
  216. _, ok := s.storage[varName]
  217. if ok {
  218. return s
  219. } else if s.parent != nil {
  220. return s.parent.(*varsScope).getScopeForVariable(varName)
  221. }
  222. return nil
  223. }
  224. /*
  225. GetValue gets the current value of a variable.
  226. */
  227. func (s *varsScope) GetValue(varName string) (interface{}, bool, error) {
  228. s.lock.Lock()
  229. defer s.lock.Unlock()
  230. return s.getValue(varName)
  231. }
  232. /*
  233. getValue gets the current value of a variable.
  234. */
  235. func (s *varsScope) getValue(varName string) (interface{}, bool, error) {
  236. // Check for dotted names which access a container structure
  237. if cFields := strings.Split(varName, "."); len(cFields) > 1 {
  238. var err error
  239. var containerAccess func(fields []string, container interface{}) (interface{}, bool, error)
  240. // Get the container
  241. container, ok, _ := s.getValue(cFields[0])
  242. if !ok {
  243. return nil, ok, err
  244. }
  245. // Now look into the container and get the value
  246. containerAccess = func(fields []string, container interface{}) (interface{}, bool, error) {
  247. var retContainer interface{}
  248. if mapContainer, ok := container.(map[interface{}]interface{}); ok {
  249. var ok bool
  250. if index, err := strconv.Atoi(fmt.Sprint(fields[0])); err == nil {
  251. // Numbers are usually converted to float64
  252. retContainer, ok = mapContainer[float64(index)]
  253. }
  254. if !ok {
  255. retContainer = mapContainer[fields[0]]
  256. }
  257. } else if listContainer, ok := container.([]interface{}); ok {
  258. var index int
  259. if index, err = strconv.Atoi(fmt.Sprint(fields[0])); err == nil {
  260. if index < 0 {
  261. // Handle negative numbers
  262. index = len(listContainer) + index
  263. }
  264. if index < len(listContainer) {
  265. retContainer = listContainer[index]
  266. } else {
  267. err = fmt.Errorf("Out of bounds access to list %v with index: %v",
  268. strings.Join(cFields[:len(cFields)-len(fields)], "."), index)
  269. }
  270. } else {
  271. err = fmt.Errorf("List %v needs a number index not: %v",
  272. strings.Join(cFields[:len(cFields)-len(fields)], "."), fields[0])
  273. }
  274. } else {
  275. err = fmt.Errorf("Variable %v is not a container",
  276. strings.Join(cFields[:len(cFields)-len(fields)], "."))
  277. }
  278. if err == nil && len(fields) > 1 {
  279. return containerAccess(fields[1:], retContainer)
  280. }
  281. return retContainer, retContainer != nil, err
  282. }
  283. return containerAccess(cFields[1:], container)
  284. }
  285. if vs := s.getScopeForVariable(varName); vs != nil {
  286. ret := vs.storage[varName]
  287. return ret, true, nil
  288. }
  289. return nil, false, nil
  290. }
  291. /*
  292. String returns a string representation of this varsScope and all its
  293. parents.
  294. */
  295. func (s *varsScope) String() string {
  296. s.lock.RLock()
  297. defer s.lock.RUnlock()
  298. return s.scopeStringParents(s.scopeStringChildren())
  299. }
  300. /*
  301. ToJSONObject returns this ASTNode and all its children as a JSON object.
  302. */
  303. func (s *varsScope) ToJSONObject() map[string]interface{} {
  304. s.lock.RLock()
  305. defer s.lock.RUnlock()
  306. ret := make(map[string]interface{})
  307. for k, v := range s.storage {
  308. var value interface{}
  309. value = fmt.Sprintf("ComplexDataStructure: %#v", v)
  310. bytes, err := json.Marshal(v)
  311. if err != nil {
  312. bytes, err = json.Marshal(stringutil.ConvertToJSONMarshalableObject(v))
  313. }
  314. if err == nil {
  315. json.Unmarshal(bytes, &value)
  316. }
  317. ret[k] = value
  318. }
  319. return ret
  320. }
  321. /*
  322. scopeStringChildren returns a string representation of all children scopes.
  323. */
  324. func (s *varsScope) scopeStringChildren() string {
  325. var buf bytes.Buffer
  326. // Write the known child scopes
  327. for i, c := range s.children {
  328. buf.WriteString(c.scopeString(c.scopeStringChildren()))
  329. if i < len(s.children)-1 {
  330. buf.WriteString("\n")
  331. }
  332. }
  333. return buf.String()
  334. }
  335. /*
  336. scopeStringParents returns a string representation of this varsScope
  337. with initial children and all its parents.
  338. */
  339. func (s *varsScope) scopeStringParents(childrenString string) string {
  340. ss := s.scopeString(childrenString)
  341. if s.parent != nil {
  342. return s.parent.(*varsScope).scopeStringParents(ss)
  343. }
  344. return fmt.Sprint(ss)
  345. }
  346. /*
  347. scopeString returns a string representation of this varsScope.
  348. */
  349. func (s *varsScope) scopeString(childrenString string) string {
  350. buf := bytes.Buffer{}
  351. varList := []string{}
  352. buf.WriteString(fmt.Sprintf("%v {\n", s.name))
  353. for k := range s.storage {
  354. varList = append(varList, k)
  355. }
  356. sort.Strings(varList)
  357. for _, v := range varList {
  358. buf.WriteString(fmt.Sprintf(" %s (%T) : %v\n", v, s.storage[v],
  359. EvalToString(s.storage[v])))
  360. }
  361. if childrenString != "" {
  362. // Indent all
  363. buf.WriteString(" ")
  364. buf.WriteString(strings.Replace(childrenString, "\n", "\n ", -1))
  365. buf.WriteString("\n")
  366. }
  367. buf.WriteString("}")
  368. return buf.String()
  369. }