-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathruntime_result.py
154 lines (129 loc) · 5.51 KB
/
runtime_result.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Nougaro : a python-interpreted high-level programming language
# Copyright (C) 2021-2024 Jean Dubois (https://github.com/jd-develop) <[email protected]>
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# IMPORTS
# __future__ import (must be first)
from __future__ import annotations
# nougaro modules imports
from src.errors.errors import Error
from src.lexer.position import Position
# built-in python imports
import pprint
# special typing import
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from src.runtime.values.basevalues.value import Value
# ##########
# RUNTIME RESULT
# ##########
class RTResult:
"""Result of a node interpretation"""
def __init__(self):
self.value = None # result value
self.function_return_value = None # for FunctionNode : the value that the function returns
self.error = None # any error that can have been encountered while interpreting
self.loop_should_continue = False # there is a 'continue' statement
self.loop_should_break = False # there is a 'break' statement
self.old_should_return = False # The old value of self.should_return()
self.break_value: Value | None = None
self.break_label: str | None = None
self.continue_label: str | None = None
self.break_or_continue_pos: tuple[Position, Position] | None = None
self.return_pos: tuple[Position, Position] | None = None
self.reset()
def reset(self):
"""Reset attrs to their default value"""
self.value = None
self.function_return_value = None
self.error = None
self.loop_should_continue = False
self.loop_should_break = False
self.old_should_return = False
self.break_value = None
self.break_label = None
self.continue_label = None
self.break_or_continue_pos = None
self.return_pos = None
def register(self, result: RTResult):
"""Register another result in this result"""
if not self.old_should_return: # True -> DON'T TOUCH IT, False -> change to the new
self.old_should_return = self.should_return()
# we copy the attrs of other result into the self attrs
if result.error is not None:
self.error = result.error
else:
self.error = None
self.function_return_value = result.function_return_value
self.loop_should_continue = result.loop_should_continue
self.loop_should_break = result.loop_should_break
self.break_value = result.break_value
self.break_label = result.break_label
self.continue_label = result.continue_label
self.break_or_continue_pos = result.break_or_continue_pos
self.return_pos = result.return_pos
return result.value # we return the other result value
def success(self, value: Value): # success, we clean up our attrs, we write the new value, and we return self
self.reset()
self.value = value
return self
def success_return(self, value: Value, pos_start: Position, pos_end: Position):
"""same as self.success for self.function_return_value"""
self.reset()
self.function_return_value = value
self.return_pos = (pos_start, pos_end)
return self
def success_continue(self, pos_start: Position, pos_end: Position, label: str | None = None):
"""same as self.success for self.loop_should_continue"""
self.reset()
self.break_or_continue_pos = (pos_start, pos_end)
self.loop_should_continue = True
self.continue_label = label
return self
def success_break(self, pos_start: Position, pos_end: Position,
value_to_return: Value | None = None, label: str | None = None):
"""same as self.success for self.loop_should_break"""
self.reset()
self.break_or_continue_pos = (pos_start, pos_end)
self.loop_should_break = True
self.break_value = value_to_return
self.break_label = label
return self
def failure(self, error: Error):
"""same as self.success for self.error"""
self.reset()
self.error = error
return self
def should_return(self, ignore_break_and_continue: bool = False):
"""if we should stop the interpretation because of an error, or a statement
(return, break, continue)"""
if ignore_break_and_continue:
return (
self.error is not None or
self.function_return_value is not None
)
return (
self.error is not None or
self.function_return_value is not None or
self.loop_should_continue or
self.loop_should_break
)
def __repr__(self):
return self.__str__()
def __str__(self):
return "RTResult: " + pprint.pformat({
"value": self.value,
"function_return_value": self.function_return_value,
"error": self.error,
"loop_should_continue": self.loop_should_continue,
"loop_should_break": self.loop_should_break,
"break_value": self.break_value,
"break_label": self.break_label,
"continue_label": self.continue_label,
"old_should_return": self.old_should_return,
"break_or_continue_pos": self.break_or_continue_pos,
"return_pos": self.return_pos
})