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