Coverage for skema/program_analysis/CAST/matlab/variable_context.py: 83%
47 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 List, Dict, Set
2from skema.program_analysis.CAST2FN.model.cast import (
3 Var,
4 Name,
5)
7class VariableContext(object):
8 def __init__(self):
9 self.context = [{}] # Stack of context dictionaries
10 self.context_return_values = [set()] # Stack of context return values
11 self.all_symbols = {}
12 self.record_definitions = {}
14 # The prefix is used to handle adding Record types to the variable context.
15 # This gives each symbol a unqique name. For example "a" would become "type_name.a"
16 # For nested type definitions (derived type in a module), multiple prefixes can be added.
17 self.prefix = []
19 # Flag neccessary to declare if a function is internal or external
20 self.internal = False
22 self.variable_id = 0
23 self.iterator_id = 0
24 self.stop_condition_id = 0
26 def push_context(self):
27 """Create a new variable context and add it to the stack"""
29 self.context.append({})
30 self.context_return_values.append(set())
32 def pop_context(self):
33 """Pop the current variable context off of the stack and remove any references to those symbols."""
35 context = self.context.pop()
37 # Remove symbols from all_symbols variable
38 for symbol in context:
39 self.all_symbols.pop(symbol)
41 self.context_return_values.pop()
43 def add_variable(self, symbol: str, type: str, source_refs: List) -> Name:
44 """Add a variable to the current variable context"""
45 # Generate the full symbol name using the prefix
46 full_symbol_name = ".".join(self.prefix + [symbol])
48 cast_name = Name(source_refs=source_refs)
49 cast_name.name = symbol
50 cast_name.id = self.variable_id
52 # Update variable id
53 self.variable_id += 1
55 # Add the node to the variable context
56 self.context[-1][full_symbol_name] = {
57 "node": cast_name,
58 "type": type,
59 }
61 # Add reference to all_symbols
62 self.all_symbols[full_symbol_name] = self.context[-1][full_symbol_name]
64 return cast_name
66 def is_variable(self, symbol: str) -> bool:
67 """Check if a symbol exists in any context"""
68 return symbol in self.all_symbols
70 def get_node(self, symbol: str) -> Dict:
71 return self.all_symbols[symbol]["node"]
73 def get_type(self, symbol: str) -> str:
74 return self.all_symbols[symbol]["type"]
76 def get_gromet_function_node(self, func_name: str) -> Name:
77 if self.is_variable(func_name):
78 return self.get_node(func_name)
80 def generate_iterator(self):
81 symbol = f"generated_iter_{self.iterator_id}"
82 self.iterator_id += 1
83 return self.add_variable(symbol, "iterator", None)
85 def generate_stop_condition(self):
86 symbol = f"sc_{self.stop_condition_id}"
87 self.stop_condition_id += 1
88 return self.add_variable(symbol, "boolean", None)