rt_general.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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. "devt.de/krotik/common/errorutil"
  14. "devt.de/krotik/ecal/parser"
  15. "devt.de/krotik/ecal/scope"
  16. "devt.de/krotik/ecal/util"
  17. )
  18. // Base Runtime
  19. // ============
  20. /*
  21. baseRuntime models a base runtime component which provides the essential fields and functions.
  22. */
  23. type baseRuntime struct {
  24. instanceID string // Unique identifier (should be used when instance state is stored)
  25. erp *ECALRuntimeProvider // Runtime provider
  26. node *parser.ASTNode // AST node which this runtime component is servicing
  27. validated bool
  28. }
  29. var instanceCounter uint64 // Global instance counter to create unique identifiers for every runtime component instance
  30. /*
  31. Validate this node and all its child nodes.
  32. */
  33. func (rt *baseRuntime) Validate() error {
  34. rt.validated = true
  35. // Validate all children
  36. for _, child := range rt.node.Children {
  37. if err := child.Runtime.Validate(); err != nil {
  38. return err
  39. }
  40. }
  41. return nil
  42. }
  43. /*
  44. Eval evaluate this runtime component.
  45. */
  46. func (rt *baseRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  47. var err error
  48. errorutil.AssertTrue(rt.validated, "Runtime component has not been validated - please call Validate() before Eval()")
  49. if rt.erp.Debugger != nil {
  50. err = rt.erp.Debugger.VisitState(rt.node, vs, tid)
  51. }
  52. return nil, err
  53. }
  54. /*
  55. newBaseRuntime returns a new instance of baseRuntime.
  56. */
  57. func newBaseRuntime(erp *ECALRuntimeProvider, node *parser.ASTNode) *baseRuntime {
  58. instanceCounter++
  59. return &baseRuntime{fmt.Sprint(instanceCounter), erp, node, false}
  60. }
  61. // Void Runtime
  62. // ============
  63. /*
  64. voidRuntime is a special runtime for constructs which are only evaluated as part
  65. of other components.
  66. */
  67. type voidRuntime struct {
  68. *baseRuntime
  69. }
  70. /*
  71. voidRuntimeInst returns a new runtime component instance.
  72. */
  73. func voidRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  74. return &voidRuntime{newBaseRuntime(erp, node)}
  75. }
  76. /*
  77. Validate this node and all its child nodes.
  78. */
  79. func (rt *voidRuntime) Validate() error {
  80. return rt.baseRuntime.Validate()
  81. }
  82. /*
  83. Eval evaluate this runtime component.
  84. */
  85. func (rt *voidRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  86. return rt.baseRuntime.Eval(vs, is, tid)
  87. }
  88. // Import Runtime
  89. // ==============
  90. /*
  91. importRuntime handles import statements.
  92. */
  93. type importRuntime struct {
  94. *baseRuntime
  95. }
  96. /*
  97. importRuntimeInst returns a new runtime component instance.
  98. */
  99. func importRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  100. return &importRuntime{newBaseRuntime(erp, node)}
  101. }
  102. /*
  103. Validate this node and all its child nodes.
  104. */
  105. func (rt *importRuntime) Validate() error {
  106. return rt.baseRuntime.Validate()
  107. }
  108. /*
  109. Eval evaluate this runtime component.
  110. */
  111. func (rt *importRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  112. _, err := rt.baseRuntime.Eval(vs, is, tid)
  113. if rt.erp.ImportLocator == nil {
  114. err = rt.erp.NewRuntimeError(util.ErrRuntimeError, "No import locator was specified", rt.node)
  115. }
  116. if err == nil {
  117. var importPath interface{}
  118. if importPath, err = rt.node.Children[0].Runtime.Eval(vs, is, tid); err == nil {
  119. var codeText string
  120. if codeText, err = rt.erp.ImportLocator.Resolve(fmt.Sprint(importPath)); err == nil {
  121. var ast *parser.ASTNode
  122. if ast, err = parser.ParseWithRuntime(fmt.Sprint(importPath), codeText, rt.erp); err == nil {
  123. if err = ast.Runtime.Validate(); err == nil {
  124. ivs := scope.NewScope(scope.GlobalScope)
  125. if _, err = ast.Runtime.Eval(ivs, make(map[string]interface{}), tid); err == nil {
  126. irt := rt.node.Children[1].Runtime.(*identifierRuntime)
  127. irt.Set(vs, is, tid, scope.ToObject(ivs))
  128. }
  129. }
  130. }
  131. }
  132. }
  133. }
  134. return nil, err
  135. }
  136. // Not Implemented Runtime
  137. // =======================
  138. /*
  139. invalidRuntime is a special runtime for not implemented constructs.
  140. */
  141. type invalidRuntime struct {
  142. *baseRuntime
  143. }
  144. /*
  145. invalidRuntimeInst returns a new runtime component instance.
  146. */
  147. func invalidRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  148. return &invalidRuntime{newBaseRuntime(erp, node)}
  149. }
  150. /*
  151. Validate this node and all its child nodes.
  152. */
  153. func (rt *invalidRuntime) Validate() error {
  154. err := rt.baseRuntime.Validate()
  155. if err == nil {
  156. err = rt.erp.NewRuntimeError(util.ErrInvalidConstruct,
  157. fmt.Sprintf("Unknown node: %s", rt.node.Name), rt.node)
  158. }
  159. return err
  160. }
  161. /*
  162. Eval evaluate this runtime component.
  163. */
  164. func (rt *invalidRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  165. _, err := rt.baseRuntime.Eval(vs, is, tid)
  166. if err == nil {
  167. err = rt.erp.NewRuntimeError(util.ErrInvalidConstruct, fmt.Sprintf("Unknown node: %s", rt.node.Name), rt.node)
  168. }
  169. return nil, err
  170. }
  171. // General Operator Runtime
  172. // ========================
  173. /*
  174. operatorRuntime is a general operator operation. Used for embedding.
  175. */
  176. type operatorRuntime struct {
  177. *baseRuntime
  178. }
  179. /*
  180. errorDetailString produces a detail string for errors.
  181. */
  182. func (rt *operatorRuntime) errorDetailString(token *parser.LexToken, opVal interface{}) string {
  183. if !token.Identifier {
  184. return token.Val
  185. }
  186. if opVal == nil {
  187. opVal = "NULL"
  188. }
  189. return fmt.Sprintf("%v=%v", token.Val, opVal)
  190. }
  191. /*
  192. numVal returns a transformed number value.
  193. */
  194. func (rt *operatorRuntime) numVal(op func(float64) interface{}, vs parser.Scope,
  195. is map[string]interface{}, tid uint64) (interface{}, error) {
  196. var ret interface{}
  197. errorutil.AssertTrue(len(rt.node.Children) == 1,
  198. fmt.Sprint("Operation requires 1 operand", rt.node))
  199. res, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
  200. if err == nil {
  201. // Check if the value is a number
  202. resNum, ok := res.(float64)
  203. if !ok {
  204. // Produce a runtime error if the value is not a number
  205. return nil, rt.erp.NewRuntimeError(util.ErrNotANumber,
  206. rt.errorDetailString(rt.node.Children[0].Token, res), rt.node.Children[0])
  207. }
  208. ret = op(resNum)
  209. }
  210. return ret, err
  211. }
  212. /*
  213. boolVal returns a transformed boolean value.
  214. */
  215. func (rt *operatorRuntime) boolVal(op func(bool) interface{},
  216. vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  217. var ret interface{}
  218. errorutil.AssertTrue(len(rt.node.Children) == 1,
  219. fmt.Sprint("Operation requires 1 operand", rt.node))
  220. res, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
  221. if err == nil {
  222. resBool, ok := res.(bool)
  223. if !ok {
  224. return nil, rt.erp.NewRuntimeError(util.ErrNotABoolean,
  225. rt.errorDetailString(rt.node.Children[0].Token, res), rt.node.Children[0])
  226. }
  227. ret = op(resBool)
  228. }
  229. return ret, err
  230. }
  231. /*
  232. numOp executes an operation on two number values.
  233. */
  234. func (rt *operatorRuntime) numOp(op func(float64, float64) interface{},
  235. vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  236. var ok bool
  237. var res1, res2 interface{}
  238. var err error
  239. errorutil.AssertTrue(len(rt.node.Children) == 2,
  240. fmt.Sprint("Operation requires 2 operands", rt.node))
  241. if res1, err = rt.node.Children[0].Runtime.Eval(vs, is, tid); err == nil {
  242. if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
  243. var res1Num, res2Num float64
  244. if res1Num, ok = res1.(float64); !ok {
  245. err = rt.erp.NewRuntimeError(util.ErrNotANumber,
  246. rt.errorDetailString(rt.node.Children[0].Token, res1), rt.node.Children[0])
  247. } else {
  248. if res2Num, ok = res2.(float64); !ok {
  249. err = rt.erp.NewRuntimeError(util.ErrNotANumber,
  250. rt.errorDetailString(rt.node.Children[1].Token, res2), rt.node.Children[1])
  251. } else {
  252. return op(res1Num, res2Num), err
  253. }
  254. }
  255. }
  256. }
  257. return nil, err
  258. }
  259. /*
  260. genOp executes an operation on two general values.
  261. */
  262. func (rt *operatorRuntime) genOp(op func(interface{}, interface{}) interface{},
  263. vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  264. var ret interface{}
  265. errorutil.AssertTrue(len(rt.node.Children) == 2,
  266. fmt.Sprint("Operation requires 2 operands", rt.node))
  267. res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
  268. if err == nil {
  269. var res2 interface{}
  270. if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
  271. ret = op(res1, res2)
  272. }
  273. }
  274. return ret, err
  275. }
  276. /*
  277. strOp executes an operation on two string values.
  278. */
  279. func (rt *operatorRuntime) strOp(op func(string, string) interface{},
  280. vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  281. var ret interface{}
  282. errorutil.AssertTrue(len(rt.node.Children) == 2,
  283. fmt.Sprint("Operation requires 2 operands", rt.node))
  284. res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
  285. if err == nil {
  286. var res2 interface{}
  287. if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
  288. ret = op(fmt.Sprint(res1), fmt.Sprint(res2))
  289. }
  290. }
  291. return ret, err
  292. }
  293. /*
  294. boolOp executes an operation on two boolean values.
  295. */
  296. func (rt *operatorRuntime) boolOp(op func(bool, bool) interface{},
  297. vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  298. var res interface{}
  299. errorutil.AssertTrue(len(rt.node.Children) == 2,
  300. fmt.Sprint("Operation requires 2 operands", rt.node))
  301. res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
  302. if err == nil {
  303. var res2 interface{}
  304. if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
  305. res1bool, ok := res1.(bool)
  306. if !ok {
  307. return nil, rt.erp.NewRuntimeError(util.ErrNotABoolean,
  308. rt.errorDetailString(rt.node.Children[0].Token, res1), rt.node.Children[0])
  309. }
  310. res2bool, ok := res2.(bool)
  311. if !ok {
  312. return nil, rt.erp.NewRuntimeError(util.ErrNotABoolean,
  313. rt.errorDetailString(rt.node.Children[1].Token, res2), rt.node.Children[0])
  314. }
  315. res = op(res1bool, res2bool)
  316. }
  317. }
  318. return res, err
  319. }
  320. /*
  321. listOp executes an operation on a value and a list.
  322. */
  323. func (rt *operatorRuntime) listOp(op func(interface{}, []interface{}) interface{},
  324. vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
  325. var res interface{}
  326. errorutil.AssertTrue(len(rt.node.Children) == 2,
  327. fmt.Sprint("Operation requires 2 operands", rt.node))
  328. res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
  329. if err == nil {
  330. var res2 interface{}
  331. if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
  332. res2list, ok := res2.([]interface{})
  333. if !ok {
  334. err = rt.erp.NewRuntimeError(util.ErrNotAList,
  335. rt.errorDetailString(rt.node.Children[1].Token, res2), rt.node.Children[0])
  336. } else {
  337. res = op(res1, res2list)
  338. }
  339. }
  340. }
  341. return res, err
  342. }