func_provider.go 16 KB

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