jaseci 1.4.2.6__py3-none-any.whl → 2.0.0__py3-none-any.whl

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.

Potentially problematic release.


This version of jaseci might be problematic. Click here for more details.

Files changed (187) hide show
  1. jaseci/__init__.py +3 -37
  2. jaseci-2.0.0.dist-info/METADATA +65 -0
  3. jaseci-2.0.0.dist-info/RECORD +4 -0
  4. {jaseci-1.4.2.6.dist-info → jaseci-2.0.0.dist-info}/WHEEL +1 -2
  5. jaseci/VERSION +0 -1
  6. jaseci/cli_tools/__init__.py +0 -0
  7. jaseci/cli_tools/book_tools.py +0 -457
  8. jaseci/cli_tools/jsctl.py +0 -500
  9. jaseci/cli_tools/tests/__init__.py +0 -0
  10. jaseci/cli_tools/tests/test_jsctl.py +0 -556
  11. jaseci/extens/__init__.py +0 -0
  12. jaseci/extens/act_lib/__init__.py +0 -0
  13. jaseci/extens/act_lib/date.py +0 -118
  14. jaseci/extens/act_lib/elastic.py +0 -87
  15. jaseci/extens/act_lib/file.py +0 -77
  16. jaseci/extens/act_lib/file_handler.py +0 -190
  17. jaseci/extens/act_lib/internal.py +0 -19
  18. jaseci/extens/act_lib/jaseci.py +0 -62
  19. jaseci/extens/act_lib/mail.py +0 -10
  20. jaseci/extens/act_lib/maths.py +0 -168
  21. jaseci/extens/act_lib/net.py +0 -192
  22. jaseci/extens/act_lib/rand.py +0 -83
  23. jaseci/extens/act_lib/regex.py +0 -85
  24. jaseci/extens/act_lib/request.py +0 -170
  25. jaseci/extens/act_lib/std.py +0 -236
  26. jaseci/extens/act_lib/storage.py +0 -53
  27. jaseci/extens/act_lib/stripe.py +0 -338
  28. jaseci/extens/act_lib/task.py +0 -14
  29. jaseci/extens/act_lib/tests/__init__.py +0 -0
  30. jaseci/extens/act_lib/tests/std_test_code.py +0 -37
  31. jaseci/extens/act_lib/tests/test_date.py +0 -26
  32. jaseci/extens/act_lib/tests/test_elastic.py +0 -159
  33. jaseci/extens/act_lib/tests/test_file.py +0 -116
  34. jaseci/extens/act_lib/tests/test_file_lib.py +0 -40
  35. jaseci/extens/act_lib/tests/test_mail_lib.py +0 -33
  36. jaseci/extens/act_lib/tests/test_maths.py +0 -147
  37. jaseci/extens/act_lib/tests/test_net_lib.py +0 -62
  38. jaseci/extens/act_lib/tests/test_regex.py +0 -61
  39. jaseci/extens/act_lib/tests/test_std.py +0 -51
  40. jaseci/extens/act_lib/tests/test_std_lib.py +0 -36
  41. jaseci/extens/act_lib/tests/test_url.py +0 -32
  42. jaseci/extens/act_lib/tests/test_vector.py +0 -36
  43. jaseci/extens/act_lib/tests/test_webtool.py +0 -44
  44. jaseci/extens/act_lib/tests/test_zlib.py +0 -24
  45. jaseci/extens/act_lib/url.py +0 -80
  46. jaseci/extens/act_lib/vector.py +0 -158
  47. jaseci/extens/act_lib/webtool.py +0 -29
  48. jaseci/extens/act_lib/zip.py +0 -34
  49. jaseci/extens/api/__init__.py +0 -0
  50. jaseci/extens/api/actions_api.py +0 -171
  51. jaseci/extens/api/alias_api.py +0 -140
  52. jaseci/extens/api/architype_api.py +0 -197
  53. jaseci/extens/api/config_api.py +0 -129
  54. jaseci/extens/api/global_api.py +0 -85
  55. jaseci/extens/api/graph_api.py +0 -168
  56. jaseci/extens/api/health_api.py +0 -21
  57. jaseci/extens/api/interface.py +0 -269
  58. jaseci/extens/api/jac_api.py +0 -172
  59. jaseci/extens/api/jsorc_api.py +0 -317
  60. jaseci/extens/api/logger_api.py +0 -90
  61. jaseci/extens/api/master_api.py +0 -134
  62. jaseci/extens/api/object_api.py +0 -102
  63. jaseci/extens/api/prometheus_api.py +0 -75
  64. jaseci/extens/api/queue_api.py +0 -141
  65. jaseci/extens/api/sentinel_api.py +0 -271
  66. jaseci/extens/api/share_api.py +0 -64
  67. jaseci/extens/api/super_api.py +0 -65
  68. jaseci/extens/api/tests/__init__.py +0 -0
  69. jaseci/extens/api/tests/test_architype_api.py +0 -66
  70. jaseci/extens/api/tests/test_global_api.py +0 -179
  71. jaseci/extens/api/tests/test_graph_api.py +0 -64
  72. jaseci/extens/api/tests/test_logger_api.py +0 -43
  73. jaseci/extens/api/tests/test_object_api.py +0 -20
  74. jaseci/extens/api/tests/test_sentinel_api.py +0 -66
  75. jaseci/extens/api/tests/test_uncommon.py +0 -107
  76. jaseci/extens/api/tests/test_user_api.py +0 -32
  77. jaseci/extens/api/tests/test_walker_api.py +0 -316
  78. jaseci/extens/api/user_api.py +0 -166
  79. jaseci/extens/api/walker_api.py +0 -299
  80. jaseci/extens/api/webhook_api.py +0 -77
  81. jaseci/extens/svc/__init__.py +0 -0
  82. jaseci/extens/svc/elastic_svc.py +0 -366
  83. jaseci/extens/svc/kube_svc.py +0 -432
  84. jaseci/extens/svc/mail_svc.py +0 -156
  85. jaseci/extens/svc/prome_svc.py +0 -378
  86. jaseci/extens/svc/redis_svc.py +0 -63
  87. jaseci/extens/svc/storage_svc.py +0 -193
  88. jaseci/extens/svc/stripe_svc.py +0 -51
  89. jaseci/extens/svc/task_svc.py +0 -155
  90. jaseci/extens/svc/tasks.py +0 -302
  91. jaseci/jac/__init__.py +0 -0
  92. jaseci/jac/interpreter/__init__.py +0 -0
  93. jaseci/jac/interpreter/architype_interp.py +0 -219
  94. jaseci/jac/interpreter/interp.py +0 -1784
  95. jaseci/jac/interpreter/sentinel_interp.py +0 -260
  96. jaseci/jac/interpreter/tests/__init__.py +0 -0
  97. jaseci/jac/interpreter/tests/test_interp.py +0 -42
  98. jaseci/jac/interpreter/walker_interp.py +0 -249
  99. jaseci/jac/ir/__init__.py +0 -0
  100. jaseci/jac/ir/ast.py +0 -73
  101. jaseci/jac/ir/ast_builder.py +0 -249
  102. jaseci/jac/ir/jac_code.py +0 -151
  103. jaseci/jac/ir/passes/__init__.py +0 -6
  104. jaseci/jac/ir/passes/ast_prune_pass.py +0 -9
  105. jaseci/jac/ir/passes/codegen_pass.py +0 -244
  106. jaseci/jac/ir/passes/ir_pass.py +0 -29
  107. jaseci/jac/ir/passes/printer_pass.py +0 -23
  108. jaseci/jac/ir/passes/pt_prune_pass.py +0 -29
  109. jaseci/jac/ir/passes/schedule.py +0 -23
  110. jaseci/jac/ir/passes/stats_pass.py +0 -16
  111. jaseci/jac/jac.g4 +0 -450
  112. jaseci/jac/jac_parse/__init__.py +0 -0
  113. jaseci/jac/jac_parse/jacLexer.py +0 -809
  114. jaseci/jac/jac_parse/jacListener.py +0 -853
  115. jaseci/jac/jac_parse/jacParser.py +0 -9192
  116. jaseci/jac/jac_set.py +0 -120
  117. jaseci/jac/jsci_vm/__init__.py +0 -0
  118. jaseci/jac/jsci_vm/disasm.py +0 -94
  119. jaseci/jac/jsci_vm/inst_ptr.py +0 -31
  120. jaseci/jac/jsci_vm/machine.py +0 -188
  121. jaseci/jac/jsci_vm/op_codes.py +0 -82
  122. jaseci/jac/jsci_vm/tests/__init__.py +0 -0
  123. jaseci/jac/jsci_vm/tests/test_codegen.py +0 -31
  124. jaseci/jac/machine/__init__.py +0 -0
  125. jaseci/jac/machine/jac_scope.py +0 -86
  126. jaseci/jac/machine/jac_value.py +0 -227
  127. jaseci/jac/machine/machine_state.py +0 -386
  128. jaseci/jac/tests/__init__.py +0 -0
  129. jaseci/jac/tests/book_code.py +0 -624
  130. jaseci/jac/tests/test_book.py +0 -380
  131. jaseci/jac/tests/test_lang_14.py +0 -49
  132. jaseci/jsorc/__init__.py +0 -7
  133. jaseci/jsorc/jsorc.py +0 -642
  134. jaseci/jsorc/jsorc_settings.py +0 -211
  135. jaseci/jsorc/jsorc_utils.py +0 -298
  136. jaseci/jsorc/live_actions.py +0 -365
  137. jaseci/jsorc/manifests/__init__.py +0 -0
  138. jaseci/jsorc/manifests/database.yaml +0 -109
  139. jaseci/jsorc/manifests/elastic.yaml +0 -6029
  140. jaseci/jsorc/manifests/prometheus.yaml +0 -1383
  141. jaseci/jsorc/manifests/redis.yaml +0 -64
  142. jaseci/jsorc/memory.py +0 -258
  143. jaseci/jsorc/redis.py +0 -140
  144. jaseci/jsorc/remote_actions.py +0 -158
  145. jaseci/jsorc/tests/__init__.py +0 -0
  146. jaseci/jsorc/tests/test_actions.py +0 -542
  147. jaseci/jsorc/tests/test_jsorc.py +0 -112
  148. jaseci/prim/__init__.py +0 -0
  149. jaseci/prim/ability.py +0 -94
  150. jaseci/prim/architype.py +0 -90
  151. jaseci/prim/edge.py +0 -173
  152. jaseci/prim/element.py +0 -233
  153. jaseci/prim/graph.py +0 -27
  154. jaseci/prim/master.py +0 -67
  155. jaseci/prim/node.py +0 -533
  156. jaseci/prim/obj_mixins.py +0 -238
  157. jaseci/prim/sentinel.py +0 -282
  158. jaseci/prim/super_master.py +0 -31
  159. jaseci/prim/walker.py +0 -261
  160. jaseci/svc/__init__.py +0 -0
  161. jaseci/tests/__init__.py +0 -0
  162. jaseci/tests/infer.py +0 -39
  163. jaseci/tests/jac_test_code.py +0 -1293
  164. jaseci/tests/jac_test_progs.py +0 -774
  165. jaseci/tests/test_core.py +0 -153
  166. jaseci/tests/test_jac.py +0 -824
  167. jaseci/tests/test_node.py +0 -89
  168. jaseci/tests/test_progs.py +0 -702
  169. jaseci/tests/test_stack.py +0 -220
  170. jaseci/tests/test_stripe.py +0 -225
  171. jaseci/utils/__init__.py +0 -0
  172. jaseci/utils/actions/__init__.py +0 -0
  173. jaseci/utils/actions/actions_manager.py +0 -254
  174. jaseci/utils/actions/actions_optimizer.py +0 -517
  175. jaseci/utils/actions/actions_state.py +0 -95
  176. jaseci/utils/file_handler.py +0 -171
  177. jaseci/utils/gprof2dot.py +0 -3786
  178. jaseci/utils/id_list.py +0 -169
  179. jaseci/utils/json_handler.py +0 -70
  180. jaseci/utils/log_utils.py +0 -57
  181. jaseci/utils/test_core.py +0 -62
  182. jaseci/utils/utils.py +0 -387
  183. jaseci-1.4.2.6.dist-info/LICENSE +0 -21
  184. jaseci-1.4.2.6.dist-info/METADATA +0 -39
  185. jaseci-1.4.2.6.dist-info/RECORD +0 -185
  186. jaseci-1.4.2.6.dist-info/entry_points.txt +0 -3
  187. jaseci-1.4.2.6.dist-info/top_level.txt +0 -1
@@ -1,1784 +0,0 @@
1
- """
2
- Interpreter for jac code in AST form
3
-
4
- This interpreter should be inhereted from the class that manages state
5
- referenced through self.
6
- """
7
-
8
- from jaseci.jsorc.jsorc import JsOrc
9
- from jaseci.extens.svc.task_svc import TaskService
10
- from jaseci.utils.utils import is_jsonable, parse_str_token, uuid_re
11
- from jaseci.prim.element import Element
12
- from jaseci.prim.node import Node
13
- from jaseci.prim.edge import Edge
14
- from jaseci.jac.jac_set import JacSet
15
- from jaseci.jac.ir.jac_code import jac_ast_to_ir, jac_ir_to_ast
16
- from jaseci.jac.machine.jac_scope import JacScope
17
- from jaseci.jac.jsci_vm.machine import VirtualMachine
18
- from jaseci.jac.machine.machine_state import TryException
19
-
20
- from jaseci.jac.machine.jac_value import JacValue
21
- from jaseci.jac.machine.jac_value import jac_elem_unwrap as jeu
22
- from jaseci.jac.machine.jac_value import jac_wrap_value as jwv
23
- from json import dumps, loads
24
- from copy import copy, deepcopy
25
- from base64 import b64decode
26
- from itertools import pairwise
27
- from types import GeneratorType
28
-
29
- from jaseci.jac.jsci_vm.op_codes import JsCmp
30
-
31
-
32
- class Interp(VirtualMachine):
33
- """Shared interpreter class across both sentinels and walkers"""
34
-
35
- def run_dotted_name(self, jac_ast):
36
- """
37
- dotted_name: NAME (DOT NAME)*;
38
- """
39
- kid = self.set_cur_ast(jac_ast)
40
- ret = ""
41
- for i in kid:
42
- if i.name == "NAME":
43
- ret += i.token_text()
44
- if i == kid[-1]:
45
- break
46
- ret += "."
47
- return ret
48
-
49
- def run_name_list(self, jac_ast):
50
- """
51
- name_list: NAME (COMMA NAME)*;
52
- """
53
- kid = self.set_cur_ast(jac_ast)
54
- ret = []
55
- for i in kid:
56
- if i.name == "NAME":
57
- ret.append(i.token_text())
58
- return ret
59
-
60
- def run_param_list(self, jac_ast):
61
- """
62
- param_list:
63
- expr_list
64
- | kw_expr_list
65
- | expr_list COMMA kw_expr_list;
66
- """
67
- kid = self.set_cur_ast(jac_ast)
68
- ret = {"args": [], "kwargs": {}}
69
- if kid[0].name == "expr_list":
70
- ret["args"] = self.run_expr_list(kid[0]).value
71
- elif kid[0].name == "kw_expr_list":
72
- ret["kwargs"] = self.run_kw_expr_list(kid[0]).value
73
- if len(kid) > 1:
74
- ret["kwargs"] = self.run_kw_expr_list(kid[2]).value
75
- return JacValue(self, value=ret)
76
-
77
- def run_expr_list(self, jac_ast):
78
- """
79
- expr_list: connect (COMMA connect)*;
80
- """
81
- kid = self.set_cur_ast(jac_ast)
82
- ret = []
83
- for i in kid:
84
- if i.name != "COMMA":
85
- ret.append(self.run_rule(i).value)
86
- return JacValue(self, value=ret)
87
-
88
- def run_kw_expr_list(self, jac_ast):
89
- """
90
- kw_expr_list: NAME EQ connect (COMMA NAME EQ connect)*;
91
- """
92
- kid = self.set_cur_ast(jac_ast)
93
- ret = {}
94
- while len(kid):
95
- ret[kid[0].token_text()] = self.run_rule(kid[2]).value
96
- kid = kid[3:]
97
- if len(kid):
98
- kid = kid[1:]
99
- return JacValue(self, value=ret)
100
-
101
- def run_code_block(self, jac_ast):
102
- """
103
- code_block: LBRACE statement* RBRACE | COLON statement;
104
- """
105
- kid = self.set_cur_ast(jac_ast)
106
- for i in kid:
107
- if i.name == "statement" and not self._loop_ctrl:
108
- self.run_statement(jac_ast=i)
109
-
110
- def run_statement(self, jac_ast):
111
- """
112
- statement:
113
- code_block
114
- | node_ctx_block
115
- | expression SEMI
116
- | if_stmt
117
- | try_stmt
118
- | for_stmt
119
- | while_stmt
120
- | assert_stmt SEMI
121
- | ctrl_stmt SEMI
122
- | destroy_action
123
- | report_action
124
- | walker_action;
125
- """
126
- if self._stopped:
127
- return
128
- kid = self.set_cur_ast(jac_ast)
129
- self.run_rule(kid[0])
130
-
131
- def run_if_stmt(self, jac_ast):
132
- """
133
- if_stmt: KW_IF expression code_block elif_stmt* else_stmt?;
134
- """
135
- kid = self.set_cur_ast(jac_ast)
136
- self.run_expression(kid[1])
137
- if self.pop().value:
138
- self.run_code_block(kid[2])
139
- return
140
- kid = kid[3:]
141
- if len(kid):
142
- while True:
143
- if kid[0].name == "elif_stmt":
144
- if self.run_elif_stmt(kid[0]):
145
- return
146
- elif kid[0].name == "else_stmt":
147
- self.run_else_stmt(kid[0])
148
- return
149
- kid = kid[1:]
150
- if not len(kid):
151
- break
152
-
153
- def run_try_stmt(self, jac_ast):
154
- """
155
- try_stmt: KW_TRY code_block else_from_try?;
156
- """
157
- kid = self.set_cur_ast(jac_ast)
158
- self._jac_try_mode += 1
159
- try:
160
- self.run_code_block(kid[1])
161
- self._jac_try_mode -= 1
162
- except TryException as e:
163
- self._jac_try_mode -= 1
164
- if len(kid) > 2:
165
- self.run_else_from_try(kid[2], e.ref)
166
- except Exception as e:
167
- self._jac_try_mode -= 1
168
- if len(kid) > 2:
169
- self.run_else_from_try(kid[2], self.jac_exception(e, kid[2]))
170
-
171
- def run_else_from_try(self, jac_ast, jac_ex):
172
- """
173
- else_from_try:
174
- KW_ELSE (LPAREN NAME RPAREN)? code_block
175
- | KW_ELSE (KW_WITH NAME)? code_block;
176
- """
177
- kid = self.set_cur_ast(jac_ast)
178
- if len(kid) > 2:
179
- JacValue(
180
- self,
181
- ctx=self._jac_scope.local_scope,
182
- name=kid[2].token_text(),
183
- value=jac_ex,
184
- ).write(kid[2])
185
- self.run_code_block(kid[-1])
186
-
187
- def run_elif_stmt(self, jac_ast):
188
- """
189
- elif_stmt: KW_ELIF expression code_block;
190
- """
191
- kid = self.set_cur_ast(jac_ast)
192
- self.run_expression(kid[1])
193
- if self.pop().value:
194
- self.run_code_block(kid[2])
195
- return True
196
- else:
197
- return False
198
-
199
- def run_else_stmt(self, jac_ast):
200
- """
201
- else_stmt: KW_ELSE code_block;
202
- """
203
- kid = self.set_cur_ast(jac_ast)
204
- self.run_code_block(kid[1])
205
-
206
- def run_for_stmt(self, jac_ast):
207
- """
208
- for_stmt:
209
- KW_FOR expression KW_TO expression KW_BY expression code_block
210
- | KW_FOR NAME (COMMA NAME)? KW_IN expression code_block;
211
- """
212
- kid = self.set_cur_ast(jac_ast)
213
- loops = 0
214
- if kid[1].name == "expression":
215
- self.run_expression(kid[1])
216
- self.pop()
217
- self.run_expression(kid[3])
218
- while self.pop().value:
219
- self._loop_ctrl = None
220
- self.run_code_block(kid[6])
221
- self.run_expression(kid[5])
222
- self.pop()
223
- loops += 1
224
- if self._loop_ctrl and self._loop_ctrl == "break":
225
- self._loop_ctrl = None
226
- break
227
- if loops > self._loop_limit:
228
- self.rt_error(f"Hit loop limit [{self._loop_limit}]!", kid[0])
229
- self.run_expression(kid[3])
230
- elif kid[3].name == "expression":
231
- var = self._jac_scope.get_live_var(kid[1].token_text(), create_mode=True)
232
- self.run_expression(kid[3])
233
- lst = self.pop().value
234
-
235
- if isinstance(lst, (list, dict, GeneratorType)):
236
- for i in lst:
237
- self._loop_ctrl = None
238
- var.value = i
239
- var.write(kid[1])
240
- self.run_code_block(kid[4])
241
- loops += 1
242
- if self._loop_ctrl and self._loop_ctrl == "break":
243
- self._loop_ctrl = None
244
- break
245
- if loops > self._loop_limit:
246
- self.rt_error(f"Hit loop limit [{self._loop_limit}]!", kid[0])
247
- else:
248
- self.rt_error("Not a list/dict for iteration!", kid[3])
249
- else:
250
- key = self._jac_scope.get_live_var(kid[1].token_text(), create_mode=True)
251
- val = self._jac_scope.get_live_var(kid[3].token_text(), create_mode=True)
252
- self.run_expression(kid[5])
253
- source = self.pop().value
254
-
255
- lst = None
256
- if isinstance(source, dict):
257
- lst = source.items()
258
- elif isinstance(source, list):
259
- lst = enumerate(source)
260
-
261
- if not (lst is None):
262
- for k, v in lst:
263
- self._loop_ctrl = None
264
- key.value = k
265
- key.write(kid[1])
266
- val.value = v
267
- val.write(kid[3])
268
- self.run_code_block(kid[6])
269
- loops += 1
270
- if self._loop_ctrl and self._loop_ctrl == "break":
271
- self._loop_ctrl = None
272
- break
273
- if loops > self._loop_limit:
274
- self.rt_error(f"Hit loop limit [{self._loop_limit}]!", kid[0])
275
- else:
276
- self.rt_error("Not a list/dict for iteration!", kid[5])
277
- if self._loop_ctrl and self._loop_ctrl == "continue":
278
- self._loop_ctrl = None
279
-
280
- def run_while_stmt(self, jac_ast):
281
- """
282
- while_stmt: KW_WHILE expression code_block;
283
- """
284
- kid = self.set_cur_ast(jac_ast)
285
- loops = 0
286
- self.run_expression(kid[1])
287
- while self.pop().value:
288
- self._loop_ctrl = None
289
- self.run_code_block(kid[2])
290
- loops += 1
291
- if self._loop_ctrl and self._loop_ctrl == "break":
292
- self._loop_ctrl = None
293
- break
294
- if loops > self._loop_limit:
295
- self.rt_error(f"Hit loop limit [{self._loop_limit}]!", kid[0])
296
- self.run_expression(kid[1])
297
- if self._loop_ctrl and self._loop_ctrl == "continue":
298
- self._loop_ctrl = None
299
-
300
- def run_ctrl_stmt(self, jac_ast):
301
- """
302
- ctrl_stmt: KW_CONTINUE | KW_BREAK | KW_SKIP;
303
- """
304
- kid = self.set_cur_ast(jac_ast)
305
- if kid[0].name == "KW_SKIP":
306
- self._stopped = "skip"
307
- elif kid[0].name == "KW_BREAK":
308
- self._loop_ctrl = "break"
309
- elif kid[0].name == "KW_CONTINUE":
310
- self._loop_ctrl = "continue"
311
-
312
- def run_assert_stmt(self, jac_ast):
313
- """
314
- assert_stmt: KW_ASSERT expression;
315
- """
316
- kid = self.set_cur_ast(jac_ast)
317
- passed = False
318
- try:
319
- self.run_expression(kid[1])
320
- passed = self.pop().value
321
- except Exception as e:
322
- e = self.jac_exception(e, jac_ast)
323
- raise Exception("Jac Assert Failed", kid[1].get_text(), e)
324
- if not passed:
325
- raise Exception("Jac Assert Failed", kid[1].get_text())
326
-
327
- def run_destroy_action(self, jac_ast):
328
- """
329
- destroy_action: KW_DESTROY expression SEMI;
330
- """
331
- from jaseci.prim.ability import Ability
332
-
333
- kid = self.set_cur_ast(jac_ast)
334
- self.run_expression(kid[1])
335
- result = self.pop()
336
-
337
- destroy_node_ids = None
338
- if isinstance(self, Ability):
339
- # currently, only walker process destroy_node_ids
340
- # ability should be able to trigger destroy but still connected to current walker
341
- destroy_node_ids = self._jac_scope.local_scope["visitor"].destroy_node_ids
342
- else:
343
- destroy_node_ids = self.destroy_node_ids
344
-
345
- if isinstance(result.value, Element):
346
- destroy_node_ids.add_obj(result.value)
347
- elif isinstance(result.value, JacSet):
348
- destroy_node_ids.add_obj_list(result.value)
349
- result.self_destruct(kid[1])
350
-
351
- def run_report_action(self, jac_ast):
352
- """
353
- report_action:
354
- KW_REPORT expression SEMI
355
- | KW_REPORT COLON NAME EQ expression SEMI;
356
- """
357
- kid = self.set_cur_ast(jac_ast)
358
- if kid[1].name == "COLON":
359
- self.run_expression(kid[4])
360
- if kid[2].token_text() in ["status", "status_code"]:
361
- self.report_status = self.pop().value
362
- elif kid[2].token_text() == "custom":
363
- self.report_custom = jwv(self.pop().value, serialize_mode=True)
364
- elif kid[2].token_text() == "file":
365
- self.report_file = self.pop().value
366
- elif kid[2].token_text() == "error":
367
- err = self.pop().value
368
- if isinstance(err, str):
369
- self.runtime_errors.append(err)
370
- else:
371
- self.runtime_errors.append(
372
- f'{err["mod"]}:{err["name"]} - line {err["line"]}, '
373
- + f'col {err["col"]} - rule {err["rule"]} - {err["msg"]}'
374
- )
375
- for stk in err.get("stack_trace", []):
376
- self.runtime_stack_trace.append(stk)
377
- else:
378
- self.rt_error("Invalid report attribute to set", kid[2])
379
- else:
380
- self.run_expression(kid[1])
381
- report = jwv(self.pop().value, serialize_mode=True)
382
- if not is_jsonable(report):
383
- self.rt_error(f"Report {report} not Json serializable", kid[0])
384
- self.report.append(copy(report))
385
-
386
- def run_expression(self, jac_ast):
387
- """
388
- expression: connect (assignment | copy_assign | inc_assign)?;
389
- """
390
- try:
391
- if self.attempt_bytecode(jac_ast):
392
- return
393
- kid = self.set_cur_ast(jac_ast)
394
- if len(kid) == 1:
395
- self.push(self.run_rule(kid[0]))
396
- else:
397
- if kid[1].name == "assignment":
398
- self._assign_mode = True
399
- dest = self.run_rule(kid[0])
400
- self._assign_mode = False
401
- self.run_assignment(kid[1])
402
- self.perform_assignment(dest, self.pop(), kid[0])
403
- elif kid[1].name == "copy_assign":
404
- self._assign_mode = True
405
- dest = self.run_rule(kid[0])
406
- self._assign_mode = False
407
- self.run_copy_assign(kid[1])
408
- self.perform_copy_fields(dest, self.pop(), kid[0])
409
- elif kid[1].name == "inc_assign":
410
- self._assign_mode = True
411
- dest = self.run_rule(kid[0])
412
- self._assign_mode = False
413
- self.run_inc_assign(kid[1])
414
- self.perform_increment(
415
- dest, self.pop(), JsCmp[kid[1].kid[0].name], kid[0]
416
- )
417
- except Exception as e:
418
- self.rt_error(e, jac_ast)
419
-
420
- def run_assignment(self, jac_ast):
421
- """
422
- assignment: EQ expression;
423
- """
424
- if self.attempt_bytecode(jac_ast):
425
- return
426
- kid = self.set_cur_ast(jac_ast)
427
- self.run_expression(kid[1])
428
-
429
- def run_copy_assign(self, jac_ast):
430
- """
431
- copy_assign: CPY_EQ expression;
432
- """
433
- if self.attempt_bytecode(jac_ast):
434
- return
435
- kid = self.set_cur_ast(jac_ast)
436
- self.run_expression(kid[1])
437
-
438
- def run_inc_assign(self, jac_ast):
439
- """
440
- inc_assign: (PEQ | MEQ | TEQ | DEQ) expression;
441
- """
442
- if self.attempt_bytecode(jac_ast):
443
- return
444
- kid = self.set_cur_ast(jac_ast)
445
- self.run_expression(kid[1])
446
-
447
- def run_connect(self, jac_ast):
448
- """
449
- connect: logical ( (NOT edge_ref | connect_op) expression)?;
450
- """
451
- kid = self.set_cur_ast(jac_ast)
452
- if len(kid) < 2:
453
- return self.run_rule(kid[0])
454
- bret = self.run_rule(kid[0])
455
- base = bret.value
456
- self.run_expression(kid[-1])
457
- tret = self.pop()
458
- target = tret.value
459
- self.rt_check_type(base, [Node, JacSet], kid[0])
460
- self.rt_check_type(target, [Node, JacSet], kid[-1])
461
- if isinstance(base, Node):
462
- base = JacSet(in_list=[base])
463
- if isinstance(target, Node):
464
- target = JacSet(in_list=[target])
465
- if kid[1].name == "NOT":
466
- for i in target.obj_list():
467
- for j in base.obj_list():
468
- j.detach_edges(i, self.run_edge_ref(kid[2]).obj_list())
469
- return bret
470
- else:
471
- direction = kid[1].kid[0].name
472
- for i in target.obj_list():
473
- for j in base.obj_list():
474
- use_edge = self.run_connect_op(kid[1])
475
- self.rt_check_type(i, Node, kid[-1])
476
- self.rt_check_type(j, Node, kid[-1])
477
- if direction == "connect_from":
478
- j.attach_inbound(i, [use_edge])
479
- elif direction == "connect_to":
480
- j.attach_outbound(i, [use_edge])
481
- else:
482
- j.attach_bidirected(i, [use_edge])
483
- return bret
484
-
485
- def run_logical(self, jac_ast):
486
- """
487
- logical: compare ((KW_AND | KW_OR) compare)*;
488
- """
489
- if self.attempt_bytecode(jac_ast):
490
- return
491
- kid = self.set_cur_ast(jac_ast)
492
- result = self.run_rule(kid[0])
493
- kid = kid[1:]
494
- while kid:
495
- if kid[0].name == "KW_AND":
496
- if result.value:
497
- result.value = result.value and self.run_rule(kid[1]).value
498
- elif kid[0].name == "KW_OR":
499
- if not result.value:
500
- result.value = result.value or self.run_rule(kid[1]).value
501
- kid = kid[2:]
502
- if not kid:
503
- break
504
- self.push(result)
505
-
506
- def run_compare(self, jac_ast):
507
- """
508
- compare: NOT compare | arithmetic (cmp_op arithmetic)*;
509
- """
510
- if self.attempt_bytecode(jac_ast):
511
- return
512
- kid = self.set_cur_ast(jac_ast)
513
- if kid[0].name == "NOT":
514
- self.push(JacValue(self, value=not self.run_rule(kid[1]).value))
515
- else:
516
- result = self.run_rule(kid[0])
517
- kid = kid[1:]
518
- while kid:
519
- other_res = self.run_rule(kid[1])
520
- self.run_cmp_op(kid[0], result, other_res)
521
- result = self.pop()
522
- kid = kid[2:]
523
- if not kid:
524
- break
525
- self.push(result)
526
-
527
- def run_cmp_op(self, jac_ast, val1, val2):
528
- """
529
- cmp_op: EE | LT | GT | LTE | GTE | NE | KW_IN | nin;
530
- """
531
- kid = self.set_cur_ast(jac_ast)
532
- if kid[0].name == "EE":
533
- self.push(JacValue(self, value=val1.value == val2.value))
534
- elif kid[0].name == "LT":
535
- self.push(JacValue(self, value=val1.value < val2.value))
536
- elif kid[0].name == "GT":
537
- self.push(JacValue(self, value=val1.value > val2.value))
538
- elif kid[0].name == "LTE":
539
- self.push(JacValue(self, value=val1.value <= val2.value))
540
- elif kid[0].name == "GTE":
541
- self.push(JacValue(self, value=val1.value >= val2.value))
542
- elif kid[0].name == "NE":
543
- self.push(JacValue(self, value=val1.value != val2.value))
544
- elif kid[0].name == "KW_IN":
545
- self.push(JacValue(self, value=val1.value in val2.value))
546
- elif kid[0].name == "nin":
547
- self.push(JacValue(self, value=val1.value not in val2.value))
548
-
549
- def run_arithmetic(self, jac_ast):
550
- """
551
- arithmetic: term ((PLUS | MINUS) term)*;
552
- """
553
- if self.attempt_bytecode(jac_ast):
554
- return
555
- kid = self.set_cur_ast(jac_ast)
556
- result = self.run_rule(kid[0])
557
- kid = kid[1:]
558
- while kid:
559
- other_res = self.run_rule(kid[1])
560
- if kid[0].name == "PLUS":
561
- result.value = result.value + other_res.value
562
- elif kid[0].name == "MINUS":
563
- result.value = result.value - other_res.value
564
- kid = kid[2:]
565
- if not kid:
566
- break
567
- self.push(result)
568
-
569
- def run_term(self, jac_ast):
570
- """
571
- term: factor ((STAR_MUL | DIV | MOD) factor)*;
572
- """
573
- if self.attempt_bytecode(jac_ast):
574
- return
575
- kid = self.set_cur_ast(jac_ast)
576
- result = self.run_rule(kid[0])
577
- kid = kid[1:]
578
- while kid:
579
- other_res = self.run_rule(kid[1])
580
- if kid[0].name == "STAR_MUL":
581
- result.value = result.value * other_res.value
582
- elif kid[0].name == "DIV":
583
- result.value = result.value / other_res.value
584
- elif kid[0].name == "MOD":
585
- result.value = result.value % other_res.value
586
- kid = kid[2:]
587
- if not kid:
588
- break
589
- self.push(result)
590
-
591
- def run_factor(self, jac_ast):
592
- """
593
- factor: (PLUS | MINUS) factor | power;
594
- """
595
- if self.attempt_bytecode(jac_ast):
596
- return
597
- kid = self.set_cur_ast(jac_ast)
598
- if len(kid) < 2:
599
- self.push(self.run_rule(kid[0]))
600
- else:
601
- result = self.run_rule(kid[1])
602
- if kid[0].name == "MINUS":
603
- result.value = -(result.value)
604
- self.push(result)
605
-
606
- def run_power(self, jac_ast):
607
- """
608
- power: atom (POW factor)*;
609
- """
610
- if self.attempt_bytecode(jac_ast):
611
- return
612
- kid = self.set_cur_ast(jac_ast)
613
- result = self.run_rule(kid[0])
614
- kid = kid[1:]
615
- if len(kid) < 1:
616
- self.push(result)
617
- elif kid[0].name == "POW":
618
- while kid:
619
- result.value = result.value ** self.run_rule(kid[1]).value
620
- kid = kid[2:]
621
- if not kid:
622
- break
623
- self.push(result)
624
-
625
- def run_global_ref(self, jac_ast):
626
- """
627
- global_ref: KW_GLOBAL DOT (obj_built_in | NAME);
628
- """
629
- try:
630
- kid = self.set_cur_ast(jac_ast)
631
- if kid[2].name == "obj_built_in":
632
- kid = self.set_cur_ast(kid[2])
633
- if kid[0].name == "KW_CONTEXT":
634
- return JacValue(self, value=self.parent().global_vars)
635
- elif kid[0].name == "KW_INFO":
636
- # Add additional accessible fields
637
- return JacValue(self, value=self.get_info())
638
- else:
639
- self.rt_error(f"Global {kid[0].name} is not supported!", jac_ast)
640
- else:
641
- token = kid[2].token_text()
642
- if token not in self.parent().global_vars:
643
- self.rt_error(f"Global not defined - {token}", kid[2])
644
-
645
- return JacValue(self, ctx=self.parent().global_vars, name=token)
646
-
647
- except Exception as e:
648
- self.rt_error(e, jac_ast)
649
-
650
- def run_atom(self, jac_ast):
651
- """
652
- atom:
653
- INT
654
- | FLOAT
655
- | multistring
656
- | BOOL
657
- | NULL
658
- | NAME
659
- | global_ref
660
- | node_edge_ref
661
- | list_val
662
- | dict_val
663
- | LPAREN expression RPAREN
664
- | ability_op NAME spawn_ctx?
665
- | atom atom_trailer
666
- | KW_SYNC atom
667
- | spawn
668
- | ref
669
- | deref
670
- | any_type;
671
- """
672
- try:
673
- if self.attempt_bytecode(jac_ast):
674
- return
675
- kid = self.set_cur_ast(jac_ast)
676
- if kid[0].name == "INT":
677
- self.push(JacValue(self, value=int(kid[0].token_text())))
678
- elif kid[0].name == "FLOAT":
679
- self.push(JacValue(self, value=float(kid[0].token_text())))
680
- elif kid[0].name == "multistring":
681
- self.run_multistring(kid[0])
682
- elif kid[0].name == "BOOL":
683
- self.push(JacValue(self, value=bool(kid[0].token_text() == "true")))
684
- elif kid[0].name == "NULL":
685
- self.push(JacValue(self, value=None))
686
- elif kid[0].name == "NAME":
687
- self.load_variable(kid[0].token_text(), kid[0])
688
- elif kid[0].name == "LPAREN":
689
- self.run_expression(kid[1])
690
- elif kid[0].name == "ability_op":
691
- self.push(
692
- self.run_ability_call(
693
- jac_ast, atom_res=JacValue(self, value=self._jac_scope.has_obj)
694
- )
695
- )
696
- elif kid[0].name == "atom":
697
- self.run_atom(kid[0])
698
- ret = self.pop()
699
- for i in kid[1:]:
700
- ret = self.run_atom_trailer(i, ret)
701
- self.push(ret)
702
- elif kid[0].name == "KW_SYNC":
703
- self.run_atom(kid[1])
704
- val = self.pop()
705
- self.push(
706
- JacValue(
707
- self,
708
- value=(
709
- JsOrc.svc("task")
710
- .poke(TaskService)
711
- .get_by_task_id(val.value["result"], True)
712
- ),
713
- )
714
- )
715
- else:
716
- self.push(self.run_rule(kid[0]))
717
-
718
- except Exception as e:
719
- self.rt_error(e, jac_ast)
720
-
721
- def run_atom_trailer(self, jac_ast, atom_res):
722
- """
723
- atom_trailer:
724
- DOT built_in
725
- | DOT NAME
726
- | index_slice
727
- | ability_call;
728
- """
729
- try:
730
- kid = self.set_cur_ast(jac_ast)
731
- if isinstance(atom_res.value, Element):
732
- self._write_candidate = atom_res.value
733
- if kid[0].name == "DOT":
734
- if kid[1].name == "built_in":
735
- return self.run_built_in(kid[1], atom_res)
736
- elif kid[1].name == "NAME":
737
- d = atom_res.value
738
- n = kid[1].token_text()
739
- if self.rt_check_type(d, [dict, Element, JacSet], kid[0]):
740
- if isinstance(d, Element):
741
- self._write_candidate = d
742
- if not isinstance(d, JacSet):
743
- ret = JacValue(self, ctx=d, name=n)
744
- else:
745
- plucked = []
746
- for i in d:
747
- if n in i.context.keys():
748
- plucked.append(i.context[n])
749
- else:
750
- self.rt_error(
751
- f"Some elements in set does not have {n}",
752
- kid[1],
753
- )
754
- ret = JacValue(self, value=plucked)
755
- return ret
756
- else:
757
- self.rt_error(f"Invalid variable {n}", kid[0])
758
- elif kid[0].name == "index_slice":
759
- if not self.rt_check_type(atom_res.value, [list, str, dict], kid[0]):
760
- return atom_res
761
- return self.run_index_slice(kid[0], atom_res)
762
- elif kid[0].name == "ability_call":
763
- return self.run_ability_call(kid[0], atom_res)
764
- except Exception as e:
765
- self.rt_error(e, jac_ast)
766
-
767
- def run_ability_call(self, jac_ast, atom_res):
768
- """
769
- ability_call:
770
- LPAREN param_list? RPAREN
771
- | ability_op NAME spawn_ctx?;
772
- """
773
- from jaseci.prim.ability import Ability
774
-
775
- kid = self.set_cur_ast(jac_ast)
776
- if kid[0].name == "LPAREN":
777
- param_list = {"args": [], "kwargs": {}}
778
- if kid[1].name == "param_list":
779
- param_list = self.run_param_list(kid[1]).value
780
- if isinstance(atom_res.value, Ability):
781
- ret = atom_res.value.run_action(
782
- param_list, self._jac_scope, self, jac_ast
783
- )
784
- return JacValue(self, value=ret)
785
- else:
786
- self.rt_error("Unable to execute ability", kid[0])
787
- elif kid[0].name == "ability_op":
788
- arch = self.run_ability_op(kid[0], atom_res)
789
- if len(kid) > 2:
790
- self.run_spawn_ctx(kid[2], atom_res.value)
791
- self.call_ability(
792
- nd=atom_res.value,
793
- name=kid[1].token_text(),
794
- act_list=arch.get_all_abilities(),
795
- )
796
- return atom_res
797
-
798
- def run_ability_op(self, jac_ast, atom_res):
799
- """
800
- ability_op: DBL_COLON | DBL_COLON NAME COLON;
801
- """
802
- kid = self.set_cur_ast(jac_ast)
803
- base_arch = atom_res.value.get_architype()
804
- if len(kid) > 1:
805
- kind = atom_res.value.kind
806
- name = kid[1].token_text()
807
- if name in base_arch.derived_types():
808
- return self.parent().arch_ids.get_obj_by_name(name=name, kind=kind)
809
- else:
810
- self.rt_error(f"{name} is not a super arch of {base_arch.name}", kid[1])
811
- else:
812
- return base_arch
813
-
814
- def run_ref(self, jac_ast):
815
- """
816
- ref: '&' atom;
817
- """
818
- kid = self.set_cur_ast(jac_ast)
819
- self.run_atom(kid[1])
820
- result = self.pop()
821
- if self.rt_check_type(result.value, Element, kid[1]):
822
- result = JacValue(self, value=result.value.jid)
823
- return result
824
-
825
- def run_deref(self, jac_ast):
826
- """
827
- deref: '*' atom;
828
- """
829
- kid = self.set_cur_ast(jac_ast)
830
- self.run_atom(kid[1])
831
- result = self.pop()
832
-
833
- if (
834
- isinstance(result.value, str)
835
- and len(result.value) < 64 # super long string, untrustworthy
836
- and not result.value.startswith("jac:uuid:") # already an object
837
- ):
838
- matcher = uuid_re.search(result.value)
839
- if matcher and matcher.group(1):
840
- nd = jeu(f"jac:uuid:{matcher.group(1)}", self)
841
- if nd is not None:
842
- return JacValue(self, value=nd)
843
-
844
- self.rt_error(f"{result.value} not valid reference", kid[1])
845
-
846
- def run_built_in(self, jac_ast, atom_res):
847
- """
848
- built_in:
849
- cast_built_in
850
- | obj_built_in
851
- | dict_built_in
852
- | list_built_in
853
- | string_built_in;
854
- """
855
- return self.run_rule(jac_ast.kid[0], atom_res)
856
-
857
- def run_cast_built_in(self, jac_ast, atom_res):
858
- """
859
- arch_built_in: any_type;
860
- """
861
- kid = self.set_cur_ast(jac_ast)
862
- self.run_any_type(kid[0])
863
- typ = self.pop()
864
- if typ.value == Edge:
865
- if isinstance(atom_res.value, Node):
866
- return JacValue(
867
- self,
868
- value=self.obj_set_to_jac_set(
869
- self.here().attached_edges(atom_res.value)
870
- ),
871
- )
872
- elif isinstance(atom_res.value, Edge):
873
- return atom_res
874
- elif isinstance(atom_res.value, JacSet):
875
- return JacValue(self, value=self._relevant_edges)
876
- else:
877
- self.rt_error(
878
- f"Cannot get edges from {atom_res.value}. "
879
- f"Type {atom_res.jac_type()} invalid",
880
- kid[0],
881
- )
882
- # may want to remove 'here" node from return below
883
- elif typ.value == Node:
884
- if isinstance(atom_res.value, Node):
885
- return atom_res
886
- elif isinstance(atom_res.value, Edge):
887
- return JacValue(
888
- self, value=self.obj_set_to_jac_set(atom_res.value.nodes())
889
- )
890
- elif isinstance(atom_res.value, JacSet):
891
- res = JacSet()
892
- for i in atom_res.value.obj_list():
893
- if isinstance(i, Edge):
894
- res.add_obj(i.to_node())
895
- res.add_obj(i.from_node())
896
- elif isinstance(i, Node):
897
- res.add_obj(i)
898
- return JacValue(self, value=res)
899
- else:
900
- self.rt_error(
901
- f"Cannot get nodes from {atom_res}. "
902
- f"Type {atom_res.jac_type()} invalid",
903
- kid[0],
904
- )
905
- else:
906
- try:
907
- if isinstance(atom_res.value, str) and typ.value == dict:
908
- atom_res.value = loads(atom_res.value)
909
- elif isinstance(atom_res.value, dict) and typ.value == str:
910
- atom_res.value = dumps(atom_res.value)
911
- else:
912
- atom_res.value = typ.value(atom_res.value)
913
- except Exception as e:
914
- self.rt_error(
915
- f"Invalid cast of {atom_res.jac_type()} "
916
- f"to {jwv(typ.value)}: {e}",
917
- kid[0],
918
- )
919
- return atom_res
920
-
921
- return atom_res
922
-
923
- def run_obj_built_in(self, jac_ast, atom_res):
924
- """
925
- obj_built_in: KW_CONTEXT | KW_INFO | KW_DETAILS;
926
- """
927
- kid = self.set_cur_ast(jac_ast)
928
- from jaseci.prim.walker import Walker
929
-
930
- if kid[0].name == "KW_CONTEXT":
931
- if self.rt_check_type(atom_res.value, [Node, Edge, Walker], kid[0]):
932
- return JacValue(self, ctx=atom_res.value, value=atom_res.value.context)
933
- elif kid[0].name == "KW_INFO":
934
- if self.rt_check_type(atom_res.value, [Node, Edge, Walker], kid[0]):
935
- return JacValue(
936
- self,
937
- ctx=atom_res.value,
938
- value=atom_res.value.serialize(detailed=False),
939
- )
940
- elif kid[0].name == "KW_DETAILS":
941
- if self.rt_check_type(atom_res.value, [Node, Edge, Walker], kid[0]):
942
- return JacValue(
943
- self,
944
- ctx=atom_res.value,
945
- value=atom_res.value.serialize(detailed=True),
946
- )
947
- return atom_res
948
-
949
- def run_dict_built_in(self, jac_ast, atom_res):
950
- """
951
- dict_built_in:
952
- KW_KEYS
953
- | LBRACE name_list RBRACE
954
- | (TYP_DICT DBL_COLON | DICT_DBL_COLON) NAME (
955
- LPAREN expr_list RPAREN
956
- )?;
957
- """
958
- kid = self.set_cur_ast(jac_ast)
959
- if kid[0].name == "KW_KEYS":
960
- if isinstance(atom_res.value, dict):
961
- return JacValue(self, value=list(atom_res.value.keys()))
962
- else:
963
- self.rt_error(
964
- f"Cannot get keys of {atom_res}. " f"Not Dictionary!", kid[0]
965
- )
966
- elif len(kid) > 1 and kid[1].name == "name_list":
967
- filter_on = self.run_name_list(kid[1])
968
- d = atom_res.value
969
- if self.rt_check_type(d, [dict], kid[0]):
970
- d = {k: d[k] for k in d if k in filter_on}
971
- return JacValue(self, value=d)
972
- else:
973
- if not self.rt_check_type(atom_res.value, [dict], kid[0]):
974
- return atom_res
975
- kid = kid[1:]
976
- if kid[0].name == "DBL_COLON":
977
- kid = kid[1:]
978
- result = None
979
- op = kid[0].token_text()
980
- try:
981
- if op == "items":
982
- result = JacValue(
983
- self, value=list(map(list, atom_res.value.items()))
984
- )
985
- elif op == "copy":
986
- result = JacValue(self, value=atom_res.value.copy())
987
- elif op == "deepcopy":
988
- result = JacValue(self, value=deepcopy(atom_res.value))
989
- elif op == "keys":
990
- result = JacValue(self, value=list(atom_res.value.keys()))
991
- elif op == "clear":
992
- result = JacValue(self, value=atom_res.value.clear())
993
- self.candidate_writethrough()
994
- elif op == "popitem":
995
- result = JacValue(self, value=list(atom_res.value.popitem()))
996
- self.candidate_writethrough()
997
- elif op == "values":
998
- result = JacValue(self, value=list(atom_res.value.values()))
999
- if result:
1000
- if len(kid) > 1:
1001
- self.rt_warn(f"{op} does not take parameters, ignoring", kid[2])
1002
- return result
1003
- if len(kid) > 1:
1004
- args = self.run_expr_list(kid[2]).value
1005
- if op == "pop":
1006
- result = JacValue(self, value=atom_res.value.pop(*args))
1007
- self.candidate_writethrough()
1008
- elif op == "update":
1009
- result = JacValue(self, value=atom_res.value.update(*args))
1010
- self.candidate_writethrough()
1011
- elif op == "get":
1012
- result = JacValue(self, value=atom_res.value.get(*args))
1013
- if result:
1014
- return result
1015
- except Exception as e:
1016
- self.rt_error(e, jac_ast)
1017
- self.rt_error(f"Call to {op} is invalid.", jac_ast)
1018
-
1019
- return atom_res
1020
-
1021
- def run_list_built_in(self, jac_ast, atom_res):
1022
- """
1023
- list_built_in:
1024
- KW_LENGTH
1025
- | (TYP_LIST DBL_COLON | LIST_DBL_COLON) NAME (
1026
- LPAREN expr_list RPAREN
1027
- )?;
1028
- """
1029
- kid = self.set_cur_ast(jac_ast)
1030
- if kid[0].name == "KW_LENGTH":
1031
- if isinstance(atom_res.value, list):
1032
- return JacValue(self, value=len(atom_res.value))
1033
- else:
1034
- self.rt_error(
1035
- f"Cannot get length of {atom_res.value}. Not List!", kid[0]
1036
- )
1037
- else:
1038
- if not self.rt_check_type(atom_res.value, [list], kid[0]):
1039
- return atom_res
1040
- kid = kid[1:]
1041
- if kid[0].name == "DBL_COLON":
1042
- kid = kid[1:]
1043
- result = None
1044
- op = kid[0].token_text()
1045
- try:
1046
- if op == "reverse":
1047
- result = JacValue(self, value=atom_res.value.reverse())
1048
- self.candidate_writethrough()
1049
- elif op == "reversed":
1050
- result = JacValue(self, value=list(reversed(atom_res.value)))
1051
- elif op == "copy":
1052
- result = JacValue(self, value=atom_res.value.copy())
1053
- elif op == "deepcopy":
1054
- result = JacValue(self, value=deepcopy(atom_res.value))
1055
- elif op == "sort":
1056
- result = JacValue(self, value=atom_res.value.sort())
1057
- self.candidate_writethrough()
1058
- elif op == "clear":
1059
- result = JacValue(self, value=atom_res.value.clear())
1060
- self.candidate_writethrough()
1061
- elif op == "max":
1062
- result = JacValue(self, value=max(atom_res.value))
1063
- elif op == "min":
1064
- result = JacValue(self, value=min(atom_res.value))
1065
- elif op == "idx_of_max":
1066
- result = JacValue(
1067
- self, value=atom_res.value.index(max(atom_res.value))
1068
- )
1069
- elif op == "idx_of_min":
1070
- result = JacValue(
1071
- self, value=atom_res.value.index(min(atom_res.value))
1072
- )
1073
- elif op == "pairwise":
1074
- result = JacValue(
1075
- self, value=[list(s) for s in pairwise(atom_res.value)]
1076
- )
1077
- elif op == "unique":
1078
- result = JacValue(self, value=list(set(atom_res.value)))
1079
-
1080
- elif len(kid) < 2 and op == "pop":
1081
- result = JacValue(self, value=atom_res.value.pop())
1082
- self.candidate_writethrough()
1083
- if result:
1084
- if len(kid) > 1:
1085
- self.rt_warn(f"{op} does not take parameters, ignoring", kid[2])
1086
- return result
1087
- if len(kid) > 1:
1088
- args = self.run_expr_list(kid[2]).value
1089
- if op == "index":
1090
- result = JacValue(self, value=atom_res.value.index(*args))
1091
- elif op == "append":
1092
- result = JacValue(self, value=atom_res.value.append(*args))
1093
- self.candidate_writethrough()
1094
- elif op == "extend":
1095
- result = JacValue(self, value=atom_res.value.extend(*args))
1096
- self.candidate_writethrough()
1097
- elif op == "insert":
1098
- result = JacValue(self, value=atom_res.value.insert(*args))
1099
- self.candidate_writethrough()
1100
- elif op == "remove":
1101
- result = JacValue(self, value=atom_res.value.remove(*args))
1102
- self.candidate_writethrough()
1103
- elif op == "count":
1104
- result = JacValue(self, value=atom_res.value.count(*args))
1105
- elif op == "pop":
1106
- result = JacValue(self, value=atom_res.value.pop(*args))
1107
- self.candidate_writethrough()
1108
- if result:
1109
- return result
1110
- except Exception as e:
1111
- self.rt_error(e, jac_ast)
1112
- self.rt_error(f"Call to {op} is invalid.", jac_ast)
1113
- return atom_res
1114
-
1115
- def run_string_built_in(self, jac_ast, atom_res):
1116
- """
1117
- string_built_in:
1118
- (TYP_STRING DBL_COLON | STR_DBL_COLON) NAME (
1119
- LPAREN expr_list RPAREN
1120
- )?;
1121
- """
1122
- kid = self.set_cur_ast(jac_ast)
1123
- if not self.rt_check_type(atom_res.value, [str], kid[0]):
1124
- return atom_res
1125
- kid = kid[1:]
1126
- if kid[0].name == "DBL_COLON":
1127
- kid = kid[1:]
1128
- result = None
1129
- str_op = kid[0].token_text()
1130
- try:
1131
- if str_op == "upper":
1132
- result = JacValue(self, value=atom_res.value.upper())
1133
- elif str_op == "lower":
1134
- result = JacValue(self, value=atom_res.value.lower())
1135
- elif str_op == "title":
1136
- result = JacValue(self, value=atom_res.value.title())
1137
- elif str_op == "capitalize":
1138
- result = JacValue(self, value=atom_res.value.capitalize())
1139
- elif str_op == "swap_case":
1140
- result = JacValue(self, value=atom_res.value.swapcase())
1141
- elif str_op == "is_alnum":
1142
- result = JacValue(self, value=atom_res.value.isalnum())
1143
- elif str_op == "is_alpha":
1144
- result = JacValue(self, value=atom_res.value.isalpha())
1145
- elif str_op == "is_digit":
1146
- result = JacValue(self, value=atom_res.value.isdigit())
1147
- elif str_op == "is_title":
1148
- result = JacValue(self, value=atom_res.value.istitle())
1149
- elif str_op == "is_upper":
1150
- result = JacValue(self, value=atom_res.value.isupper())
1151
- elif str_op == "is_lower":
1152
- result = JacValue(self, value=atom_res.value.islower())
1153
- elif str_op == "is_space":
1154
- result = JacValue(self, value=atom_res.value.isspace())
1155
- elif str_op == "load_json":
1156
- import json
1157
-
1158
- result = JacValue(self, value=json.loads(atom_res.value))
1159
- elif len(kid) < 2 and str_op == "split":
1160
- result = JacValue(self, value=atom_res.value.split())
1161
- elif len(kid) < 2 and str_op == "strip":
1162
- result = JacValue(self, value=atom_res.value.strip())
1163
- elif len(kid) < 2 and str_op == "lstrip":
1164
- result = JacValue(self, value=atom_res.value.lstrip())
1165
- elif len(kid) < 2 and str_op == "rstrip":
1166
- result = JacValue(self, value=atom_res.value.rstrip())
1167
- if result:
1168
- if len(kid) > 1:
1169
- self.rt_warn(f"{str_op} does not take parameters, ignoring", kid[2])
1170
- return result
1171
- if len(kid) > 1:
1172
- args = self.run_expr_list(kid[2]).value
1173
- if str_op == "count":
1174
- result = JacValue(self, value=atom_res.value.count(*args))
1175
- elif str_op == "find":
1176
- result = JacValue(self, value=atom_res.value.find(*args))
1177
- elif str_op == "split":
1178
- result = JacValue(self, value=atom_res.value.split(*args))
1179
- elif str_op == "join":
1180
- if len(args) == 1 and type(args[0]) is list:
1181
- args = args[0]
1182
-
1183
- result = JacValue(
1184
- self, value=atom_res.value.join([str(arg) for arg in args])
1185
- )
1186
- elif str_op == "startswith":
1187
- result = JacValue(self, value=atom_res.value.startswith(*args))
1188
- elif str_op == "endswith":
1189
- result = JacValue(self, value=atom_res.value.endswith(*args))
1190
- elif str_op == "replace":
1191
- result = JacValue(self, value=atom_res.value.replace(*args))
1192
- elif str_op == "strip":
1193
- result = JacValue(self, value=atom_res.value.strip(*args))
1194
- elif str_op == "lstrip":
1195
- result = JacValue(self, value=atom_res.value.lstrip(*args))
1196
- elif str_op == "rstrip":
1197
- result = JacValue(self, value=atom_res.value.rstrip(*args))
1198
- if result:
1199
- return result
1200
- except Exception as e:
1201
- self.rt_error(e, jac_ast)
1202
- self.rt_error(f"Call to {str_op} is invalid.", jac_ast)
1203
- return atom_res
1204
-
1205
- def run_node_edge_ref(self, jac_ast, viable_nodes=None):
1206
- """
1207
- node_edge_ref:
1208
- node_ref filter_ctx? node_edge_ref?
1209
- | edge_ref node_edge_ref?;
1210
- """
1211
- kid = self.set_cur_ast(jac_ast)
1212
- result = JacSet()
1213
- if kid[0].name == "node_ref":
1214
- result = self.run_node_ref(kid[0], viable_nodes=viable_nodes)
1215
- kid = kid[1:]
1216
- if len(kid) and kid[0].name == "filter_ctx":
1217
- result = self.run_filter_ctx(kid[0], result)
1218
- kid = kid[1:]
1219
- if len(kid):
1220
- result = self.run_node_edge_ref(kid[0], viable_nodes=result).value
1221
-
1222
- elif kid[0].name == "edge_ref":
1223
- if not viable_nodes:
1224
- viable_nodes = [None]
1225
- self._relevant_edges = JacSet()
1226
- for i in viable_nodes:
1227
- relevant_edges = self.run_edge_ref(kid[0], location=i)
1228
- result += self.visibility_prune(
1229
- self.edge_to_node_jac_set(relevant_edges, location=i)
1230
- )
1231
- kid = kid[1:]
1232
- if len(kid):
1233
- result = self.run_node_edge_ref(kid[0], viable_nodes=result).value
1234
-
1235
- relevant_edges = self.edges_filter_on_nodes(relevant_edges, result)
1236
- self._relevant_edges += relevant_edges
1237
- return JacValue(self, value=result)
1238
-
1239
- def run_node_ref(self, jac_ast, is_spawn=False, viable_nodes=None):
1240
- """
1241
- node_ref: NODE_DBL_COLON NAME;
1242
- """
1243
- kid = self.set_cur_ast(jac_ast)
1244
- if not is_spawn:
1245
- result = JacSet()
1246
- viable_nodes = self.visibility_prune(viable_nodes)
1247
- if len(kid) > 1:
1248
- for i in viable_nodes.obj_list():
1249
- try:
1250
- if i.get_architype().is_instance(kid[-1].token_text()):
1251
- result.add_obj(i)
1252
- except:
1253
- self.rt_warn(
1254
- f"Error occured while getting architype {i.name}. Skipping..."
1255
- )
1256
- else:
1257
- result += viable_nodes
1258
- else:
1259
- result = self.parent().run_architype(
1260
- kid[-1].token_text(), kind="node", caller=self
1261
- )
1262
- return result
1263
-
1264
- def run_walker_ref(self, jac_ast, to_await=False):
1265
- """
1266
- walker_ref: WALKER_DBL_COLON NAME;
1267
- """
1268
- kid = self.set_cur_ast(jac_ast)
1269
- name = kid[-1].token_text()
1270
- wlk = self.yielded_walkers_ids.get_obj_by_name(name, silent=True)
1271
- if wlk is None:
1272
- wlk = self.parent().run_architype(name=name, kind="walker", caller=self)
1273
- if wlk is None:
1274
- self.rt_error(f"No walker {name} exists!", kid[-1])
1275
- else:
1276
- wlk._to_await = to_await
1277
- return wlk
1278
-
1279
- def run_graph_ref(self, jac_ast):
1280
- """
1281
- graph_ref: GRAPH_DBL_COLON NAME;
1282
- """
1283
- kid = self.set_cur_ast(jac_ast)
1284
- gph = self.parent().run_architype(
1285
- kid[-1].token_text(), kind="graph", caller=self
1286
- )
1287
- return gph
1288
-
1289
- def run_type_ref(self, jac_ast):
1290
- """
1291
- type_ref: TYPE_DBL_COLON NAME;
1292
- """
1293
- kid = self.set_cur_ast(jac_ast)
1294
- obj = self.parent().run_architype(
1295
- kid[-1].token_text(), kind="type", caller=self
1296
- )
1297
- return JacValue(self, value=obj)
1298
-
1299
- def run_edge_ref(self, jac_ast, location=None):
1300
- """
1301
- edge_ref: edge_to | edge_from | edge_any;
1302
- """
1303
- kid = self.set_cur_ast(jac_ast)
1304
- return self.run_rule(kid[0], location)
1305
-
1306
- def run_edge_to(self, jac_ast, location=None):
1307
- """
1308
- edge_to:
1309
- '-->'
1310
- | '-' ('[' NAME (spawn_ctx | filter_ctx)? ']')? '->';
1311
- """
1312
- kid = self.set_cur_ast(jac_ast)
1313
- if not location:
1314
- location = self.here()
1315
- result = JacSet()
1316
- for i in location.outbound_edges() + location.bidirected_edges():
1317
- if len(kid) > 2 and not i.get_architype().is_instance(kid[2].token_text()):
1318
- continue
1319
- result.add_obj(i)
1320
- if len(kid) > 2 and kid[3].name == "filter_ctx":
1321
- result = self.run_filter_ctx(kid[3], result)
1322
- elif len(kid) > 2 and kid[3].name == "spawn_ctx":
1323
- self.rt_error("Assigning values not allowed here", kid[3])
1324
- return result
1325
-
1326
- def run_edge_from(self, jac_ast, location=None):
1327
- """
1328
- edge_from:
1329
- '<--'
1330
- | '<-' ('[' NAME (spawn_ctx | filter_ctx)? ']')? '-';
1331
- """
1332
- kid = self.set_cur_ast(jac_ast)
1333
- if not location:
1334
- location = self.here()
1335
- result = JacSet()
1336
- for i in location.inbound_edges() + location.bidirected_edges():
1337
- if len(kid) > 2 and not i.get_architype().is_instance(kid[2].token_text()):
1338
- continue
1339
- result.add_obj(i)
1340
- if len(kid) > 2 and kid[3].name == "filter_ctx":
1341
- result = self.run_filter_ctx(kid[3], result)
1342
- elif len(kid) > 2 and kid[3].name == "spawn_ctx":
1343
- self.rt_error("Assigning values not allowed here", kid[3])
1344
- return result
1345
-
1346
- def run_edge_any(self, jac_ast, location=None):
1347
- """
1348
- edge_any:
1349
- '<-->'
1350
- | '<-' ('[' NAME (spawn_ctx | filter_ctx)? ']')? '->';
1351
- NOTE: these do not use strict bidirected semantic but any edge
1352
- """
1353
- kid = self.set_cur_ast(jac_ast)
1354
- if not location:
1355
- location = self.here()
1356
- result = JacSet()
1357
- for i in location.attached_edges():
1358
- if len(kid) > 2 and not i.get_architype().is_instance(kid[2].token_text()):
1359
- continue
1360
- result.add_obj(i)
1361
- if len(kid) > 2 and kid[3].name == "filter_ctx":
1362
- result = self.run_filter_ctx(kid[3], result)
1363
- elif len(kid) > 2 and kid[3].name == "spawn_ctx":
1364
- self.rt_error("Assigning values not allowed here", kid[3])
1365
- return result
1366
-
1367
- def run_connect_op(self, jac_ast):
1368
- """
1369
- connect_op: connect_to | connect_from | connect_any;
1370
- """
1371
- kid = self.set_cur_ast(jac_ast)
1372
- if len(kid[0].kid) > 2:
1373
- result = self.parent().run_architype(
1374
- kid[0].kid[2].token_text(), kind="edge", caller=self
1375
- )
1376
- if kid[0].kid[3].name == "spawn_ctx":
1377
- self.run_spawn_ctx(kid[0].kid[3], result)
1378
- else:
1379
- result = Edge(
1380
- m_id=self._m_id,
1381
- h=self._h,
1382
- kind="edge",
1383
- name="generic",
1384
- )
1385
- return result
1386
-
1387
- def run_list_val(self, jac_ast):
1388
- """
1389
- list_val: LSQUARE expr_list? RSQUARE;
1390
- """
1391
- kid = self.set_cur_ast(jac_ast)
1392
- if kid[1].name == "expr_list":
1393
- return self.run_expr_list(kid[1])
1394
- return JacValue(self, value=[])
1395
-
1396
- def run_index_slice(self, jac_ast, atom_res):
1397
- """
1398
- index_slice:
1399
- LSQUARE expression RSQUARE
1400
- | LSQUARE expression COLON expression RSQUARE;
1401
- """
1402
- kid = self.set_cur_ast(jac_ast)
1403
- self.run_expression(kid[1])
1404
- idx = self.pop().value
1405
- if kid[2].name == "RSQUARE":
1406
- if not self.rt_check_type(idx, [int, str], kid[1]):
1407
- self.rt_error(
1408
- f"Index of type {type(idx)} not valid. "
1409
- f"Indicies must be an integer or string!",
1410
- kid[1],
1411
- )
1412
- try:
1413
- return JacValue(self, ctx=atom_res.value, name=idx)
1414
- except Exception as e:
1415
- self.rt_error(e, jac_ast, isinstance(e, (IndexError, AttributeError)))
1416
- else:
1417
- self.run_expression(kid[3])
1418
- end = self.pop().value
1419
- if not self.rt_check_type(idx, [int], kid[1]) or not self.rt_check_type(
1420
- end, [int], kid[3]
1421
- ):
1422
- self.rt_error(
1423
- "List slice range not valid. Indicies must be an integers!",
1424
- kid[1],
1425
- )
1426
- try:
1427
- return JacValue(self, ctx=atom_res.value, name=idx, end=end)
1428
- except Exception as e:
1429
- self.rt_error(e, jac_ast, isinstance(e, (IndexError, AttributeError)))
1430
-
1431
- def run_dict_val(self, jac_ast):
1432
- """
1433
- dict_val: LBRACE (kv_pair (COMMA kv_pair)*)? RBRACE;
1434
- """
1435
- kid = self.set_cur_ast(jac_ast)
1436
- dict_res = {}
1437
- for i in kid:
1438
- if i.name == "kv_pair":
1439
- self.run_kv_pair(i, dict_res)
1440
- return JacValue(self, value=dict_res)
1441
-
1442
- def run_kv_pair(self, jac_ast, obj):
1443
- """
1444
- kv_pair: STRING COLON expression;
1445
- """
1446
- kid = self.set_cur_ast(jac_ast)
1447
- self.run_expression(kid[0])
1448
- key = self.pop().value
1449
- if isinstance(key, str):
1450
- self.run_expression(kid[2])
1451
- obj[key] = self.pop().value
1452
- else:
1453
- self.rt_error(f"Key is not str type : {type(key)}!", kid[0])
1454
-
1455
- def run_spawn(self, jac_ast):
1456
- """
1457
- spawn: KW_SPAWN spawn_object;
1458
-
1459
- NOTE: spawn statements support locations that are either nodes or
1460
- jac_sets
1461
- """
1462
- kid = self.set_cur_ast(jac_ast)
1463
- return self.run_spawn_object(kid[1])
1464
-
1465
- def run_spawn_object(self, jac_ast):
1466
- """
1467
- spawn_object:
1468
- node_spawn
1469
- | walker_spawn
1470
- | graph_spawn
1471
- | type_spawn;
1472
- """
1473
- kid = self.set_cur_ast(jac_ast)
1474
- return self.run_rule(kid[0])
1475
-
1476
- def run_spawn_edge(self, jac_ast):
1477
- """
1478
- spawn_edge: expression connect_op;
1479
- """
1480
- kid = self.set_cur_ast(jac_ast)
1481
- self.run_expression(kid[0])
1482
- loc = self.pop().value
1483
- if isinstance(loc, JacSet):
1484
- edge_set = [self.run_connect_op(kid[1]) for _ in loc]
1485
- loc = loc.obj_list()
1486
- else:
1487
- edge_set = self.run_connect_op(kid[1])
1488
- return {
1489
- "location": loc,
1490
- "use_edge": edge_set,
1491
- "direction": kid[1].kid[0].name,
1492
- }
1493
-
1494
- def run_node_spawn(self, jac_ast):
1495
- """
1496
- node_spawn: spawn_edge? node_ref spawn_ctx?;
1497
- """
1498
- kid = self.set_cur_ast(jac_ast)
1499
- if kid[0].name == "node_ref":
1500
- ret_node = self.run_node_ref(kid[0], is_spawn=True)
1501
- if kid[-1].name == "spawn_ctx":
1502
- self.run_spawn_ctx(kid[-1], ret_node)
1503
- return JacValue(self, value=ret_node)
1504
- else:
1505
- sp = self.run_spawn_edge(kid[0])
1506
- if isinstance(sp["location"], Node):
1507
- ret_node = self.run_node_ref(kid[1], is_spawn=True)
1508
- if sp["direction"] == "connect_from":
1509
- sp["location"].attach_inbound(ret_node, [sp["use_edge"]])
1510
- elif sp["direction"] == "connect_to":
1511
- sp["location"].attach_outbound(ret_node, [sp["use_edge"]])
1512
- else:
1513
- sp["location"].attach_bidirected(ret_node, [sp["use_edge"]])
1514
- if kid[-1].name == "spawn_ctx":
1515
- self.run_spawn_ctx(kid[-1], ret_node)
1516
- return JacValue(self, value=ret_node)
1517
- elif isinstance(sp["location"], JacSet):
1518
- res = []
1519
- sp["location"] = sp["location"].obj_list()
1520
- for i in range(len(sp["location"])):
1521
- ret_node = self.run_node_ref(kid[1], is_spawn=True)
1522
- if sp["direction"] == "connect_from":
1523
- sp["location"][i].attach_inbound(ret_node, [sp["use_edge"][i]])
1524
- elif sp["direction"] == "connect_to":
1525
- sp["location"][i].attach_outbound(ret_node, [sp["use_edge"][i]])
1526
- else:
1527
- sp["location"][i].attach_bidirected(
1528
- ret_node, [sp["use_edge"][i]]
1529
- )
1530
- if kid[-1].name == "spawn_ctx":
1531
- self.run_spawn_ctx(kid[-1], ret_node)
1532
- res.append(ret_node)
1533
- return JacValue(self, value=res)
1534
- else:
1535
- self.rt_error(f'Spawn can not occur on {type(sp["location"])}!', kid[1])
1536
-
1537
- def run_graph_spawn(self, jac_ast):
1538
- """
1539
- graph_spawn: spawn_edge? graph_ref;
1540
- """
1541
- kid = self.set_cur_ast(jac_ast)
1542
- if kid[0].name == "graph_ref":
1543
- result = self.run_graph_ref(kid[0])
1544
- return JacValue(self, value=result)
1545
- else:
1546
- sp = self.run_spawn_edge(kid[0])
1547
- if isinstance(sp["location"], Node):
1548
- ret_node = self.run_graph_ref(kid[1])
1549
- if sp["direction"] == "connect_from":
1550
- sp["location"].attach_inbound(ret_node, [sp["use_edge"]])
1551
- elif sp["direction"] == "connect_to":
1552
- sp["location"].attach_outbound(ret_node, [sp["use_edge"]])
1553
- else:
1554
- sp["location"].attach_bidirected(ret_node, [sp["use_edge"]])
1555
- return JacValue(self, value=ret_node)
1556
- elif isinstance(sp["location"], JacSet):
1557
- res = []
1558
- sp["location"] = sp["location"].obj_list()
1559
- for i in range(len(sp["location"])):
1560
- ret_node = self.run_graph_ref(kid[1])
1561
- if sp["direction"] == "connect_from":
1562
- sp["location"][i].attach_inbound(ret_node, [sp["use_edge"][i]])
1563
- elif sp["direction"] == "connect_to":
1564
- sp["location"][i].attach_outbound(ret_node, [sp["use_edge"][i]])
1565
- else:
1566
- sp["location"][i].attach_bidirected(
1567
- ret_node, [sp["use_edge"][i]]
1568
- )
1569
- res.append(ret_node)
1570
- return JacValue(self, value=res)
1571
- else:
1572
- self.rt_error(f'Spawn can not occur on {type(sp["location"])}!', kid[1])
1573
-
1574
- def run_walker_spawn(self, jac_ast):
1575
- """
1576
- walker_spawn: expression KW_SYNC? walker_ref spawn_ctx?;
1577
- """
1578
- kid = self.set_cur_ast(jac_ast)
1579
- is_await = kid[1].name == "KW_SYNC" and bool(kid.pop(1))
1580
- self.run_expression(kid[0])
1581
- location = self.pop().value
1582
- if isinstance(location, Node):
1583
- location = JacSet(in_list=[location])
1584
- ret = []
1585
- for i in location.obj_list():
1586
- walk = self.run_walker_ref(kid[1], is_await)
1587
- walk.prime(i, request_ctx=getattr(self, "request_context", {}))
1588
- if len(kid) > 2:
1589
- self.run_spawn_ctx(kid[2], walk)
1590
-
1591
- res = walk.run()
1592
-
1593
- if walk.for_queue() and not res["is_queued"]:
1594
- res["result"] = walk.anchor_value()
1595
-
1596
- tr = JacValue(self, value=res if walk.for_queue() else walk.anchor_value())
1597
- ret.append(tr.value)
1598
- self.inherit_runtime_state(walk)
1599
- walk.register_yield_or_destroy(self.yielded_walkers_ids)
1600
- return JacValue(self, value=ret[0] if len(ret) == 1 else ret)
1601
-
1602
- def run_type_spawn(self, jac_ast):
1603
- """
1604
- type_spawn: type_ref spawn_ctx?;
1605
- """
1606
- kid = self.set_cur_ast(jac_ast)
1607
- ret = self.run_type_ref(kid[0])
1608
- if kid[-1].name == "spawn_ctx":
1609
- self.run_spawn_ctx(kid[-1], ret.value)
1610
- return ret
1611
-
1612
- def run_spawn_ctx(self, jac_ast, obj):
1613
- """
1614
- spawn_ctx: LPAREN (spawn_assign (COMMA spawn_assign)*)? RPAREN;
1615
- """
1616
- kid = self.set_cur_ast(jac_ast)
1617
- for i in kid:
1618
- if i.name == "spawn_assign":
1619
- self.run_spawn_assign(i, obj)
1620
-
1621
- def run_filter_ctx(self, jac_ast, obj):
1622
- """
1623
- filter_ctx:
1624
- LPAREN (filter_compare (COMMA filter_compare)*)? RPAREN;
1625
- """
1626
- kid = self.set_cur_ast(jac_ast)
1627
- ret = JacSet()
1628
- for i in obj.obj_list():
1629
- for j in kid:
1630
- if j.name == "filter_compare":
1631
- if self.run_filter_compare(j, i):
1632
- ret.add_obj(i)
1633
- return ret
1634
-
1635
- def run_spawn_assign(self, jac_ast, obj):
1636
- """
1637
- spawn_assign: NAME EQ expression;
1638
- """
1639
- kid = self.set_cur_ast(jac_ast)
1640
- name = kid[0].token_text()
1641
- self.run_expression(kid[-1])
1642
- result = self.pop().value
1643
- if isinstance(obj, dict):
1644
- obj[name] = result
1645
- return
1646
- dest = JacValue(self, ctx=obj, name=name, value=result)
1647
- if obj.j_type == "walker":
1648
- dest.write(kid[0], force=True)
1649
- else:
1650
- dest.write(kid[0])
1651
-
1652
- def run_filter_compare(self, jac_ast, obj):
1653
- """
1654
- filter_compare: NAME cmp_op expression;
1655
- """
1656
- kid = self.set_cur_ast(jac_ast)
1657
- name = kid[0].token_text()
1658
- if name in obj.context.keys():
1659
- self.run_expression(kid[-1])
1660
- result = self.pop()
1661
- self.run_cmp_op(kid[1], JacValue(self, ctx=obj, name=name), result)
1662
- return self.pop().value
1663
- else:
1664
- self.rt_error(f"{name} not present in object", kid[0])
1665
-
1666
- def run_any_type(self, jac_ast):
1667
- """
1668
- any_type:
1669
- TYP_STRING
1670
- | TYP_INT
1671
- | TYP_FLOAT
1672
- | TYP_LIST
1673
- | TYP_DICT
1674
- | TYP_BOOL
1675
- | KW_NODE
1676
- | KW_EDGE
1677
- | KW_TYPE;
1678
- """
1679
- if self.attempt_bytecode(jac_ast):
1680
- return
1681
- kid = self.set_cur_ast(jac_ast)
1682
- if kid[0].name == "TYP_STRING":
1683
- self.push(JacValue(self, value=str))
1684
- elif kid[0].name == "TYP_INT":
1685
- self.push(JacValue(self, value=int))
1686
- elif kid[0].name == "TYP_FLOAT":
1687
- self.push(JacValue(self, value=float))
1688
- elif kid[0].name == "TYP_LIST":
1689
- self.push(JacValue(self, value=list))
1690
- elif kid[0].name == "TYP_DICT":
1691
- self.push(JacValue(self, value=dict))
1692
- elif kid[0].name == "TYP_BOOL":
1693
- self.push(JacValue(self, value=bool))
1694
- elif kid[0].name == "KW_NODE":
1695
- self.push(JacValue(self, value=Node))
1696
- elif kid[0].name == "KW_EDGE":
1697
- self.push(JacValue(self, value=Edge))
1698
- elif kid[0].name == "KW_TYPE":
1699
- self.push(JacValue(self, value=type))
1700
- else:
1701
- self.rt_error("Unrecognized type", kid[0])
1702
-
1703
- def run_multistring(self, jac_ast):
1704
- """
1705
- multistring: STRING+;
1706
- """
1707
- if self.attempt_bytecode(jac_ast):
1708
- return
1709
- kid = self.set_cur_ast(jac_ast)
1710
- ret = ""
1711
- for i in kid:
1712
- ret += parse_str_token(i.token_text())
1713
- self.push(JacValue(self, value=ret))
1714
-
1715
- def destroy(self):
1716
- """
1717
- Destroys self from memory and persistent storage
1718
- """
1719
- super().destroy()
1720
-
1721
- # Helper Functions ##################
1722
- def attempt_bytecode(self, jac_ast):
1723
- if hasattr(jac_ast, "bytecode") and jac_ast.bytecode:
1724
- self.run_bytecode(b64decode(jac_ast.bytecode.encode()))
1725
- return True
1726
- return False
1727
-
1728
- def call_ability(self, nd, name, act_list):
1729
- ability = act_list.get_obj_by_name(name)
1730
- try:
1731
- ability.j_master = self.j_master
1732
- ability._mast = self._mast
1733
- ability.run_ability(here=nd, visitor=self._jac_scope.visitor())
1734
- except Exception as e:
1735
- self.rt_error(f"Internal Exception: {e}", ability._cur_jac_ast)
1736
- self.inherit_runtime_state(ability)
1737
-
1738
- def visibility_prune(self, node_set=None):
1739
- """Returns all nodes that shouldnt be ignored"""
1740
- ret = JacSet()
1741
- if node_set is None:
1742
- node_set = self.here().attached_nodes()
1743
- for i in node_set:
1744
- if i not in self.ignore_node_ids.obj_list():
1745
- ret.add_obj(i)
1746
- return ret
1747
-
1748
- def run_rule(self, jac_ast, *args):
1749
- """Helper to run rule if exists in execution context"""
1750
- try:
1751
- val = getattr(self, f"run_{jac_ast.name}")(jac_ast, *args)
1752
- # TODO: Rewrite after stack integration
1753
- if jac_ast.name in [
1754
- "any_type",
1755
- "atom",
1756
- "arithmetic",
1757
- "term",
1758
- "factor",
1759
- "power",
1760
- "cmp_op",
1761
- "compare",
1762
- "logical",
1763
- "expression",
1764
- "assignment",
1765
- "copy_assign",
1766
- "inc_assign",
1767
- "multistring",
1768
- ]:
1769
- return self.pop()
1770
- else:
1771
- return val
1772
- # return getattr(self, f"run_{jac_ast.name}")(jac_ast, *args)
1773
- except AttributeError as e:
1774
- if not hasattr(self, f"run_{jac_ast.name}"):
1775
- self.rt_error(
1776
- f"This scope cannot execute the statement "
1777
- f'"{jac_ast.get_text()}" of type {jac_ast.name}',
1778
- jac_ast,
1779
- )
1780
- else:
1781
- self.rt_error(e, jac_ast)
1782
- return
1783
- except Exception as e:
1784
- self.rt_error(e, jac_ast)