nc-gcode-interpreter 0.1.12__tar.gz → 0.2.0__tar.gz
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.
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/.github/workflows/build-and-release.yml +45 -17
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/.gitignore +16 -0
- nc_gcode_interpreter-0.2.0/CHANGELOG.md +219 -0
- nc_gcode_interpreter-0.2.0/Cargo.lock +1018 -0
- nc_gcode_interpreter-0.2.0/Cargo.toml +49 -0
- nc_gcode_interpreter-0.2.0/PKG-INFO +27 -0
- nc_gcode_interpreter-0.1.12/PKG-INFO → nc_gcode_interpreter-0.2.0/README.md +39 -30
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/TODO.md +2 -2
- nc_gcode_interpreter-0.2.0/docs/sinumerik-execution-model.md +302 -0
- nc_gcode_interpreter-0.2.0/examples/actual_position.csv +20 -0
- nc_gcode_interpreter-0.2.0/examples/actual_position.mpf +17 -0
- nc_gcode_interpreter-0.2.0/examples/arc.csv +14 -0
- nc_gcode_interpreter-0.2.0/examples/arc.mpf +14 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/arrays.csv +12 -12
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/basic_math.csv +2 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/basic_math.mpf +3 -1
- nc_gcode_interpreter-0.2.0/examples/case.csv +6 -0
- nc_gcode_interpreter-0.2.0/examples/case.mpf +11 -0
- nc_gcode_interpreter-0.2.0/examples/case_insensitive_variables.csv +10 -0
- nc_gcode_interpreter-0.2.0/examples/case_insensitive_variables.mpf +13 -0
- nc_gcode_interpreter-0.2.0/examples/def_string.csv +8 -0
- nc_gcode_interpreter-0.2.0/examples/def_string.mpf +14 -0
- nc_gcode_interpreter-0.2.0/examples/edge_cases.csv +46 -0
- nc_gcode_interpreter-0.2.0/examples/edge_cases.mpf +73 -0
- nc_gcode_interpreter-0.2.0/examples/flattening/flatten_demo.mpf +14 -0
- nc_gcode_interpreter-0.2.0/examples/flattening/flatten_demo_flattened.csv +55 -0
- nc_gcode_interpreter-0.2.0/examples/flattening/flatten_demo_raw.csv +15 -0
- nc_gcode_interpreter-0.2.0/examples/goto.csv +18 -0
- nc_gcode_interpreter-0.2.0/examples/goto.mpf +15 -0
- nc_gcode_interpreter-0.2.0/examples/logic_operators.csv +13 -0
- nc_gcode_interpreter-0.2.0/examples/logic_operators.mpf +29 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/multiple_m_codes.csv +0 -1
- nc_gcode_interpreter-0.2.0/examples/precedence.csv +13 -0
- nc_gcode_interpreter-0.2.0/examples/precedence.mpf +12 -0
- nc_gcode_interpreter-0.2.0/examples/spline.csv +19 -0
- nc_gcode_interpreter-0.2.0/examples/spline.mpf +22 -0
- nc_gcode_interpreter-0.2.0/examples/trans2.csv +5 -0
- nc_gcode_interpreter-0.2.0/examples/trans2.mpf +5 -0
- nc_gcode_interpreter-0.2.0/examples/trans_ic.csv +14 -0
- nc_gcode_interpreter-0.2.0/examples/trans_ic.mpf +21 -0
- nc_gcode_interpreter-0.2.0/examples/trans_reset.csv +11 -0
- nc_gcode_interpreter-0.2.0/examples/trans_reset.mpf +15 -0
- nc_gcode_interpreter-0.2.0/examples/trig.csv +11 -0
- nc_gcode_interpreter-0.2.0/examples/trig.mpf +10 -0
- nc_gcode_interpreter-0.2.0/ggroups/generate_g_commands.py +51 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/pyproject.toml +17 -2
- nc_gcode_interpreter-0.2.0/python/example/streaming.py +31 -0
- nc_gcode_interpreter-0.2.0/python/nc_gcode_interpreter/__init__.py +530 -0
- nc_gcode_interpreter-0.2.0/python/nc_gcode_interpreter/_internal.pyi +40 -0
- nc_gcode_interpreter-0.2.0/python/nc_gcode_interpreter/cli.py +187 -0
- nc_gcode_interpreter-0.2.0/python/nc_gcode_interpreter/viz.py +343 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_arithmetic_functions.py +35 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_batches.py +157 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_diagnostics.py +111 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_field_defects.py +121 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_flatten.py +378 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_g_vocabulary.py +60 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_jumps.py +202 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_real_comparisons.py +57 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_stage1.py +144 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_streaming.py +227 -0
- nc_gcode_interpreter-0.2.0/python/tests/test_unsupported.py +110 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/src/errors.rs +62 -0
- nc_gcode_interpreter-0.2.0/src/flatten.rs +1637 -0
- nc_gcode_interpreter-0.2.0/src/grammar.pest +238 -0
- nc_gcode_interpreter-0.2.0/src/interpret_rules.rs +2041 -0
- nc_gcode_interpreter-0.2.0/src/interpreter.rs +897 -0
- nc_gcode_interpreter-0.2.0/src/lib.rs +615 -0
- nc_gcode_interpreter-0.2.0/src/line_driver.rs +1247 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/src/main.rs +20 -6
- nc_gcode_interpreter-0.2.0/src/modal_groups.rs +137 -0
- nc_gcode_interpreter-0.2.0/src/output.rs +778 -0
- nc_gcode_interpreter-0.2.0/src/state.rs +305 -0
- nc_gcode_interpreter-0.2.0/src/structure_scan.rs +242 -0
- nc_gcode_interpreter-0.2.0/src/types.rs +14 -0
- nc_gcode_interpreter-0.2.0/tests/cli.rs +80 -0
- nc_gcode_interpreter-0.2.0/uv.lock +1970 -0
- nc_gcode_interpreter-0.1.12/Cargo.lock +0 -3754
- nc_gcode_interpreter-0.1.12/Cargo.toml +0 -20
- nc_gcode_interpreter-0.1.12/README.md +0 -164
- nc_gcode_interpreter-0.1.12/ggroups/generate_modal_ggroups.py +0 -29
- nc_gcode_interpreter-0.1.12/ggroups/generate_pest.py +0 -57
- nc_gcode_interpreter-0.1.12/ggroups/ggroups.pest +0 -66
- nc_gcode_interpreter-0.1.12/python/nc_gcode_interpreter/__init__.py +0 -268
- nc_gcode_interpreter-0.1.12/python/nc_gcode_interpreter/_internal.pyi +0 -68
- nc_gcode_interpreter-0.1.12/src/grammar.pest +0 -204
- nc_gcode_interpreter-0.1.12/src/interpret_rules.rs +0 -1037
- nc_gcode_interpreter-0.1.12/src/interpreter.rs +0 -280
- nc_gcode_interpreter-0.1.12/src/lib.rs +0 -69
- nc_gcode_interpreter-0.1.12/src/modal_groups.rs +0 -65
- nc_gcode_interpreter-0.1.12/src/state.rs +0 -149
- nc_gcode_interpreter-0.1.12/src/types.rs +0 -25
- nc_gcode_interpreter-0.1.12/uv.lock +0 -1568
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/CONTRIBUTING.md +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/Development.md +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/LICENSE +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/arrays.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/axis_index_assignment.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/axis_index_assignment.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/custom_vars.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/custom_vars.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/defaults.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/defaults.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/for_loop.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/for_loop.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/function_calls.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/function_calls.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/if_statement.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/if_statement.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/increment.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/increment.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/loop.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/loop.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/multiple_m_codes.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/r_param.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/r_param.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/repeat.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/repeat.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/simple.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/simple.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/tool.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/tool.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/trans.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/trans.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/variables.csv +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/examples/variables.mpf +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/python/example/minimal.py +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/python/nc_gcode_interpreter/ggroups.json +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/python/nc_gcode_interpreter/py.typed +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/python/tests/test_expected_output.py +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/python/tests/test_flags.py +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/python/tests/test_g_groups.py +0 -0
- {nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/rustfmt.toml +0 -0
{nc_gcode_interpreter-0.1.12 → nc_gcode_interpreter-0.2.0}/.github/workflows/build-and-release.yml
RENAMED
|
@@ -30,8 +30,8 @@ jobs:
|
|
|
30
30
|
lint:
|
|
31
31
|
runs-on: ubuntu-latest
|
|
32
32
|
steps:
|
|
33
|
-
- uses: actions/checkout@
|
|
34
|
-
- uses: actions/setup-python@
|
|
33
|
+
- uses: actions/checkout@v5
|
|
34
|
+
- uses: actions/setup-python@v6
|
|
35
35
|
with:
|
|
36
36
|
python-version: 3.13
|
|
37
37
|
- name: Install Python linter
|
|
@@ -39,6 +39,14 @@ jobs:
|
|
|
39
39
|
- name: Lint Python code with ruff
|
|
40
40
|
run: ruff check .
|
|
41
41
|
|
|
42
|
+
rust-test:
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v5
|
|
46
|
+
- uses: Swatinem/rust-cache@v2
|
|
47
|
+
- name: Run Rust unit and integration tests
|
|
48
|
+
run: cargo test
|
|
49
|
+
|
|
42
50
|
linux-x64:
|
|
43
51
|
needs: [lint]
|
|
44
52
|
runs-on: ${{ matrix.platform.runner }}
|
|
@@ -49,8 +57,8 @@ jobs:
|
|
|
49
57
|
target: x86_64
|
|
50
58
|
python-version: ["3.12", "3.13"]
|
|
51
59
|
steps:
|
|
52
|
-
- uses: actions/checkout@
|
|
53
|
-
- uses: actions/setup-python@
|
|
60
|
+
- uses: actions/checkout@v5
|
|
61
|
+
- uses: actions/setup-python@v6
|
|
54
62
|
with:
|
|
55
63
|
python-version: ${{ matrix.python-version }}
|
|
56
64
|
- name: Update Cargo.toml Version
|
|
@@ -79,12 +87,12 @@ jobs:
|
|
|
79
87
|
matrix:
|
|
80
88
|
python-version: ["3.12", "3.13"]
|
|
81
89
|
steps:
|
|
82
|
-
- uses: actions/checkout@
|
|
90
|
+
- uses: actions/checkout@v5
|
|
83
91
|
- uses: actions/download-artifact@v4
|
|
84
92
|
with:
|
|
85
93
|
name: wheels-ubuntu-latest-x86_64-py${{ matrix.python-version }}-${{ github.sha }}
|
|
86
94
|
path: dist
|
|
87
|
-
- uses: actions/setup-python@
|
|
95
|
+
- uses: actions/setup-python@v6
|
|
88
96
|
with:
|
|
89
97
|
python-version: ${{ matrix.python-version }}
|
|
90
98
|
- name: Install py_opw_kinematics
|
|
@@ -120,8 +128,8 @@ jobs:
|
|
|
120
128
|
target: aarch64
|
|
121
129
|
python-version: ["3.12", "3.13"]
|
|
122
130
|
steps:
|
|
123
|
-
- uses: actions/checkout@
|
|
124
|
-
- uses: actions/setup-python@
|
|
131
|
+
- uses: actions/checkout@v5
|
|
132
|
+
- uses: actions/setup-python@v6
|
|
125
133
|
with:
|
|
126
134
|
python-version: ${{ matrix.python-version }}
|
|
127
135
|
- name: Update Cargo.toml Version
|
|
@@ -159,8 +167,8 @@ jobs:
|
|
|
159
167
|
target: x64
|
|
160
168
|
python-version: ["3.12", "3.13"]
|
|
161
169
|
steps:
|
|
162
|
-
- uses: actions/checkout@
|
|
163
|
-
- uses: actions/setup-python@
|
|
170
|
+
- uses: actions/checkout@v5
|
|
171
|
+
- uses: actions/setup-python@v6
|
|
164
172
|
with:
|
|
165
173
|
python-version: ${{ matrix.python-version }}
|
|
166
174
|
architecture: ${{ matrix.platform.target }}
|
|
@@ -218,8 +226,8 @@ jobs:
|
|
|
218
226
|
target: aarch64
|
|
219
227
|
python-version: ["3.12", "3.13"]
|
|
220
228
|
steps:
|
|
221
|
-
- uses: actions/checkout@
|
|
222
|
-
- uses: actions/setup-python@
|
|
229
|
+
- uses: actions/checkout@v5
|
|
230
|
+
- uses: actions/setup-python@v6
|
|
223
231
|
with:
|
|
224
232
|
python-version: ${{ matrix.python-version }}
|
|
225
233
|
- name: Update Cargo.toml Version
|
|
@@ -250,8 +258,8 @@ jobs:
|
|
|
250
258
|
needs: [lint, test]
|
|
251
259
|
runs-on: ubuntu-latest
|
|
252
260
|
steps:
|
|
253
|
-
- uses: actions/checkout@
|
|
254
|
-
- uses: actions/setup-python@
|
|
261
|
+
- uses: actions/checkout@v5
|
|
262
|
+
- uses: actions/setup-python@v6
|
|
255
263
|
with:
|
|
256
264
|
python-version: 3.12
|
|
257
265
|
- name: Update Cargo.toml Version
|
|
@@ -286,13 +294,33 @@ jobs:
|
|
|
286
294
|
contents: write
|
|
287
295
|
attestations: write
|
|
288
296
|
steps:
|
|
297
|
+
# Do NOT use `merge-multiple: true`. With `--find-interpreter`, every
|
|
298
|
+
# build matrix leg (py3.12 AND py3.13) produces cp312/cp313/cp314 wheels
|
|
299
|
+
# with identical filenames but non-identical bytes (sccache makes builds
|
|
300
|
+
# nondeterministic). Merging them into one directory makes
|
|
301
|
+
# download-artifact overwrite colliding paths concurrently, truncating
|
|
302
|
+
# the file mid-write and corrupting the ZIP central directory - which
|
|
303
|
+
# PyPI reports as "Trailing data" and `wheel unpack` as "Bad magic
|
|
304
|
+
# number for central directory". Instead download each artifact into its
|
|
305
|
+
# own subdirectory and collect one intact copy of each filename.
|
|
289
306
|
- uses: actions/download-artifact@v4
|
|
290
307
|
with:
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
- uses: actions/setup-python@v5
|
|
308
|
+
path: artifacts
|
|
309
|
+
- uses: actions/setup-python@v6
|
|
294
310
|
with:
|
|
295
311
|
python-version: 3.12
|
|
312
|
+
- name: Collect unique wheels and sdist
|
|
313
|
+
run: |
|
|
314
|
+
mkdir -p dist
|
|
315
|
+
# Each artifact is in its own subdir, so no path collides during
|
|
316
|
+
# download. Copy the first occurrence of each basename; duplicate
|
|
317
|
+
# filenames are the same wheel for the same platform tag, so either
|
|
318
|
+
# copy is a valid, complete ZIP.
|
|
319
|
+
find artifacts -type f \( -name '*.whl' -o -name '*.tar.gz' \) | while read -r f; do
|
|
320
|
+
b=$(basename "$f")
|
|
321
|
+
[ -e "dist/$b" ] || cp "$f" "dist/$b"
|
|
322
|
+
done
|
|
323
|
+
echo "Collected artifacts:" && ls -1 dist/
|
|
296
324
|
- name: Generate artifact attestation
|
|
297
325
|
uses: actions/attest-build-provenance@v1
|
|
298
326
|
with:
|
|
@@ -26,3 +26,19 @@ dist/
|
|
|
26
26
|
__pycache__
|
|
27
27
|
python/**/*.so
|
|
28
28
|
python/**/*.pyc
|
|
29
|
+
|
|
30
|
+
# macOS
|
|
31
|
+
.DS_Store
|
|
32
|
+
|
|
33
|
+
# local scratch
|
|
34
|
+
tmp/
|
|
35
|
+
|
|
36
|
+
# real-world NC files used for manual/local testing, not for CI
|
|
37
|
+
test-data/
|
|
38
|
+
|
|
39
|
+
# local exploration scripts
|
|
40
|
+
python/example/plot_trace.py
|
|
41
|
+
python/example/smooth_e.py
|
|
42
|
+
|
|
43
|
+
# local field-test data (customer programs; never commit)
|
|
44
|
+
test-data/
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to **nc-gcode-interpreter**. The format loosely follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/); versions are git tags,
|
|
5
|
+
released to PyPI.
|
|
6
|
+
|
|
7
|
+
## [v0.2.0] - 2026-07-07
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Rust-side polars is gone. The Table -> Python DataFrame handoff no longer
|
|
12
|
+
builds a polars DataFrame in Rust (via `pyo3-polars`); it builds an Arrow
|
|
13
|
+
record batch with the minimal `arrow-array`/`arrow-schema`/`arrow-data`
|
|
14
|
+
crates and hands it to Python zero-copy through the Arrow PyCapsule
|
|
15
|
+
interface (`__arrow_c_array__`), where `pl.DataFrame(...)` wraps it. The
|
|
16
|
+
Python API is unchanged (still returns `polars.DataFrame`), needs no
|
|
17
|
+
`pyarrow`, and performance is unchanged. This drops ~60 crates from the
|
|
18
|
+
`python`-feature build (127 -> 64), cutting a clean release build ~4x
|
|
19
|
+
(83s -> 21s), and bumps PyO3 0.28 -> 0.29 (resolving the RUSTSEC pyo3
|
|
20
|
+
advisories).
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `dwell` output column: F/S on a `G4` block is the dwell time (seconds /
|
|
25
|
+
spindle revolutions), a per-block parameter - it now lands in its own
|
|
26
|
+
never-forward-filled `dwell` column instead of polluting the modal F/S
|
|
27
|
+
columns (previously `G4 F0.01` set the feed to 0.01 mm/min for every
|
|
28
|
+
following block until the next real F word)
|
|
29
|
+
- Loud warnings for known-but-uninterpreted constructs (never silently
|
|
30
|
+
butcher a statement): assignments to `AR`/`AP`/`RP` (opening-angle and
|
|
31
|
+
polar arc forms) warn once per run that the motion will be wrong; `G91`
|
|
32
|
+
warns once that incremental dimensioning is not applied; the flattener
|
|
33
|
+
warns per word for CIP/CT/POLY/thread/involute pass-through
|
|
34
|
+
- `TURN` output column (block address, never forward-filled): additional
|
|
35
|
+
full helix turns on G2/G3 blocks; previously swallowed as a user variable
|
|
36
|
+
- Curve flattening: `flatten_tolerance` on `nc_to_dataframe` / `nc_to_rows` /
|
|
37
|
+
`nc_to_batches` (CLI: `--flatten-tolerance`) converts G2/G3 arcs (I/J/K and
|
|
38
|
+
CR= forms, all planes, helical, full circles) and ASPLINE/BSPLINE/CSPLINE
|
|
39
|
+
splines (PW weights, SD degree) into runs of G1 rows within a single
|
|
40
|
+
max-deviation tolerance of the true curve; interpolation addresses are
|
|
41
|
+
consumed, source line numbers and auxiliary cells preserved; generated
|
|
42
|
+
samples carry a `flattened = 1` marker column so the original programmed
|
|
43
|
+
points remain distinguishable
|
|
44
|
+
- Optional `viz` extra (threejs-viewer >= 0.0.41):
|
|
45
|
+
`nc_gcode_interpreter.viz.view_toolpath(df)` shows a toolpath in
|
|
46
|
+
threejs-viewer as an animated bead tube (feed-rate float64 time base,
|
|
47
|
+
programmed vs flattened point coloring), and the `nc-view` console command
|
|
48
|
+
interprets + flattens + animates an .mpf in one step, with a nozzle
|
|
49
|
+
marker riding the path tip, camera follow/look-at tracking, and travel
|
|
50
|
+
moves drawn natively as a thin line in lockstep with the bead
|
|
51
|
+
|
|
52
|
+
- Program jumps and branches: `GOTOF`/`GOTOB`/`GOTO`/`GOTOC`/`GOTOS` and
|
|
53
|
+
`CASE ... OF ... DEFAULT`, with per-scope label/block-number resolution,
|
|
54
|
+
jumps out of IF bodies and loops, and alarm-14080 semantics for an
|
|
55
|
+
unresolved target (`GOTOC` warns and continues) (#29)
|
|
56
|
+
- Streaming API `nc_to_rows(program)`: yields `(line_no, row)` lazily while
|
|
57
|
+
the interpreter runs on a background thread — batch-identical typing and
|
|
58
|
+
forward-fill, constant memory, early abort by dropping the iterator,
|
|
59
|
+
errors raised at the offending row, final state on the exhausted
|
|
60
|
+
iterator (#35)
|
|
61
|
+
- `nc_to_rows(..., include_variables=True)` yields `(line_no, row,
|
|
62
|
+
variables)` with per-block variable-assignment deltas, exposing
|
|
63
|
+
variable-only blocks that the batch DataFrame prunes (#35)
|
|
64
|
+
- Spline programming: `PW`/`SD`/`PL` block addresses become output columns
|
|
65
|
+
(not forward-filled, no `TRANS` offset) instead of being silently
|
|
66
|
+
swallowed (#18)
|
|
67
|
+
- G2/G3 arc interpolation parameters `I`/`J`/`K`/`CR` become per-block output
|
|
68
|
+
columns (not forward-filled, no `TRANS` offset) instead of being silently
|
|
69
|
+
dropped — arcs previously came out as straight-line endpoints (#37)
|
|
70
|
+
- `nc_to_batches(program, batch_size=...)`: interpret a program into a
|
|
71
|
+
stream of columnar polars DataFrames built on a worker thread and handed
|
|
72
|
+
over via the Arrow C data interface — bounded memory for programs too
|
|
73
|
+
large to fit in one DataFrame (#37)
|
|
74
|
+
- Parsing: leading-underscore identifiers (`_WITH_M0`), assignment to
|
|
75
|
+
`$AC_*` system variables (`$AC_TIMER[1] = 0`), and the `NOT` logical
|
|
76
|
+
operator (#37)
|
|
77
|
+
- `DEF STRING[n]` string-variable declarations and quoted-string
|
|
78
|
+
assignments; strings stay out of the numeric pipeline (a string in an
|
|
79
|
+
expression, or a type mismatch, is a hard error, never a silent 0.0).
|
|
80
|
+
String *processing* (`SPRINT`/`INDEX`/`<<`) remains out of scope and
|
|
81
|
+
fails loudly (#40)
|
|
82
|
+
- Logic, comparison and bit operators in expressions (`AND`/`OR`/`XOR`,
|
|
83
|
+
`B_AND`/`B_OR`/`B_XOR`, `==`/`<>`/`<`/`>`/`<=`/`>=`) at the manual's
|
|
84
|
+
priorities, so conditions like `IF (A == 1 AND B == 1)` work and
|
|
85
|
+
comparison results are assignable (`R11 = R10 >= 100`) (#41)
|
|
86
|
+
- `$AA_IW[<axis>]` / `$AA_IM[<axis>]` read the interpreted actual work /
|
|
87
|
+
machine position of an axis, so layer loops
|
|
88
|
+
(`REPEAT ... UNTIL $AA_IW[Z] > H`) terminate; reading before the axis is
|
|
89
|
+
positioned errors loudly and the variables are read-only (#42)
|
|
90
|
+
- `nc-view` prints a corrected retry command on the classic new-machine
|
|
91
|
+
failures (missing `--axis-index-map`, undefined machine-parameter
|
|
92
|
+
variables) instead of a bare traceback
|
|
93
|
+
- `docs/sinumerik-execution-model.md`: how a real control executes NC code
|
|
94
|
+
versus this interpreter, and why (#30)
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
- **Breaking:** `I`/`J`/`K`/`CR` are now treated as arc interpolation-parameter
|
|
99
|
+
block addresses (output columns), so they can no longer be used as user
|
|
100
|
+
variable names: `I=5` followed by `X=I+1` was a variable read before and is
|
|
101
|
+
now an undefined-variable error. Matches Sinumerik address semantics (#37)
|
|
102
|
+
- `nc_to_dataframe` is now the concatenation of the internal batch stream
|
|
103
|
+
rather than collecting every row up front: same output, but bounded
|
|
104
|
+
intermediate memory and interpretation overlapped with DataFrame assembly
|
|
105
|
+
(a 1.1 GB program went from ~209 s / 6 GB to ~33 s / 3.3 GB) (#37)
|
|
106
|
+
- An executed `M2`/`M17`/`M30` now ends the program immediately, even
|
|
107
|
+
mid-file, instead of being ignored (#29)
|
|
108
|
+
- Unknown G codes now error like Sinumerik alarm 12470 instead of silently
|
|
109
|
+
parsing as a subprogram call (#31)
|
|
110
|
+
- Unsupported or unmodeled statements (parameterized `ROT`/`SCALE`/`MIRROR`
|
|
111
|
+
frames, and previously jumps/`LOOP` before #29 implemented them) raise a
|
|
112
|
+
clear `UnsupportedStatement` error instead of corrupting output; a frame
|
|
113
|
+
instruction following another statement in the same block errors (#20,
|
|
114
|
+
#32)
|
|
115
|
+
- Frame semantics per the manual: absolute frame instructions (`TRANS`,
|
|
116
|
+
bare `ROT`/`SCALE`/`MIRROR`) substitute — deleting previously programmed
|
|
117
|
+
offsets — rather than accumulate (#20, #26)
|
|
118
|
+
- Values are f64 end-to-end to match the control's 64-bit `REAL`:
|
|
119
|
+
coordinates are bit-exact for decimal literals, `DIV` truncates the real
|
|
120
|
+
result (`7 DIV 4.1 = 1`), and `==`/`<>`/`<=`/`>=` use the manual's 1e-12
|
|
121
|
+
relative tolerance (#23)
|
|
122
|
+
- The ~488-command G vocabulary and its 60 G-groups moved out of the PEG
|
|
123
|
+
grammar into a Rust table generated from `ggroups.json`; the grammar
|
|
124
|
+
recognizes lexical shape only (#32)
|
|
125
|
+
- Rust-side polars removed: the core returns a plain typed table and the
|
|
126
|
+
Python wrapper builds the DataFrame, so any Python polars version works;
|
|
127
|
+
CSV and DataFrame output are unchanged (#27)
|
|
128
|
+
- Dependency refresh: pest 2.8.6, pyo3 0.28, clap 4.6, polars 1.42.1 (#28)
|
|
129
|
+
|
|
130
|
+
### Fixed
|
|
131
|
+
|
|
132
|
+
- The NC language is case-insensitive (manual 3.3.2): lowercase axis
|
|
133
|
+
words (`g1 x0 y0`) are axis moves rather than silently-dropped subprogram
|
|
134
|
+
calls, G/M values are normalized to uppercase, and user-variable
|
|
135
|
+
identifiers fold case (a program that declares `lAYER_HEIGHT` but assigns
|
|
136
|
+
`LAYER_HEIGHT` is one variable, not two) (#43)
|
|
137
|
+
- The IC-before-position warning now states what actually happens ("axis
|
|
138
|
+
incremented with `IC()` before any absolute position was set; assuming it
|
|
139
|
+
starts at 0") instead of the vague "behavior may be indeterminate"
|
|
140
|
+
- Expression evaluation: correct operator precedence (`2+3*4` is now 14,
|
|
141
|
+
not 20), degree-based trig per the manual, corrected `ATAN2` argument
|
|
142
|
+
order, and `DIV` by zero errors instead of panicking (#19)
|
|
143
|
+
- `TRANS`/`ATRANS` translation is applied per row at output time under the
|
|
144
|
+
frame active at that block; fixes double-applied offsets on `IC()` moves
|
|
145
|
+
and axis movement as a parsing side effect (#26)
|
|
146
|
+
- Unclosed or crossed `IF`/`WHILE`/`FOR`/`LOOP`/`REPEAT` structures are
|
|
147
|
+
reported at the (innermost) opener's own line instead of as a parse
|
|
148
|
+
failure at end-of-file (#33)
|
|
149
|
+
- Parse errors are phrased for humans (no grammar-internal rule names),
|
|
150
|
+
mistyped axis words like `Y2O` warn, and unresolved jump targets get
|
|
151
|
+
did-you-mean suggestions — direction-aware when the label exists but only
|
|
152
|
+
in the other search direction (#31)
|
|
153
|
+
|
|
154
|
+
### Performance
|
|
155
|
+
|
|
156
|
+
- Stage-1 line triage: structure-free CAM programs run through a byte
|
|
157
|
+
decoder for the >99.9% trivial lines, per-line parses for the rest —
|
|
158
|
+
a 319k-line program drops from ~33 s to ~9 s in `nc_to_dataframe`
|
|
159
|
+
(`NC_STAGE1=0` disables) (#34)
|
|
160
|
+
- Grammar restructuring: ~15% faster parsing, plus an ignored 1M-line
|
|
161
|
+
benchmark harness (#30); an earlier redundant-lookahead removal cut parse
|
|
162
|
+
time ~27% (#25)
|
|
163
|
+
|
|
164
|
+
## [v0.1.12] - 2025-06-26
|
|
165
|
+
|
|
166
|
+
- Added `allow_undefined_variables`: undefined variables initialize to 0.0
|
|
167
|
+
with a warning instead of erroring (#17)
|
|
168
|
+
- Dependency updates
|
|
169
|
+
|
|
170
|
+
## [v0.1.11] - 2025-06-25
|
|
171
|
+
|
|
172
|
+
- Added arithmetic functions and `REPEAT ... UNTIL` (#15)
|
|
173
|
+
- Added `axis_index_map` to map axis identifiers to array indices (e.g.
|
|
174
|
+
`FL[E]=10`)
|
|
175
|
+
- Improved error messages and grammar edge cases (comments in `IF`
|
|
176
|
+
statements, relational-operator ordering)
|
|
177
|
+
|
|
178
|
+
## [v0.1.10] - 2025-02-21
|
|
179
|
+
|
|
180
|
+
- Updated supported Python versions and release versioning; no interpreter
|
|
181
|
+
changes
|
|
182
|
+
|
|
183
|
+
## [v0.1.9] - 2024-10-25
|
|
184
|
+
|
|
185
|
+
- Added `dataframe_to_nc`: write a polars DataFrame back out as NC G-code
|
|
186
|
+
(round-trip), with the `sanitize_dataframe` helper exposed (#13)
|
|
187
|
+
|
|
188
|
+
## [v0.1.8] - 2024-10-22
|
|
189
|
+
|
|
190
|
+
- Exposed G-code groups (ggroups) in the API (#12); added type hints (#11)
|
|
191
|
+
|
|
192
|
+
## [v0.1.7] - 2024-10-17
|
|
193
|
+
|
|
194
|
+
- Git-tag-based versioning; CI cleanup (minimum Python 3.11)
|
|
195
|
+
|
|
196
|
+
## [v0.1.6] - 2024-10-16
|
|
197
|
+
|
|
198
|
+
- Implemented tool selection (`T="..."`/`T5`); M and T matching is
|
|
199
|
+
case-insensitive; quoted strings are unquoted in output (#8)
|
|
200
|
+
|
|
201
|
+
## [v0.1.5] - 2024-10-09
|
|
202
|
+
|
|
203
|
+
- Reordered G-group parsing, roughly doubling parse performance (#7)
|
|
204
|
+
|
|
205
|
+
## [v0.1.1] – [v0.1.4] - 2024-10-03
|
|
206
|
+
|
|
207
|
+
- Packaging and CI: PyPI publishing via Trusted Publisher, contributing
|
|
208
|
+
guidelines, macOS builds, WASM and binary bindings disabled to fix the
|
|
209
|
+
Python package (#1–#3)
|
|
210
|
+
|
|
211
|
+
## [v0.1] - 2024-09-26
|
|
212
|
+
|
|
213
|
+
- Initial release: Rust (pest) interpreter for Sinumerik-flavored NC
|
|
214
|
+
G-code with a CLI (MPF → CSV) and Python bindings (MPF → polars
|
|
215
|
+
DataFrame + final state)
|
|
216
|
+
- G-code groups and modal commands, `TRANS`/`ATRANS`, `WHILE`/`FOR`/
|
|
217
|
+
`IF`/`ELSE`, local variables and arrays, arithmetic, incremental moves
|
|
218
|
+
(`IC()`), custom/extra axes, initial-state file, iteration limit,
|
|
219
|
+
forward-fill toggle
|