Coverage for skema/gromet/execution_engine/symbol_table.py: 56%

43 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-30 17:15 +0000

1from typing import Dict, List 

2class SymbolTable(): 

3 def __init__(self): 

4 self.symbols = {} 

5 

6 self.current_scope = self.symbols 

7 

8 # Function definitions is a mapping between function name and the node id of the function definition node in memgraph. 

9 # We need this because the function body is only represented in memgraph for the first call to a function. 

10 self.function_definitions = {} 

11 

12 # Function stack is needed to support nested function calls. 

13 # It is a list of call scopes [{}] 

14 self.function_stack = [] 

15 

16 # Function history is a dictionary mapping function names to a list of call scopes 

17 # { 

18 # "func1": [{}] 

19 # } 

20 self.function_history = {} 

21 

22 

23 def register_function(self, function_name: str, node_id: int): 

24 """Register a function definition.""" 

25 self.function_definitions[function_name] = node_id 

26 

27 def get_function_definition(self, function_name: str): 

28 return self.function_definitions[function_name] 

29 

30 def push_function_call(self, function_name: str, initial_scope: Dict): 

31 """Push a new function call onto the function stack and set the current scope.""" 

32 self.function_stack.append(initial_scope) 

33 self.current_scope = self.function_stack[-1] 

34 

35 

36 def pop_function_call(self, function_name: str): 

37 """Pop a function call""" 

38 

39 # Pop call and add it to history 

40 scope = self.function_stack.pop() 

41 if function_name in self.function_history: 

42 self.function_history[function_name].append(scope) 

43 else: 

44 self.function_history[function_name] = [scope] 

45 

46 # Update the current_scope pointer 

47 if len(self.function_stack) > 0: 

48 self.current_scope = self.function_stack[-1] 

49 else: 

50 self.current_scope = self.symbols 

51 

52 

53 

54 def add_symbol(self, name, value, data_type): 

55 self.current_scope[name] = { 

56 "current_value": value, 

57 "history": [value], 

58 "data_type": data_type, 

59 "data_type_history": [data_type], 

60 } 

61 

62 def update_symbol(self, name, value, data_type): 

63 #for scope in reversed(self.scope_stack): 

64 symbol = self.current_scope[name] 

65 symbol["current_value"] = value 

66 symbol["history"].append(value) 

67 if symbol["data_type"] != data_type: 

68 symbol["data_type"] = data_type 

69 symbol["data_type_history"].append(data_type) 

70 

71 def get_symbol(self, name): 

72 return self.symbols.get(name, None) 

73 

74 

75 def get_all_symbols(self): 

76 return self.symbols 

77 

78 def get_scope_stack(self): 

79 return self.scope_stack 

80 

81 def get_initial_values(self): 

82 initial_values = {} 

83 for symbol, symbol_dict in self.symbols.items(): 

84 initial_values = {symbol: symbol_dict["history"][0] for symbol, symbol_dict in self.symbols.items()} 

85 return initial_values