opencrbasic 1.0.0__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.
- opencrbasic/__init__.py +3 -0
- opencrbasic/__main__.py +5 -0
- opencrbasic/analysis.py +184 -0
- opencrbasic/bindings.py +1034 -0
- opencrbasic/catalog.py +173 -0
- opencrbasic/checkconfig.py +144 -0
- opencrbasic/checker/__init__.py +977 -0
- opencrbasic/checker/cr3xx.py +3118 -0
- opencrbasic/checker/ess.py +81 -0
- opencrbasic/checker/expressions.py +3581 -0
- opencrbasic/checker/instr_data.py +1802 -0
- opencrbasic/checker/instr_measure.py +1547 -0
- opencrbasic/checker/instr_rules.py +3540 -0
- opencrbasic/checker/instructions.py +17 -0
- opencrbasic/checker/intervals.py +678 -0
- opencrbasic/checker/longconv.py +133 -0
- opencrbasic/checker/scan_time.py +580 -0
- opencrbasic/checker/storage.py +456 -0
- opencrbasic/checker/structs.py +240 -0
- opencrbasic/checker/structure.py +6213 -0
- opencrbasic/checker/symbols.py +609 -0
- opencrbasic/checker/terminals.py +249 -0
- opencrbasic/checker/unused.py +186 -0
- opencrbasic/checker/var_types.py +564 -0
- opencrbasic/checker/warnings.py +661 -0
- opencrbasic/checks.py +491 -0
- opencrbasic/cli.py +391 -0
- opencrbasic/commands.py +128 -0
- opencrbasic/compiler.py +320 -0
- opencrbasic/consteval.py +327 -0
- opencrbasic/data/background_calibration.json +4 -0
- opencrbasic/data/before_beginprog.json +99 -0
- opencrbasic/data/cr1000x/background_calibration.json +4 -0
- opencrbasic/data/cr1000x/before_beginprog.json +138 -0
- opencrbasic/data/cr1000x/ess_variables.json +1087 -0
- opencrbasic/data/cr1000x/fnotch.json +29 -0
- opencrbasic/data/cr1000x/functions.json +1337 -0
- opencrbasic/data/cr1000x/instructions.json +4836 -0
- opencrbasic/data/cr1000x/measure.json +121 -0
- opencrbasic/data/cr1000x/mode.json +111 -0
- opencrbasic/data/cr1000x/pipeline_tasks.json +88 -0
- opencrbasic/data/cr1000x/settings_fields.json +321 -0
- opencrbasic/data/cr1000x/status_members.json +318 -0
- opencrbasic/data/cr1000x/symbols.json +872 -0
- opencrbasic/data/cr1000x/terminals.json +225 -0
- opencrbasic/data/cr300/before_beginprog.json +42 -0
- opencrbasic/data/cr300/ess_variables.json +1087 -0
- opencrbasic/data/cr300/fnotch.json +22 -0
- opencrbasic/data/cr300/functions.json +1261 -0
- opencrbasic/data/cr300/instructions.json +2837 -0
- opencrbasic/data/cr300/measure.json +33 -0
- opencrbasic/data/cr300/mode.json +121 -0
- opencrbasic/data/cr300/settings_fields.json +259 -0
- opencrbasic/data/cr300/status_members.json +303 -0
- opencrbasic/data/cr300/symbols.json +584 -0
- opencrbasic/data/cr300/terminals.json +193 -0
- opencrbasic/data/cr350/before_beginprog.json +44 -0
- opencrbasic/data/cr350/ess_variables.json +1087 -0
- opencrbasic/data/cr350/fnotch.json +22 -0
- opencrbasic/data/cr350/functions.json +1262 -0
- opencrbasic/data/cr350/instructions.json +2848 -0
- opencrbasic/data/cr350/measure.json +35 -0
- opencrbasic/data/cr350/mode.json +121 -0
- opencrbasic/data/cr350/settings_fields.json +292 -0
- opencrbasic/data/cr350/status_members.json +303 -0
- opencrbasic/data/cr350/symbols.json +572 -0
- opencrbasic/data/cr350/terminals.json +190 -0
- opencrbasic/data/ess_variables.json +1087 -0
- opencrbasic/data/fnotch.json +34 -0
- opencrbasic/data/functions.json +1337 -0
- opencrbasic/data/instructions.json +4965 -0
- opencrbasic/data/measure.json +123 -0
- opencrbasic/data/mode.json +121 -0
- opencrbasic/data/notices_cr6.json +890 -0
- opencrbasic/data/pipeline_tasks.json +84 -0
- opencrbasic/data/settings_fields.json +322 -0
- opencrbasic/data/status_members.json +319 -0
- opencrbasic/data/status_table.json +684 -0
- opencrbasic/data/symbols.json +902 -0
- opencrbasic/data/terminals.json +195 -0
- opencrbasic/data/type_codes.json +249 -0
- opencrbasic/diagnostics.py +196 -0
- opencrbasic/editing.py +827 -0
- opencrbasic/formatting.py +310 -0
- opencrbasic/helpdocs.py +677 -0
- opencrbasic/hover.py +667 -0
- opencrbasic/inlay.py +169 -0
- opencrbasic/lexer.py +183 -0
- opencrbasic/lsp/__init__.py +5 -0
- opencrbasic/lsp/__main__.py +7 -0
- opencrbasic/lsp/config.py +202 -0
- opencrbasic/lsp/features.py +602 -0
- opencrbasic/lsp/server.py +741 -0
- opencrbasic/lsp/session.py +1189 -0
- opencrbasic/lsp/worker.py +128 -0
- opencrbasic/mode.py +143 -0
- opencrbasic/navigation.py +401 -0
- opencrbasic/parser.py +3264 -0
- opencrbasic/positions.py +274 -0
- opencrbasic/preprocess.py +269 -0
- opencrbasic/profiles.py +266 -0
- opencrbasic/provenance.py +17 -0
- opencrbasic/quickfix.py +331 -0
- opencrbasic/rename.py +662 -0
- opencrbasic/signature.py +33 -0
- opencrbasic/source.py +600 -0
- opencrbasic/sources.py +125 -0
- opencrbasic/syntax.py +337 -0
- opencrbasic/tables.py +2173 -0
- opencrbasic/tables_hook.py +14 -0
- opencrbasic/tdf.py +142 -0
- opencrbasic/timing.py +565 -0
- opencrbasic-1.0.0.dist-info/METADATA +223 -0
- opencrbasic-1.0.0.dist-info/RECORD +117 -0
- opencrbasic-1.0.0.dist-info/WHEEL +4 -0
- opencrbasic-1.0.0.dist-info/entry_points.txt +3 -0
- opencrbasic-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
{
|
|
2
|
+
"channels": {
|
|
3
|
+
"u_terminal": {
|
|
4
|
+
"ranges": [[201, 212]],
|
|
5
|
+
"transform": "none",
|
|
6
|
+
"skip_nonpositive": false,
|
|
7
|
+
"message": "Invalid channel {v}, must use U1..U12."
|
|
8
|
+
},
|
|
9
|
+
"u_terminal_se": {
|
|
10
|
+
"ranges": [[201, 212]],
|
|
11
|
+
"span": {"message": "Channel {v} exceeds number of valid channels.", "shift": -200, "start_upper": false},
|
|
12
|
+
"transform": "abs",
|
|
13
|
+
"skip_nonpositive": false,
|
|
14
|
+
"message": "Invalid channel {v}, must use U1..U12."
|
|
15
|
+
},
|
|
16
|
+
"u_terminal_diff": {
|
|
17
|
+
"ranges": [[201, 212]],
|
|
18
|
+
"span": {"message": "Channel {v} exceeds number of valid channels.", "shift": -200, "start_upper": false, "step": 2},
|
|
19
|
+
"transform": "abs",
|
|
20
|
+
"skip_nonpositive": false,
|
|
21
|
+
"message": "Invalid channel {v}, must use U1..U12.",
|
|
22
|
+
"odd_only": true,
|
|
23
|
+
"odd_message": "Invalid start channel for Differential Measurement. Must be U1, U3, U5 ..."
|
|
24
|
+
},
|
|
25
|
+
"excite_channel": {
|
|
26
|
+
"ranges": [[201, 212]],
|
|
27
|
+
"transform": "none",
|
|
28
|
+
"skip_nonpositive": false,
|
|
29
|
+
"message": "Invalid Excitation channel (must be U1-U12)."
|
|
30
|
+
},
|
|
31
|
+
"port_c1c4_u1u12": {
|
|
32
|
+
"ranges": [[101, 116], [201, 212]],
|
|
33
|
+
"port_wrap": true,
|
|
34
|
+
"transform": "none",
|
|
35
|
+
"skip_nonpositive": false,
|
|
36
|
+
"message": "Invalid port {v}, use C1..C4 or U1..U12.",
|
|
37
|
+
"string_int_min": true
|
|
38
|
+
},
|
|
39
|
+
"sdi_port": {
|
|
40
|
+
"ranges": [[101, 103], [201, 211]],
|
|
41
|
+
"transform": "none",
|
|
42
|
+
"skip_nonpositive": false,
|
|
43
|
+
"odd_only": true,
|
|
44
|
+
"message": "Invalid SDI-12 port, must be C1,C3 or U1,U3...U11",
|
|
45
|
+
"string_int_min": true,
|
|
46
|
+
"odd_message": "Invalid SDI-12 port, must be C1,C3 or U1,U3...U11"
|
|
47
|
+
},
|
|
48
|
+
"i2c_port": {
|
|
49
|
+
"ranges": [[101, 116], [201, 212]],
|
|
50
|
+
"transform": "none",
|
|
51
|
+
"skip_nonpositive": false,
|
|
52
|
+
"message": "Invalid port {v}, use C1..C4 or U1..U12.",
|
|
53
|
+
"odd_only": true,
|
|
54
|
+
"odd_message": "I2C port must be 1,3,5,7..."
|
|
55
|
+
},
|
|
56
|
+
"spi_port": {
|
|
57
|
+
"ranges": [[101, 116], [201, 212]],
|
|
58
|
+
"transform": "none",
|
|
59
|
+
"skip_nonpositive": false,
|
|
60
|
+
"message": "Invalid port {v}, use C1..C4 or U1..U12.",
|
|
61
|
+
"allowed": [101, 105, 109, 113, 201, 205, 209],
|
|
62
|
+
"allowed_message": "SPI Port must be C1, U1, U5, or U9.",
|
|
63
|
+
"string_int_min": true
|
|
64
|
+
},
|
|
65
|
+
"timer_port": {
|
|
66
|
+
"ranges": [[101, 116], [201, 212]],
|
|
67
|
+
"transform": "none",
|
|
68
|
+
"skip_nonpositive": false,
|
|
69
|
+
"message": "Invalid port {v}, use C1..C4 or U1..U12.",
|
|
70
|
+
"allowed": [101, 105, 201],
|
|
71
|
+
"allowed_message": "TimerInput starting channel must be C1 or U1."
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"instructions": {
|
|
75
|
+
"TCDIFF": [
|
|
76
|
+
[4, "u_terminal_diff", 2]
|
|
77
|
+
],
|
|
78
|
+
"TCSE": [
|
|
79
|
+
[4, "u_terminal_se", 2]
|
|
80
|
+
],
|
|
81
|
+
"VOLTSE": [
|
|
82
|
+
[4, "u_terminal_se", 2]
|
|
83
|
+
],
|
|
84
|
+
"VOLTDIFF": [
|
|
85
|
+
[4, "u_terminal_diff", 2]
|
|
86
|
+
],
|
|
87
|
+
"BRHALF": [
|
|
88
|
+
[4, "u_terminal_se", 2]
|
|
89
|
+
],
|
|
90
|
+
"BRHALF3W": [
|
|
91
|
+
[4, "u_terminal_se", 2, 2]
|
|
92
|
+
],
|
|
93
|
+
"BRFULL": [
|
|
94
|
+
[4, "u_terminal_diff", 2]
|
|
95
|
+
],
|
|
96
|
+
"BRHALF4W": [
|
|
97
|
+
[5, "u_terminal_diff", 2, 2]
|
|
98
|
+
],
|
|
99
|
+
"BRFULL6W": [
|
|
100
|
+
[5, "u_terminal_diff", 2, 2]
|
|
101
|
+
],
|
|
102
|
+
"THERM107": [
|
|
103
|
+
[3, "u_terminal_se", 2]
|
|
104
|
+
],
|
|
105
|
+
"THERM108": [
|
|
106
|
+
[3, "u_terminal_se", 2]
|
|
107
|
+
],
|
|
108
|
+
"THERM109": [
|
|
109
|
+
[3, "u_terminal_se", 2]
|
|
110
|
+
],
|
|
111
|
+
"ACPOWER": [
|
|
112
|
+
[4, "u_terminal"],
|
|
113
|
+
[7, "u_terminal"]
|
|
114
|
+
],
|
|
115
|
+
"CS616": [
|
|
116
|
+
[3, "u_terminal"],
|
|
117
|
+
[4, "port_c1c4_u1u12"]
|
|
118
|
+
],
|
|
119
|
+
"EXCITEV": [
|
|
120
|
+
[1, "u_terminal"],
|
|
121
|
+
[1, "excite_channel"]
|
|
122
|
+
],
|
|
123
|
+
"EXCITEI": [
|
|
124
|
+
[1, "u_terminal"],
|
|
125
|
+
[1, "excite_channel"]
|
|
126
|
+
],
|
|
127
|
+
"PORTSET": [
|
|
128
|
+
[1, "port_c1c4_u1u12"]
|
|
129
|
+
],
|
|
130
|
+
"PORTGET": [
|
|
131
|
+
[2, "port_c1c4_u1u12"]
|
|
132
|
+
],
|
|
133
|
+
"SDI12RECORDER": [
|
|
134
|
+
[2, "sdi_port"]
|
|
135
|
+
],
|
|
136
|
+
"AM25T": [
|
|
137
|
+
[5, "u_terminal_diff"],
|
|
138
|
+
[8, "port_c1c4_u1u12"],
|
|
139
|
+
[9, "port_c1c4_u1u12"],
|
|
140
|
+
[10, "u_terminal"]
|
|
141
|
+
],
|
|
142
|
+
"I2COPEN": [
|
|
143
|
+
[1, "i2c_port"]
|
|
144
|
+
],
|
|
145
|
+
"I2CREAD": [
|
|
146
|
+
[1, "i2c_port"]
|
|
147
|
+
],
|
|
148
|
+
"I2CWRITE": [
|
|
149
|
+
[1, "i2c_port"]
|
|
150
|
+
],
|
|
151
|
+
"MUXSELECT": [
|
|
152
|
+
[1, "port_c1c4_u1u12"],
|
|
153
|
+
[2, "port_c1c4_u1u12"]
|
|
154
|
+
],
|
|
155
|
+
"PWM": [
|
|
156
|
+
[2, "port_c1c4_u1u12"]
|
|
157
|
+
],
|
|
158
|
+
"PORTPAIRCONFIG": [
|
|
159
|
+
[1, "port_c1c4_u1u12"]
|
|
160
|
+
],
|
|
161
|
+
"PULSEPORT": [
|
|
162
|
+
[1, "port_c1c4_u1u12"]
|
|
163
|
+
],
|
|
164
|
+
"PULSECOUNT": [
|
|
165
|
+
[3, "port_c1c4_u1u12"]
|
|
166
|
+
],
|
|
167
|
+
"QUADRATURE": [
|
|
168
|
+
[2, "port_c1c4_u1u12"]
|
|
169
|
+
],
|
|
170
|
+
"SPIOPEN": [
|
|
171
|
+
[1, "spi_port"]
|
|
172
|
+
],
|
|
173
|
+
"SPIREAD": [
|
|
174
|
+
[1, "spi_port"]
|
|
175
|
+
],
|
|
176
|
+
"SPIWRITE": [
|
|
177
|
+
[1, "spi_port"]
|
|
178
|
+
],
|
|
179
|
+
"TIMERINPUT": [
|
|
180
|
+
[2, "timer_port"]
|
|
181
|
+
],
|
|
182
|
+
"WAITDIGTRIG": [
|
|
183
|
+
[1, "port_c1c4_u1u12"]
|
|
184
|
+
],
|
|
185
|
+
"CWB100RSSI": [
|
|
186
|
+
[1, "sdi_port"]
|
|
187
|
+
],
|
|
188
|
+
"CWB100DIAGNOSTICS": [
|
|
189
|
+
[1, "sdi_port"]
|
|
190
|
+
],
|
|
191
|
+
"SDI12SENSORSETUP": [
|
|
192
|
+
[2, "sdi_port"]
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
{
|
|
2
|
+
"1": {
|
|
3
|
+
"kind": "const_expr",
|
|
4
|
+
"desc": "Compile-time constant numeric expression: named constant fast-path or a full folded expression (literals, Consts, predefined symbols, arithmetic); a quoted numeric string is also accepted; rejects a live variable."
|
|
5
|
+
},
|
|
6
|
+
"2": {
|
|
7
|
+
"kind": "expr",
|
|
8
|
+
"desc": "General runtime expression or value; may be a variable, literal, or arithmetic expression; no compile-time type check."
|
|
9
|
+
},
|
|
10
|
+
"3": {
|
|
11
|
+
"kind": "for_header",
|
|
12
|
+
"desc": "FOR loop header: Var = start TO end [STEP step], parsed as one unit (4 words: variable, start, end, step)."
|
|
13
|
+
},
|
|
14
|
+
"4": {
|
|
15
|
+
"kind": "const_int_kw",
|
|
16
|
+
"desc": "Constant integer/keyword, tolerant of being absent at end of line (e.g. Do/Loop/Else's optional While/Until marker); when absent, all remaining codes for the instruction are silently defaulted."
|
|
17
|
+
},
|
|
18
|
+
"5": {
|
|
19
|
+
"kind": "const_expr_only",
|
|
20
|
+
"desc": "Compile-time constant only; always rejects a variable reference (paired with 38, the time-unit-scaled variant)."
|
|
21
|
+
},
|
|
22
|
+
"6": {
|
|
23
|
+
"kind": "identifier",
|
|
24
|
+
"desc": "A name token whose meaning is instruction-specific (Sub name, table name, or a Var=UnitString pair for Units); captured as raw text and interpreted/validated later, not compiled here."
|
|
25
|
+
},
|
|
26
|
+
"7": {
|
|
27
|
+
"kind": "bool_expr",
|
|
28
|
+
"desc": "General expression used as a condition (If/While/Select/Case); no compile-time type restriction."
|
|
29
|
+
},
|
|
30
|
+
"8": {
|
|
31
|
+
"kind": "variable_or_array",
|
|
32
|
+
"desc": "Destination variable or array (no index required); accepts a promotable expression but rejects a bare literal."
|
|
33
|
+
},
|
|
34
|
+
"9": {
|
|
35
|
+
"kind": "var_decl",
|
|
36
|
+
"desc": "Dim variable declaration: Name[(dims)] [As Type] [= init | {init,...}]."
|
|
37
|
+
},
|
|
38
|
+
"10": {
|
|
39
|
+
"kind": "var_decl",
|
|
40
|
+
"desc": "Public variable declaration; identical parser to code 9."
|
|
41
|
+
},
|
|
42
|
+
"11": {
|
|
43
|
+
"kind": "deferred_text",
|
|
44
|
+
"desc": "Raw expression text captured verbatim for later compilation (DataTable statistics function Source parameters); no type/constancy check at this layer."
|
|
45
|
+
},
|
|
46
|
+
"12": {
|
|
47
|
+
"kind": "sub_params",
|
|
48
|
+
"desc": "Sub parameter-list declaration; enforces OPTIONAL/required ordering and initializer rules."
|
|
49
|
+
},
|
|
50
|
+
"13": {
|
|
51
|
+
"kind": "expr_list",
|
|
52
|
+
"desc": "Comma-separated list of general expressions up to a closing ')' (Call's argument list)."
|
|
53
|
+
},
|
|
54
|
+
"14": {
|
|
55
|
+
"kind": "none",
|
|
56
|
+
"desc": "No argument (EndSub/EndFunction)."
|
|
57
|
+
},
|
|
58
|
+
"15": {
|
|
59
|
+
"kind": "unused",
|
|
60
|
+
"desc": "Not emitted by any CR6 instruction; real switch case exists in the decompiled parser but is unreachable from instructions.json."
|
|
61
|
+
},
|
|
62
|
+
"16": {
|
|
63
|
+
"kind": "end_exit_kw",
|
|
64
|
+
"desc": "End/Exit's optional target keyword (Prog/Sub/Function/...); absent is valid."
|
|
65
|
+
},
|
|
66
|
+
"17": {
|
|
67
|
+
"kind": "next_kw",
|
|
68
|
+
"desc": "NEXT's optional trailing keyword (Scan or SubScan); an unrecognised token is silently treated as absent."
|
|
69
|
+
},
|
|
70
|
+
"18": {
|
|
71
|
+
"kind": "raw_line_text",
|
|
72
|
+
"desc": "Rest-of-line text captured verbatim (MenuPick's menu label)."
|
|
73
|
+
},
|
|
74
|
+
"19": {
|
|
75
|
+
"kind": "const_int_kw",
|
|
76
|
+
"desc": "Constant integer/keyword (e.g. bridge RevEx flag); failure to resolve is silently ignored rather than reported."
|
|
77
|
+
},
|
|
78
|
+
"20": {
|
|
79
|
+
"kind": "datatype_kw",
|
|
80
|
+
"desc": "Data-type/range/units keyword, constant-only, validated against a per-instruction allowed set."
|
|
81
|
+
},
|
|
82
|
+
"21": {
|
|
83
|
+
"kind": "unused",
|
|
84
|
+
"desc": "Not emitted by any CR6 instruction."
|
|
85
|
+
},
|
|
86
|
+
"22": {
|
|
87
|
+
"kind": "unused",
|
|
88
|
+
"desc": "Not emitted by any CR6 instruction."
|
|
89
|
+
},
|
|
90
|
+
"23": {
|
|
91
|
+
"kind": "unused",
|
|
92
|
+
"desc": "Not emitted by any CR6 instruction (shares a no-op goto with used code 32)."
|
|
93
|
+
},
|
|
94
|
+
"24": {
|
|
95
|
+
"kind": "expr",
|
|
96
|
+
"desc": "General expression/value (shares a handler with 40, without 40's extra output-marking flag)."
|
|
97
|
+
},
|
|
98
|
+
"25": {
|
|
99
|
+
"kind": "expr",
|
|
100
|
+
"desc": "General runtime expression/value; second most common code; a non-constant argument here is one of the documented triggers for forcing Sequential mode (docs/modes.md)."
|
|
101
|
+
},
|
|
102
|
+
"26": {
|
|
103
|
+
"kind": "expr_or_name",
|
|
104
|
+
"desc": "General expression/reference, flagged variant of 25, used where the token may need to resolve against a different namespace (e.g. table/module name)."
|
|
105
|
+
},
|
|
106
|
+
"27": {
|
|
107
|
+
"kind": "variable_or_array",
|
|
108
|
+
"desc": "Variable/array reference, array-checked like 8/29; oracle testing showed it rejects a table name and accepts a plain variable."
|
|
109
|
+
},
|
|
110
|
+
"28": {
|
|
111
|
+
"kind": "expr",
|
|
112
|
+
"desc": "General expression/value (shares a handler with 2/27); accepts a variable syntactically even where the consuming instruction then imposes its own stricter constant-only rule."
|
|
113
|
+
},
|
|
114
|
+
"29": {
|
|
115
|
+
"kind": "variable_or_array",
|
|
116
|
+
"desc": "Destination variable/array, array-checked; stricter sibling of code 8."
|
|
117
|
+
},
|
|
118
|
+
"30": {
|
|
119
|
+
"kind": "expr_pair",
|
|
120
|
+
"desc": "Two words per argument: an internal word followed by the value (VoiceSpeak only); purpose of the extra word not fully determined."
|
|
121
|
+
},
|
|
122
|
+
"31": {
|
|
123
|
+
"kind": "unused",
|
|
124
|
+
"desc": "Not emitted by any CR6 instruction; real switch case exists (constant-only expression with a 'Parameter %s must be a constant.' check) but unreachable from instructions.json."
|
|
125
|
+
},
|
|
126
|
+
"32": {
|
|
127
|
+
"kind": "none",
|
|
128
|
+
"desc": "No-op marker: consumes no argument text (RainFlowSample's first parameter)."
|
|
129
|
+
},
|
|
130
|
+
"33": {
|
|
131
|
+
"kind": "variable_or_array",
|
|
132
|
+
"desc": "Variable/array reference, array-checked, with an extra 2-word allowance when a string/array-length flag is set."
|
|
133
|
+
},
|
|
134
|
+
"34": {
|
|
135
|
+
"kind": "expr_typed",
|
|
136
|
+
"desc": "Return's expression; accepted shape depends on the enclosing Function's declared return type."
|
|
137
|
+
},
|
|
138
|
+
"35": {
|
|
139
|
+
"kind": "sub_params",
|
|
140
|
+
"desc": "Function parameter-list declaration; identical parser to code 12."
|
|
141
|
+
},
|
|
142
|
+
"36": {
|
|
143
|
+
"kind": "none",
|
|
144
|
+
"desc": "No argument; EndSelect only."
|
|
145
|
+
},
|
|
146
|
+
"37": {
|
|
147
|
+
"kind": "expr_marker",
|
|
148
|
+
"desc": "ConstTable's optional table-name argument; presence is checked but the text itself is not stored (0 words) - only ever used as its optional form, 137."
|
|
149
|
+
},
|
|
150
|
+
"38": {
|
|
151
|
+
"kind": "const_expr_only",
|
|
152
|
+
"desc": "Paired, unit-scaled sibling of code 5 (rounds by a stored time-unit divisor after parsing)."
|
|
153
|
+
},
|
|
154
|
+
"39": {
|
|
155
|
+
"kind": "const_expr",
|
|
156
|
+
"desc": "Paired sibling of code 1 with an extra rounding step against a stored time-unit divisor (e.g. Scan's Units parameter)."
|
|
157
|
+
},
|
|
158
|
+
"40": {
|
|
159
|
+
"kind": "expr",
|
|
160
|
+
"desc": "General expression/value (shares a handler with 24); additionally sets an internal output/disable-reference flag."
|
|
161
|
+
},
|
|
162
|
+
"41": {
|
|
163
|
+
"kind": "variable_or_array",
|
|
164
|
+
"desc": "Variable/array reference (Move's Dest); shares flags with 27/28's handler family."
|
|
165
|
+
},
|
|
166
|
+
"42": {
|
|
167
|
+
"kind": "expr_special",
|
|
168
|
+
"desc": "Variant of the general expression handler with extra auto-temp-variable machinery specific to VibratingWire."
|
|
169
|
+
},
|
|
170
|
+
"43": {
|
|
171
|
+
"kind": "unused",
|
|
172
|
+
"desc": "Not emitted by any CR6 instruction."
|
|
173
|
+
},
|
|
174
|
+
"44": {
|
|
175
|
+
"kind": "unused",
|
|
176
|
+
"desc": "Not emitted by any CR6 instruction."
|
|
177
|
+
},
|
|
178
|
+
"45": {
|
|
179
|
+
"kind": "type_name",
|
|
180
|
+
"desc": "StructureType/ObjectType name declaration; registers a new named type context, rejects nesting."
|
|
181
|
+
},
|
|
182
|
+
"46": {
|
|
183
|
+
"kind": "none",
|
|
184
|
+
"desc": "Closes a structure/object type context (EndStructureType/EndObjectType)."
|
|
185
|
+
},
|
|
186
|
+
"47": {
|
|
187
|
+
"kind": "variable_or_array",
|
|
188
|
+
"desc": "Variable/array reference, array-checked (flags 0x200)."
|
|
189
|
+
},
|
|
190
|
+
"48": {
|
|
191
|
+
"kind": "variable_or_array",
|
|
192
|
+
"desc": "Variable/array reference, array-checked (flags 0x4000); only ever used as its optional form, 148."
|
|
193
|
+
},
|
|
194
|
+
"101": {
|
|
195
|
+
"kind": "const_expr",
|
|
196
|
+
"desc": "Optional Mask/Interval-style constant (e.g. WriteIO's, ExciteV's trailing constant); still rejects a variable once present.",
|
|
197
|
+
"optional_of": 1
|
|
198
|
+
},
|
|
199
|
+
"105": {
|
|
200
|
+
"kind": "const_expr_only",
|
|
201
|
+
"desc": "Optional constant-only value (e.g. Thermistor/VibratingWire trailing settling/multiplier constants).",
|
|
202
|
+
"optional_of": 5
|
|
203
|
+
},
|
|
204
|
+
"108": {
|
|
205
|
+
"kind": "variable_or_array",
|
|
206
|
+
"desc": "Optional constant/keyword (e.g. SlowSequence's, Calibrate's trailing option).",
|
|
207
|
+
"optional_of": 8
|
|
208
|
+
},
|
|
209
|
+
"120": {
|
|
210
|
+
"kind": "datatype_kw",
|
|
211
|
+
"desc": "Optional data-type/units keyword (VibratingWire).",
|
|
212
|
+
"optional_of": 20
|
|
213
|
+
},
|
|
214
|
+
"124": {
|
|
215
|
+
"kind": "expr",
|
|
216
|
+
"desc": "Optional general expression (AvgRun/TotalRun/StdDevRun's Count parameter).",
|
|
217
|
+
"optional_of": 24
|
|
218
|
+
},
|
|
219
|
+
"125": {
|
|
220
|
+
"kind": "expr",
|
|
221
|
+
"desc": "Optional general expression (AvgRun/TotalRun/StdDevRun's RunReset/TotalCalls/Call_ID parameters); confirmed to accept a variable, a literal, or omission.",
|
|
222
|
+
"optional_of": 25
|
|
223
|
+
},
|
|
224
|
+
"126": {
|
|
225
|
+
"kind": "expr_or_name",
|
|
226
|
+
"desc": "Optional expression/reference (SDI12SensorSetup, FieldClassify, MQTTPublishMeta).",
|
|
227
|
+
"optional_of": 26
|
|
228
|
+
},
|
|
229
|
+
"127": {
|
|
230
|
+
"kind": "variable_or_array",
|
|
231
|
+
"desc": "Optional expression/reference (GPS, ModBus family, GetDataRecord).",
|
|
232
|
+
"optional_of": 27
|
|
233
|
+
},
|
|
234
|
+
"129": {
|
|
235
|
+
"kind": "variable_or_array",
|
|
236
|
+
"desc": "Optional expression/reference (CDM_VW300Config trailing parameters).",
|
|
237
|
+
"optional_of": 29
|
|
238
|
+
},
|
|
239
|
+
"137": {
|
|
240
|
+
"kind": "expr_marker",
|
|
241
|
+
"desc": "Optional identifier (ConstTable's table name); presence-only, no text stored.",
|
|
242
|
+
"optional_of": 37
|
|
243
|
+
},
|
|
244
|
+
"148": {
|
|
245
|
+
"kind": "variable_or_array",
|
|
246
|
+
"desc": "Optional variable/array reference (MQTTPublishTable's trailing fields).",
|
|
247
|
+
"optional_of": 48
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""Diagnostics in CR6Comp.exe's format.
|
|
2
|
+
|
|
3
|
+
CR6Comp prints errors as `line N: <message>` and warnings as `Warning: <message>`; the message
|
|
4
|
+
texts mirror the exe's format strings (docs/messages.tsv). Line numbers are per-file, not
|
|
5
|
+
translated to the site of the `Include`/`IncludeSection` call that pulled the code in
|
|
6
|
+
(`source.py`'s own docstring, oracle-confirmed).
|
|
7
|
+
|
|
8
|
+
**File-origin prefix** (`docs/checker.md` "Errors from an included file" and "Prefix by message
|
|
9
|
+
kind in an included file"): an *error* whose statement came from a file other than the main program
|
|
10
|
+
is printed as `<file> line N: <message>`, the included file's own name in angle brackets before the
|
|
11
|
+
usual `line N:`, when the real compiler emits it while reading the file. Messages it emits after the
|
|
12
|
+
file was closed carry none: `_DEFERRED` below (message families) and `Diagnostic.show_file` (call
|
|
13
|
+
sites: False never, "cr3xx" only on CR300/CR350).
|
|
14
|
+
Warnings are untested against this rule and are left unprefixed (`cr6comp` only applies it to
|
|
15
|
+
errors) rather than guessed at.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import re
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
|
|
21
|
+
from .provenance import LoadProvenance
|
|
22
|
+
|
|
23
|
+
_DRIVE_RE = re.compile(r"^(CPU|USR|CRD|USB):", re.IGNORECASE)
|
|
24
|
+
|
|
25
|
+
# Messages the real compiler reports after the included file was closed (block pairing, placement
|
|
26
|
+
# before `BeginProg`, table/scan/array checks run after the read loop): they never carry the
|
|
27
|
+
# `<file>` prefix when the file has no `BeginProg` of its own (and print a garbled name when it
|
|
28
|
+
# has, not modelled). Observed per logger family on corpus programs split around `BeginProg`
|
|
29
|
+
# (`docs/checker.md` "Prefix by message kind"); a family with any prefixed observation is absent.
|
|
30
|
+
_DEFERRED_COMMON = (
|
|
31
|
+
r".+ illegally occurs before BeginProg\.$",
|
|
32
|
+
r"Could not find ",
|
|
33
|
+
r"Cannot find DataTable",
|
|
34
|
+
r"Cannot autoallocate memory for DataTable",
|
|
35
|
+
r"Duplicate Sub ",
|
|
36
|
+
r"EndTable without DataTable",
|
|
37
|
+
r"Table \S+ declared with no output fields",
|
|
38
|
+
r"Table with DataInterval must be called",
|
|
39
|
+
r"Sample must be used inside a table",
|
|
40
|
+
r"Illegal Matrix",
|
|
41
|
+
r"END IF without IF",
|
|
42
|
+
r"Else with no If",
|
|
43
|
+
r"LOOP without DO",
|
|
44
|
+
r"EndSub without Sub",
|
|
45
|
+
r"NEXT without FOR",
|
|
46
|
+
r"NextScan with no Scan",
|
|
47
|
+
r"Scan without NextScan",
|
|
48
|
+
r"Missing NextScan",
|
|
49
|
+
r"FOR NEXT statement illegally has",
|
|
50
|
+
r"IF or SELECT statement illegally has",
|
|
51
|
+
r"LOOP statement illegally has",
|
|
52
|
+
r"Variable .* out of bounds",
|
|
53
|
+
r"FileManage ",
|
|
54
|
+
r"Out of memory\.",
|
|
55
|
+
r"Illegal Semaphore",
|
|
56
|
+
)
|
|
57
|
+
_DEFERRED_PATTERNS = {
|
|
58
|
+
False: _DEFERRED_COMMON
|
|
59
|
+
+ ( # CR6 / CR1000X
|
|
60
|
+
r"Case with no Select",
|
|
61
|
+
r"Next SubScan without SubScan",
|
|
62
|
+
r"Delay not allowed outside",
|
|
63
|
+
r"Scan \S+ invalid",
|
|
64
|
+
r"Scan interval too short",
|
|
65
|
+
r"Scan (Interval|BufferOption|Count) parameter",
|
|
66
|
+
r"Slow Scan interval",
|
|
67
|
+
r"MenuRecompile must be used",
|
|
68
|
+
r"MenuPick must",
|
|
69
|
+
r"EndMenu must be used",
|
|
70
|
+
r"Invalid channel ",
|
|
71
|
+
r"Invalid port ",
|
|
72
|
+
r"Invalid reps ",
|
|
73
|
+
r"Invalid SDM Address",
|
|
74
|
+
r"Illegal table name",
|
|
75
|
+
r"Table name .* illegal",
|
|
76
|
+
r"DataTable name .* too long",
|
|
77
|
+
r"DNP Variable must be",
|
|
78
|
+
r"Can't assign units to",
|
|
79
|
+
r"\S+ already assigned Units",
|
|
80
|
+
r"PanelTemp channel out of range",
|
|
81
|
+
r"Input channel",
|
|
82
|
+
r"Reps cycle input",
|
|
83
|
+
r"SPIOpen must precede",
|
|
84
|
+
r"Illegal PakBus address",
|
|
85
|
+
r"Insufficient ",
|
|
86
|
+
r"CPI Address must",
|
|
87
|
+
r"Bridge parameter must",
|
|
88
|
+
r"Optional Count parameter",
|
|
89
|
+
r"Source and Dest types",
|
|
90
|
+
r"Unable to find Dest",
|
|
91
|
+
r"multiply result illegal",
|
|
92
|
+
r"Destination variable must",
|
|
93
|
+
r"Legal configuration is",
|
|
94
|
+
r"Sig\d+ must be of length",
|
|
95
|
+
r"Number of bytes ",
|
|
96
|
+
r"number of averages ",
|
|
97
|
+
r"SampleFieldCal with no FieldCal",
|
|
98
|
+
r"CDM_PulsePort instruction not supported",
|
|
99
|
+
r"CH\d+Status update interval",
|
|
100
|
+
r".+ is not a Settings Field Name",
|
|
101
|
+
r"GoesTable not active",
|
|
102
|
+
r"Missing DialSequence",
|
|
103
|
+
r"Boolean picklist must",
|
|
104
|
+
r"\S+ must be declared as a integer Const",
|
|
105
|
+
r"If source and destination are of type STRING",
|
|
106
|
+
r"DataInterval TintoInt",
|
|
107
|
+
r"Multiple BeginProgs",
|
|
108
|
+
r"Sub .* EndSub not matched",
|
|
109
|
+
r"IF or SELECT without EndIf",
|
|
110
|
+
),
|
|
111
|
+
True: _DEFERRED_COMMON
|
|
112
|
+
+ ( # CR300 / CR350
|
|
113
|
+
r"FOR without NEXT",
|
|
114
|
+
r"Scans > ",
|
|
115
|
+
r"DNP\d+Statics and/or",
|
|
116
|
+
r"Destination variable cannot",
|
|
117
|
+
r"Illegal option",
|
|
118
|
+
r"Illegal dimension",
|
|
119
|
+
r"Illegal message type",
|
|
120
|
+
r"Only one DataInterval allowed",
|
|
121
|
+
r"Settling time ",
|
|
122
|
+
r"\S+ must be of length",
|
|
123
|
+
r"Invalid drive or no drive",
|
|
124
|
+
r"Invalid file type option",
|
|
125
|
+
r"\S+ is not a Status or Settings Field Name",
|
|
126
|
+
r"DataTable name .* too long",
|
|
127
|
+
),
|
|
128
|
+
}
|
|
129
|
+
_DEFERRED = {k: re.compile("|".join(f"(?:{p})" for p in v)) for k, v in _DEFERRED_PATTERNS.items()}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass(frozen=True)
|
|
133
|
+
class Diagnostic:
|
|
134
|
+
severity: str # "error" or "warning"
|
|
135
|
+
line: int # 0 when the message has no line (e.g. "No BeginProg in Program.")
|
|
136
|
+
message: str # without the "line N: " / "Warning: " prefix
|
|
137
|
+
file: str = "" # originating file, for our own richer output
|
|
138
|
+
show_file: bool | str = True # whether an origin outside `main_file` gets a `<file>` prefix:
|
|
139
|
+
# True always, False never, "cr3xx" only on CR300/CR350 (pass-2 on CR6/CR1000X, pass-1 there);
|
|
140
|
+
# see this module's docstring.
|
|
141
|
+
cascade: bool = True # CR300/CR350: may start the `Too many parameters` cascade (`cr3xx`)
|
|
142
|
+
trigger: bool = field(default=False, compare=False) # starts it whatever the message (`cr3xx`)
|
|
143
|
+
stmt: int = field(default=0, compare=False) # id() of the statement that raised it, when tagged
|
|
144
|
+
|
|
145
|
+
def cr6comp(self, main_file: str = "", drive_prefix: bool = False) -> str:
|
|
146
|
+
if self.severity == "warning":
|
|
147
|
+
# A warning with a real line (`checker/warnings.py`'s ungated reachability/background-
|
|
148
|
+
# calibration/fnotch checks) is prefixed `line N: `, same as an error (oracle:
|
|
149
|
+
# `docs/instructions.md`, e.g. `line 6: Warning: Delay never reached at run time.`); one
|
|
150
|
+
# with no line (the pre-existing "table declared but never called" check, `diags.warning
|
|
151
|
+
# (0, ...)`) stays bare (oracle: `Warning: Table Foo, is declared but never called.`,
|
|
152
|
+
# no `line N:` at all). The `<file>` include prefix is left untested for warnings, as
|
|
153
|
+
# before (see this module's docstring).
|
|
154
|
+
if self.line:
|
|
155
|
+
return f"line {self.line}: Warning: {self.message}"
|
|
156
|
+
return f"Warning: {self.message}"
|
|
157
|
+
if not self.line:
|
|
158
|
+
return self.message
|
|
159
|
+
prefix = ""
|
|
160
|
+
name = _DRIVE_RE.sub("", self.file or "")
|
|
161
|
+
show = self.show_file
|
|
162
|
+
if show == "cr3xx":
|
|
163
|
+
show = drive_prefix
|
|
164
|
+
if show and _DEFERRED[drive_prefix].match(self.message):
|
|
165
|
+
show = False
|
|
166
|
+
if show and name and (name.lower() != main_file.lower() or _DRIVE_RE.match(self.file)):
|
|
167
|
+
# An included file prints as written in its `Include`: CR6/CR1000X without the drive
|
|
168
|
+
# (`<lib.CRB>` for `"cpu:lib.CRB"`), CR300/CR350 with it, `cpu:` added when none was
|
|
169
|
+
# written (`<cpu:Lib.crb>`) -- oracle, 2026-09-27, `docs/loggers.md`.
|
|
170
|
+
if drive_prefix:
|
|
171
|
+
name = self.file if _DRIVE_RE.match(self.file) else f"cpu:{self.file}"
|
|
172
|
+
prefix = f"<{name}> "
|
|
173
|
+
return f"{prefix}line {self.line}: {self.message}"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@dataclass
|
|
177
|
+
class Diagnostics(LoadProvenance):
|
|
178
|
+
items: list[Diagnostic] = field(default_factory=list)
|
|
179
|
+
cascade_gone: set[str] = field(default_factory=set) # CR300/CR350 names a declaration cascade left unregistered
|
|
180
|
+
|
|
181
|
+
def error(self, line: int, message: str, file: str = "", show_file: bool | str = True, stmt: object = None) -> None:
|
|
182
|
+
self.items.append(Diagnostic("error", line, message, file, show_file, stmt=id(stmt) if stmt else 0))
|
|
183
|
+
|
|
184
|
+
def warning(self, line: int, message: str, file: str = "") -> None:
|
|
185
|
+
self.items.append(Diagnostic("warning", line, message, file))
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def errors(self) -> list[Diagnostic]:
|
|
189
|
+
return [d for d in self.items if d.severity == "error"]
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def warnings(self) -> list[Diagnostic]:
|
|
193
|
+
return [d for d in self.items if d.severity == "warning"]
|
|
194
|
+
|
|
195
|
+
def __bool__(self) -> bool:
|
|
196
|
+
return bool(self.errors)
|