func_provider.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  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 interpreter
  11. import (
  12. "fmt"
  13. "strconv"
  14. "strings"
  15. "devt.de/krotik/ecal/engine"
  16. "devt.de/krotik/ecal/parser"
  17. "devt.de/krotik/ecal/scope"
  18. "devt.de/krotik/ecal/util"
  19. )
  20. /*
  21. inbuildFuncMap contains the mapping of inbuild functions.
  22. */
  23. var inbuildFuncMap = map[string]util.ECALFunction{
  24. "range": &rangeFunc{&inbuildBaseFunc{}},
  25. "new": &newFunc{&inbuildBaseFunc{}},
  26. "len": &lenFunc{&inbuildBaseFunc{}},
  27. "del": &delFunc{&inbuildBaseFunc{}},
  28. "add": &addFunc{&inbuildBaseFunc{}},
  29. "concat": &concatFunc{&inbuildBaseFunc{}},
  30. "dumpenv": &dumpenvFunc{&inbuildBaseFunc{}},
  31. "sinkError": &sinkerror{&inbuildBaseFunc{}},
  32. "addEvent": &addevent{&inbuildBaseFunc{}},
  33. "addEventAndWait": &addeventandwait{&addevent{&inbuildBaseFunc{}}},
  34. }
  35. /*
  36. inbuildBaseFunc is the base structure for inbuild functions providing some
  37. utility functions.
  38. */
  39. type inbuildBaseFunc struct {
  40. }
  41. /*
  42. AssertNumParam converts a general interface{} parameter into a number.
  43. */
  44. func (ibf *inbuildBaseFunc) AssertNumParam(index int, val interface{}) (float64, error) {
  45. var err error
  46. resNum, ok := val.(float64)
  47. if !ok {
  48. resNum, err = strconv.ParseFloat(fmt.Sprint(val), 64)
  49. if err != nil {
  50. err = fmt.Errorf("Parameter %v should be a number", index)
  51. }
  52. }
  53. return resNum, err
  54. }
  55. /*
  56. AssertMapParam converts a general interface{} parameter into a map.
  57. */
  58. func (ibf *inbuildBaseFunc) AssertMapParam(index int, val interface{}) (map[interface{}]interface{}, error) {
  59. valMap, ok := val.(map[interface{}]interface{})
  60. if ok {
  61. return valMap, nil
  62. }
  63. return nil, fmt.Errorf("Parameter %v should be a map", index)
  64. }
  65. /*
  66. AssertListParam converts a general interface{} parameter into a list.
  67. */
  68. func (ibf *inbuildBaseFunc) AssertListParam(index int, val interface{}) ([]interface{}, error) {
  69. valList, ok := val.([]interface{})
  70. if ok {
  71. return valList, nil
  72. }
  73. return nil, fmt.Errorf("Parameter %v should be a list", index)
  74. }
  75. // Range
  76. // =====
  77. /*
  78. rangeFunc is an interator function which returns a range of numbers.
  79. */
  80. type rangeFunc struct {
  81. *inbuildBaseFunc
  82. }
  83. /*
  84. Run executes this function.
  85. */
  86. func (rf *rangeFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  87. var currVal, to float64
  88. var err error
  89. lenargs := len(args)
  90. from := 0.
  91. step := 1.
  92. if lenargs == 0 {
  93. err = fmt.Errorf("Need at least an end range as first parameter")
  94. }
  95. if err == nil {
  96. if stepVal, ok := is[instanceID+"step"]; ok {
  97. step = stepVal.(float64)
  98. from = is[instanceID+"from"].(float64)
  99. to = is[instanceID+"to"].(float64)
  100. currVal = is[instanceID+"currVal"].(float64)
  101. is[instanceID+"currVal"] = currVal + step
  102. // Check for end of iteration
  103. if (from < to && currVal > to) || (from > to && currVal < to) || from == to {
  104. err = util.ErrEndOfIteration
  105. }
  106. } else {
  107. if lenargs == 1 {
  108. to, err = rf.AssertNumParam(1, args[0])
  109. } else {
  110. from, err = rf.AssertNumParam(1, args[0])
  111. if err == nil {
  112. to, err = rf.AssertNumParam(2, args[1])
  113. }
  114. if err == nil && lenargs > 2 {
  115. step, err = rf.AssertNumParam(3, args[2])
  116. }
  117. }
  118. if err == nil {
  119. is[instanceID+"from"] = from
  120. is[instanceID+"to"] = to
  121. is[instanceID+"step"] = step
  122. is[instanceID+"currVal"] = from
  123. currVal = from
  124. }
  125. }
  126. }
  127. if err == nil {
  128. err = util.ErrIsIterator // Identify as iterator
  129. }
  130. return currVal, err
  131. }
  132. /*
  133. DocString returns a descriptive string.
  134. */
  135. func (rf *rangeFunc) DocString() (string, error) {
  136. return "Range function which can be used to iterate over number ranges. Parameters are start, end and step.", nil
  137. }
  138. // New
  139. // ===
  140. /*
  141. newFunc instantiates a new object.
  142. */
  143. type newFunc struct {
  144. *inbuildBaseFunc
  145. }
  146. /*
  147. Run executes this function.
  148. */
  149. func (rf *newFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  150. var res interface{}
  151. err := fmt.Errorf("Need a map as first parameter")
  152. if len(args) > 0 {
  153. var argMap map[interface{}]interface{}
  154. if argMap, err = rf.AssertMapParam(1, args[0]); err == nil {
  155. obj := make(map[interface{}]interface{})
  156. res = obj
  157. _, err = rf.addSuperClasses(vs, is, obj, argMap)
  158. if initObj, ok := obj["init"]; ok {
  159. if initFunc, ok := initObj.(*function); ok {
  160. initvs := scope.NewScope(fmt.Sprintf("newfunc: %v", instanceID))
  161. initis := make(map[string]interface{})
  162. _, err = initFunc.Run(instanceID, initvs, initis, args[1:])
  163. }
  164. }
  165. }
  166. }
  167. return res, err
  168. }
  169. /*
  170. addSuperClasses adds super class functions to a given object.
  171. */
  172. func (rf *newFunc) addSuperClasses(vs parser.Scope, is map[string]interface{},
  173. obj map[interface{}]interface{}, template map[interface{}]interface{}) (interface{}, error) {
  174. var err error
  175. var initFunc interface{}
  176. var initSuperList []interface{}
  177. // First loop into the base classes (i.e. top-most classes)
  178. if super, ok := template["super"]; ok {
  179. if superList, ok := super.([]interface{}); ok {
  180. for _, superObj := range superList {
  181. var superInit interface{}
  182. if superTemplate, ok := superObj.(map[interface{}]interface{}); ok {
  183. superInit, err = rf.addSuperClasses(vs, is, obj, superTemplate)
  184. initSuperList = append(initSuperList, superInit) // Build up the list of super functions
  185. }
  186. }
  187. } else {
  188. err = fmt.Errorf("Property _super must be a list of super classes")
  189. }
  190. }
  191. // Copy all properties from template to obj
  192. for k, v := range template {
  193. // Save previous init function
  194. if funcVal, ok := v.(*function); ok {
  195. newFunction := &function{funcVal.name, nil, obj, funcVal.declaration}
  196. if k == "init" {
  197. newFunction.super = initSuperList
  198. initFunc = newFunction
  199. }
  200. obj[k] = newFunction
  201. } else {
  202. obj[k] = v
  203. }
  204. }
  205. return initFunc, err
  206. }
  207. /*
  208. DocString returns a descriptive string.
  209. */
  210. func (rf *newFunc) DocString() (string, error) {
  211. return "New creates a new object instance.", nil
  212. }
  213. // Len
  214. // ===
  215. /*
  216. lenFunc returns the size of a list or map.
  217. */
  218. type lenFunc struct {
  219. *inbuildBaseFunc
  220. }
  221. /*
  222. Run executes this function.
  223. */
  224. func (rf *lenFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  225. var res float64
  226. err := fmt.Errorf("Need a list or a map as first parameter")
  227. if len(args) > 0 {
  228. argList, ok1 := args[0].([]interface{})
  229. argMap, ok2 := args[0].(map[interface{}]interface{})
  230. if ok1 {
  231. res = float64(len(argList))
  232. err = nil
  233. } else if ok2 {
  234. res = float64(len(argMap))
  235. err = nil
  236. }
  237. }
  238. return res, err
  239. }
  240. /*
  241. DocString returns a descriptive string.
  242. */
  243. func (rf *lenFunc) DocString() (string, error) {
  244. return "Len returns the size of a list or map.", nil
  245. }
  246. // Del
  247. // ===
  248. /*
  249. delFunc removes an element from a list or map.
  250. */
  251. type delFunc struct {
  252. *inbuildBaseFunc
  253. }
  254. /*
  255. Run executes this function.
  256. */
  257. func (rf *delFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  258. var res interface{}
  259. err := fmt.Errorf("Need a list or a map as first parameter and an index or key as second parameter")
  260. if len(args) == 2 {
  261. if argList, ok1 := args[0].([]interface{}); ok1 {
  262. var index float64
  263. index, err = rf.AssertNumParam(2, args[1])
  264. if err == nil {
  265. res = append(argList[:int(index)], argList[int(index+1):]...)
  266. }
  267. }
  268. if argMap, ok2 := args[0].(map[interface{}]interface{}); ok2 {
  269. key := fmt.Sprint(args[1])
  270. delete(argMap, key)
  271. res = argMap
  272. err = nil
  273. }
  274. }
  275. return res, err
  276. }
  277. /*
  278. DocString returns a descriptive string.
  279. */
  280. func (rf *delFunc) DocString() (string, error) {
  281. return "Del removes an item from a list or map.", nil
  282. }
  283. // Add
  284. // ===
  285. /*
  286. addFunc adds an element to a list.
  287. */
  288. type addFunc struct {
  289. *inbuildBaseFunc
  290. }
  291. /*
  292. Run executes this function.
  293. */
  294. func (rf *addFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  295. var res interface{}
  296. err := fmt.Errorf("Need a list as first parameter and a value as second parameter")
  297. if len(args) > 1 {
  298. var argList []interface{}
  299. if argList, err = rf.AssertListParam(1, args[0]); err == nil {
  300. if len(args) == 3 {
  301. var index float64
  302. if index, err = rf.AssertNumParam(3, args[2]); err == nil {
  303. argList = append(argList, 0)
  304. copy(argList[int(index+1):], argList[int(index):])
  305. argList[int(index)] = args[1]
  306. res = argList
  307. }
  308. } else {
  309. res = append(argList, args[1])
  310. }
  311. }
  312. }
  313. return res, err
  314. }
  315. /*
  316. DocString returns a descriptive string.
  317. */
  318. func (rf *addFunc) DocString() (string, error) {
  319. return "Add adds an item to a list. The item is added at the optionally given index or at the end if no index is specified.", nil
  320. }
  321. // Concat
  322. // ======
  323. /*
  324. concatFunc joins one or more lists together.
  325. */
  326. type concatFunc struct {
  327. *inbuildBaseFunc
  328. }
  329. /*
  330. Run executes this function.
  331. */
  332. func (rf *concatFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  333. var res interface{}
  334. err := fmt.Errorf("Need at least two lists as parameters")
  335. if len(args) > 1 {
  336. var argList []interface{}
  337. resList := make([]interface{}, 0)
  338. err = nil
  339. for _, a := range args {
  340. if err == nil {
  341. if argList, err = rf.AssertListParam(1, a); err == nil {
  342. resList = append(resList, argList...)
  343. }
  344. }
  345. }
  346. if err == nil {
  347. res = resList
  348. }
  349. }
  350. return res, err
  351. }
  352. /*
  353. DocString returns a descriptive string.
  354. */
  355. func (rf *concatFunc) DocString() (string, error) {
  356. return "Concat joins one or more lists together. The result is a new list.", nil
  357. }
  358. // dumpenv
  359. // =======
  360. /*
  361. dumpenvFunc returns the current variable environment as a string.
  362. */
  363. type dumpenvFunc struct {
  364. *inbuildBaseFunc
  365. }
  366. /*
  367. Run executes this function.
  368. */
  369. func (rf *dumpenvFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  370. return vs.String(), nil
  371. }
  372. /*
  373. DocString returns a descriptive string.
  374. */
  375. func (rf *dumpenvFunc) DocString() (string, error) {
  376. return "Dumpenv returns the current variable environment as a string.", nil
  377. }
  378. // sinkerror
  379. // =========
  380. /*
  381. sinkerror returns a sink error object which indicates that the sink execution failed.
  382. This error can be used to break trigger sequences of sinks if
  383. FailOnFirstErrorInTriggerSequence is set.
  384. */
  385. type sinkerror struct {
  386. *inbuildBaseFunc
  387. }
  388. /*
  389. Run executes this function.
  390. */
  391. func (rf *sinkerror) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  392. var msg string
  393. var detail interface{}
  394. if len(args) > 0 {
  395. msg = fmt.Sprint(args[0])
  396. if len(args) > 1 {
  397. detail = args[1]
  398. }
  399. }
  400. erp := is["erp"].(*ECALRuntimeProvider)
  401. node := is["astnode"].(*parser.ASTNode)
  402. return nil, &SinkRuntimeError{
  403. erp.NewRuntimeError(util.ErrSink, msg, node).(*util.RuntimeError),
  404. nil,
  405. detail,
  406. }
  407. }
  408. /*
  409. DocString returns a descriptive string.
  410. */
  411. func (rf *sinkerror) DocString() (string, error) {
  412. return "Sinkerror returns a sink error object which indicates that the sink execution failed.", nil
  413. }
  414. // addEvent
  415. // ========
  416. /*
  417. addevent adds an event to trigger sinks. This function will return immediately
  418. and not wait for the event cascade to finish. Use this function for event cascades.
  419. */
  420. type addevent struct {
  421. *inbuildBaseFunc
  422. }
  423. /*
  424. Run executes this function.
  425. */
  426. func (rf *addevent) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  427. return rf.addEvent(func(proc engine.Processor, event *engine.Event, scope *engine.RuleScope) (interface{}, error) {
  428. var monitor engine.Monitor
  429. parentMonitor, ok := is["monitor"]
  430. if scope != nil || !ok {
  431. monitor = proc.NewRootMonitor(nil, scope)
  432. } else {
  433. monitor = parentMonitor.(engine.Monitor).NewChildMonitor(0)
  434. }
  435. _, err := proc.AddEvent(event, monitor)
  436. return nil, err
  437. }, is, args)
  438. }
  439. func (rf *addevent) addEvent(addFunc func(engine.Processor, *engine.Event, *engine.RuleScope) (interface{}, error),
  440. is map[string]interface{}, args []interface{}) (interface{}, error) {
  441. var res interface{}
  442. var stateMap map[interface{}]interface{}
  443. erp := is["erp"].(*ECALRuntimeProvider)
  444. proc := erp.Processor
  445. if proc.Stopped() {
  446. proc.Start()
  447. }
  448. err := fmt.Errorf("Need at least three parameters: name, kind and state")
  449. if len(args) > 2 {
  450. if stateMap, err = rf.AssertMapParam(3, args[2]); err == nil {
  451. var scope *engine.RuleScope
  452. event := engine.NewEvent(
  453. fmt.Sprint(args[0]),
  454. strings.Split(fmt.Sprint(args[1]), "."),
  455. stateMap,
  456. )
  457. if len(args) > 3 {
  458. var scopeMap = map[interface{}]interface{}{}
  459. // Add optional scope - if not specified it is { "": true }
  460. if scopeMap, err = rf.AssertMapParam(4, args[3]); err == nil {
  461. var scopeData = map[string]bool{}
  462. for k, v := range scopeMap {
  463. b, _ := strconv.ParseBool(fmt.Sprint(v))
  464. scopeData[fmt.Sprint(k)] = b
  465. }
  466. scope = engine.NewRuleScope(scopeData)
  467. }
  468. }
  469. if err == nil {
  470. res, err = addFunc(proc, event, scope)
  471. }
  472. }
  473. }
  474. return res, err
  475. }
  476. /*
  477. DocString returns a descriptive string.
  478. */
  479. func (rf *addevent) DocString() (string, error) {
  480. return "AddEvent adds an event to trigger sinks. This function will return " +
  481. "immediately and not wait for the event cascade to finish.", nil
  482. }
  483. // addEventAndWait
  484. // ===============
  485. /*
  486. addeventandwait adds an event to trigger sinks. This function will return once
  487. the event cascade has finished and return all errors.
  488. */
  489. type addeventandwait struct {
  490. *addevent
  491. }
  492. /*
  493. Run executes this function.
  494. */
  495. func (rf *addeventandwait) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  496. return rf.addEvent(func(proc engine.Processor, event *engine.Event, scope *engine.RuleScope) (interface{}, error) {
  497. var res []interface{}
  498. rm := proc.NewRootMonitor(nil, scope)
  499. m, err := proc.AddEventAndWait(event, rm)
  500. if m != nil {
  501. allErrors := m.(*engine.RootMonitor).AllErrors()
  502. for _, e := range allErrors {
  503. errors := map[interface{}]interface{}{}
  504. for k, v := range e.ErrorMap {
  505. se := v.(*SinkRuntimeError)
  506. // Note: The variable scope of the sink (se.environment)
  507. // was also captured - for now it is not exposed to the
  508. // language environment
  509. errors[k] = map[interface{}]interface{}{
  510. "message": se.Error(),
  511. "detail": se.detail,
  512. }
  513. }
  514. item := map[interface{}]interface{}{
  515. "event": map[interface{}]interface{}{
  516. "name": e.Event.Name(),
  517. "kind": strings.Join(e.Event.Kind(), "."),
  518. "state": e.Event.State(),
  519. },
  520. "errors": errors,
  521. }
  522. res = append(res, item)
  523. }
  524. }
  525. return res, err
  526. }, is, args)
  527. }
  528. /*
  529. DocString returns a descriptive string.
  530. */
  531. func (rf *addeventandwait) DocString() (string, error) {
  532. return "AddEventAndWait adds an event to trigger sinks. This function will " +
  533. "return once the event cascade has finished.", nil
  534. }