rt_func_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. "testing"
  13. "devt.de/krotik/common/stringutil"
  14. "devt.de/krotik/ecal/scope"
  15. )
  16. func TestFunctions(t *testing.T) {
  17. vs := scope.NewScope(scope.GlobalScope)
  18. res, err := UnitTestEvalAndAST(`
  19. foo := [ [ func (a, b, c=1) {
  20. return a + b + c
  21. }
  22. ]]
  23. result1 := foo[0][0](3, 2)
  24. `, vs, `
  25. statements
  26. :=
  27. identifier: foo
  28. list
  29. list
  30. function
  31. params
  32. identifier: a
  33. identifier: b
  34. preset
  35. identifier: c
  36. number: 1
  37. statements
  38. return
  39. plus
  40. plus
  41. identifier: a
  42. identifier: b
  43. identifier: c
  44. :=
  45. identifier: result1
  46. identifier: foo
  47. compaccess
  48. number: 0
  49. compaccess
  50. number: 0
  51. funccall
  52. number: 3
  53. number: 2
  54. `[1:])
  55. if vsRes := vs.String(); err != nil || res != nil || vsRes != `GlobalScope {
  56. foo ([]interface {}) : [["ecal.function: (Line 2, Pos 12)"]]
  57. result1 (float64) : 6
  58. }` {
  59. t.Error("Unexpected result: ", vsRes, res, err)
  60. return
  61. }
  62. vs = scope.NewScope(scope.GlobalScope)
  63. res, err = UnitTestEval(`
  64. b := "a"
  65. foo := [{
  66. b : func (a, b, c=1) {
  67. return [1,[a + b + c]]
  68. }
  69. }]
  70. result1 := foo[0].a(3, 2)[1][0]
  71. `, vs)
  72. if vsRes := vs.String(); err != nil || res != nil || vsRes != `GlobalScope {
  73. b (string) : a
  74. foo ([]interface {}) : [{"a":"ecal.function: (Line 4, Pos 7)"}]
  75. result1 (float64) : 6
  76. }` {
  77. t.Error("Unexpected result: ", vsRes, res, err)
  78. return
  79. }
  80. vs = scope.NewScope(scope.GlobalScope)
  81. res, err = UnitTestEval(`
  82. b := "a"
  83. foo := {
  84. b : [func (a, b, c=1) {
  85. return { "x" : { "y" : [a + b + c] }}
  86. }]
  87. }
  88. result1 := foo.a[0](3, 2).x.y[0]
  89. `, vs)
  90. if vsRes := vs.String(); err != nil || res != nil || vsRes != `GlobalScope {
  91. b (string) : a
  92. foo (map[interface {}]interface {}) : {"a":["ecal.function: (Line 4, Pos 8)"]}
  93. result1 (float64) : 6
  94. }` {
  95. t.Error("Unexpected result: ", vsRes, res, err)
  96. return
  97. }
  98. vs = scope.NewScope(scope.GlobalScope)
  99. res, err = UnitTestEvalAndAST(`
  100. foo := {
  101. "a" : {
  102. "b" : func myfunc(a, b, c=1) {
  103. d := a + b + c
  104. return d
  105. }
  106. }
  107. }
  108. result1 := foo.a.b(3, 2)
  109. result2 := myfunc(3, 3)
  110. `, vs, `
  111. statements
  112. :=
  113. identifier: foo
  114. map
  115. kvp
  116. string: 'a'
  117. map
  118. kvp
  119. string: 'b'
  120. function
  121. identifier: myfunc
  122. params
  123. identifier: a
  124. identifier: b
  125. preset
  126. identifier: c
  127. number: 1
  128. statements
  129. :=
  130. identifier: d
  131. plus
  132. plus
  133. identifier: a
  134. identifier: b
  135. identifier: c
  136. return
  137. identifier: d
  138. :=
  139. identifier: result1
  140. identifier: foo
  141. identifier: a
  142. identifier: b
  143. funccall
  144. number: 3
  145. number: 2
  146. :=
  147. identifier: result2
  148. identifier: myfunc
  149. funccall
  150. number: 3
  151. number: 3
  152. `[1:])
  153. if vsRes := vs.String(); err != nil || res != nil || vsRes != `GlobalScope {
  154. foo (map[interface {}]interface {}) : {"a":{"b":"ecal.function: myfunc (Line 4, Pos 8)"}}
  155. myfunc (*interpreter.function) : ecal.function: myfunc (Line 4, Pos 8)
  156. result1 (float64) : 6
  157. result2 (float64) : 7
  158. }` {
  159. t.Error("Unexpected result: ", vsRes, res, err)
  160. return
  161. }
  162. }
  163. func TestFunctionScoping(t *testing.T) {
  164. vs := scope.NewScope(scope.GlobalScope)
  165. res, err := UnitTestEval(`
  166. c := 1
  167. foo := func (a, b=1) {
  168. return a + b + c
  169. }
  170. result1 := foo(3, 2)
  171. `, vs)
  172. if vsRes := vs.String(); err != nil || res != nil || vsRes != `GlobalScope {
  173. c (float64) : 1
  174. foo (*interpreter.function) : ecal.function: (Line 3, Pos 8)
  175. result1 (float64) : 6
  176. }` {
  177. t.Error("Unexpected result: ", vsRes, res, err)
  178. return
  179. }
  180. }
  181. func TestObjectInstantiation(t *testing.T) {
  182. vs := scope.NewScope(scope.GlobalScope)
  183. res, err := UnitTestEvalAndAST(`
  184. Super := {
  185. "name" : "base"
  186. "init" : func() {
  187. this.name := "baseclass"
  188. }
  189. }
  190. Bar := {
  191. "super" : [ Super ]
  192. "test" : ""
  193. "init" : func(test) {
  194. this.test := test
  195. x := super[0]()
  196. }
  197. }
  198. Bar2 := {
  199. "getTest" : func() {
  200. return this.test
  201. }
  202. }
  203. Foo := {
  204. "super" : [ Bar, Bar2 ]
  205. # Object ID
  206. #
  207. "id" : 0
  208. "idx" : 0
  209. # Constructor
  210. #
  211. "init" : func(id, test) {
  212. this.id := id
  213. x := super[0](test)
  214. }
  215. # Return the object ID
  216. #
  217. "getId" : func() {
  218. return this.idx
  219. }
  220. # Set the object ID
  221. #
  222. "setId" : func(id) {
  223. this.idx := id
  224. }
  225. }
  226. result1 := new(Foo, 123, "tester")
  227. result1.setId(500)
  228. result2 := result1.getId() + result1.id
  229. `, vs, "")
  230. if err == nil {
  231. v, _, _ := vs.GetValue("result1")
  232. if res := stringutil.ConvertToPrettyString(v); res != `{
  233. "getId": "ecal.function: (Line 45, Pos 42)",
  234. "getTest": "ecal.function: (Line 22, Pos 15)",
  235. "id": 123,
  236. "idx": 500,
  237. "init": "ecal.function: (Line 38, Pos 32)",
  238. "name": "baseclass",
  239. "setId": "ecal.function: (Line 51, Pos 39)",
  240. "super": [
  241. {
  242. "init": "ecal.function: (Line 15, Pos 12)",
  243. "super": [
  244. {
  245. "init": "ecal.function: (Line 5, Pos 12)",
  246. "name": "base"
  247. }
  248. ],
  249. "test": ""
  250. },
  251. {
  252. "getTest": "ecal.function: (Line 22, Pos 15)"
  253. }
  254. ],
  255. "test": "tester"
  256. }` {
  257. t.Error("Unexpected result: ", res)
  258. return
  259. }
  260. }
  261. if vsRes := vs.String(); err != nil || res != nil || vsRes != `GlobalScope {
  262. Bar (map[interface {}]interface {}) : {"init":"ecal.function: (Line 15, Pos 12)","super":[{"init":"ecal.function: (Line 5, Pos 12)","name":"base"}],"test":""}
  263. Bar2 (map[interface {}]interface {}) : {"getTest":"ecal.function: (Line 22, Pos 15)"}
  264. Foo (map[interface {}]interface {}) : {"getId":"ecal.function: (Line 45, Pos 42)","id":0,"idx":0,"init":"ecal.function: (Line 38, Pos 32)","setId":"ecal.function: (Line 51, Pos 39)","super":[{"init":"ecal.function: (Line 15, Pos 12)","super":[{"init":"ecal.function: (Line 5, Pos 12)","name":"base"}],"test":""},{"getTest":"ecal.function: (Line 22, Pos 15)"}]}
  265. Super (map[interface {}]interface {}) : {"init":"ecal.function: (Line 5, Pos 12)","name":"base"}
  266. result1 (map[interface {}]interface {}) : {"getId":"ecal.function: (Line 45, Pos 42)","getTest":"ecal.function: (Line 22, Pos 15)","id":123,"idx":500,"init":"ecal.function: (Line 38, Pos 32)","name":"baseclass","setId":"ecal.function: (Line 51, Pos 39)","super":[{"init":"ecal.function: (Line 15, Pos 12)","super":[{"init":"ecal.function: (Line 5, Pos 12)","name":"base"}],"test":""},{"getTest":"ecal.function: (Line 22, Pos 15)"}],"test":"tester"}
  267. result2 (float64) : 623
  268. }` {
  269. t.Error("Unexpected result: ", vsRes, res, err)
  270. return
  271. }
  272. }