Coverage for skema/program_analysis/CAST2FN/ann_cast/annotated_cast.py: 66%
540 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-30 17:15 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-30 17:15 +0000
1import typing
2import difflib
4from skema.program_analysis.CAST2FN.model.cast import (
5 AstNode,
6 Assignment,
7 Attribute,
8 Call,
9 CASTLiteralValue,
10 FunctionDef,
11 Goto,
12 Label,
13 Loop,
14 ModelBreak,
15 ModelContinue,
16 ModelIf,
17 ModelReturn,
18 Module,
19 Name,
20 Operator,
21 RecordDef,
22 Var,
23)
25from skema.model_assembly.networks import GroundedFunctionNetwork, VariableNode
26from skema.program_analysis.CAST2FN.model.cast.model_import import (
27 ModelImport,
28)
31class PipelineState:
32 def __init__(self, ann_nodes: typing.List, grfn2_2: bool):
33 self.GENERATE_GRFN_2_2 = grfn2_2
34 self.PRINT_DEBUGGING_INFO = False
35 self.nodes = ann_nodes
36 # populated after IdCollapsePass, and used to give ids to GrFN condition variables
37 self.collapsed_id_counter = 0
38 # dict mapping FunctionDef container scopestr to its id
39 self.func_con_scopestr_to_id = {}
40 # dict mapping container scope strings to their nodes
41 self.con_scopestr_to_node = {}
42 # dict mapping function IDs to their FunctionDef nodes.
43 self.func_id_to_def = {}
44 self.grfn_id_to_grfn_var = {}
45 # the fullid of a AnnCastName node is a string which includes its
46 # variable name, numerical id, version, and scope
47 self.fullid_to_grfn_id = {}
48 # `module_node` is simply a reference to the AnnCastModule node
49 # FUTURE: to handle multiple modules for Python this will need to be extended
50 # for the most part, the module node is used to determine globals
51 self.module_node = None
52 # GrFN stored after ToGrfnPass
53 self.grfn: typing.Optional[GroundedFunctionNetwork] = None
55 # flag deciding whether or not to use GE's interpretation of From Source
56 # when populating metadata information
57 #
58 # For GE, all instances of a variable which exists in the source code should
59 # be considered from source.
60 # We think this loses information about the GrFN variables we create to facilitate
61 # transition between interfaces. That is, we create many GrFN variables which
62 # do not literally exist in source, and so don't consider those to be from source
63 self.FROM_SOURCE_FOR_GE = True
65 self.gromet_collection = None
67 def get_nodes(self):
68 return self.nodes
70 def is_var_local_to_func(self, scopestr: str, id: int):
71 """
72 Precondition: scopestr is the scopestr of a FunctionDef
73 Check if the variable with id `id` is neither a global nor a formal parameter
74 """
75 if self.is_global_var(id):
76 return False
78 func_def_node = self.func_def_node_from_scopestr(scopestr)
79 for param in func_def_node.func_args:
80 if id == param.val.id:
81 return False
83 return True
85 def is_container(self, scopestr: str):
86 """
87 Check if scopestr is a container scopestr
88 """
89 return scopestr in self.con_scopestr_to_node
91 def con_node_from_scopestr(self, scopestr: str):
92 """
93 Precondition: scopestr is a container scopestr
94 Return the container node associated with scopestr
95 """
96 return self.con_scopestr_to_node[scopestr]
98 def get_grfn(self) -> typing.Optional[GroundedFunctionNetwork]:
99 return self.grfn
101 def func_def_exists(self, id: int) -> bool:
102 """
103 Check if there is a FuncionDef for id
104 """
105 return id in self.func_id_to_def
107 def is_con_scopestr_func_def(self, con_scopestr: str):
108 return con_scopestr in self.func_con_scopestr_to_id
110 def func_def_node_from_scopestr(self, con_scopestr: str):
111 """
112 Return the AnnCastFuncitonDef node for the container scope
113 defined by `con_scopestr`
114 """
115 function_id = self.func_con_scopestr_to_id[con_scopestr]
116 return self.func_id_to_def[function_id]
118 def func_def_node_from_id(self, id: int):
119 """
120 Return the FunctionDef for `id`
121 """
122 assert self.func_def_exists(id)
123 return self.func_id_to_def[id]
125 def is_global_var(self, id: int):
126 """
127 Check if id is in the used_variables attribute of the module node
128 """
129 return id in self.module_node.used_vars
131 def all_globals_dict(self):
132 """
133 Return a dict mapping id to string name for all global variables
134 """
135 return self.module_node.used_vars
137 def next_collapsed_id(self):
138 """
139 Return the next collapsed id, and increment `collapsed_id_counter`
140 """
141 to_return = self.collapsed_id_counter
142 self.collapsed_id_counter += 1
143 return to_return
145 def store_grfn_var(self, fullid: str, grfn_var: VariableNode):
146 """
147 Cache `grfn_var` in `grfn_id_to_grfn_var` and add `fullid` to `fullid_to_grfn_id`
148 """
149 self.fullid_to_grfn_id[fullid] = grfn_var.uid
150 self.grfn_id_to_grfn_var[grfn_var.uid] = grfn_var
152 def grfn_var_exists(self, fullid: str):
153 """
154 Returns the whether the GrFN VariableNode associated with `fullid` has already been created
155 """
156 return fullid in self.fullid_to_grfn_id
158 def get_grfn_var(self, fullid: str):
159 """
160 Returns the cached GrFN VariableNode associated with `fullid`
161 """
162 grfn_id = self.fullid_to_grfn_id[fullid]
163 return self.grfn_id_to_grfn_var[grfn_id]
165 def alias_grfn_vars(self, src_fullid: str, tgt_fullid: str):
166 """
167 Put the GrFN id associated with `tgt_fullid` into dict `fullid_to_grfn_id` for key
168 `src_fullid`
169 """
170 self.fullid_to_grfn_id[src_fullid] = self.fullid_to_grfn_id[tgt_fullid]
172 def equiv(self, other):
173 """
174 Check if the PipelineState nodes are equivalent to other's
175 Used in the test suite
176 """
177 # FUTURE: once the PiplelineState nodes attribute stores multiple modules,
178 # we may need to check that the ordering is consistent. Currently,
179 # CAST and the AnnnotatedCast nodes only have a single module, so this is not a concern
180 for i, node in enumerate(self.nodes):
181 if not node.equiv(other.nodes[i]):
182 # printing diff to help locating difference
183 # because we do not overwrite the __str__() methods,
184 # this has limited usefullness, but its better than nothing
185 print(f"AnnCast equiv failed:")
186 self_lines = str(node).splitlines()
187 other_lines = str(other.nodes[i]).splitlines()
188 for i, diff in enumerate(
189 difflib.ndiff(self_lines, other_lines)
190 ):
191 if diff[0] == " ":
192 continue
193 print(f"Line {i}: {diff}")
195 return False
197 return True
200class AnnCastNode(AstNode):
201 def __init__(self, *args, **kwargs):
202 super().__init__(self)
203 self.expr_str: str = ""
205 def to_dict(self):
206 result = super().to_dict()
207 result["expr_str"] = self.expr_str
208 return result
210 def equiv(self, other):
211 if not isinstance(other, AnnCastNode):
212 return False
213 return self.to_dict() == other.to_dict()
216class AnnCastAssignment(AnnCastNode):
217 def __init__(self, left, right, source_refs):
218 super().__init__(self)
219 self.left = left
220 self.right = right
221 self.source_refs = source_refs
223 self.grfn_assignment: GrfnAssignment
225 def to_dict(self):
226 result = super().to_dict()
227 result["left"] = self.left.to_dict()
228 result["right"] = self.right.to_dict()
229 return result
231 def equiv(self, other):
232 if not isinstance(other, AnnCastAssignment):
233 return False
234 return self.to_dict() == other.to_dict()
236 def __str__(self):
237 return Assignment.__str__(self)
240class AnnCastAttribute(AnnCastNode):
241 def __init__(self, value, attr, source_refs):
242 super().__init__(self)
243 self.value = value
244 self.attr = attr
245 self.source_refs = source_refs
247 def to_dict(self):
248 result = super().to_dict()
249 # FUTURE: add value and attr to result
250 return result
252 def equiv(self, other):
253 if not isinstance(other, AnnCastAttribute):
254 return False
255 return self.to_dict() == other.to_dict()
257 def __str__(self):
258 return Attribute.__str__(self)
261class AnnCastCall(AnnCastNode):
262 def __init__(self, func, arguments, source_refs):
263 super().__init__(self)
264 self.func: AnnCastName = func
265 self.arguments = arguments
266 self.source_refs = source_refs
268 # the index of this Call node over all invocations of this function
269 self.invocation_index: int
271 # dicts mapping a Name id to its fullid
272 self.top_interface_in = {}
273 self.top_interface_out = {}
274 self.bot_interface_in = {}
275 self.bot_interface_out = {}
276 # dicts mapping Name id to Name string
277 self.top_interface_vars = {}
278 self.bot_interface_vars = {}
279 # GrFN lambda expressions
280 self.top_interface_lambda: str
281 self.bot_interface_lambda: str
283 # for top_interface_out
284 # mapping Name id to fullid
285 # to determine this, we check if we store version 0 on any Name node
286 self.globals_accessed_before_mod = {}
287 self.used_globals = {}
289 # for bot_interface
290 # map Name id to fullid
291 self.in_ret_val = {}
292 self.out_ret_val = {}
294 # if this is a GrFN 2.2 Call, we will copy the associated FunctionDef
295 # to make the GrFN 2.2 container
296 self.is_grfn_2_2: bool = False
297 # copied function def for GrFN 2.2
298 self.func_def_copy: typing.Optional[AnnCastFunctionDef] = None
300 # keep track of whether the Call has an associated FunctionDef
301 # and if the Call should return a value
302 self.has_func_def: bool = False
303 self.has_ret_val: bool = False
305 # dict mapping argument index to created argument fullid
306 self.arg_index_to_fullid = {}
307 self.param_index_to_fullid = {}
308 # this dict maps argument positional index to GrfnAssignment's
309 # Each GrfnAssignment stores the ASSIGN/LITERAL node,
310 # the inputs to the ASSIGN/LITERAL node, and the outputs to the ASSIGN/LITERAL node
311 # In this case, the output will map the arguments fullid to its grfn_id
312 self.arg_assignments: typing.Dict[int, GrfnAssignment] = {}
314 # metadata attributes
315 self.grfn_con_src_ref: GrfnContainerSrcRef
317 def to_dict(self):
318 result = super().to_dict()
319 result["func"] = self.func.to_dict()
320 result["arguments"] = [arg.to_dict() for arg in self.arguments]
321 return result
323 def equiv(self, other):
324 if not isinstance(other, AnnCastCall):
325 return False
326 return self.to_dict() == other.to_dict()
328 def __str__(self):
329 return Call.__str__(self)
331class AnnCastFunctionDef(AnnCastNode):
332 def __init__(self, name, func_args, body, source_refs):
333 super().__init__(self)
334 self.name = name
335 self.func_args = func_args
336 self.body = body
337 self.source_refs = source_refs
339 self.con_scope: typing.List
341 # For CAST coming from C, we determine if the function
342 # has a return value by looking for a CAST Return node.
343 # We do this during the ContainerScopePass.
344 # FUTURE: What should be done with CAST coming from Python?
345 # In Python, every function returns something,
346 # either None or the explicit return value
347 self.has_ret_val: bool = False
348 # for bot_interface
349 # in_ret_val and out_ret_val map Name id to fullid
350 self.in_ret_val = {}
351 self.out_ret_val = {}
353 # dicts mapping a Name id to its string name
354 # used for container interfaces
355 self.modified_vars: typing.Dict[int, str]
356 self.vars_accessed_before_mod: typing.Dict[int, str]
357 self.used_vars: typing.Dict[int, str]
358 # for now, top_interface_vars and bot_interface_vars only include globals
359 # since those variables cross the container boundaries
360 self.top_interface_vars: typing.Dict[int, str] = {}
361 self.bot_interface_vars: typing.Dict[int, str] = {}
362 # dicts for global variables
363 # for top_interface_out
364 # mapping Name id to fullid
365 # to determine this, we check if we store version 0 on any Name node
366 self.globals_accessed_before_mod = {}
367 self.used_globals = {}
368 # for bot interface in
369 self.modified_globals = {}
371 # dict mapping argument index to created argument fullid
372 self.arg_index_to_fullid = {}
373 self.param_index_to_fullid = {}
375 # dicts mapping a Name id to its fullid
376 self.top_interface_in = {}
377 self.top_interface_out = {}
378 self.bot_interface_in = {}
379 self.bot_interface_out = {}
380 # GrFN lambda expressions
381 self.top_interface_lambda: str
382 self.bot_interface_lambda: str
384 # dict mapping Name id to highest version at end of "block"
385 self.body_highest_var_vers = {}
387 # metadata attributes
388 self.grfn_con_src_ref: GrfnContainerSrcRef
390 # dummy assignments to handle Python dynamic variable creation
391 self.dummy_grfn_assignments = []
393 def to_dict(self):
394 result = super().to_dict()
395 result["name"] = self.name.to_dict()
396 result["func_args"] = [arg.to_dict() for arg in self.func_args]
397 result["body"] = [node.to_dict() for node in self.body]
398 result["con_scope"] = self.con_scope
399 result["has_ret_val"] = self.has_ret_val
400 # FUTURE: add attributes to enhance test coverage
401 return result
403 def equiv(self, other):
404 if not isinstance(other, AnnCastFunctionDef):
405 return False
406 return self.to_dict() == other.to_dict()
408 def __str__(self):
409 return FunctionDef.__str__(self)
411class AnnCastRecordDef(AnnCastNode):
412 def __init__(self, name, bases, funcs, fields, source_refs):
413 super().__init__(self)
414 self.name = name
415 self.bases = bases
416 self.funcs = funcs
417 self.fields = fields
418 self.source_refs = source_refs
420 def to_dict(self):
421 result = super().to_dict()
422 # FUTURE: add attributes to result
423 return result
425 def equiv(self, other):
426 if not isinstance(other, AnnCastRecordDef):
427 return False
428 return self.to_dict() == other.to_dict()
430 def __str__(self):
431 return RecordDef.__str__(self)
434class AnnCastLiteralValue(AnnCastNode):
435 def __init__(self, value_type, value, source_code_data_type, source_refs):
436 super().__init__(self)
437 self.value_type = value_type
438 self.value = value
439 self.source_code_data_type = source_code_data_type
440 self.source_refs = source_refs
442 def to_dict(self):
443 result = super().to_dict()
444 return result
446 def equiv(self, other):
447 if not isinstance(other, AnnCastLiteralValue):
448 return False
449 return self.to_dict() == other.to_dict()
451 def __str__(self):
452 return CASTLiteralValue.__str__(self)
455class AnnCastLoop(AnnCastNode):
456 def __init__(self, pre, expr, body, post, source_refs):
457 super().__init__(self)
458 self.pre = pre
459 self.expr = expr
460 self.body = body
461 self.post = post
462 self.source_refs = source_refs
464 # Loop container scope
465 self.con_scope: typing.List
466 # Function scopestr this Loop node is "living" in
467 self.base_func_scopestr: str = ""
469 # dicts mapping a Name id to its string name
470 # used for container interfaces
471 self.modified_vars: typing.Dict[int, str]
472 self.vars_accessed_before_mod: typing.Dict[int, str]
473 self.used_vars: typing.Dict[int, str]
474 self.top_interface_vars: typing.Dict[int, str] = {}
475 self.top_interface_updated_vars: typing.Dict[int, str] = {}
476 self.bot_interface_vars: typing.Dict[int, str] = {}
478 # dicts mapping Name id to highest version at end of "block"
479 self.pre_highest_var_vers = {}
480 self.expr_highest_var_vers = {}
481 self.body_highest_var_vers = {}
482 self.post_highest_var_vers = {}
484 # dicts mapping a Name id to variable string name
485 # for variables used in the Loop expr
486 self.expr_vars_accessed_before_mod = {}
487 self.expr_modified_vars = {}
488 self.expr_used_vars = {}
490 # dicts mapping a Name id to its fullid
491 # initial versions for the top interface come from enclosing scope
492 # updated versions for the top interface are versions
493 # at the bottom of the loop after one or more executions of the loop
494 self.top_interface_initial = {}
495 self.top_interface_updated = {}
496 self.top_interface_out = {}
497 self.bot_interface_in = {}
498 self.bot_interface_out = {}
499 self.condition_in = {}
500 self.condition_out = {}
501 # GrFN VariableNode for the condition node
502 self.condition_var = None
504 # GrFN lambda expressions
505 self.top_interface_lambda: str
506 self.bot_interface_lambda: str
507 self.condition_lambda: str
508 # metadata attributes
509 self.grfn_con_src_ref: GrfnContainerSrcRef
511 def to_dict(self):
512 result = super().to_dict()
513 # result["init"] = [node.to_dict() for node in self.init]
514 result["expr"] = self.expr.to_dict()
515 result["body"] = [node.to_dict() for node in self.body]
516 result["con_scope"] = self.con_scope
517 result["base_func_scopestr"] = self.base_func_scopestr
518 # FUTURE: add attributes to enhance test coverage
519 return result
521 def equiv(self, other):
522 if not isinstance(other, AnnCastLoop):
523 return False
524 return self.to_dict() == other.to_dict()
526 def __str__(self):
527 return Loop.__str__(self)
529class AnnCastGoto(AnnCastNode):
530 def __init__(self, expr, label, source_refs):
531 super().__init__(self)
532 self.expr = expr
533 self.label = label
534 self.source_refs = source_refs
536 def to_dict(self):
537 result = super().to_dict()
538 result["expr"] = self.expr.to_dict() if self.expr != None else ""
539 result["label"] = self.label
540 return result
542 def equiv(self, other):
543 if not isinstance(other, AnnCastGoto):
544 return False
545 return self.to_dict() == other.to_dict()
547 def __str__(self):
548 return Goto.__str__(self)
550class AnnCastLabel(AnnCastNode):
551 def __init__(self, label, source_refs):
552 super().__init__(self)
553 self.label = label
554 self.source_refs = source_refs
556 def to_dict(self):
557 result = super().to_dict()
558 result["label"] = self.label
559 return result
561 def equiv(self, other):
562 if not isinstance(other, AnnCastLabel):
563 return False
564 return self.to_dict() == other.to_dict()
566 def __str__(self):
567 return Label.__str__(self)
569class AnnCastModelBreak(AnnCastNode):
570 def __init__(self, source_refs):
571 super().__init__(self)
572 self.source_refs = source_refs
574 def to_dict(self):
575 result = super().to_dict()
576 return result
578 def equiv(self, other):
579 if not isinstance(other, AnnCastModelBreak):
580 return False
581 return self.to_dict() == other.to_dict()
583 def __str__(self):
584 return ModelBreak.__str__(self)
587class AnnCastModelContinue(AnnCastNode):
588 def __init__(self, node: ModelContinue):
589 super().__init__(self)
590 self.source_refs = node.source_refs
592 def to_dict(self):
593 result = super().to_dict()
594 return result
596 def equiv(self, other):
597 if not isinstance(other, AnnCastModelContinue):
598 return False
599 return self.to_dict() == other.to_dict()
601 def __str__(self):
602 return ModelContinue.__str__(self)
605class AnnCastModelImport(AnnCastNode):
606 def __init__(self, node: ModelImport):
607 super().__init__(self)
608 self.name = node.name
609 self.alias = node.alias
610 self.symbol = node.symbol
611 self.all = node.all
612 self.source_refs = node.source_refs
614 def to_dict(self):
615 result = super().to_dict()
616 return result
618 def equiv(self, other):
619 if not isinstance(other, AnnCastModelImport):
620 return False
621 return self.to_dict() == other.to_dict()
623 def __str__(self):
624 return ModelImport.__str__(self)
627class AnnCastModelIf(AnnCastNode):
628 def __init__(self, expr, body, orelse, source_refs):
629 super().__init__(self)
630 self.expr = expr
631 self.body = body
632 self.orelse = orelse
633 self.source_refs = source_refs
635 # ModelIf container scope
636 self.con_scope: typing.List
637 # Function scopestr this ModelIf node is "living" in
638 self.base_func_scopestr: str = ""
640 # dicts mapping a Name id to string name
641 # used for container interfaces
642 self.modified_vars: typing.Dict[int, str]
643 self.vars_accessed_before_mod: typing.Dict[int, str]
644 self.used_vars: typing.Dict[int, str]
645 self.top_interface_vars: typing.Dict[int, str] = {}
646 self.bot_interface_vars: typing.Dict[int, str] = {}
647 # dicts mapping a Name id to variable string name
648 # for variables used in the if expr
649 self.expr_vars_accessed_before_mod = {}
650 self.expr_modified_vars = {}
651 self.expr_used_vars = {}
652 # dicts mapping Name id to highest version at end of "block"
653 self.expr_highest_var_vers = {}
654 self.ifbody_highest_var_vers = {}
655 self.elsebody_highest_var_vers = {}
657 # dicts mapping a Name id to its fullid
658 self.top_interface_in = {}
659 self.top_interface_out = {}
660 self.bot_interface_in = {}
661 self.bot_interface_out = {}
662 self.condition_in = {}
663 self.condition_out = {}
664 self.decision_in = {}
665 self.decision_out = {}
666 # GrFN VariableNode for the condition node
667 self.condition_var = None
669 # GrFN lambda expressions
670 self.top_interface_lambda: str
671 self.bot_interface_lambda: str
672 self.condition_lambda: str
673 self.decision_lambda: str
675 # metadata attributes
676 self.grfn_con_src_ref: GrfnContainerSrcRef
678 def to_dict(self):
679 result = super().to_dict()
680 result["expr"] = self.expr.to_dict()
681 result["body"] = [node.to_dict() for node in self.body]
682 result["orelse"] = [node.to_dict() for node in self.orelse]
683 result["con_scope"] = self.con_scope
684 result["base_func_scopestr"] = self.base_func_scopestr
685 # FUTURE: add attributes to enhance test coverage
686 return result
688 def equiv(self, other):
689 if not isinstance(other, AnnCastModelIf):
690 return False
691 return self.to_dict() == other.to_dict()
693 def __str__(self):
694 return ModelIf.__str__(self)
697class AnnCastModelReturn(AnnCastNode):
698 def __init__(self, value, source_refs):
699 super().__init__(self)
700 self.value = value
701 self.source_refs = source_refs
702 # cache the FunctionDef node that this return statement lies in
703 self.owning_func_def: typing.Optional[AnnCastFunctionDef] = None
704 # store GrfnAssignment for use in GrFN generation
705 self.grfn_assignment: typing.Optional[GrfnAssignment] = None
707 def to_dict(self):
708 result = super().to_dict()
709 result["value"] = self.value.to_dict()
710 return result
712 def equiv(self, other):
713 if not isinstance(other, AnnCastModelReturn):
714 return False
715 return self.to_dict() == other.to_dict()
717 def __str__(self):
718 return ModelReturn.__str__(self)
721class AnnCastModule(AnnCastNode):
722 def __init__(self, name, body, source_refs):
723 super().__init__(self)
724 self.name = name
725 self.body = body
726 self.source_refs = source_refs
728 # dicts mapping a Name id to string name
729 # used for container interfaces
730 self.modified_vars: typing.Dict[int, str] = {}
731 self.vars_accessed_before_mod: typing.Dict[int, str] = {}
732 self.used_vars: typing.Dict[int, str] = {}
733 self.con_scope: typing.List
735 # metadata attributes
736 self.grfn_con_src_ref: GrfnContainerSrcRef
738 def to_dict(self):
739 result = super().to_dict()
740 result["name"] = str(self.name)
741 result["body"] = [node.to_dict() for node in self.body]
742 result["con_scope"] = self.con_scope
743 # FUTURE: add attributes to enhance test coverage
744 return result
746 def equiv(self, other):
747 if not isinstance(other, AnnCastModule):
748 return False
749 return self.to_dict() == other.to_dict()
751 def __str__(self):
752 return Module.__str__(self)
755class AnnCastName(AnnCastNode):
756 def __init__(self, name, id, source_refs):
757 super().__init__(self)
758 self.name = name
759 self.id = id
760 self.source_refs = source_refs
761 # container_scope is used to aid GrFN generation
762 self.con_scope: typing.List = []
763 # Function scopestr this Name node is "living" in
764 self.base_func_scopestr: str = ""
765 # versions are bound to the cope of the variable
766 self.version = None
767 self.grfn_id = None
769 def to_dict(self):
770 result = super().to_dict()
771 result["name"] = self.name
772 result["id"] = self.id
773 result["version"] = self.version
774 result["con_scope"] = self.con_scope
775 return result
777 def equiv(self, other):
778 if not isinstance(other, AnnCastName):
779 return False
780 return self.to_dict() == other.to_dict()
782 def __str__(self):
783 return Name.__str__(self)
785class AnnCastOperator(AnnCastNode):
786 def __init__(self, source_language, interpreter, version, op, operands, source_refs):
787 super().__init__(self)
788 self.source_language = source_language
789 self.interpreter = interpreter
790 self.version = version
791 self.op = op
792 self.operands = operands
793 self.source_refs = source_refs
795 def to_dict(self):
796 result = super().to_dict()
797 result["source_language"] = str(self.source_language)
798 result["interpreter"] = str(self.interpreter)
799 result["version"] = str(self.version)
800 result["op"] = str(self.op)
801 result["operands"] = [operand.to_dict() for operand in self.operands]
802 return result
804 def equiv(self, other):
805 if not isinstance(other, AnnCastOperator):
806 return False
807 return self.to_dict() == other.to_dict()
809 def __str__(self):
810 return Operator.__str__(self)
813class AnnCastSet(AnnCastNode):
814 def __init__(self, values, source_refs):
815 super().__init__(self)
816 self.values = values
817 self.source_refs = source_refs
819 def to_dict(self):
820 result = super().to_dict()
821 # FUTURE: add values to result
822 return result
824 def equiv(self, other):
825 if not isinstance(other, AnnCastSet):
826 return False
827 return self.to_dict() == other.to_dict()
829 def __str__(self):
830 return Set.__str__(self)
833class AnnCastTuple(AnnCastNode):
834 def __init__(self, values, source_refs):
835 super().__init__(self)
836 self.values = values
837 self.source_refs = source_refs
839 def to_dict(self):
840 result = super().to_dict()
841 # FUTURE: add values to result
842 return result
844 def equiv(self, other):
845 if not isinstance(other, AnnCastTuple):
846 return False
847 return self.to_dict() == other.to_dict()
849 def __str__(self):
850 return Tuple.__str__(self)
853class AnnCastVar(AnnCastNode):
854 def __init__(self, val, type, default_value, source_refs):
855 super().__init__(self)
856 self.val = val
857 self.type = type
858 self.default_value = default_value
859 self.source_refs = source_refs
861 def to_dict(self):
862 result = super().to_dict()
863 result["val"] = self.val.to_dict()
864 result["type"] = str(self.type)
865 result["default_value"] = str(self.default_value)
866 return result
868 def equiv(self, other):
869 if not isinstance(other, AnnCastVar):
870 return False
871 return self.to_dict() == other.to_dict()
873 def __str__(self):
874 return Var.__str__(self)