easycoder 260401.2__tar.gz → 260401.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. {easycoder-260401.2 → easycoder-260401.4}/PKG-INFO +1 -1
  2. {easycoder-260401.2 → easycoder-260401.4}/easycoder/__init__.py +1 -1
  3. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_classes.py +3 -0
  4. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_core.py +223 -91
  5. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_program.py +1 -0
  6. easycoder-260401.2/test.py +0 -7
  7. easycoder-260401.2/testController.py +0 -7
  8. easycoder-260401.2/testDoclets.py +0 -7
  9. easycoder-260401.2/testServer.py +0 -7
  10. easycoder-260401.2/test_debug_graphics.py +0 -42
  11. easycoder-260401.2/test_debug_launch.py +0 -36
  12. easycoder-260401.2/test_init_debug.py +0 -23
  13. easycoder-260401.2/test_initializers.py +0 -149
  14. easycoder-260401.2/test_mqtt_listener.py +0 -7
  15. easycoder-260401.2/test_mqtt_publisher.py +0 -7
  16. easycoder-260401.2/testdbg.py +0 -7
  17. easycoder-260401.2/testg.py +0 -7
  18. easycoder-260401.2/testgetconfig.py +0 -7
  19. easycoder-260401.2/testmodules.py +0 -7
  20. easycoder-260401.2/testmqtt.py +0 -7
  21. easycoder-260401.2/testnewui.py +0 -7
  22. easycoder-260401.2/testrbr.py +0 -7
  23. easycoder-260401.2/testrc.py +0 -7
  24. easycoder-260401.2/testrmain.py +0 -7
  25. easycoder-260401.2/tests.py +0 -7
  26. easycoder-260401.2/testsql.py +0 -7
  27. easycoder-260401.2/testui.py +0 -7
  28. {easycoder-260401.2 → easycoder-260401.4}/.github/copilot-instructions.md +0 -0
  29. {easycoder-260401.2 → easycoder-260401.4}/.github/workflows/conformance-report.yml +0 -0
  30. {easycoder-260401.2 → easycoder-260401.4}/.gitignore +0 -0
  31. {easycoder-260401.2 → easycoder-260401.4}/.vscode/EXTENSION_GUIDE.md +0 -0
  32. {easycoder-260401.2 → easycoder-260401.4}/.vscode/PYTHON_SETUP.md +0 -0
  33. {easycoder-260401.2 → easycoder-260401.4}/.vscode/easycoder/README.md +0 -0
  34. {easycoder-260401.2 → easycoder-260401.4}/.vscode/easycoder/language-configuration.json +0 -0
  35. {easycoder-260401.2 → easycoder-260401.4}/.vscode/easycoder/package.json +0 -0
  36. {easycoder-260401.2 → easycoder-260401.4}/.vscode/easycoder/snippets/easycoder.json +0 -0
  37. {easycoder-260401.2 → easycoder-260401.4}/.vscode/easycoder/syntaxes/easycoder.tmLanguage.json +0 -0
  38. {easycoder-260401.2 → easycoder-260401.4}/.vscode/launch.json +0 -0
  39. {easycoder-260401.2 → easycoder-260401.4}/.vscode/settings.json +0 -0
  40. {easycoder-260401.2 → easycoder-260401.4}/AI/ARCHITECTURE.md +0 -0
  41. {easycoder-260401.2 → easycoder-260401.4}/AI/EASYCODER_AND_WEBSON.md +0 -0
  42. {easycoder-260401.2 → easycoder-260401.4}/AI/EXAMPLES.md +0 -0
  43. {easycoder-260401.2 → easycoder-260401.4}/AI/PROJECT_OVERVIEW.md +0 -0
  44. {easycoder-260401.2 → easycoder-260401.4}/AI/README.md +0 -0
  45. {easycoder-260401.2 → easycoder-260401.4}/AI/WORKING_RULES.md +0 -0
  46. {easycoder-260401.2 → easycoder-260401.4}/AI/articles/Arrays and Modules.md +0 -0
  47. {easycoder-260401.2 → easycoder-260401.4}/AI/examples/primes/primes.ecs +0 -0
  48. {easycoder-260401.2 → easycoder-260401.4}/AI/examples/primes/primes.md +0 -0
  49. {easycoder-260401.2 → easycoder-260401.4}/AI/examples/wordlist/wordlist.ecs +0 -0
  50. {easycoder-260401.2 → easycoder-260401.4}/AI/examples/wordlist/wordlist.md +0 -0
  51. {easycoder-260401.2 → easycoder-260401.4}/AI/log/CONTRIBUTING.md +0 -0
  52. {easycoder-260401.2 → easycoder-260401.4}/AI/log/DEVELOPER_RESOURCES.md +0 -0
  53. {easycoder-260401.2 → easycoder-260401.4}/AI/log/GRAPHICS_PHASE1.md +0 -0
  54. {easycoder-260401.2 → easycoder-260401.4}/AI/log/PHASE1_COMPLETION_SUMMARY.md +0 -0
  55. {easycoder-260401.2 → easycoder-260401.4}/AI/log/PHASE_1_3_COMPLETION_REPORT.md +0 -0
  56. {easycoder-260401.2 → easycoder-260401.4}/AI/log/PHASE_4_COMPLETION_REPORT.md +0 -0
  57. {easycoder-260401.2 → easycoder-260401.4}/AI/log/PLUGIN_PATTERNS.md +0 -0
  58. {easycoder-260401.2 → easycoder-260401.4}/AI/log/PROJECT_COMPLETION_SUMMARY.md +0 -0
  59. {easycoder-260401.2 → easycoder-260401.4}/AI/log/START_HERE.md +0 -0
  60. {easycoder-260401.2 → easycoder-260401.4}/AI/log/SYNTAX_REFACTORING.md +0 -0
  61. {easycoder-260401.2 → easycoder-260401.4}/LICENSE +0 -0
  62. {easycoder-260401.2 → easycoder-260401.4}/README.md +0 -0
  63. {easycoder-260401.2 → easycoder-260401.4}/RELEASE_NOTES.md +0 -0
  64. {easycoder-260401.2 → easycoder-260401.4}/backdrop.jpg +0 -0
  65. {easycoder-260401.2 → easycoder-260401.4}/basic.py +0 -0
  66. {easycoder-260401.2 → easycoder-260401.4}/conformance/README.md +0 -0
  67. {easycoder-260401.2 → easycoder-260401.4}/conformance/actuals-python-cli.json +0 -0
  68. {easycoder-260401.2 → easycoder-260401.4}/conformance/ec_py_runner.py +0 -0
  69. {easycoder-260401.2 → easycoder-260401.4}/conformance/parity-report-template.json +0 -0
  70. {easycoder-260401.2 → easycoder-260401.4}/conformance/parity-report.generated.json +0 -0
  71. {easycoder-260401.2 → easycoder-260401.4}/conformance/parity-report.initial.json +0 -0
  72. {easycoder-260401.2 → easycoder-260401.4}/conformance/plugin-interface-matrix.json +0 -0
  73. {easycoder-260401.2 → easycoder-260401.4}/conformance/run_conformance.py +0 -0
  74. {easycoder-260401.2 → easycoder-260401.4}/conformance/runner-contract.md +0 -0
  75. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0001-basic-assignment.ecs +0 -0
  76. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0001-basic-assignment.json +0 -0
  77. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0002-arithmetic-chain.ecs +0 -0
  78. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0002-arithmetic-chain.json +0 -0
  79. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0003-condition-branch.ecs +0 -0
  80. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0003-condition-branch.json +0 -0
  81. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0004-while-sum.ecs +0 -0
  82. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0004-while-sum.json +0 -0
  83. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0005-array-index-access.ecs +0 -0
  84. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0005-array-index-access.json +0 -0
  85. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0006-and-or-conditions.ecs +0 -0
  86. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0006-and-or-conditions.json +0 -0
  87. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0007-includes-membership.ecs +0 -0
  88. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/EC-0007-includes-membership.json +0 -0
  89. {easycoder-260401.2 → easycoder-260401.4}/conformance/tests/index.json +0 -0
  90. {easycoder-260401.2 → easycoder-260401.4}/doc/README.md +0 -0
  91. {easycoder-260401.2 → easycoder-260401.4}/doc/RESERVED_STEMS.md +0 -0
  92. {easycoder-260401.2 → easycoder-260401.4}/doc/core/README.md +0 -0
  93. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/boolean.md +0 -0
  94. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/empty.md +0 -0
  95. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/ends.md +0 -0
  96. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/even.md +0 -0
  97. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/exists.md +0 -0
  98. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/greater.md +0 -0
  99. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/hasProperty.md +0 -0
  100. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/includes.md +0 -0
  101. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/is.md +0 -0
  102. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/less.md +0 -0
  103. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/list.md +0 -0
  104. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/none.md +0 -0
  105. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/not.md +0 -0
  106. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/numeric.md +0 -0
  107. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/object.md +0 -0
  108. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/odd.md +0 -0
  109. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/starts.md +0 -0
  110. {easycoder-260401.2 → easycoder-260401.4}/doc/core/conditions/string.md +0 -0
  111. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/add.md +0 -0
  112. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/append.md +0 -0
  113. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/assert.md +0 -0
  114. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/begin.md +0 -0
  115. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/clear.md +0 -0
  116. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/close.md +0 -0
  117. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/create.md +0 -0
  118. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/debug.md +0 -0
  119. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/decrement.md +0 -0
  120. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/delete.md +0 -0
  121. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/divide.md +0 -0
  122. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/download.md +0 -0
  123. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/exit.md +0 -0
  124. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/file.md +0 -0
  125. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/fork.md +0 -0
  126. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/get.md +0 -0
  127. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/go.md +0 -0
  128. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/gosub.md +0 -0
  129. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/if.md +0 -0
  130. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/import.md +0 -0
  131. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/increment.md +0 -0
  132. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/index.md +0 -0
  133. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/init.md +0 -0
  134. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/input.md +0 -0
  135. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/load.md +0 -0
  136. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/lock.md +0 -0
  137. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/log.md +0 -0
  138. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/module.md +0 -0
  139. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/multiply.md +0 -0
  140. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/negate.md +0 -0
  141. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/on.md +0 -0
  142. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/open.md +0 -0
  143. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/pass.md +0 -0
  144. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/pop.md +0 -0
  145. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/post.md +0 -0
  146. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/print.md +0 -0
  147. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/push.md +0 -0
  148. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/put.md +0 -0
  149. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/read.md +0 -0
  150. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/release.md +0 -0
  151. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/replace.md +0 -0
  152. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/return.md +0 -0
  153. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/run.md +0 -0
  154. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/save.md +0 -0
  155. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/script.md +0 -0
  156. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/send.md +0 -0
  157. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/set.md +0 -0
  158. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/shuffle.md +0 -0
  159. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/split.md +0 -0
  160. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/stack.md +0 -0
  161. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/stop.md +0 -0
  162. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/system.md +0 -0
  163. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/take.md +0 -0
  164. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/toggle.md +0 -0
  165. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/trim.md +0 -0
  166. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/truncate.md +0 -0
  167. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/unlock.md +0 -0
  168. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/use.md +0 -0
  169. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/variable.md +0 -0
  170. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/wait.md +0 -0
  171. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/while.md +0 -0
  172. {easycoder-260401.2 → easycoder-260401.4}/doc/core/keywords/write.md +0 -0
  173. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/arg.md +0 -0
  174. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/args.md +0 -0
  175. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/cat.md +0 -0
  176. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/cos.md +0 -0
  177. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/datime.md +0 -0
  178. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/decode.md +0 -0
  179. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/element.md +0 -0
  180. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/elements.md +0 -0
  181. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/empty.md +0 -0
  182. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/encode.md +0 -0
  183. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/error.md +0 -0
  184. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/files.md +0 -0
  185. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/float.md +0 -0
  186. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/from.md +0 -0
  187. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/hash.md +0 -0
  188. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/index.md +0 -0
  189. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/integer.md +0 -0
  190. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/json.md +0 -0
  191. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/keys.md +0 -0
  192. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/left.md +0 -0
  193. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/length.md +0 -0
  194. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/lowercase.md +0 -0
  195. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/memory.md +0 -0
  196. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/modification.md +0 -0
  197. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/modulo.md +0 -0
  198. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/newline.md +0 -0
  199. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/now.md +0 -0
  200. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/operations.md +0 -0
  201. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/position.md +0 -0
  202. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/property.md +0 -0
  203. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/random.md +0 -0
  204. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/right.md +0 -0
  205. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/sin.md +0 -0
  206. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/stringify.md +0 -0
  207. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/tab.md +0 -0
  208. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/tan.md +0 -0
  209. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/timestamp.md +0 -0
  210. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/today.md +0 -0
  211. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/trim.md +0 -0
  212. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/type.md +0 -0
  213. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/uppercase.md +0 -0
  214. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/value.md +0 -0
  215. {easycoder-260401.2 → easycoder-260401.4}/doc/core/values/weekday.md +0 -0
  216. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/PATTERNS.md +0 -0
  217. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/README.md +0 -0
  218. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/add.md +0 -0
  219. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/attach.md +0 -0
  220. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/center.md +0 -0
  221. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/checkbox.md +0 -0
  222. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/clear.md +0 -0
  223. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/close.md +0 -0
  224. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/combobox.md +0 -0
  225. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/create.md +0 -0
  226. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/dialog.md +0 -0
  227. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/disable.md +0 -0
  228. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/enable.md +0 -0
  229. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/group.md +0 -0
  230. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/hide.md +0 -0
  231. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/label.md +0 -0
  232. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/layout.md +0 -0
  233. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/lineinput.md +0 -0
  234. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/listbox.md +0 -0
  235. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/messagebox.md +0 -0
  236. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/move.md +0 -0
  237. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/multiline.md +0 -0
  238. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/on.md +0 -0
  239. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/pushbutton.md +0 -0
  240. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/remove.md +0 -0
  241. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/select.md +0 -0
  242. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/set.md +0 -0
  243. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/keywords/window.md +0 -0
  244. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/values/attribute.md +0 -0
  245. {easycoder-260401.2 → easycoder-260401.4}/doc/graphics/values/window.md +0 -0
  246. {easycoder-260401.2 → easycoder-260401.4}/easycoder/debugger/__init__.py +0 -0
  247. {easycoder-260401.2 → easycoder-260401.4}/easycoder/debugger/ec_dbg_value_display copy.py +0 -0
  248. {easycoder-260401.2 → easycoder-260401.4}/easycoder/debugger/ec_dbg_value_display.py +0 -0
  249. {easycoder-260401.2 → easycoder-260401.4}/easycoder/debugger/ec_dbg_watch_list copy.py +0 -0
  250. {easycoder-260401.2 → easycoder-260401.4}/easycoder/debugger/ec_dbg_watchlist.py +0 -0
  251. {easycoder-260401.2 → easycoder-260401.4}/easycoder/debugger/ec_debug.py +0 -0
  252. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_border.py +0 -0
  253. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_compiler.py +0 -0
  254. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_condition.py +0 -0
  255. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_gclasses.py +0 -0
  256. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_graphics.py +0 -0
  257. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_handler.py +0 -0
  258. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_keyboard.py +0 -0
  259. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_mqtt.py +0 -0
  260. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_psutil.py +0 -0
  261. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_server.py +0 -0
  262. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_timestamp.py +0 -0
  263. {easycoder-260401.2 → easycoder-260401.4}/easycoder/ec_value.py +0 -0
  264. {easycoder-260401.2 → easycoder-260401.4}/easycoder/icons/close.png +0 -0
  265. {easycoder-260401.2 → easycoder-260401.4}/easycoder/icons/exit.png +0 -0
  266. {easycoder-260401.2 → easycoder-260401.4}/easycoder/icons/run.png +0 -0
  267. {easycoder-260401.2 → easycoder-260401.4}/easycoder/icons/step.png +0 -0
  268. {easycoder-260401.2 → easycoder-260401.4}/easycoder/icons/stop.png +0 -0
  269. {easycoder-260401.2 → easycoder-260401.4}/easycoder/icons/tick.png +0 -0
  270. {easycoder-260401.2 → easycoder-260401.4}/easycoder/mqtt_listener.py +0 -0
  271. {easycoder-260401.2 → easycoder-260401.4}/easycoder/mqtt_publisher.py +0 -0
  272. {easycoder-260401.2 → easycoder-260401.4}/easycoder.tmLanguage.json +0 -0
  273. {easycoder-260401.2 → easycoder-260401.4}/flash.py +0 -0
  274. {easycoder-260401.2 → easycoder-260401.4}/images/Semoigo Dawn.jpg +0 -0
  275. {easycoder-260401.2 → easycoder-260401.4}/json/graphics-demo.json +0 -0
  276. {easycoder-260401.2 → easycoder-260401.4}/mqtt_listen.py +0 -0
  277. {easycoder-260401.2 → easycoder-260401.4}/mqtt_publish.py +0 -0
  278. {easycoder-260401.2 → easycoder-260401.4}/mqtt_test.html +0 -0
  279. {easycoder-260401.2 → easycoder-260401.4}/plugins/ec_p100.py +0 -0
  280. {easycoder-260401.2 → easycoder-260401.4}/plugins/ec_points.py +0 -0
  281. {easycoder-260401.2 → easycoder-260401.4}/plugins/ec_sql.py +0 -0
  282. {easycoder-260401.2 → easycoder-260401.4}/pyproject.toml +0 -0
  283. {easycoder-260401.2 → easycoder-260401.4}/spec/README.md +0 -0
  284. {easycoder-260401.2 → easycoder-260401.4}/spec/easycoder-language-contract.md +0 -0
  285. {easycoder-260401.2 → easycoder-260401.4}/spec/easycoder-plugin-contract.md +0 -0
  286. {easycoder-260401.2 → easycoder-260401.4}/spec/easycoder-versioning-policy.md +0 -0
  287. {easycoder-260401.2 → easycoder-260401.4}/tests/benchmark.ecs +0 -0
  288. {easycoder-260401.2 → easycoder-260401.4}/tests/child.ecs +0 -0
  289. {easycoder-260401.2 → easycoder-260401.4}/tests/ec_mqtt.py +0 -0
  290. {easycoder-260401.2 → easycoder-260401.4}/tests/editor_server.ecs +0 -0
  291. {easycoder-260401.2 → easycoder-260401.4}/tests/fizzbuzz.ecs +0 -0
  292. {easycoder-260401.2 → easycoder-260401.4}/tests/hello.ecs +0 -0
  293. {easycoder-260401.2 → easycoder-260401.4}/tests/mqtt.ecs +0 -0
  294. {easycoder-260401.2 → easycoder-260401.4}/tests/mqtt_listener.ecs +0 -0
  295. {easycoder-260401.2 → easycoder-260401.4}/tests/mqtt_publisher.ecs +0 -0
  296. {easycoder-260401.2 → easycoder-260401.4}/tests/parent.ecs +0 -0
  297. {easycoder-260401.2 → easycoder-260401.4}/tests/points.ecs +0 -0
  298. {easycoder-260401.2 → easycoder-260401.4}/tests/rbr_ui.py +0 -0
  299. {easycoder-260401.2 → easycoder-260401.4}/tests/rbrconf.ecs +0 -0
  300. {easycoder-260401.2 → easycoder-260401.4}/tests/rbrwidgets.py +0 -0
  301. {easycoder-260401.2 → easycoder-260401.4}/tests/server.ecs +0 -0
  302. {easycoder-260401.2 → easycoder-260401.4}/tests/server_test.html +0 -0
  303. {easycoder-260401.2 → easycoder-260401.4}/tests/server_test.sh +0 -0
  304. {easycoder-260401.2 → easycoder-260401.4}/tests/test.ecs +0 -0
  305. {easycoder-260401.2 → easycoder-260401.4}/tests/testg.ecs +0 -0
  306. {easycoder-260401.2 → easycoder-260401.4}/tests/tests.ecs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easycoder
3
- Version: 260401.2
3
+ Version: 260401.4
4
4
  Summary: Rapid scripting in English
5
5
  Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
6
6
  Author-email: Graham Trott <gtanyware@gmail.com>
@@ -3,7 +3,7 @@
3
3
  import importlib
4
4
  import math
5
5
 
6
- __version__ = "260401.2"
6
+ __version__ = "260401.4"
7
7
 
8
8
  from .ec_classes import *
9
9
  from .ec_compiler import *
@@ -59,6 +59,9 @@ class RuntimeError(BaseException):
59
59
  def __init__(self, program, message):
60
60
  if program == None:
61
61
  sys.exit(f'Runtime Error: {message}')
62
+ elif program.onError:
63
+ program.errorMessage = message
64
+ program.run(program.onError)
62
65
  else:
63
66
  code = program.code[program.pc]
64
67
  lino = code['lino']
@@ -89,13 +89,15 @@ class Core(Handler):
89
89
  record = self.getSymbolRecord()
90
90
  self.checkObjectType(record, ECVariable)
91
91
  command['target'] = record['name']
92
- self.add(command)
92
+ orPC = self.getCodeSize()
93
+ self.processOr(command, orPC)
93
94
  return True
94
95
  else:
95
96
  # Here the variable is the target
96
97
  command['target'] = record['name']
97
98
  if self.getObject(record).isMutable():
98
- self.add(command)
99
+ orPC = self.getCodeSize()
100
+ self.processOr(command, orPC)
99
101
  return True
100
102
  else:
101
103
  # Here we have 2 values so 'giving' must come next
@@ -105,26 +107,30 @@ class Core(Handler):
105
107
  record = self.getSymbolRecord()
106
108
  self.checkObjectType(record, ECVariable)
107
109
  command['target'] = record['name']
108
- self.add(command)
110
+ orPC = self.getCodeSize()
111
+ self.processOr(command, orPC)
109
112
  return True
110
113
  # raise FatalError(self.compiler, 'Cannot add values: target variable expected')
111
114
  return False
112
115
 
113
116
  def r_add(self, command):
114
- value1 = self.textify(command['value1'])
115
- value2 = self.textify(command['value2']) if 'value2' in command else None
116
- target = self.getVariable(command['target'])
117
- # Check that the target variable is mutable. If not, it's not an arithmetic add
118
- # If value2 exists, we are adding two values and storing the result in target
119
- if value2 != None:
120
- # add X to Y giving Z
121
- targetValue = ECValue(type=int, content=int(value1) + int(value2))
122
- else:
123
- # add X to Y
124
- targetValue = self.getSymbolValue(target)
125
- targetValue.setContent(int(targetValue.getContent()) + int(value1))
126
- self.putSymbolValue(target, targetValue)
127
- return self.nextPC()
117
+ try:
118
+ value1 = self.textify(command['value1'])
119
+ value2 = self.textify(command['value2']) if 'value2' in command else None
120
+ target = self.getVariable(command['target'])
121
+ if value2 != None:
122
+ targetValue = ECValue(type=int, content=int(value1) + int(value2))
123
+ else:
124
+ targetValue = self.getSymbolValue(target)
125
+ targetValue.setContent(int(targetValue.getContent()) + int(value1))
126
+ self.putSymbolValue(target, targetValue)
127
+ return self.nextPC()
128
+ except Exception as e:
129
+ msg = f'Arithmetic error in add: {str(e)}'
130
+ self.program.errorMessage = msg
131
+ if command.get('or') != None:
132
+ return command['or']
133
+ RuntimeError(self.program, msg)
128
134
 
129
135
  # Append a value to a list or a queue
130
136
  # append {value} to {list/queue}
@@ -461,32 +467,37 @@ class Core(Handler):
461
467
  self.checkObjectType(record, ECVariable)
462
468
  command['target'] = record['name']
463
469
  command['value1'] = value1
464
- self.add(command)
470
+ orPC = self.getCodeSize()
471
+ self.processOr(command, orPC)
465
472
  return True
466
473
  else:
467
474
  # Here the first variable is the target
468
475
  if variable1 != None:
469
476
  command['target'] = variable1
470
- self.add(command)
477
+ orPC = self.getCodeSize()
478
+ self.processOr(command, orPC)
471
479
  return True
472
480
  return False
473
481
 
474
482
  def r_divide(self, command):
475
- value1 = self.textify(command['value1']) if 'value1' in command else None
476
- value2 = self.textify(command['value2'])
477
- target = self.getVariable(command['target'])
478
- # Check that the target variable can hold a value
479
- self.checkObjectType(target, ECVariable)
480
- # If value1 exists, we are adding two values and storing the result in target
481
- if value1 != None:
482
- # divide X by Y giving Z
483
- targetValue = ECValue(type=int, content=int(value1) // int(value2))
484
- else:
485
- # divide X by Y
486
- targetValue = self.getSymbolValue(target)
487
- targetValue.setContent(int(targetValue.getContent()) // int(value2))
488
- self.putSymbolValue(target, targetValue)
489
- return self.nextPC()
483
+ try:
484
+ value1 = self.textify(command['value1']) if 'value1' in command else None
485
+ value2 = self.textify(command['value2'])
486
+ target = self.getVariable(command['target'])
487
+ self.checkObjectType(target, ECVariable)
488
+ if value1 != None:
489
+ targetValue = ECValue(type=int, content=int(value1) // int(value2))
490
+ else:
491
+ targetValue = self.getSymbolValue(target)
492
+ targetValue.setContent(int(targetValue.getContent()) // int(value2))
493
+ self.putSymbolValue(target, targetValue)
494
+ return self.nextPC()
495
+ except Exception as e:
496
+ msg = f'Arithmetic error in divide: {str(e)}'
497
+ self.program.errorMessage = msg
498
+ if command.get('or') != None:
499
+ return command['or']
500
+ RuntimeError(self.program, msg)
490
501
 
491
502
  # download [binary] {url} to {path}
492
503
  def k_download(self, command):
@@ -594,16 +605,18 @@ class Core(Handler):
594
605
  if response.status_code >= 400:
595
606
  errorCode = response.status_code
596
607
  errorReason = response.reason
608
+ self.program.errorMessage = f'Error code {errorCode}: {errorReason}'
597
609
  if command['or'] != None:
598
610
  return command['or']
599
611
  else:
600
- RuntimeError(self.program, f'Error code {errorCode}: {errorReason}')
612
+ RuntimeError(self.program, self.program.errorMessage)
601
613
  except Exception as e:
602
614
  errorReason = str(e)
615
+ self.program.errorMessage = f'Error: {errorReason}'
603
616
  if command['or'] != None:
604
617
  return command['or']
605
618
  else:
606
- RuntimeError(self.program, f'Error: {errorReason}')
619
+ RuntimeError(self.program, self.program.errorMessage)
607
620
  retval.setContent(response.text) # type: ignore
608
621
  self.program.putSymbolValue(target, retval)
609
622
  return self.nextPC()
@@ -757,15 +770,23 @@ class Core(Handler):
757
770
  if self.nextToken() == 'to':
758
771
  # get the value
759
772
  command['value'] = self.nextValue()
760
- self.add(command)
773
+ orPC = self.getCodeSize()
774
+ self.processOr(command, orPC)
761
775
  return True
762
776
  return False
763
777
 
764
778
  def r_index(self, command):
765
- value = self.textify(command['value'])
766
- record = self.getVariable(command['target'])
767
- self.getObject(record).setIndex(value)
768
- return self.nextPC()
779
+ try:
780
+ value = self.textify(command['value'])
781
+ record = self.getVariable(command['target'])
782
+ self.getObject(record).setIndex(value)
783
+ return self.nextPC()
784
+ except Exception as e:
785
+ msg = f'Index error: {str(e)}'
786
+ self.program.errorMessage = msg
787
+ if command.get('or') != None:
788
+ return command['or']
789
+ RuntimeError(self.program, msg)
769
790
 
770
791
  # Input a value from the terminal
771
792
  # input {variable} [with {prompt}]
@@ -841,6 +862,7 @@ class Core(Handler):
841
862
  with sftp.open(path, 'r') as remote_file: content = remote_file.read().decode()
842
863
  except:
843
864
  errorReason = f'Unable to read from {path}'
865
+ self.program.errorMessage = errorReason
844
866
  if command['or'] != None:
845
867
  print(f'Exception "{errorReason}": Running the "or" clause')
846
868
  return command['or']
@@ -855,6 +877,7 @@ class Core(Handler):
855
877
  errorReason = f'Unable to read from {filename}'
856
878
 
857
879
  if errorReason:
880
+ self.program.errorMessage = errorReason
858
881
  if command['or'] != None:
859
882
  print(f'Exception "{errorReason}": Running the "or" clause')
860
883
  return command['or']
@@ -922,32 +945,37 @@ class Core(Handler):
922
945
  self.checkObjectType(record, ECVariable)
923
946
  command['target'] = record['name']
924
947
  command['value1'] = value1
925
- self.add(command)
948
+ orPC = self.getCodeSize()
949
+ self.processOr(command, orPC)
926
950
  return True
927
951
  else:
928
952
  # Here the first variable is the target
929
953
  if variable1 != None:
930
954
  command['target'] = variable1
931
- self.add(command)
955
+ orPC = self.getCodeSize()
956
+ self.processOr(command, orPC)
932
957
  return True
933
958
  return False
934
959
 
935
960
  def r_multiply(self, command):
936
- value1 = self.textify(command['value1']) if 'value1' in command else None
937
- value2 = self.textify(command['value2'])
938
- target = self.getVariable(command['target'])
939
- # Check that the target variable can hold a value
940
- self.checkObjectType(target, ECVariable)
941
- # If value1 exists, we are adding two values and storing the result in target
942
- if value1 != None:
943
- # multiply X by Y giving Z
944
- targetValue = ECValue(type=int, content=int(value1) * int(value2))
945
- else:
946
- # multiply X by Y
947
- targetValue = self.getSymbolValue(target)
948
- targetValue.setContent(int(targetValue.getContent()) * int(value2))
949
- self.putSymbolValue(target, targetValue)
950
- return self.nextPC()
961
+ try:
962
+ value1 = self.textify(command['value1']) if 'value1' in command else None
963
+ value2 = self.textify(command['value2'])
964
+ target = self.getVariable(command['target'])
965
+ self.checkObjectType(target, ECVariable)
966
+ if value1 != None:
967
+ targetValue = ECValue(type=int, content=int(value1) * int(value2))
968
+ else:
969
+ targetValue = self.getSymbolValue(target)
970
+ targetValue.setContent(int(targetValue.getContent()) * int(value2))
971
+ self.putSymbolValue(target, targetValue)
972
+ return self.nextPC()
973
+ except Exception as e:
974
+ msg = f'Arithmetic error in multiply: {str(e)}'
975
+ self.program.errorMessage = msg
976
+ if command.get('or') != None:
977
+ return command['or']
978
+ RuntimeError(self.program, msg)
951
979
 
952
980
  # Negate a variable
953
981
  def k_negate(self, command):
@@ -1029,7 +1057,8 @@ class Core(Handler):
1029
1057
  command['mode'] = mode
1030
1058
  else:
1031
1059
  command['mode'] = 'r'
1032
- self.add(command)
1060
+ orPC = self.getCodeSize()
1061
+ self.processOr(command, orPC)
1033
1062
  return True
1034
1063
  else:
1035
1064
  FatalError(self.compiler, f'Variable "{record["name"]}" is not a file')
@@ -1041,10 +1070,17 @@ class Core(Handler):
1041
1070
  record = self.getVariable(command['target'])
1042
1071
  path = self.textify(command['path'])
1043
1072
  file_path = self.resolveLocalPath(path)
1044
- if command['mode'] == 'r' and os.path.exists(file_path) or command['mode'] != 'r':
1073
+ try:
1074
+ if command['mode'] == 'r' and not os.path.exists(file_path):
1075
+ raise FileNotFoundError(f"File {path} does not exist")
1045
1076
  record['file'] = open(file_path, command['mode'])
1046
1077
  return self.nextPC()
1047
- RuntimeError(self.program, f"File {path} does not exist")
1078
+ except Exception as e:
1079
+ msg = str(e)
1080
+ self.program.errorMessage = msg
1081
+ if command.get('or') != None:
1082
+ return command['or']
1083
+ RuntimeError(self.program, msg)
1048
1084
 
1049
1085
  # Dummy command to hit a debugger breakpoint
1050
1086
  def k_pass(self, command):
@@ -1067,16 +1103,24 @@ class Core(Handler):
1067
1103
  record = self.getSymbolRecord()
1068
1104
  self.checkObjectType(record, (ECStack, ECQueue))
1069
1105
  command['from'] = record['name']
1070
- self.add(command)
1106
+ orPC = self.getCodeSize()
1107
+ self.processOr(command, orPC)
1071
1108
  return True
1072
1109
  return False
1073
1110
 
1074
1111
  def r_pop(self, command):
1075
- record = self.getVariable(command['target'])
1076
- stackRecord = self.getVariable(command['from'])
1077
- value = stackRecord['object'].pop()
1078
- self.putSymbolValue(record, value)
1079
- return self.nextPC()
1112
+ try:
1113
+ record = self.getVariable(command['target'])
1114
+ stackRecord = self.getVariable(command['from'])
1115
+ value = stackRecord['object'].pop()
1116
+ self.putSymbolValue(record, value)
1117
+ return self.nextPC()
1118
+ except Exception as e:
1119
+ msg = f'Pop failed: {str(e)}'
1120
+ self.program.errorMessage = msg
1121
+ if command.get('or') != None:
1122
+ return command['or']
1123
+ RuntimeError(self.program, msg)
1080
1124
 
1081
1125
  # Perform an HTTP POST
1082
1126
  # post {value} to {url} [giving {variable}] [or {command}]
@@ -1109,18 +1153,20 @@ class Core(Handler):
1109
1153
  if response.status_code >= 400:
1110
1154
  errorCode = response.status_code
1111
1155
  errorReason = response.reason
1156
+ self.program.errorMessage = f'Error code {errorCode}: {errorReason}'
1112
1157
  if command['or'] != None:
1113
1158
  print(f'Error {errorCode} {errorReason}: Running the "or" clause')
1114
1159
  return command['or']
1115
1160
  else:
1116
- RuntimeError(self.program, f'Error code {errorCode}: {errorReason}')
1161
+ RuntimeError(self.program, self.program.errorMessage)
1117
1162
  except Exception as e:
1118
1163
  errorReason = str(e)
1164
+ self.program.errorMessage = f'Error: {errorReason}'
1119
1165
  if command['or'] != None:
1120
1166
  print(f'Exception "{errorReason}": Running the "or" clause')
1121
1167
  return command['or']
1122
1168
  else:
1123
- RuntimeError(self.program, f'Error: {errorReason}')
1169
+ RuntimeError(self.program, self.program.errorMessage)
1124
1170
  if command['result'] != None:
1125
1171
  result = self.getVariable(command['result'])
1126
1172
  self.program.putSymbolValue(result, retval)
@@ -1223,25 +1269,33 @@ class Core(Handler):
1223
1269
  self.checkObjectType(fileRecord['object'], ECFile)
1224
1270
  command['target'] = record['name']
1225
1271
  command['file'] = fileRecord['name']
1226
- self.add(command)
1272
+ orPC = self.getCodeSize()
1273
+ self.processOr(command, orPC)
1227
1274
  return True
1228
1275
  return False
1229
1276
  FatalError(self.compiler, f'Symbol "{self.getToken()}" has not been declared')
1230
1277
  return False
1231
1278
 
1232
1279
  def r_read(self, command):
1233
- record = self.getVariable(command['target'])
1234
- fileRecord = self.getVariable(command['file'])
1235
- line = command['line']
1236
- file = fileRecord['file']
1237
- if file.mode == 'r':
1238
- if line:
1239
- content = file.readline().split('\n')[0]
1240
- else:
1241
- content = file.readline().rstrip('\n')
1242
- value = ECValue(type=str, content=content)
1243
- self.putSymbolValue(record, value)
1244
- return self.nextPC()
1280
+ try:
1281
+ record = self.getVariable(command['target'])
1282
+ fileRecord = self.getVariable(command['file'])
1283
+ line = command['line']
1284
+ file = fileRecord['file']
1285
+ if file.mode == 'r':
1286
+ if line:
1287
+ content = file.readline().split('\n')[0]
1288
+ else:
1289
+ content = file.readline().rstrip('\n')
1290
+ value = ECValue(type=str, content=content)
1291
+ self.putSymbolValue(record, value)
1292
+ return self.nextPC()
1293
+ except Exception as e:
1294
+ msg = f'Read error: {str(e)}'
1295
+ self.program.errorMessage = msg
1296
+ if command.get('or') != None:
1297
+ return command['or']
1298
+ RuntimeError(self.program, msg)
1245
1299
 
1246
1300
  # Release the parent script
1247
1301
  def k_release(self, command):
@@ -1389,6 +1443,7 @@ class Core(Handler):
1389
1443
  with sftp.open(path, 'w') as remote_file: remote_file.write(content)
1390
1444
  except:
1391
1445
  errorReason = 'Unable to write to {path}'
1446
+ self.program.errorMessage = errorReason
1392
1447
  if command['or'] != None:
1393
1448
  print(f'Exception "{errorReason}": Running the "or" clause')
1394
1449
  return command['or']
@@ -1409,6 +1464,7 @@ class Core(Handler):
1409
1464
  errorReason = f'Unable to write to {filename}: {str(e)}'
1410
1465
 
1411
1466
  if errorReason:
1467
+ self.program.errorMessage = errorReason
1412
1468
  if command['or'] != None:
1413
1469
  print(f'Exception "{errorReason}": Running the "or" clause')
1414
1470
  return command['or']
@@ -2069,18 +2125,86 @@ class Core(Handler):
2069
2125
  fileRecord = self.getSymbolRecord()
2070
2126
  if fileRecord['keyword'] == 'file':
2071
2127
  command['file'] = fileRecord['name']
2072
- self.add(command)
2128
+ orPC = self.getCodeSize()
2129
+ self.processOr(command, orPC)
2073
2130
  return True
2074
2131
  return False
2075
2132
 
2076
2133
  def r_write(self, command):
2077
- value = self.textify(command['value'])
2078
- fileRecord = self.getVariable(command['file'])
2079
- file = fileRecord['file']
2080
- if file.mode in ['w', 'w+', 'a', 'a+']:
2081
- file.write(f'{value}')
2082
- if command['line']:
2083
- file.write('\n')
2134
+ try:
2135
+ value = self.textify(command['value'])
2136
+ fileRecord = self.getVariable(command['file'])
2137
+ file = fileRecord['file']
2138
+ if file.mode in ['w', 'w+', 'a', 'a+']:
2139
+ file.write(f'{value}')
2140
+ if command['line']:
2141
+ file.write('\n')
2142
+ return self.nextPC()
2143
+ except Exception as e:
2144
+ msg = f'Write error: {str(e)}'
2145
+ self.program.errorMessage = msg
2146
+ if command.get('or') != None:
2147
+ return command['or']
2148
+ RuntimeError(self.program, msg)
2149
+
2150
+ # Try/or handle block
2151
+ # try ... or handle ... end
2152
+ def k_try(self, command):
2153
+ # Add the try command (handlerPC will be fixed up)
2154
+ tryPC = self.getCodeSize()
2155
+ command['handlerPC'] = 0
2156
+ self.add(command)
2157
+ # Compile the try body up to 'or'
2158
+ self.nextToken()
2159
+ while self.getToken() != 'or':
2160
+ self.compileOne()
2161
+ self.nextToken()
2162
+ # Expect 'handle' after 'or'
2163
+ if self.peek() != 'handle':
2164
+ FatalError(self.compiler, 'Expected "handle" after "or" in try block')
2165
+ self.nextToken()
2166
+ self.nextToken()
2167
+ # Add a gotoPC to skip the handler on success
2168
+ skipPC = self.getCodeSize()
2169
+ cmd = {}
2170
+ cmd['lino'] = command['lino']
2171
+ cmd['domain'] = 'core'
2172
+ cmd['keyword'] = 'gotoPC'
2173
+ cmd['goto'] = 0
2174
+ cmd['debug'] = False
2175
+ self.add(cmd)
2176
+ # Fix up the try command's handlerPC
2177
+ self.getCommandAt(tryPC)['handlerPC'] = self.getCodeSize()
2178
+ # Compile the handler body up to 'end'
2179
+ while self.getToken() != 'end':
2180
+ self.compileOne()
2181
+ self.nextToken()
2182
+ # Add the endTry command
2183
+ endPC = self.getCodeSize()
2184
+ cmd = {}
2185
+ cmd['lino'] = command['lino']
2186
+ cmd['domain'] = 'core'
2187
+ cmd['keyword'] = 'endTry'
2188
+ cmd['debug'] = False
2189
+ self.add(cmd)
2190
+ # Fix up the skip goto
2191
+ self.getCommandAt(skipPC)['goto'] = endPC
2192
+ return True
2193
+
2194
+ def r_try(self, command):
2195
+ # Save current onError and set up the try handler
2196
+ if not hasattr(self.program, 'onErrorStack'):
2197
+ self.program.onErrorStack = []
2198
+ self.program.onErrorStack.append(self.program.onError)
2199
+ self.program.onError = command['handlerPC']
2200
+ return self.nextPC()
2201
+
2202
+ def r_endTry(self, command):
2203
+ # Restore onError from the stack
2204
+ if hasattr(self.program, 'onErrorStack') and len(self.program.onErrorStack) > 0:
2205
+ self.program.onError = self.program.onErrorStack.pop()
2206
+ else:
2207
+ self.program.onError = 0
2084
2208
  return self.nextPC()
2085
2209
 
2086
2210
  #############################################################################
@@ -2324,6 +2448,10 @@ class Core(Handler):
2324
2448
  self.nextToken()
2325
2449
  value.item = 'errorReason' # type: ignore
2326
2450
  return value
2451
+ elif token == 'message':
2452
+ self.nextToken()
2453
+ value.item = 'errorMessage' # type: ignore
2454
+ return value
2327
2455
  elif token in ['in', 'of']:
2328
2456
  self.nextToken()
2329
2457
  if self.nextIsSymbol():
@@ -2332,7 +2460,9 @@ class Core(Handler):
2332
2460
  value.item = 'sshError' # type: ignore
2333
2461
  value.name = record['name'] # type: ignore
2334
2462
  return value
2335
- return None
2463
+ # Unqualified 'the error' returns errorMessage (same as JS)
2464
+ value.item = 'errorMessage' # type: ignore
2465
+ return value
2336
2466
 
2337
2467
  if token == 'type':
2338
2468
  if self.nextIs('of'):
@@ -2474,6 +2604,8 @@ class Core(Handler):
2474
2604
  value.setValue(type=int, content=errorCode)
2475
2605
  elif item == 'errorReason':
2476
2606
  value.setValue(type=str, content=errorReason)
2607
+ elif item == 'errorMessage':
2608
+ value.setValue(type=str, content=getattr(self.program, 'errorMessage', ''))
2477
2609
  elif item == 'sshError':
2478
2610
  record = self.getVariable(v.name)
2479
2611
  value.setValue(type=str, content=record['error'] if 'error' in record else '')
@@ -75,6 +75,7 @@ class Program:
75
75
  self.pc = 0
76
76
  self.symbols = {}
77
77
  self.onError = 0
78
+ self.errorMessage = ''
78
79
  self.debugStep = False
79
80
  self.debugSkip = False
80
81
  self.stack = []
@@ -1,7 +0,0 @@
1
- #!/bin/python3
2
-
3
- import os
4
- from easycoder import Program
5
-
6
- os.chdir('/home/graham/dev/easycoder/easycoder-py/tests')
7
- Program('test.ecs').start()
@@ -1,7 +0,0 @@
1
- #!/bin/python3
2
-
3
- import os
4
- from easycoder import Program
5
-
6
- os.chdir('/home/graham/dev/rbr/Controller/')
7
- Program('newController.ecs').start()
@@ -1,7 +0,0 @@
1
- #!/bin/python3
2
-
3
- import os
4
- from easycoder import Program
5
-
6
- os.chdir('/home/graham/dev/doclets')
7
- Program('doclets.ecs').start()
@@ -1,7 +0,0 @@
1
- #!/bin/python3
2
-
3
- import os
4
- from easycoder import Program
5
-
6
- os.chdir('/home/graham/dev/doclets')
7
- Program('docletServer.ecs').start()
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import os
4
- import sys
5
- from easycoder import Program
6
-
7
- # Test with a graphics script
8
- test_script = """
9
- script TestDebugGraphics
10
- use graphics
11
-
12
- window MainWindow
13
- create MainWindow title `Debug Graphics Test` size 400 300
14
-
15
- show MainWindow
16
- exit
17
- """
18
-
19
- # Create temporary test script
20
- test_file = '/tmp/test_debug_graphics.ecs'
21
- with open(test_file, 'w') as f:
22
- f.write(test_script)
23
-
24
- print("Testing debug mode with graphics...")
25
- try:
26
- program = Program(f'debug {test_file}')
27
- print(f"Debugging enabled: {program.debugging}")
28
- print(f"Script: {program.scriptName}")
29
-
30
- # Note: This will hang waiting for user interaction with the GUI
31
- # In a real test, we'd close the windows automatically
32
- program.start()
33
-
34
- if program.debugger:
35
- print("SUCCESS: Debugger was created for graphics!")
36
- else:
37
- print("FAILED: Debugger was not created for graphics")
38
-
39
- except Exception as e:
40
- print(f"Error: {e}")
41
- import traceback
42
- traceback.print_exc()
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import os
4
- import sys
5
- from easycoder import Program
6
-
7
- # Test with a simple script
8
- test_script = """
9
- script TestDebug
10
- print `Debug launch test`
11
- exit
12
- """
13
-
14
- # Create temporary test script
15
- test_file = '/tmp/test_debug.ecs'
16
- with open(test_file, 'w') as f:
17
- f.write(test_script)
18
-
19
- print("Testing debug mode launch...")
20
- try:
21
- program = Program(f'debug {test_file}')
22
- print(f"Debugging enabled: {program.debugging}")
23
- print(f"Script: {program.scriptName}")
24
-
25
- # Check that debugger is created
26
- program.start()
27
-
28
- if program.debugger:
29
- print("SUCCESS: Debugger was created!")
30
- else:
31
- print("FAILED: Debugger was not created")
32
-
33
- except Exception as e:
34
- print(f"Error: {e}")
35
- import traceback
36
- traceback.print_exc()