varsscope.go 11 KB

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