fprime-gds 4.0.2a2__py3-none-any.whl → 4.0.2a4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fprime_gds/common/distributor/distributor.py +9 -6
- fprime_gds/common/fpy/README.md +190 -42
- fprime_gds/common/fpy/SPEC.md +153 -39
- fprime_gds/common/fpy/bytecode/assembler.py +62 -0
- fprime_gds/common/fpy/bytecode/directives.py +620 -294
- fprime_gds/common/fpy/codegen.py +687 -910
- fprime_gds/common/fpy/grammar.lark +44 -9
- fprime_gds/common/fpy/main.py +27 -4
- fprime_gds/common/fpy/model.py +799 -0
- fprime_gds/common/fpy/parser.py +29 -34
- fprime_gds/common/fpy/test_helpers.py +119 -0
- fprime_gds/common/fpy/types.py +563 -0
- fprime_gds/common/models/dictionaries.py +23 -0
- fprime_gds/common/pipeline/standard.py +5 -0
- fprime_gds/common/testing_fw/api.py +8 -1
- fprime_gds/executables/cli.py +9 -0
- fprime_gds/executables/run_deployment.py +2 -0
- fprime_gds/flask/app.py +17 -2
- fprime_gds/flask/default_settings.py +1 -0
- fprime_gds/flask/static/index.html +7 -4
- fprime_gds/flask/static/js/config.js +9 -1
- fprime_gds/flask/static/js/vue-support/channel.js +16 -0
- fprime_gds/flask/static/js/vue-support/event.js +1 -0
- fprime_gds/flask/static/js/vue-support/fp-row.js +25 -1
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/METADATA +1 -1
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/RECORD +31 -27
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/entry_points.txt +2 -1
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/WHEEL +0 -0
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/licenses/LICENSE.txt +0 -0
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/licenses/NOTICE.txt +0 -0
- {fprime_gds-4.0.2a2.dist-info → fprime_gds-4.0.2a4.dist-info}/top_level.txt +0 -0
fprime_gds/common/fpy/parser.py
CHANGED
@@ -71,7 +71,7 @@ class AstBoolean(Ast):
|
|
71
71
|
value: TypingLiteral[True] | TypingLiteral[False]
|
72
72
|
|
73
73
|
|
74
|
-
AstLiteral = AstString
|
74
|
+
AstLiteral = Union[AstString, AstNumber, AstBoolean]
|
75
75
|
|
76
76
|
|
77
77
|
@dataclass
|
@@ -92,43 +92,29 @@ class AstFuncCall(Ast):
|
|
92
92
|
args: list["AstExpr"] | None
|
93
93
|
|
94
94
|
|
95
|
-
@dataclass
|
96
|
-
class AstInfixOp(Ast):
|
97
|
-
value: str
|
98
|
-
|
99
|
-
|
100
95
|
@dataclass()
|
101
96
|
class AstPass(Ast):
|
102
97
|
pass
|
103
98
|
|
104
|
-
|
105
|
-
@dataclass
|
106
|
-
class AstComparison(Ast):
|
107
|
-
lhs: "AstExpr"
|
108
|
-
op: AstInfixOp
|
109
|
-
rhs: "AstExpr"
|
110
|
-
|
111
|
-
|
112
99
|
@dataclass
|
113
|
-
class
|
114
|
-
|
100
|
+
class AstBinaryOp(Ast):
|
101
|
+
lhs: AstExpr
|
102
|
+
op: str
|
103
|
+
rhs: AstExpr
|
115
104
|
|
116
105
|
|
117
106
|
@dataclass
|
118
|
-
class
|
119
|
-
|
107
|
+
class AstUnaryOp(Ast):
|
108
|
+
op: str
|
109
|
+
val: AstExpr
|
120
110
|
|
121
111
|
|
122
|
-
|
123
|
-
class AstOr(Ast):
|
124
|
-
values: list["AstExpr"]
|
125
|
-
|
126
|
-
|
127
|
-
AstTest = AstOr | AstAnd | AstNot | AstComparison
|
128
|
-
|
112
|
+
AstOp = Union[AstBinaryOp, AstUnaryOp]
|
129
113
|
|
130
|
-
AstReference = AstGetAttr
|
131
|
-
AstExpr = Union[
|
114
|
+
AstReference = Union[AstGetAttr, AstGetItem, AstVar]
|
115
|
+
AstExpr = Union[
|
116
|
+
AstFuncCall, AstLiteral, AstReference, AstOp
|
117
|
+
]
|
132
118
|
|
133
119
|
|
134
120
|
@dataclass
|
@@ -165,9 +151,14 @@ class AstBody(Ast):
|
|
165
151
|
stmts: list[AstStmt]
|
166
152
|
|
167
153
|
|
154
|
+
@dataclass
|
155
|
+
class AstScopedBody(Ast):
|
156
|
+
stmts: list[AstStmt]
|
157
|
+
|
158
|
+
|
168
159
|
for cls in Ast.__subclasses__():
|
169
160
|
cls.__hash__ = Ast.__hash__
|
170
|
-
|
161
|
+
cls.__repr__ = Ast.__repr__
|
171
162
|
|
172
163
|
|
173
164
|
@v_args(meta=False, inline=False)
|
@@ -204,7 +195,7 @@ def handle_str(meta, s: str):
|
|
204
195
|
|
205
196
|
@v_args(meta=True, inline=True)
|
206
197
|
class FpyTransformer(Transformer):
|
207
|
-
input = no_inline(
|
198
|
+
input = no_inline(AstScopedBody)
|
208
199
|
pass_stmt = AstPass
|
209
200
|
|
210
201
|
assign = AstAssign
|
@@ -213,11 +204,8 @@ class FpyTransformer(Transformer):
|
|
213
204
|
elifs = no_inline(AstElifs)
|
214
205
|
elif_ = AstElif
|
215
206
|
body = no_inline(AstBody)
|
216
|
-
|
217
|
-
|
218
|
-
not_test = AstNot
|
219
|
-
comparison = AstComparison
|
220
|
-
comp_op = AstInfixOp
|
207
|
+
binary_op = AstBinaryOp
|
208
|
+
unary_op = AstUnaryOp
|
221
209
|
|
222
210
|
func_call = AstFuncCall
|
223
211
|
arguments = no_inline_or_meta(list)
|
@@ -237,3 +225,10 @@ class FpyTransformer(Transformer):
|
|
237
225
|
STRING = handle_str
|
238
226
|
CONST_TRUE = lambda a, b: True
|
239
227
|
CONST_FALSE = lambda a, b: False
|
228
|
+
ADD_OP: str
|
229
|
+
SUB_OP: str
|
230
|
+
DIV_OP: str
|
231
|
+
MUL_OP: str
|
232
|
+
FLOOR_DIV_OP: str
|
233
|
+
MOD_OP: str
|
234
|
+
POW_OP: str
|
@@ -0,0 +1,119 @@
|
|
1
|
+
import ast
|
2
|
+
from pathlib import Path
|
3
|
+
import tempfile
|
4
|
+
import traceback
|
5
|
+
from fprime.common.models.serialize.type_base import BaseType
|
6
|
+
from fprime.common.models.serialize.numerical_types import U32Type, U8Type
|
7
|
+
from fprime_gds.common.fpy.bytecode.assembler import deserialize_directives
|
8
|
+
from fprime_gds.common.fpy.model import DirectiveErrorCode, FpySequencerModel
|
9
|
+
from fprime_gds.common.fpy.bytecode.directives import Directive
|
10
|
+
from fprime_gds.common.fpy.codegen import compile, serialize_directives
|
11
|
+
from fprime_gds.common.fpy.parser import parse
|
12
|
+
from fprime_gds.common.loaders.ch_json_loader import ChJsonLoader
|
13
|
+
from fprime_gds.common.loaders.cmd_json_loader import CmdJsonLoader
|
14
|
+
from fprime_gds.common.loaders.event_json_loader import EventJsonLoader
|
15
|
+
from fprime_gds.common.loaders.prm_json_loader import PrmJsonLoader
|
16
|
+
from fprime_gds.common.testing_fw.api import IntegrationTestAPI
|
17
|
+
|
18
|
+
default_dictionary = str(
|
19
|
+
Path(__file__).parent.parent.parent.parent.parent
|
20
|
+
/ "test"
|
21
|
+
/ "fprime_gds"
|
22
|
+
/ "common"
|
23
|
+
/ "fpy"
|
24
|
+
/ "RefTopologyDictionary.json"
|
25
|
+
)
|
26
|
+
|
27
|
+
|
28
|
+
def compile_seq(fprime_test_api, seq: str) -> list[Directive]:
|
29
|
+
return compile(parse(seq), default_dictionary) #fprime_test_api.pipeline.dictionary_path)
|
30
|
+
|
31
|
+
|
32
|
+
def lookup_type(fprime_test_api, type_name: str):
|
33
|
+
dictionary = default_dictionary #fprime_test_api.pipeline.dictionary_path
|
34
|
+
cmd_json_dict_loader = CmdJsonLoader(dictionary)
|
35
|
+
(cmd_id_dict, cmd_name_dict, versions) = cmd_json_dict_loader.construct_dicts(
|
36
|
+
dictionary
|
37
|
+
)
|
38
|
+
|
39
|
+
ch_json_dict_loader = ChJsonLoader(dictionary)
|
40
|
+
(ch_id_dict, ch_name_dict, versions) = ch_json_dict_loader.construct_dicts(
|
41
|
+
dictionary
|
42
|
+
)
|
43
|
+
prm_json_dict_loader = PrmJsonLoader(dictionary)
|
44
|
+
(prm_id_dict, prm_name_dict, versions) = prm_json_dict_loader.construct_dicts(
|
45
|
+
dictionary
|
46
|
+
)
|
47
|
+
event_json_dict_loader = EventJsonLoader(dictionary)
|
48
|
+
(event_id_dict, event_name_dict, versions) = event_json_dict_loader.construct_dicts(
|
49
|
+
dictionary
|
50
|
+
)
|
51
|
+
type_name_dict = cmd_json_dict_loader.parsed_types
|
52
|
+
type_name_dict.update(ch_json_dict_loader.parsed_types)
|
53
|
+
type_name_dict.update(prm_json_dict_loader.parsed_types)
|
54
|
+
type_name_dict.update(event_json_dict_loader.parsed_types)
|
55
|
+
|
56
|
+
return type_name_dict[type_name]
|
57
|
+
|
58
|
+
|
59
|
+
def run_seq(
|
60
|
+
fprime_test_api: IntegrationTestAPI,
|
61
|
+
dirs: list[Directive],
|
62
|
+
tlm: dict[str, bytes] = None,
|
63
|
+
):
|
64
|
+
for idx, d in enumerate(dirs):
|
65
|
+
print(idx, d)
|
66
|
+
if tlm is None:
|
67
|
+
tlm = {}
|
68
|
+
file = tempfile.NamedTemporaryFile(suffix=".bin", delete=False)
|
69
|
+
|
70
|
+
serialize_directives(dirs, Path(file.name))
|
71
|
+
|
72
|
+
# fprime_test_api.send_and_assert_command("Ref.cmdSeq.RUN", [file.name, "BLOCK"], timeout=4)
|
73
|
+
# return
|
74
|
+
|
75
|
+
dictionary = default_dictionary # fprime_test_api.pipeline.dictionary_path
|
76
|
+
|
77
|
+
deserialized_dirs = deserialize_directives(Path(file.name).read_bytes())
|
78
|
+
|
79
|
+
model = FpySequencerModel()
|
80
|
+
ch_json_dict_loader = ChJsonLoader(dictionary)
|
81
|
+
(ch_id_dict, ch_name_dict, versions) = ch_json_dict_loader.construct_dicts(
|
82
|
+
dictionary
|
83
|
+
)
|
84
|
+
tlm_db = {}
|
85
|
+
for chan_name, val in tlm.items():
|
86
|
+
ch_template = ch_name_dict[chan_name]
|
87
|
+
tlm_db[ch_template.get_id()] = val
|
88
|
+
ret = model.run(deserialized_dirs, tlm_db)
|
89
|
+
if ret != DirectiveErrorCode.NO_ERROR:
|
90
|
+
raise RuntimeError("Sequence returned", ret)
|
91
|
+
|
92
|
+
|
93
|
+
def assert_compile_success(fprime_test_api, seq: str):
|
94
|
+
compile_seq(fprime_test_api, seq)
|
95
|
+
|
96
|
+
|
97
|
+
def assert_run_success(fprime_test_api, seq: str, tlm: dict[str, bytes] = None):
|
98
|
+
seq = compile_seq(fprime_test_api, seq)
|
99
|
+
|
100
|
+
run_seq(fprime_test_api, seq, tlm)
|
101
|
+
|
102
|
+
|
103
|
+
def assert_compile_failure(fprime_test_api, seq: str):
|
104
|
+
try:
|
105
|
+
compile_seq(fprime_test_api, seq)
|
106
|
+
except BaseException as e:
|
107
|
+
traceback.print_exc()
|
108
|
+
return
|
109
|
+
raise RuntimeError("compile_seq succeeded")
|
110
|
+
|
111
|
+
|
112
|
+
def assert_run_failure(fprime_test_api, seq: str):
|
113
|
+
directives = compile_seq(fprime_test_api, seq)
|
114
|
+
try:
|
115
|
+
run_seq(fprime_test_api, directives)
|
116
|
+
except BaseException as e:
|
117
|
+
print(e)
|
118
|
+
return
|
119
|
+
raise RuntimeError("run_seq succeeded")
|