Coverage for skema/gromet/primitive_map.py: 0%
709 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
1from typing import Iterator, Union, Tuple, Dict, List, Set, Any
2from dataclasses import dataclass
3import numpy
5import sys
6import inspect
9@dataclass(frozen=True)
10class Field:
11 name: str
12 type: str
13 variatic: bool = False
16@dataclass
17class RecordField:
18 name: str
19 value_type: type
20 value: Any
23@dataclass
24class Record(object):
25 name: str
26 fields: "list[RecordField]"
29class UAdd(object):
30 source_language_name = {"Python": "UAdd", "CAST": "UAdd"}
31 inputs = [Field("operand", "Number")]
32 outputs = [Field("result", "Number")]
33 shorthand = "u+"
34 documentation = ""
36 def exec(
37 operand: Union[int, float, complex]
38 ) -> Union[int, float, complex]:
39 return +operand
42class USub(object):
43 source_language_name = {"Python": "USub", "CAST": "USub"}
44 inputs = [Field("operand", "Number")]
45 outputs = [Field("result", "Number")]
46 shorthand = "u-"
47 documentation = ""
49 def exec(
50 operand: Union[int, float, complex]
51 ) -> Union[int, float, complex]:
52 return -operand
55class Not(object):
56 source_language_name = {"Python": "Not", "CAST": "Not"}
57 inputs = [Field("operand", "Boolean")]
58 outputs = [Field("result", "Boolean")]
59 shorthand = "not"
60 documentation = ""
62 def exec(operand: bool) -> bool:
63 return not operand
66class Invert(object):
67 source_language_name = {"Python": "Invert", "CAST": "Invert"}
68 inputs = [Field("operand", "Number")]
69 outputs = [Field("result", "Number")]
70 shorthand = "~"
71 documentation = ""
73 def exec(
74 operand: Union[int, float, complex]
75 ) -> Union[int, float, complex]:
76 return ~operand
79class Add(object):
80 source_language_name = {"Python": "Add", "GCC": "plus_expr", "CAST": "Add"}
81 inputs = [Field("augend", "Number"), Field("addend", "Number")]
82 outputs = [Field("sum", "Number")]
83 shorthand = "+"
84 documentation = "Add is the numerical addition operator. For a general addition operation (For example, the case of concatanation with +) see GenAdd."
86 @staticmethod # TODO: Look into if this is required. Only need @staticmethod if you intend to call the method from an instance of class
87 def exec(
88 augend: Union[int, float, complex], addend: Union[int, float, complex]
89 ) -> Union[int, float, complex]:
90 return augend + addend
93class GenAdd(object):
94 source_language_name = {"Python": "Add"}
95 inputs = [Field("operand1", "Any"), Field("operand2", "Any")]
96 outputs = [Field("result", "Any")]
97 shorthand = "g+"
98 documentation = ""
100 def exec(operand1: Any, operand2: Any) -> Any:
101 return operand1 + operand2
104class Sub(object):
105 source_language_name = {
106 "Python": "Sub",
107 "GCC": "minus_expr",
108 "CAST": "Sub",
109 }
110 inputs = [Field("minuend", "Number"), Field("subtrahend", "Number")]
111 outputs = [Field("difference", "Number")]
112 shorthand = "-"
113 documentation = "Sub is the numerical subtraction operator. For a general subtraction operation () see GenSub."
115 def exec(
116 minuend: Union[int, float, complex],
117 subtahend: Union[int, float, complex],
118 ) -> Union[int, float, complex]:
119 return minuend - subtahend
122class GenSub(object):
123 source_language_name = {"Python": "Sub"}
124 inputs = [Field("operand1", "Any"), Field("operand2", "Any")]
125 outputs = [Field("result", "Any")]
126 shorthand = "g-"
127 documentation = ""
129 def exec(operand1: Any, operand2: Any) -> Any:
130 return operand1 - operand2
133class Mult(object):
134 source_language_name = {
135 "Python": "Mult",
136 "GCC": "mult_expr",
137 "CAST": "Mult",
138 }
139 inputs = [Field("multiplier", "Number"), Field("multiplicand", "Number")]
140 outputs = [Field("product", "Number")]
141 shorthand = "*"
142 documentation = ""
144 def exec(
145 multiplier: Union[int, float, complex],
146 multiplicand: Union[int, float, complex],
147 ) -> Union[int, float, complex]:
148 return multiplier * multiplicand
151# TODO: Do we need a general operator for all overloadable operators in Python (https://www.programiz.com/python-programming/operator-overloading)?
154class Div(object):
155 source_language_name = {"Python": "Div", "GCC": "rdiv_expr", "CAST": "Div"}
156 inputs = [Field("dividend", "Number"), Field("divisor", "Number")]
157 outputs = [Field("quotient", "Number")]
158 shorthand = "/"
159 documentation = ""
161 def exec(
162 dividend: Union[int, float, complex],
163 divisor: Union[int, float, complex],
164 ) -> Union[int, float, complex]:
165 return dividend / divisor
168class FloorDiv(object):
169 source_language_name = {"Python": "FloorDiv", "CAST": "FloorDiv"}
170 inputs = [Field("dividend", "Number"), Field("divisor", "Number")]
171 outputs = [Field("quotient", "Number")]
172 shorthand = "//"
173 documentation = ""
175 def exec(
176 dividend: Union[int, float, complex],
177 divisor: Union[int, float, complex],
178 ) -> Union[int, float, complex]:
179 return dividend // divisor
182class Mod(object):
183 source_language_name = {
184 "Python": "Mod",
185 "GCC": "trunc_mod_expr",
186 "CAST": "Mod",
187 }
188 inputs = [Field("dividend", "Number"), Field("divisor", "Number")]
189 outputs = [Field("remainder", "Number")]
190 shorthand = "%"
191 documentation = ""
193 def exec(
194 dividend: Union[int, float, complex],
195 divisor: Union[int, float, complex],
196 ) -> Union[int, float, complex]:
197 return dividend % divisor
200class Pow(object):
201 source_language_name = {"Python": "Pow", "CAST": "Pow"}
202 inputs = [Field("base", "Number"), Field("exponent", "Number")]
203 outputs = [Field("power", "Number")]
204 shorthand = "**"
205 documentation = ""
207 def exec(
208 base: Union[int, float, complex], power: Union[int, float, complex]
209 ) -> Union[int, float, complex]:
210 return base**power
213class LShift(object):
214 source_language_name = {
215 "Python": "LShift",
216 "GCC": "lshift_expr",
217 "CAST": "LShift",
218 }
219 inputs = [Field("operand1", "Number"), Field("operand2", "Number")]
220 outputs = [Field("result", "Number")]
221 shorthand = "<<"
222 documentation = ""
224 def exec(
225 operand1: Union[int, float, complex],
226 operand2: Union[int, float, complex],
227 ) -> Union[int, float, complex]:
228 return operand1 << operand2
231class RShift(object):
232 source_language_name = {
233 "Python": "RShift",
234 "GCC": "rshift_expr",
235 "CAST": "RShift",
236 }
237 inputs = [Field("operand1", "Number"), Field("operand2", "Number")]
238 outputs = [Field("result", "Number")]
239 shorthand = ">>"
240 documentation = ""
242 def exec(
243 operand1: Union[int, float, complex],
244 operand2: Union[int, float, complex],
245 ) -> Union[int, float, complex]:
246 return operand1 >> operand2
249class BitOr(object):
250 source_language_name = {
251 "Python": "BitOr",
252 "GCC": "bit_ior_expr",
253 "CAST": "BitOr",
254 }
255 inputs = [Field("binary1", "Number"), Field("binary2", "Number")]
256 outputs = [Field("result", "Number")]
257 shorthand = "|"
258 documentation = ""
260 def exec(
261 binary1: Union[int, float, complex],
262 binary2: Union[int, float, complex],
263 ) -> Union[int, float, complex]:
264 return binary1 | binary2
267class BitXor(object):
268 source_language_name = {
269 "Python": "BitXor",
270 "GCC": "bit_xor_expr",
271 "CAST": "BitXor",
272 }
273 inputs = [Field("binary1", "Number"), Field("binary2", "Number")]
274 outputs = [Field("result", "Number")]
275 shorthand = "^"
276 documentation = ""
278 def exec(
279 binary1: Union[int, float, complex],
280 binary2: Union[int, float, complex],
281 ) -> Union[int, float, complex]:
282 return binary1 ^ binary2
285class BitAnd(object):
286 source_language_name = {
287 "Python": "BitAnd",
288 "GCC": "bit_and_expr",
289 "CAST": "BitAnd",
290 }
291 inputs = [Field("binary1", "Number"), Field("binary2", "Number")]
292 outputs = [Field("result", "Number")]
293 shorthand = "&"
294 documentation = ""
296 def exec(
297 binary1: Union[int, float, complex],
298 binary2: Union[int, float, complex],
299 ) -> Union[int, float, complex]:
300 return binary1 & binary2
303class And(object):
304 source_language_name = {
305 "Python": "And",
306 "GCC": "logical_and",
307 "CAST": "And",
308 }
309 inputs = [Field("logical1", "Boolean"), Field("logical2", "Boolean")]
310 outputs = [Field("result", "Boolean")]
311 shorthand = "and"
312 documentation = ""
314 def exec(logical1: bool, logical2: bool) -> bool:
315 return logical1 and logical2
318class Or(object):
319 source_language_name = {"Python": "Or", "GCC": "logical_or", "CAST": "Or"}
320 inputs = [Field("logical1", "Boolean"), Field("logical2", "Boolean")]
321 outputs = [Field("result", "Boolean")]
322 shorthand = "or"
323 documentation = ""
325 def exec(logical1: bool, logical2: bool) -> bool:
326 return logical1 or logical2
329class Eq(object):
330 source_language_name = {"Python": "Eq", "GCC": "eq_expr", "CAST": "Eq"}
331 inputs = [Field("operand1", "Any"), Field("operand2", "Any")]
332 outputs = [Field("result", "Boolean")]
333 shorthand = "=="
334 documentation = ""
336 def exec(operand1: Any, operand2: Any) -> bool:
337 return operand1 == operand2
340class NotEq(object):
341 source_language_name = {
342 "Python": "NotEq",
343 "GCC": "ne_expr",
344 "CAST": "NotEq",
345 }
346 inputs = [Field("operand1", "Any"), Field("operand2", "Any")]
347 outputs = [Field("result", "Boolean")]
348 shorthand = "!="
349 documentation = ""
351 def exec(operand1: Any, operand2: Any) -> bool:
352 return operand1 != operand2
355class Lt(object):
356 source_language_name = {"Python": "Lt", "GCC": "lt_expr", "CAST": "Lt"}
357 inputs = [Field("number1", "Number"), Field("number2", "Number")]
358 outputs = [Field("result", "Boolean")]
359 shorthand = "<"
360 documentation = ""
362 def exec(
363 number1: Union[int, float, complex],
364 number2: Union[int, float, complex],
365 ) -> bool:
366 return number1 < number2
369class Lte(object):
370 source_language_name = {
371 "Python": "Lte",
372 "GCC": "le_expr",
373 "CAST": "Lte",
374 } # TODO: Is it LtE or Lte for Python and CAST
375 inputs = [Field("number1", "Number"), Field("number2", "Number")]
376 outputs = [Field("result", "Boolean")]
377 shorthand = "<="
378 documentation = ""
380 def exec(
381 number1: Union[int, float, complex],
382 number2: Union[int, float, complex],
383 ) -> bool:
384 return number1 <= number2
387class Gt(object):
388 source_language_name = {"Python": "Gt", "GCC": "gt_expr", "CAST": "Gt"}
389 inputs = [Field("number1", "Number"), Field("number2", "Number")]
390 outputs = [Field("result", "Boolean")]
391 shorthand = ">"
392 documentation = ""
394 def exec(
395 number1: Union[int, float, complex],
396 number2: Union[int, float, complex],
397 ) -> bool:
398 return number1 > number2
401class Gte(object):
402 source_language_name = {"Python": "GtE", "GCC": "ge_expr", "CAST": "Gte"}
403 inputs = [Field("number1", "Number"), Field("number2", "Number")]
404 outputs = [Field("result", "Boolean")]
405 shorthand = ">="
406 documentation = ""
408 def exec(
409 number1: Union[int, float, complex],
410 number2: Union[int, float, complex],
411 ) -> bool:
412 return number1 >= number2
415class In(
416 object
417): # TODO: How should In and NotIn work? What is the difference between in, member, List_in?
418 source_language_name = {"Python": "In", "CAST": "In"}
419 inputs = [Field("container_input", "Any"), Field("value", "Any")]
420 outputs = [Field("result", "Boolean")]
421 shorthand = "in"
422 documentation = ""
424 def exec(container_input: Any, value: Any) -> bool:
425 return value in container_input
428class NotIn(
429 object
430): # TODO: How should In and NotIn work? What is the difference between in, member, List_in?
431 source_language_name = {"Python": "NotIn", "CAST": "NotIn"}
432 inputs = [Field("container_input", "Any"), Field("value", "Any")]
433 outputs = [Field("result", "Boolean")]
434 shorthand = "not in"
435 documentation = ""
437 def exec(container_input: Any, value: Any) -> bool:
438 return value not in container_input
441class Set_new_Iterator(object):
442 source_language_name = {"Python": "Set_new_Iterator"}
443 inputs = [Field("set_input", "Set")]
444 outputs = [Field("set_iterator", "IteratorSet")]
445 shorthand = "Set_new_Iterator"
446 documentation = ""
448 def exec(set_input: set) -> Iterator[set]:
449 return iter(set_input)
452class Set_in(object):
453 source_language_name = {"Python": "Set_in"}
454 inputs = [Field("set_input", "set"), Field("value", "Any")]
455 outputs = [Field("result", "Boolean")]
456 shorthand = "Set_in"
457 documentation = ""
459 def exec(set_input: set, value: Any) -> bool:
460 return value in set_input
463class new_Set(object):
464 source_language_name = {"Python": "new_set"}
465 inputs = [Field("elements", "Any", True)]
466 outputs = [Field("set_output", "Set")]
467 shorthand = "new_Set"
468 documentation = ""
470 def exec(*elements: Any) -> set:
471 return set(elements)
474class member(object): # TODO: Still unsure the difference between this and in
475 source_language_name = {"Python": "member"}
476 inputs = [Field("set_input", "Set", True), Field("value", "Any")]
477 outputs = [Field("result", "Boolean")]
478 shorthand = "member"
479 documentation = ""
481 def exec(set_input: set, value: Any) -> set:
482 return value in set_input
485class add_elm(object):
486 source_language_name = {"Python": "add_elm"}
487 inputs = [Field("input_set", "Set"), Field("element", "Any")]
488 outputs = [Field("set_output", "Set")]
489 shorthand = "add_elm"
490 documentation = ""
492 def exec(input_set: set, element: Any) -> set:
493 return input_set.add(element)
496class del_elm(object):
497 source_language_name = {"Python": "del_elm"}
498 inputs = [Field("input_set", "Set"), Field("element", "Any")]
499 outputs = [Field("set_output", "Set")]
500 shorthand = "del_elm"
501 documentation = ""
503 def exec(input_set: set, element: Any) -> set:
504 return input_set.remove(
505 element
506 ) # TODO: Do we need to check if this exists first? Will throw KeyError if it does not
509class List_get(object):
510 source_language_name = {"Python": "List_get"} # TODO: What should this be?
511 inputs = [Field("list_input", "List"), Field("index", "Integer")]
512 outputs = [Field("item", "Any")]
513 shorthand = "List_get"
514 documentation = ""
516 def exec(list_input: list, index: int) -> Any:
517 return list_input[index]
520class List_set(object):
521 source_language_name = {"Python": "List_set"}
522 inputs = [
523 Field("list_input", "List"),
524 Field("index", "Integer"),
525 Field("value", "Any"),
526 ]
527 outputs = [Field("list_output", "List")]
528 shorthand = "List_set"
529 documentation = ""
531 def exec(list_input: list, index: int, value: Any) -> list:
532 list_input[index] = value
533 return list_input
536class List_in(object):
537 source_language_name = {"Python": "List_in"}
538 inputs = [Field("list_input", "List"), Field("value", "Any")]
539 outputs = [Field("result", "Boolean")]
540 shorthand = "List_in"
541 documentation = ""
543 def exec(list_input: list, value: Any) -> bool:
544 return value in list_input
547class List_new_Iterator(object):
548 source_language_name = {"Python": "List_new_Iterator"}
549 inputs = [Field("list_input", "List")]
550 outputs = [Field("list_iterator", "IteratorList")]
551 shorthand = "List_new_Iterator"
552 documentation = ""
554 def exec(list_input: list) -> Iterator[list]:
555 return iter(list_input)
558class new_List(object):
559 source_language_name = {"Python": "new_List"}
560 inputs = [Field("elements", "Any", True)]
561 outputs = [Field("list_output", "List")]
562 shorthand = "new_List"
563 documentation = ""
565 def exec(*elements: Any) -> list:
566 return list(
567 elements
568 ) # Interestingly when passing variable sized arguments, it is passeed as a tuple
571class new_List_num(object):
572 source_language_name = {"Python": "new_List_num"}
573 inputs = [Field("element", "Any", True), Field("count", "Integer")]
574 outputs = [Field("list_output", "List")]
575 shorthand = "new_List_num"
576 documentation = ""
578 def exec(element: Any, count: int) -> list:
579 return [element] * count
582class Array_get(
583 object
584): # TODO: Should this do type checking for each element?
585 source_language_name = {"Python": "Array_get"}
586 inputs = [Field("array_input", "Array"), Field("index", "Integer")]
587 outputs = [Field("item", "Any")]
588 shorthand = "Array_get"
589 documentation = ""
591 def exec(array_input: numpy.ndarray, index: int) -> Any:
592 return array_input[index]
595class Array_set(object):
596 source_language_name = {"Python": "Array_set"}
597 inputs = [
598 Field("array_input", "Array"),
599 Field("index", "Integer"),
600 Field("value", "Any"),
601 ]
602 outputs = [Field("array_output", "Array")]
603 shorthand = "Array_set"
604 documentation = ""
606 def exec(
607 array_input: numpy.ndarray, index: int, value: Any
608 ) -> numpy.ndarray:
609 array_input[index] = value
610 return array_input
613class Array_in(object):
614 source_language_name = {"Python": "Array_in"}
615 inputs = [Field("array_input", "Array"), Field("value", "Any")]
616 outputs = [Field("result", "Boolean")]
617 shorthand = "Array_in"
618 documentation = ""
620 def exec(array_input: numpy.ndarray, value: Any) -> bool:
621 return value in array_input
624class Array_new_Iterator(object):
625 source_language_name = {"Python": "Array_new_Iterator"}
626 inputs = [Field("array_input", "Array")]
627 outputs = [Field("array_iterator", "IteratorArray")]
628 shorthand = "Array_new_Iterator"
629 documentation = ""
631 def exec(
632 array_input: numpy.ndarray,
633 ) -> Iterator: # TODO: Numpy array is not built in type, can we still customize type hints
634 return iter(array_input)
637class new_Array(object):
638 source_language_name = {"Python": "new_Array"}
639 inputs = [Field("elements", "Any", True)]
640 outputs = [Field("array_output", "Array")]
641 shorthand = "new_Array"
642 documentation = ""
644 def exec(*elements: Any) -> numpy.ndarray:
645 return numpy.array(list(elements))
648class new_Array_num(object):
649 source_language_name = {"Python": "new_Array_num"}
650 inputs = [Field("element", "Any", True), Field("count", "Integer")]
651 outputs = [Field("array_output", "Array")]
652 shorthand = "new_Array_num"
653 documentation = ""
655 def exec(element: Any, count: int) -> numpy.ndarray:
656 return numpy.array([element] * count)
659class Tuple_get(object):
660 source_language_name = {
661 "Python": "Tuple_get"
662 } # TODO: What should this be?
663 inputs = [Field("tuple_input", "Tuple"), Field("index", "Integer")]
664 outputs = [Field("item", "Any")]
665 shorthand = "Tuple_get"
666 documentation = ""
668 def exec(tuple_input: tuple, index: int) -> Any:
669 return tuple_input[index]
672class Tuple_set(object): # TODO: Should this exist?
673 source_language_name = {"Python": "Tuple_set"}
674 inputs = [
675 Field("tuple_input", "Tuple"),
676 Field("index", "Integer"),
677 Field("value", "Any"),
678 ]
679 outputs = [Field("tuple_output", "Tuple")]
680 shorthand = "Tuple_set"
681 documentation = ""
683 def exec(tuple_input: tuple, index: int, value: Any) -> tuple:
684 placeholder_list = list(
685 tuple_input
686 ) # tuples are immutable, so conversions must be made
687 placeholder_list[index] = value
688 return tuple(placeholder_list) # Convert back to tuple for output
691class Tuple_in(object):
692 source_language_name = {"Python": "Tuple_in"}
693 inputs = [Field("tuple_input", "Tuple"), Field("value", "Any")]
694 outputs = [Field("result", "Boolean")]
695 shorthand = "Tuple_in"
696 documentation = ""
698 def exec(tuple_input: list, value: Any) -> bool:
699 return value in tuple_input
702class Tuple_new_Iterator(object):
703 source_language_name = {"Python": "Tuple_new_Iterator"}
704 inputs = [Field("tuple_input", "Tuple")]
705 outputs = [Field("tuple_iterator", "IteratorTuple")]
706 shorthand = "Tuple_new_Iterator"
707 documentation = ""
709 def exec(tuple_input: list) -> Iterator[tuple]:
710 return iter(tuple_input)
713class new_Tuple(object):
714 source_language_name = {"Python": "new_Tuple"}
715 inputs = [Field("elements", "Any", True)]
716 outputs = [Field("tuple_output", "Tuple")]
717 shorthand = "new_Tuple"
718 documentation = ""
720 def exec(*elements: Any) -> tuple:
721 return elements # Interestingly when passing variable sized arguments, it is passeed as a tuple
724class new_Tuple_num(object):
725 source_language_name = {"Python": "new_Tuple_num"}
726 inputs = [Field("element", "Any", True), Field("count", "Integer")]
727 outputs = [Field("tuple_output", "Tuple")]
728 shorthand = "new_Tuple_num"
729 documentation = ""
731 def exec(element: Any, count: int) -> tuple:
732 return tuple([element] * count)
735class Map_get(object):
736 source_language_name = {"Python": "Map_get"} # TODO: What should this be?
737 inputs = [Field("map_input", "Map"), Field("index", "Any")]
738 outputs = [Field("item", "Any")]
739 shorthand = "Map_get"
740 documentation = ""
742 def exec(
743 map_input: dict, index: Any
744 ) -> Any: # TODO: Should index really be Any for dict?
745 return map_input[index]
748class Map_set(object):
749 source_language_name = {"Python": "Map_set"}
750 inputs = [
751 Field("map_input", "List"),
752 Field("index", "Any"),
753 Field("value", "Any"),
754 ]
755 outputs = [Field("map_output", "Map")]
756 shorthand = "Map_set"
757 documentation = ""
759 def exec(map_input: dict, index: Any, value: Any) -> dict:
760 map_input[index] = value
761 return map_input
764class Map_in(object):
765 source_language_name = {"Python": "Map_in"}
766 inputs = [Field("map_input", "List"), Field("value", "Any")]
767 outputs = [Field("result", "Boolean")]
768 shorthand = "Map_in"
769 documentation = ""
771 def exec(map_input: dict, value: Any) -> bool:
772 return value in map_input
775class Map_new_Iterator(object):
776 source_language_name = {"Python": "Map_new_Iterator"}
777 inputs = [Field("map_input", "Map")]
778 outputs = [Field("map_iterator", "IteratorMap")]
779 shorthand = "Map_new_Iterator"
780 documentation = ""
782 def exec(map_input: dict) -> Iterator[dict]:
783 return iter(map_input)
786class new_Map(object): # TODO: Should we have inputs for this?
787 source_language_name = {"Python": "new_Map"}
788 inputs = []
789 outputs = [Field("map_output", "Map")]
790 shorthand = "new_Map"
791 documentation = ""
793 def exec() -> dict:
794 return {}
797class new_List_num(object):
798 source_language_name = {"Python": "new_List_num"}
799 inputs = [Field("element", "Any", True), Field("count", "Integer")]
800 outputs = [Field("list_output", "List")]
801 shorthand = "new_List_num"
802 documentation = ""
804 def exec(element: Any, count: int) -> list:
805 return [element] * count
808class Record_get(object):
809 source_language_name = {"Python": "Record_get"}
810 inputs = [Field("record_input", "Record"), Field("field_name", "String")]
811 outputs = [Field("field", "Field")]
812 shorthand = "Record_get"
813 documentation = ""
815 def exec(record_input: Record, field_name: str) -> RecordField:
816 for field in record_input.fields:
817 if field.name == field_name:
818 return field
819 return None
822class Record_set(object):
823 source_language_name = {"Python": "Record_set"}
824 inputs = [
825 Field("record_input", "Record"),
826 Field("field_name", "String"),
827 Field("value", "Any"),
828 ]
829 outputs = [Field("record_output", "Record")]
830 shorthand = "Record_set"
831 documentation = ""
833 def exec(record_input: Record, field_name: str, value: Any) -> Record:
834 for field in record_input.fields:
835 if field.name == field_name:
836 field.value = value # TODO: Do we need type checking here?
839class new_Record(object):
840 source_language_name = {"Python": "new_Record"}
841 inputs = [Field("record_name", "String")]
842 outputs = [Field("record_output", "Record")]
843 shorthand = "new_Record"
844 documentation = ""
846 def exec(record_name: str) -> Record:
847 return Record(record_name)
850class new_Field(object):
851 source_language_name = {"Python": "new_Field"}
852 inputs = [
853 Field("record_input", "Record"),
854 Field("field_name", "String"),
855 Field("value_type", "Type"),
856 ]
857 outputs = [Field("record_output", "Record")]
858 shorthand = "new_Field"
859 documentation = ""
861 def exec(
862 record_input: Record, field_name: str, value_type: type
863 ) -> Record:
864 return record_input.fields.append(
865 RecordField(field_name, value_type, None)
866 ) # #TODO: Do we need to set a default value?
869class IteratorSet_next(object):
870 source_language_name = {"Python": "IteratorSet_next"}
871 inputs = [Field("iterator_input", "IteratorSet")]
872 outputs = [
873 Field("element", "Any"),
874 Field("iterator_output", "IteratorSet"),
875 Field("stop_condition", "Boolean"),
876 ]
877 shorthand = "IteratorSet_next"
878 documentation = ""
880 def exec(iterator_input: Iterator[set]) -> Tuple[Any, Iterator[Set], bool]:
881 current_element = None
882 # We have to wrap this code in a try except block because of the call to next()
883 # next() will throw an error if you've reached the end of the iterator
884 # You can specify a default value for it to return instead of an exception,
885 # but we can't use this since there is no way to differentiate between a regular value and the default value
887 try:
888 current_element = next(iterator_input)
889 return (current_element, iterator_input, False)
890 except:
891 return (None, iterator_input, True)
894class IteratorTuple_next(object):
895 source_language_name = {"Python": "IteratorTuple_next"}
896 inputs = [Field("iterator_input", "IteratorTuple")]
897 outputs = [
898 Field("element", "Any"),
899 Field("iterator_output", "IteratorTuple"),
900 Field("stop_condition", "Boolean"),
901 ]
902 shorthand = "IteratorTuple_next"
903 documentation = ""
905 def exec(
906 iterator_input: Iterator[tuple],
907 ) -> Tuple[Any, Iterator[Tuple], bool]:
908 current_element = None
909 # We have to wrap this code in a try except block because of the call to next()
910 # next() will throw an error if you've reached the end of the iterator
911 # You can specify a default value for it to return instead of an exception,
912 # but we can't use this since there is no way to differentiate between a regular value and the default value
914 try:
915 current_element = next(iterator_input)
916 return (current_element, iterator_input, False)
917 except:
918 return (None, iterator_input, True)
921class IteratorArray_next(object):
922 source_language_name = {"Python": "IteratorArray_next"}
923 inputs = [Field("iterator_input", "IteratorArray")]
924 outputs = [
925 Field("element", "Any"),
926 Field("iterator_output", "IteratorArray"),
927 Field("stop_condition", "Boolean"),
928 ]
929 shorthand = "IteratorArray_next"
930 documentation = ""
932 def exec(
933 iterator_input: Iterator,
934 ) -> Tuple[
935 Any, Iterator, bool
936 ]: # TODO: Can we say Iterator[numpy.ndarray]
937 current_element = None
938 # We have to wrap this code in a try except block because of the call to next()
939 # next() will throw an error if you've reached the end of the iterator
940 # You can specify a default value for it to return instead of an exception,
941 # but we can't use this since there is no way to differentiate between a regular value and the default value
943 try:
944 current_element = next(iterator_input)
945 return (current_element, iterator_input, False)
946 except:
947 return (None, iterator_input, True)
950class IteratorList_next(object):
951 source_language_name = {"Python": "IteratorList_next"}
952 inputs = [Field("iterator_input", "IteratorList")]
953 outputs = [
954 Field("element", "Any"),
955 Field("iterator_output", "IteratorList"),
956 Field("stop_condition", "Boolean"),
957 ]
958 shorthand = "IteratorList_next"
959 documentation = ""
961 def exec(
962 iterator_input: Iterator[List],
963 ) -> Tuple[Any, Iterator[List], bool]:
964 current_element = None
965 # We have to wrap this code in a try except block because of the call to next()
966 # next() will throw an error if you've reached the end of the iterator
967 # You can specify a default value for it to return instead of an exception,
968 # but we can't use this since there is no way to differentiate between a regular value and the default value
970 try:
971 current_element = next(iterator_input)
972 return (current_element, iterator_input, False)
973 except:
974 return (None, iterator_input, True)
977class IteratorMap_next(object):
978 source_language_name = {"Python": "IteratorMap_next"}
979 inputs = [Field("iterator_input", "IteratorMap")]
980 outputs = [
981 Field("element", "Any"),
982 Field("iterator_output", "IteratorMap"),
983 Field("stop_condition", "Boolean"),
984 ]
985 shorthand = "IteratorMap_next"
986 documentation = ""
988 def exec(
989 iterator_input: Iterator[dict],
990 ) -> Tuple[Any, Iterator[Dict], bool]:
991 current_element = None
992 # We have to wrap this code in a try except block because of the call to next()
993 # next() will throw an error if you've reached the end of the iterator
994 # You can specify a default value for it to return instead of an exception,
995 # but we can't use this since there is no way to differentiate between a regular value and the default value
997 try:
998 current_element = next(iterator_input)
999 return (current_element, iterator_input, False)
1000 except:
1001 return (None, iterator_input, True)
1004class CASTGenericGet:
1005 source_language_name = {"CAST": "_get"}
1006 inputs = [Field("indexible_input", "Indexable"), Field("index", "Any")]
1007 outputs = [Field("element", "Any")]
1008 shorthand = "_get"
1009 documentation = "The cast currently uses generic primitive operators (_get, _set, iter, next) while the Gromet uses specific operators (IteratorMap_next). These primitive ops are a tempory fix for that mismatch"
1012class CASTGenericSet:
1013 source_language_name = {"CAST": "_set"}
1014 inputs = [
1015 Field("indexible_input", "Indexable"),
1016 Field("index", "Any"),
1017 Field("value", "Any"),
1018 ]
1019 outputs = [Field("indexible_output", "Indexable")]
1020 shorthand = "_set"
1021 documentation = "The cast currently uses generic primitive operators (_get, _set, iter, next) while the Gromet uses specific operators (IteratorMap_next). These primitive ops are a tempory fix for that mismatch"
1024class CASTGenericIter:
1025 source_language_name = {"CAST": "iter"}
1026 inputs = [Field("iterable_input", "Iterable")]
1027 outputs = [Field("iterator_output", "Iterator")]
1028 shorthand = "iter"
1029 documentation = "The cast currently uses generic primitive operators (_get, _set, iter, next) while the Gromet uses specific operators (IteratorMap_next). These primitive ops are a tempory fix for that mismatch"
1032class CASTGenericNext:
1033 source_language_name = {"CAST": "next"}
1034 inputs = [Field("iterator_input", "Iterator")]
1035 outputs = [
1036 Field("element", "Any"),
1037 Field("iterator_output", "Iterator"),
1038 Field("stop_condition", "Boolean"),
1039 ]
1040 shorthand = "next"
1041 documentation = "The cast currently uses generic primitive operators (_get, _set, iter, next) while the Gromet uses specific operators (IteratorMap_next). These primitive ops are a tempory fix for that mismatch"
1044class Is(object):
1045 source_language_name = {
1046 "Python": "is",
1047 "CAST": "Is",
1048 } # TODO: Should Python/CAST be Is or is?
1049 inputs = [Field("operand1", "Any"), Field("operand2", "Any")]
1050 outputs = [Field("result", "Boolean")]
1051 shorthand = "is"
1052 documentation = ""
1054 def exec(operand1: Any, operand2: Any) -> bool:
1055 return operand1 is operand2
1058class NotIs(object):
1059 source_language_name = {
1060 "Python": "is not",
1061 "CAST": "NotIs",
1062 } # TODO: What should Python name be here?
1063 inputs = [Field("operand1", "Any"), Field("operand2", "Any")]
1064 outputs = [Field("result", "Boolean")]
1065 shorthand = "not is"
1066 documentation = ""
1068 def exec(operand1: Any, operand2: Any) -> bool:
1069 return operand1 is not operand2
1072class IsInstance(object):
1073 source_language_name = {"Python": "isinstance"}
1074 inputs = [
1075 Field("operand", "Any"),
1076 Field("type", "Type"),
1077 ] # TODO: Get confirmation on adding Type field
1078 outputs = [Field("result", "Boolean")]
1079 shorthand = "type"
1080 documentation = ""
1082 def exec(
1083 operand: Any, type: type
1084 ) -> bool: # TODO: Fix name of right argument
1085 return isinstance(operand, type)
1088class Type(object):
1089 source_language_name = {"Python": "type"}
1090 inputs = [Field("operand", "Any")]
1091 outputs = [Field("result", "Type")]
1092 shorthand = "type"
1093 documentation = ""
1095 def exec(operand: Any) -> type:
1096 return type(operand)
1099class Print: # TODO: How should print work? Will likely not be a CASTGeneric function
1100 source_language_name = {"CAST": "print"}
1101 inputs = [Field("input", "Any")]
1102 outputs = []
1103 shorthand = "print"
1104 documentation = "The cast currently uses generic primitive operators (_get, _set, iter, next) while the Gromet uses specific operators (IteratorMap_next). These primitive ops are a tempory fix for that mismatch"
1106 def exec(input: Any) -> None:
1107 print(input)
1110class Range:
1111 source_language_name = {"CAST": "range"}
1112 inputs = [Field("input", "Integer")] # TODO: What is the input to range?
1113 outputs = [Field("range_output", "Range")]
1114 shorthand = "range"
1115 documentation = ""
1117 def exec(input: int) -> range:
1118 return range(input)
1121#### Interface for accessing fields of classes
1122def get_class_obj(
1123 op: str, language: str, debug=False
1124) -> Any: # TODO: Update the type hints for this
1125 global primitive_map
1127 try:
1128 return primitive_map[language][op]
1129 except:
1130 if debug:
1131 print(
1132 f"Operation not supported: {op} for language {language} ... Returning None"
1133 )
1134 return None
1137def get_shorthand(op: str, language: str) -> str:
1138 class_obj = get_class_obj(op, language, debug=True)
1140 if class_obj:
1141 try:
1142 return class_obj.shorthand
1143 except:
1144 print(
1145 f"Operation has no shorthand: {op} for language {language} ... Returning None"
1146 )
1148 return None
1151def get_inputs(op: str, language: str) -> str:
1152 class_obj = get_class_obj(op, language, debug=True)
1154 if class_obj:
1155 try:
1156 return class_obj.inputs
1157 except:
1158 print(
1159 f"Operation has no inputs: {op} for language {language} ... Returning None"
1160 )
1162 return None
1165def get_outputs(op: str, language: str, debug=True) -> str:
1166 class_obj = get_class_obj(op, language)
1168 if class_obj:
1169 try:
1170 return class_obj.outputs
1171 except:
1172 print(
1173 f"Operation has no outputs: {op} for language {language} ... Returning None"
1174 )
1176 return None
1179def is_primitive(op: str, language: str):
1180 return get_class_obj(op, language) is not None
1183# Create table ob primitive op classes
1184primitive_ops = inspect.getmembers(
1185 sys.modules[__name__], predicate=inspect.isclass
1186)
1188# Create map between langauge names and python class objects
1189python_primitive_dict = {}
1190gcc_primitive_dict = {}
1191cast_primitive_dict = {}
1192for class_name, class_obj in primitive_ops:
1193 if hasattr(class_obj, "source_language_name"):
1194 if "Python" in class_obj.source_language_name:
1195 python_primitive_dict[
1196 class_obj.source_language_name["Python"]
1197 ] = class_obj
1198 if "GCC" in class_obj.source_language_name:
1199 gcc_primitive_dict[
1200 class_obj.source_language_name["GCC"]
1201 ] = class_obj
1202 if "CAST" in class_obj.source_language_name:
1203 cast_primitive_dict[
1204 class_obj.source_language_name["CAST"]
1205 ] = class_obj
1207primitive_map = {
1208 "Python": python_primitive_dict,
1209 "GCC": gcc_primitive_dict,
1210 "CAST": cast_primitive_dict,
1211}