fprime-gds 4.0.0a8__py3-none-any.whl → 4.0.0a9__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.
@@ -0,0 +1,56 @@
1
+ # Fpy Advanced Sequencing Language Version 0.1
2
+ The Fpy advanced sequencing language is a combination of a high-level scripting language and a low-level bytecode language for running complex command sequences on spacecraft flight software.
3
+ ## Fpy Syntax
4
+ ### Modules, components, channels, commands and types
5
+ You can imagine the Fpy syntax as Python with the following mappings:
6
+ 1. FPrime modules become Python namespaces
7
+ 2. FPrime components become Python classes
8
+ 3. FPrime types (structs, arrays and enums) become Python classes
9
+ 4. FPrime component instances become Python object instances
10
+ 5. FPrime commands become member functions of Python object instances
11
+ 6. FPrime telemetry channels become member properties of Python object instances
12
+
13
+ FPrime declaration:
14
+ ```
15
+ module Ref {
16
+ passive component ExampleComponent {
17
+ telemetry testChannel: U8
18
+ sync command TEST_COMMAND(arg: string size 40)
19
+ }
20
+
21
+ instance exampleInstance: ExampleComponent base id 0x01
22
+ }
23
+ ```
24
+ Fpy usage:
25
+ ```py
26
+ # reference a telemetry channel
27
+ Ref.exampleInstance.testChannel
28
+ # call a command
29
+ Ref.exampleInstance.TEST_COMMAND("arg value")
30
+ ```
31
+
32
+
33
+ FPrime declaration:
34
+ ```
35
+ struct ExampleStruct {
36
+ member: F32
37
+ }
38
+
39
+ enum TestEnum {
40
+ ONE
41
+ TWO
42
+ THREE
43
+ }
44
+
45
+ array TestArray = [3] U8
46
+ ```
47
+
48
+ Fpy usage:
49
+ ```py
50
+ # construct a struct
51
+ ExampleStruct(0.0)
52
+ # reference an enum const
53
+ TestEnum.THREE
54
+ # construct an array
55
+ TestArray(1, 2, 3)
56
+ ```
@@ -0,0 +1,69 @@
1
+ Nothing type is a type whose set of values is an empty set
2
+ Unit type is a type whose set of values is a set with one element
3
+
4
+ # `if` statement
5
+
6
+ ## Syntactical and semantic checks
7
+
8
+ `"if" condition ":" INDENT stmt* DEDENT ("elif" condition ":" INDENT stmt* DEDENT)* ["else" ":" INDENT stmt* DEDENT]`
9
+
10
+ 1. where `condition` is an expression which evaluates to a boolean
11
+ 2. where `stmt` is a statement
12
+
13
+ ## Code generation
14
+
15
+ 1. `if` generates `IF`, followed by the generated code for the first body, followed by `GOTO` to the end of the if statement
16
+ 2. `elif` generates `IF`, followed by the generated code for its body, followed by `GOTO` to the end of the if statement
17
+ 3. `else` generates the code for its body
18
+
19
+ # `not` boolean operator
20
+
21
+ ## Syntactical and semantic checks
22
+
23
+ `"not" value` evaluates to a boolean at runtime
24
+
25
+ 1. where `value` is an expression which evaluates to a boolean
26
+
27
+ ## Code generation
28
+
29
+ 1. `not` generates `NOT`
30
+
31
+ # `and` and `or` boolean operators
32
+
33
+ ## Syntactical and semantic checks
34
+
35
+ `value (op value)+` evaluates to a boolean at runtime
36
+
37
+ 1. where `op: "and"|"or"`
38
+ 2. where `value` is an expression which evaluates to a boolean
39
+
40
+ ## Code generation
41
+
42
+ 1. Each `and` or `or` between two `value`s generates an `AND` or `OR`, respectively
43
+
44
+ # Infix comparisons
45
+
46
+ ## Syntactical and semantic checks
47
+
48
+ `lhs op rhs` evaluates to a boolean at runtime
49
+
50
+ 1. where `op: ">" | "<" | "<=" | ">=" | "==" | "!="`
51
+ 2. and `lhs`, `rhs` are expressions which evaluate to a number
52
+
53
+ If either `lhs` or `rhs` evaluate to a float:
54
+ 3. both `lhs` and `rhs` must evaluate to floats of the same bit width
55
+
56
+ Otherwise, `lhs` and `rhs` evaluate to integer values. All comparisons between integer values are valid.
57
+
58
+ ## Code generation
59
+
60
+ ### Equality comparisons
61
+
62
+ 1. `==` or `!=` between two floats generates `FEQ` or `FNE`, respectively
63
+ 2. `==` or `!=` between two ints generates `IEQ` or `INE`, respectively
64
+
65
+ ### Inequality comparisons
66
+
67
+ 1. `>`, `<`, `<=`, or `>=` between two floats generates `FGT`, `FLT`, `FLE` or `FGE`, respectively
68
+ 2. `>`, `<`, `<=`, or `>=` between two unsigned ints generates `UGT`, `ULT`, `ULE` or `UGE`, respectively
69
+ 2. `>`, `<`, `<=`, or `>=` between two ints, where at least one is signed, generates `SGT`, `SLT`, `SLE` or `SGE`, respectively
File without changes
@@ -0,0 +1,490 @@
1
+ from dataclasses import astuple, dataclass
2
+ from pathlib import Path
3
+ import struct
4
+ from typing import ClassVar
5
+ import zlib
6
+ from fprime.common.models.serialize.time_type import TimeType
7
+ from fprime.common.models.serialize.numerical_types import (
8
+ U32Type,
9
+ U16Type,
10
+ U64Type,
11
+ U8Type,
12
+ I64Type,
13
+ )
14
+ from fprime.common.models.serialize.bool_type import BoolType
15
+ from enum import Enum
16
+
17
+ FwSizeType = U64Type
18
+ FwChanIdType = U32Type
19
+ FwPrmIdType = U32Type
20
+ FwOpcodeType = U32Type
21
+
22
+ MAX_SERIALIZABLE_REGISTER_SIZE = 512 - 4 - 4
23
+
24
+
25
+ class DirectiveOpcode(Enum):
26
+ INVALID = 0
27
+ WAIT_REL = 1
28
+ WAIT_ABS = 2
29
+ SET_SER_REG = 3
30
+ GOTO = 4
31
+ IF = 5
32
+ NO_OP = 6
33
+ GET_TLM = 7
34
+ GET_PRM = 8
35
+ CMD = 9
36
+ SET_REG = 10
37
+ DESER_SER_REG_8 = 11
38
+ DESER_SER_REG_4 = 12
39
+ DESER_SER_REG_2 = 13
40
+ DESER_SER_REG_1 = 14
41
+ # binary reg op directives
42
+ # all of these are handled at the CPP level by one BinaryRegOpDirective
43
+ # boolean ops
44
+ OR = 15
45
+ AND = 16
46
+ # integer equalities
47
+ IEQ = 17
48
+ INE = 18
49
+ # unsigned integer inequalities
50
+ ULT = 19
51
+ ULE = 20
52
+ UGT = 21
53
+ UGE = 22
54
+ # signed integer inequalities
55
+ SLT = 23
56
+ SLE = 24
57
+ SGT = 25
58
+ SGE = 26
59
+ # floating point equalities
60
+ FEQ = 27
61
+ FNE = 28
62
+ # floating point inequalities
63
+ FLT = 29
64
+ FLE = 30
65
+ FGT = 31
66
+ FGE = 32
67
+ # end binary reg op directives
68
+
69
+ # unary reg op dirs
70
+ NOT = 33
71
+ # floating point extension and truncation
72
+ FPEXT = 34
73
+ FPTRUNC = 35
74
+ # floating point conversion to signed/unsigned integer,
75
+ # and vice versa
76
+ FPTOSI = 36
77
+ FPTOUI = 37
78
+ SITOFP = 38
79
+ UITOFP = 39
80
+ # end unary reg op dirs
81
+
82
+ EXIT = 40
83
+
84
+
85
+ class Directive:
86
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.INVALID
87
+
88
+ def serialize(self) -> bytes:
89
+ arg_bytes = self.serialize_args()
90
+
91
+ output = U8Type(self.opcode.value).serialize()
92
+ output += U16Type(len(arg_bytes)).serialize()
93
+ output += arg_bytes
94
+
95
+ return output
96
+
97
+ def serialize_args(self) -> bytes:
98
+ raise NotImplementedError("serialize_args not implemented")
99
+
100
+
101
+ HEADER_FORMAT = "!BBBBBHI"
102
+ HEADER_SIZE = struct.calcsize(HEADER_FORMAT)
103
+
104
+
105
+ @dataclass
106
+ class Header:
107
+ majorVersion: int
108
+ minorVersion: int
109
+ patchVersion: int
110
+ schemaVersion: int
111
+ argumentCount: int
112
+ statementCount: int
113
+ bodySize: int
114
+
115
+
116
+ FOOTER_FORMAT = "!I"
117
+ FOOTER_SIZE = struct.calcsize(FOOTER_FORMAT)
118
+
119
+
120
+ @dataclass
121
+ class Footer:
122
+ crc: int
123
+
124
+
125
+ def serialize_directives(dirs: list[Directive], output: Path = None):
126
+ output_bytes = bytes()
127
+
128
+ for dir in dirs:
129
+ output_bytes += dir.serialize()
130
+
131
+ header = Header(0, 0, 0, 1, 0, len(dirs), len(output_bytes))
132
+ output_bytes = struct.pack(HEADER_FORMAT, *astuple(header)) + output_bytes
133
+
134
+ crc = zlib.crc32(output_bytes) % (1 << 32)
135
+ footer = Footer(crc)
136
+ output_bytes += struct.pack(FOOTER_FORMAT, *astuple(footer))
137
+
138
+ if output is None:
139
+ output = input.with_suffix(".bin")
140
+
141
+ output.write_bytes(output_bytes)
142
+
143
+
144
+ @dataclass
145
+ class WaitRelDirective(Directive):
146
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.WAIT_REL
147
+ seconds: int
148
+ useconds: int
149
+
150
+ def serialize_args(self) -> bytes:
151
+ return U32Type(self.seconds).serialize() + U32Type(self.useconds).serialize()
152
+
153
+
154
+ @dataclass
155
+ class WaitAbsDirective(Directive):
156
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.WAIT_ABS
157
+ wakeup_time: TimeType
158
+
159
+ def serialize_args(self) -> bytes:
160
+ return self.wakeup_time.serialize()
161
+
162
+
163
+ @dataclass
164
+ class SetSerRegDirective(Directive):
165
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SET_SER_REG
166
+
167
+ index: int
168
+ """U8: The index of the local variable to set."""
169
+ value: bytes
170
+ """[Fpy.MAX_SERIALIZABLE_REGISTER_SIZE] U8: The value of the local variable."""
171
+
172
+ def serialize_args(self) -> bytes:
173
+ data = bytearray()
174
+ data.extend(U8Type(self.index).serialize())
175
+ data.extend(self.value)
176
+ return bytes(data)
177
+
178
+
179
+ @dataclass
180
+ class GotoDirective(Directive):
181
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.GOTO
182
+ statement_index: int
183
+ """U32: The statement index to execute next."""
184
+
185
+ def serialize_args(self) -> bytes:
186
+ return U32Type(self.statement_index).serialize()
187
+
188
+
189
+ @dataclass
190
+ class IfDirective(Directive):
191
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.IF
192
+ conditional_reg: int
193
+ """U8: The register to branch based off of (interpreted as a C++ boolean)."""
194
+ false_goto_stmt_index: int
195
+ """U32: The statement index to go to if the register is false."""
196
+
197
+ def serialize_args(self) -> bytes:
198
+ return (
199
+ U8Type(self.conditional_reg).serialize()
200
+ + U32Type(self.false_goto_stmt_index).serialize()
201
+ )
202
+
203
+
204
+ @dataclass
205
+ class NoOpDirective(Directive):
206
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.NO_OP
207
+
208
+ def serialize_args(self) -> bytes:
209
+ return bytes()
210
+
211
+
212
+ @dataclass
213
+ class GetTlmDirective(Directive):
214
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.GET_TLM
215
+ value_dest_sreg: int
216
+ """U8: The local variable to store the telemetry value in."""
217
+ time_dest_sreg: int
218
+ """U8: The local variable to store the telemetry time in."""
219
+ chan_id: int
220
+ """FwChanIdType: The telemetry channel ID to get."""
221
+
222
+ def serialize_args(self) -> bytes:
223
+ data = bytearray()
224
+ data.extend(U8Type(self.value_dest_sreg).serialize())
225
+ data.extend(U8Type(self.time_dest_sreg).serialize())
226
+ data.extend(FwChanIdType(self.chan_id).serialize())
227
+ return bytes(data)
228
+
229
+
230
+ @dataclass
231
+ class GetPrmDirective(Directive):
232
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.GET_PRM
233
+ dest_sreg_index: int
234
+ """U8: The local variable to store the parameter value in."""
235
+ prm_id: int
236
+ """FwPrmIdType: The parameter ID to get the value of."""
237
+
238
+ def serialize_args(self) -> bytes:
239
+ return (
240
+ U8Type(self.dest_sreg_index).serialize()
241
+ + FwPrmIdType(self.prm_id).serialize()
242
+ )
243
+
244
+
245
+ @dataclass
246
+ class CmdDirective(Directive):
247
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.CMD
248
+ op_code: int
249
+ """FwOpcodeType: The opcode of the command."""
250
+ arg_buf: bytes
251
+ """[Fpy.MAX_SERIALIZABLE_REGISTER_SIZE] U8: The argument buffer of the command."""
252
+
253
+ def serialize_args(self) -> bytes:
254
+ data = bytearray()
255
+ data.extend(FwOpcodeType(self.op_code).serialize())
256
+ data.extend(self.arg_buf)
257
+ return bytes(data)
258
+
259
+
260
+ @dataclass
261
+ class _DeserSerRegDirective(Directive):
262
+ """
263
+ Deserializes up to 8 bytes from a local variable into a register.
264
+ """
265
+
266
+ src_sreg_idx: int
267
+ """U8: The local variable to deserialize from."""
268
+ src_offset: int
269
+ """FwSizeType: The starting offset to deserialize from."""
270
+ dest_reg: int
271
+ """U8: The destination register to deserialize into."""
272
+
273
+ def serialize_args(self) -> bytes:
274
+ data = bytearray()
275
+ data.extend(U8Type(self.src_sreg_idx).serialize())
276
+ data.extend(FwSizeType(self.src_offset).serialize())
277
+ data.extend(U8Type(self.dest_reg).serialize())
278
+ return bytes(data)
279
+
280
+
281
+ class DeserSerReg8Directive(_DeserSerRegDirective):
282
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_8
283
+
284
+
285
+ class DeserSerReg4Directive(_DeserSerRegDirective):
286
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_4
287
+
288
+
289
+ class DeserSerReg2Directive(_DeserSerRegDirective):
290
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_2
291
+
292
+
293
+ class DeserSerReg1Directive(_DeserSerRegDirective):
294
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.DESER_SER_REG_1
295
+
296
+
297
+ @dataclass
298
+ class SetRegDirective(Directive):
299
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SET_REG
300
+
301
+ dest: int
302
+ """U8: The register to store the value in."""
303
+ value: int
304
+ """I64: The value to store in the register."""
305
+
306
+ def serialize_args(self) -> bytes:
307
+ return U8Type(self.dest).serialize() + I64Type(self.value).serialize()
308
+
309
+
310
+ @dataclass
311
+ class _BinaryRegOpDirective(Directive):
312
+ lhs: int
313
+ """U8: The left-hand side register for comparison."""
314
+ rhs: int
315
+ """U8: The right-hand side register for comparison."""
316
+ res: int
317
+ """U8: The destination register for the boolean result."""
318
+
319
+ def serialize_args(self) -> bytes:
320
+ data = bytearray()
321
+ data.extend(U8Type(self.lhs).serialize())
322
+ data.extend(U8Type(self.rhs).serialize())
323
+ data.extend(U8Type(self.res).serialize())
324
+ return bytes(data)
325
+
326
+
327
+ class OrDirective(_BinaryRegOpDirective):
328
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.OR
329
+
330
+
331
+ class AndDirective(_BinaryRegOpDirective):
332
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.AND
333
+
334
+
335
+ class IntEqualDirective(_BinaryRegOpDirective):
336
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.IEQ
337
+
338
+
339
+ class IntNotEqualDirective(_BinaryRegOpDirective):
340
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.INE
341
+
342
+
343
+ class UnsignedLessThanDirective(_BinaryRegOpDirective):
344
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.ULT
345
+
346
+
347
+ class UnsignedLessThanOrEqualDirective(_BinaryRegOpDirective):
348
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.ULE
349
+
350
+
351
+ class UnsignedGreaterThanDirective(_BinaryRegOpDirective):
352
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.UGT
353
+
354
+
355
+ class UnsignedGreaterThanOrEqualDirective(_BinaryRegOpDirective):
356
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.UGE
357
+
358
+
359
+ class SignedLessThanDirective(_BinaryRegOpDirective):
360
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SLT
361
+
362
+
363
+ class SignedLessThanOrEqualDirective(_BinaryRegOpDirective):
364
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SLE
365
+
366
+
367
+ class SignedGreaterThanDirective(_BinaryRegOpDirective):
368
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SGT
369
+
370
+
371
+ class SignedGreaterThanOrEqualDirective(_BinaryRegOpDirective):
372
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SGE
373
+
374
+
375
+ class FloatGreaterThanOrEqualDirective(_BinaryRegOpDirective):
376
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FGE
377
+
378
+
379
+ class FloatLessThanOrEqualDirective(_BinaryRegOpDirective):
380
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FLE
381
+
382
+
383
+ class FloatLessThanDirective(_BinaryRegOpDirective):
384
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FLT
385
+
386
+
387
+ class FloatGreaterThanDirective(_BinaryRegOpDirective):
388
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FGT
389
+
390
+
391
+ class FloatEqualDirective(_BinaryRegOpDirective):
392
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FEQ
393
+
394
+
395
+ class FloatNotEqualDirective(_BinaryRegOpDirective):
396
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FNE
397
+
398
+
399
+ @dataclass
400
+ class _UnaryRegOpDirective(Directive):
401
+ src: int
402
+ res: int
403
+
404
+ def serialize_args(self) -> bytes:
405
+ data = bytearray()
406
+ data.extend(U8Type(self.src).serialize())
407
+ data.extend(U8Type(self.res).serialize())
408
+ return bytes(data)
409
+
410
+
411
+ @dataclass
412
+ class NotDirective(_UnaryRegOpDirective):
413
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.NOT
414
+
415
+
416
+ @dataclass
417
+ class FloatTruncateDirective(_UnaryRegOpDirective):
418
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPTRUNC
419
+
420
+
421
+ @dataclass
422
+ class FloatExtendDirective(_UnaryRegOpDirective):
423
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPEXT
424
+
425
+
426
+ @dataclass
427
+ class FloatToSignedIntDirective(_UnaryRegOpDirective):
428
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPTOSI
429
+
430
+
431
+ @dataclass
432
+ class SignedIntToFloatDirective(_UnaryRegOpDirective):
433
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.SITOFP
434
+
435
+
436
+ @dataclass
437
+ class FloatToUnsignedIntDirective(_UnaryRegOpDirective):
438
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.FPTOUI
439
+
440
+
441
+ @dataclass
442
+ class UnsignedIntToFloatDirective(_UnaryRegOpDirective):
443
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.UITOFP
444
+
445
+
446
+ @dataclass
447
+ class ExitDirective(Directive):
448
+ opcode: ClassVar[DirectiveOpcode] = DirectiveOpcode.EXIT
449
+ success: bool
450
+
451
+ def serialize_args(self):
452
+ return BoolType(self.success).serialize()
453
+
454
+
455
+ INT_EQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
456
+ "==": IntEqualDirective,
457
+ "!=": IntNotEqualDirective,
458
+ }
459
+
460
+ FLOAT_EQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
461
+ "==": FloatEqualDirective,
462
+ "!=": FloatNotEqualDirective,
463
+ }
464
+
465
+
466
+ INT_SIGNED_INEQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
467
+ ">": SignedGreaterThanDirective,
468
+ "<": SignedLessThanDirective,
469
+ ">=": SignedGreaterThanOrEqualDirective,
470
+ "<=": SignedLessThanOrEqualDirective,
471
+ }
472
+ INT_UNSIGNED_INEQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
473
+ ">": UnsignedGreaterThanDirective,
474
+ "<": UnsignedLessThanDirective,
475
+ ">=": UnsignedGreaterThanOrEqualDirective,
476
+ "<=": UnsignedLessThanOrEqualDirective,
477
+ }
478
+ FLOAT_INEQUALITY_DIRECTIVES: dict[str, type[_BinaryRegOpDirective]] = {
479
+ ">": FloatGreaterThanDirective,
480
+ "<": FloatLessThanDirective,
481
+ ">=": FloatGreaterThanOrEqualDirective,
482
+ "<=": FloatLessThanOrEqualDirective,
483
+ }
484
+
485
+ BINARY_COMPARISON_DIRECTIVES = {}
486
+ BINARY_COMPARISON_DIRECTIVES.update(INT_EQUALITY_DIRECTIVES)
487
+ BINARY_COMPARISON_DIRECTIVES.update(INT_SIGNED_INEQUALITY_DIRECTIVES)
488
+ BINARY_COMPARISON_DIRECTIVES.update(INT_UNSIGNED_INEQUALITY_DIRECTIVES)
489
+ BINARY_COMPARISON_DIRECTIVES.update(FLOAT_EQUALITY_DIRECTIVES)
490
+ BINARY_COMPARISON_DIRECTIVES.update(FLOAT_INEQUALITY_DIRECTIVES)