func_provider.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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. "devt.de/krotik/ecal/parser"
  15. "devt.de/krotik/ecal/scope"
  16. "devt.de/krotik/ecal/util"
  17. )
  18. /*
  19. inbuildFuncMap contains the mapping of inbuild functions.
  20. */
  21. var inbuildFuncMap = map[string]util.ECALFunction{
  22. "range": &rangeFunc{&inbuildBaseFunc{}},
  23. "new": &newFunc{&inbuildBaseFunc{}},
  24. "len": &lenFunc{&inbuildBaseFunc{}},
  25. "del": &delFunc{&inbuildBaseFunc{}},
  26. "add": &addFunc{&inbuildBaseFunc{}},
  27. "concat": &concatFunc{&inbuildBaseFunc{}},
  28. "dumpenv": &dumpenvFunc{&inbuildBaseFunc{}},
  29. }
  30. /*
  31. inbuildBaseFunc is the base structure for inbuild functions providing some
  32. utility functions.
  33. */
  34. type inbuildBaseFunc struct {
  35. }
  36. /*
  37. AssertNumParam converts a general interface{} parameter into a number.
  38. */
  39. func (ibf *inbuildBaseFunc) AssertNumParam(index int, val interface{}) (float64, error) {
  40. var err error
  41. resNum, ok := val.(float64)
  42. if !ok {
  43. resNum, err = strconv.ParseFloat(fmt.Sprint(val), 64)
  44. if err != nil {
  45. err = fmt.Errorf("Parameter %v should be a number", index)
  46. }
  47. }
  48. return resNum, err
  49. }
  50. /*
  51. AssertMapParam converts a general interface{} parameter into a map.
  52. */
  53. func (ibf *inbuildBaseFunc) AssertMapParam(index int, val interface{}) (map[interface{}]interface{}, error) {
  54. valMap, ok := val.(map[interface{}]interface{})
  55. if ok {
  56. return valMap, nil
  57. }
  58. return nil, fmt.Errorf("Parameter %v should be a map", index)
  59. }
  60. /*
  61. AssertListParam converts a general interface{} parameter into a list.
  62. */
  63. func (ibf *inbuildBaseFunc) AssertListParam(index int, val interface{}) ([]interface{}, error) {
  64. valList, ok := val.([]interface{})
  65. if ok {
  66. return valList, nil
  67. }
  68. return nil, fmt.Errorf("Parameter %v should be a list", index)
  69. }
  70. // Range
  71. // =====
  72. /*
  73. rangeFunc is an interator function which returns a range of numbers.
  74. */
  75. type rangeFunc struct {
  76. *inbuildBaseFunc
  77. }
  78. /*
  79. Run executes this function.
  80. */
  81. func (rf *rangeFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  82. var currVal, to float64
  83. var err error
  84. lenargs := len(args)
  85. from := 0.
  86. step := 1.
  87. if lenargs == 0 {
  88. err = fmt.Errorf("Need at least an end range as first parameter")
  89. }
  90. if err == nil {
  91. if stepVal, ok := is[instanceID+"step"]; ok {
  92. step = stepVal.(float64)
  93. from = is[instanceID+"from"].(float64)
  94. to = is[instanceID+"to"].(float64)
  95. currVal = is[instanceID+"currVal"].(float64)
  96. is[instanceID+"currVal"] = currVal + step
  97. // Check for end of iteration
  98. if (from < to && currVal > to) || (from > to && currVal < to) || from == to {
  99. err = util.ErrEndOfIteration
  100. }
  101. } else {
  102. if lenargs == 1 {
  103. to, err = rf.AssertNumParam(1, args[0])
  104. } else {
  105. from, err = rf.AssertNumParam(1, args[0])
  106. if err == nil {
  107. to, err = rf.AssertNumParam(2, args[1])
  108. }
  109. if err == nil && lenargs > 2 {
  110. step, err = rf.AssertNumParam(3, args[2])
  111. }
  112. }
  113. if err == nil {
  114. is[instanceID+"from"] = from
  115. is[instanceID+"to"] = to
  116. is[instanceID+"step"] = step
  117. is[instanceID+"currVal"] = from
  118. currVal = from
  119. }
  120. }
  121. }
  122. if err == nil {
  123. err = util.ErrIsIterator // Identify as iterator
  124. }
  125. return currVal, err
  126. }
  127. /*
  128. DocString returns a descriptive string.
  129. */
  130. func (rf *rangeFunc) DocString() (string, error) {
  131. return "Range function which can be used to iterate over number ranges. Parameters are start, end and step.", nil
  132. }
  133. // New
  134. // ===
  135. /*
  136. newFunc instantiates a new object.
  137. */
  138. type newFunc struct {
  139. *inbuildBaseFunc
  140. }
  141. /*
  142. Run executes this function.
  143. */
  144. func (rf *newFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  145. var res interface{}
  146. err := fmt.Errorf("Need a map as first parameter")
  147. if len(args) > 0 {
  148. var argMap map[interface{}]interface{}
  149. if argMap, err = rf.AssertMapParam(1, args[0]); err == nil {
  150. obj := make(map[interface{}]interface{})
  151. res = obj
  152. _, err = rf.addSuperClasses(vs, is, obj, argMap)
  153. if initObj, ok := obj["init"]; ok {
  154. if initFunc, ok := initObj.(*function); ok {
  155. initvs := scope.NewScope(fmt.Sprintf("newfunc: %v", instanceID))
  156. initis := make(map[string]interface{})
  157. _, err = initFunc.Run(instanceID, initvs, initis, args[1:])
  158. }
  159. }
  160. }
  161. }
  162. return res, err
  163. }
  164. /*
  165. addSuperClasses adds super class functions to a given object.
  166. */
  167. func (rf *newFunc) addSuperClasses(vs parser.Scope, is map[string]interface{},
  168. obj map[interface{}]interface{}, template map[interface{}]interface{}) (interface{}, error) {
  169. var err error
  170. var initFunc interface{}
  171. var initSuperList []interface{}
  172. // First loop into the base classes (i.e. top-most classes)
  173. if super, ok := template["super"]; ok {
  174. if superList, ok := super.([]interface{}); ok {
  175. for _, superObj := range superList {
  176. var superInit interface{}
  177. if superTemplate, ok := superObj.(map[interface{}]interface{}); ok {
  178. superInit, err = rf.addSuperClasses(vs, is, obj, superTemplate)
  179. initSuperList = append(initSuperList, superInit) // Build up the list of super functions
  180. }
  181. }
  182. } else {
  183. err = fmt.Errorf("Property _super must be a list of super classes")
  184. }
  185. }
  186. // Copy all properties from template to obj
  187. for k, v := range template {
  188. // Save previous init function
  189. if funcVal, ok := v.(*function); ok {
  190. newFunction := &function{funcVal.name, nil, obj, funcVal.declaration}
  191. if k == "init" {
  192. newFunction.super = initSuperList
  193. initFunc = newFunction
  194. }
  195. obj[k] = newFunction
  196. } else {
  197. obj[k] = v
  198. }
  199. }
  200. return initFunc, err
  201. }
  202. /*
  203. DocString returns a descriptive string.
  204. */
  205. func (rf *newFunc) DocString() (string, error) {
  206. return "New creates a new object instance.", nil
  207. }
  208. // Len
  209. // ===
  210. /*
  211. lenFunc returns the size of a list or map.
  212. */
  213. type lenFunc struct {
  214. *inbuildBaseFunc
  215. }
  216. /*
  217. Run executes this function.
  218. */
  219. func (rf *lenFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  220. var res float64
  221. err := fmt.Errorf("Need a list or a map as first parameter")
  222. if len(args) > 0 {
  223. argList, ok1 := args[0].([]interface{})
  224. argMap, ok2 := args[0].(map[interface{}]interface{})
  225. if ok1 {
  226. res = float64(len(argList))
  227. err = nil
  228. } else if ok2 {
  229. res = float64(len(argMap))
  230. err = nil
  231. }
  232. }
  233. return res, err
  234. }
  235. /*
  236. DocString returns a descriptive string.
  237. */
  238. func (rf *lenFunc) DocString() (string, error) {
  239. return "Len returns the size of a list or map.", nil
  240. }
  241. // Del
  242. // ===
  243. /*
  244. delFunc removes an element from a list or map.
  245. */
  246. type delFunc struct {
  247. *inbuildBaseFunc
  248. }
  249. /*
  250. Run executes this function.
  251. */
  252. func (rf *delFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  253. var res interface{}
  254. err := fmt.Errorf("Need a list or a map as first parameter and an index or key as second parameter")
  255. if len(args) == 2 {
  256. if argList, ok1 := args[0].([]interface{}); ok1 {
  257. var index float64
  258. index, err = rf.AssertNumParam(2, args[1])
  259. if err == nil {
  260. res = append(argList[:int(index)], argList[int(index+1):]...)
  261. }
  262. }
  263. if argMap, ok2 := args[0].(map[interface{}]interface{}); ok2 {
  264. key := fmt.Sprint(args[1])
  265. delete(argMap, key)
  266. res = argMap
  267. err = nil
  268. }
  269. }
  270. return res, err
  271. }
  272. /*
  273. DocString returns a descriptive string.
  274. */
  275. func (rf *delFunc) DocString() (string, error) {
  276. return "Del removes an item from a list or map.", nil
  277. }
  278. // Add
  279. // ===
  280. /*
  281. addFunc adds an element to a list.
  282. */
  283. type addFunc struct {
  284. *inbuildBaseFunc
  285. }
  286. /*
  287. Run executes this function.
  288. */
  289. func (rf *addFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  290. var res interface{}
  291. err := fmt.Errorf("Need a list as first parameter and a value as second parameter")
  292. if len(args) > 1 {
  293. var argList []interface{}
  294. if argList, err = rf.AssertListParam(1, args[0]); err == nil {
  295. if len(args) == 3 {
  296. var index float64
  297. if index, err = rf.AssertNumParam(3, args[2]); err == nil {
  298. argList = append(argList, 0)
  299. copy(argList[int(index+1):], argList[int(index):])
  300. argList[int(index)] = args[1]
  301. res = argList
  302. }
  303. } else {
  304. res = append(argList, args[1])
  305. }
  306. }
  307. }
  308. return res, err
  309. }
  310. /*
  311. DocString returns a descriptive string.
  312. */
  313. func (rf *addFunc) DocString() (string, error) {
  314. 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
  315. }
  316. // Concat
  317. // ======
  318. /*
  319. concatFunc joins one or more lists together.
  320. */
  321. type concatFunc struct {
  322. *inbuildBaseFunc
  323. }
  324. /*
  325. Run executes this function.
  326. */
  327. func (rf *concatFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  328. var res interface{}
  329. err := fmt.Errorf("Need at least two lists as parameters")
  330. if len(args) > 1 {
  331. var argList []interface{}
  332. resList := make([]interface{}, 0)
  333. err = nil
  334. for _, a := range args {
  335. if err == nil {
  336. if argList, err = rf.AssertListParam(1, a); err == nil {
  337. resList = append(resList, argList...)
  338. }
  339. }
  340. }
  341. if err == nil {
  342. res = resList
  343. }
  344. }
  345. return res, err
  346. }
  347. /*
  348. DocString returns a descriptive string.
  349. */
  350. func (rf *concatFunc) DocString() (string, error) {
  351. return "Concat joins one or more lists together. The result is a new list.", nil
  352. }
  353. // dumpenv
  354. // =======
  355. /*
  356. dumpenvFunc returns the current variable environment as a string.
  357. */
  358. type dumpenvFunc struct {
  359. *inbuildBaseFunc
  360. }
  361. /*
  362. Run executes this function.
  363. */
  364. func (rf *dumpenvFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  365. return vs.String(), nil
  366. }
  367. /*
  368. DocString returns a descriptive string.
  369. */
  370. func (rf *dumpenvFunc) DocString() (string, error) {
  371. return "Dumpenv returns the current variable environment as a string.", nil
  372. }