openscad-cpp-evaluator 1.41.0__tar.gz → 1.43.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.
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/CLAUDE.md +39 -18
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/PKG-INFO +3 -2
- openscad_cpp_evaluator-1.43.0/external/openscad_cpp_parser/LICENSE +21 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/bytecode.hpp +14 -46
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/colored_body.hpp +3 -3
- openscad_cpp_evaluator-1.43.0/include/openscad_cpp_evaluator/dxf_svg_import.hpp +67 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/evaluator.hpp +31 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/export.hpp +5 -8
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/import_builtin.hpp +3 -1
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/segments.hpp +9 -18
- openscad_cpp_evaluator-1.43.0/include/openscad_cpp_evaluator/surface_load.hpp +20 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/value.hpp +6 -7
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/pyproject.toml +3 -3
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/CMakeLists.txt +1 -1
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/booleans.cpp +2 -2
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/builtins.hpp +15 -2
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/control.cpp +3 -4
- openscad_cpp_evaluator-1.43.0/src/builtins/dxf_dim.cpp +220 -0
- openscad_cpp_evaluator-1.43.0/src/builtins/extrude.cpp +563 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/function_builtins.cpp +332 -378
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/import.cpp +150 -80
- openscad_cpp_evaluator-1.43.0/src/builtins/primitives_2d.cpp +266 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/primitives_3d.cpp +122 -173
- openscad_cpp_evaluator-1.43.0/src/builtins/roof.cpp +485 -0
- openscad_cpp_evaluator-1.43.0/src/builtins/segments.cpp +253 -0
- openscad_cpp_evaluator-1.43.0/src/builtins/surface.cpp +114 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/transforms.cpp +206 -190
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/bytecode_compiler.cpp +40 -82
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/bytecode_vm.cpp +10 -29
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/colored_body.cpp +1 -1
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/eval_context.cpp +2 -1
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/export.cpp +91 -45
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/expr_eval.cpp +50 -25
- openscad_cpp_evaluator-1.43.0/src/import/dxf_import.cpp +370 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/import/mesh_import.cpp +56 -18
- openscad_cpp_evaluator-1.43.0/src/import/surface_load.cpp +124 -0
- openscad_cpp_evaluator-1.43.0/src/import/svg_import.cpp +1017 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/stmt_eval.cpp +36 -15
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/text/freetype_font_provider.cpp +18 -3
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/user_calls.cpp +38 -30
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/value.cpp +229 -158
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_bytecode_compiler.cpp +10 -7
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_control_flow.cpp +10 -3
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_dxf_svg_import.cpp +314 -51
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_eval_context.cpp +2 -1
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_export.cpp +18 -5
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_expr_eval.cpp +3 -6
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_extrude_roof.cpp +2 -2
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_helpers.hpp +24 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_import_export.cpp +56 -54
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_openscad_parity.cpp +113 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_python_bindings.py +14 -2
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_transforms.cpp +1 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/uv.lock +1 -1
- openscad_cpp_evaluator-1.41.0/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -46
- openscad_cpp_evaluator-1.41.0/include/openscad_cpp_evaluator/surface_load.hpp +0 -23
- openscad_cpp_evaluator-1.41.0/src/builtins/dxf_dim.cpp +0 -244
- openscad_cpp_evaluator-1.41.0/src/builtins/extrude.cpp +0 -549
- openscad_cpp_evaluator-1.41.0/src/builtins/primitives_2d.cpp +0 -242
- openscad_cpp_evaluator-1.41.0/src/builtins/roof.cpp +0 -489
- openscad_cpp_evaluator-1.41.0/src/builtins/segments.cpp +0 -284
- openscad_cpp_evaluator-1.41.0/src/builtins/surface.cpp +0 -118
- openscad_cpp_evaluator-1.41.0/src/import/dxf_import.cpp +0 -115
- openscad_cpp_evaluator-1.41.0/src/import/surface_load.cpp +0 -132
- openscad_cpp_evaluator-1.41.0/src/import/svg_import.cpp +0 -628
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/cmake/patch_manifold.cmake +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/.DS_Store +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/import/scene_import.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/xkcd_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/xkcd_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_discretizer.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_undef_args.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.41.0 → openscad_cpp_evaluator-1.43.0}/tools/cli/main.cpp +0 -0
|
@@ -63,7 +63,7 @@ plus gating the silent `is_undef` probe on the call actually resolving to the bu
|
|
|
63
63
|
CSG-tree shape like union/difference/intersection, role-split via the shared `splitByRole`),
|
|
64
64
|
`linear_extrude()`/`rotate_extrude()`/`projection(cut=)`, and `roof()`; and (Phase 7) `offset()`,
|
|
65
65
|
`surface()` (`.dat` text + PNG/JPEG/BMP/GIF via `stb_image`), hand-rolled DXF (`LWPOLYLINE`/2D
|
|
66
|
-
`POLYLINE`) and SVG (
|
|
66
|
+
`POLYLINE`) and SVG (a port of upstream's libsvg: shapes, strokes, `<use>`, layers, nested
|
|
67
67
|
`transform=`, all path commands including elliptical arcs) 2D contour import in both module
|
|
68
68
|
(Region geometry) and expression (Region value) contexts, and the `FontProvider` abstraction
|
|
69
69
|
(`font_provider.hpp`) + built-in FreeType/HarfBuzz backend + `text()`/`textmetrics()`/
|
|
@@ -1248,9 +1248,13 @@ grep for `ponytail:`.
|
|
|
1248
1248
|
the module *and* expression forms, enclosing transforms still apply to a selected element (it
|
|
1249
1249
|
has to land where it does in the drawing), and **a filter that matches nothing imports nothing
|
|
1250
1250
|
and warns** rather than falling back to the whole file — a cut layer that quietly became every
|
|
1251
|
-
layer is the worst answer available. `layer=`
|
|
1252
|
-
|
|
1253
|
-
|
|
1251
|
+
layer is the worst answer available. `layer=` (and deprecated `layername=`) also selects in
|
|
1252
|
+
SVG, as upstream does: an Inkscape layer (`inkscape:groupmode="layer"` with an
|
|
1253
|
+
`inkscape:label`). Alone it takes that layer's own group; with `id=`/`class=` it restricts them
|
|
1254
|
+
to elements inside the named layer at any depth. The selection rules were read off the binary:
|
|
1255
|
+
the nearest selected or `display:none` ancestor-or-self decides whether a shape is drawn, so an
|
|
1256
|
+
id selects an element even under a hidden layer, while `layer=` alone does not reach into a
|
|
1257
|
+
hidden sublayer. The miss warning names `id`, `layer`, `class` in that order. `id` had been in
|
|
1254
1258
|
`registry.cpp`'s declared parameter list since long before anything read it, so a script
|
|
1255
1259
|
filtering by id was accepted in full and silently handed the whole drawing.
|
|
1256
1260
|
`resolveFilePath()` (also declared here, defined in import.cpp) — resolves a file argument
|
|
@@ -1281,20 +1285,37 @@ grep for `ponytail:`.
|
|
|
1281
1285
|
triangle-count parity.
|
|
1282
1286
|
- `include/openscad_cpp_evaluator/dxf_svg_import.hpp`, `src/import/dxf_import.cpp`,
|
|
1283
1287
|
`src/import/svg_import.cpp` — hand-rolled, dependency-free 2D-contour loaders (no XML/DXF library
|
|
1284
|
-
pulled in, matching the plan's §9 dependency table). `
|
|
1285
|
-
text format directly
|
|
1286
|
-
|
|
1288
|
+
pulled in, matching the plan's §9 dependency table). `loadDxf()` reads DXF's group-code
|
|
1289
|
+
text format directly and matches OpenSCAD 2026.02.01's import, established black-box (its DXF
|
|
1290
|
+
source is GPL; do not read or port it): `LINE`/`CIRCLE`/`ARC`/`ELLIPSE`/`LWPOLYLINE`/`INSERT`
|
|
1291
|
+
become segments (arcs by the circle fragment rules), points snap to a 1/1024 grid, segments chain
|
|
1292
|
+
into paths that are ALL closed (an open chain gets a straight closing edge), filled even-odd;
|
|
1293
|
+
`origin=`/`scale=`/`layer=` and its warnings ("Illegal value", "Not enough input values",
|
|
1294
|
+
"Unsupported DXF Entity") as OpenSCAD has them. The notes atop `dxf_import.cpp` list the rules,
|
|
1295
|
+
the two ellipse bugs deliberately not copied, and the `POLYLINE` extension.
|
|
1287
1296
|
`loadSvgContours()` pairs a minimal recursive-descent XML tree parser (open/close/self-closing
|
|
1288
|
-
tags, quoted attributes, comments/CDATA/prolog skipping, entity
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
`
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1297
|
+
tags, quoted attributes, comments/CDATA/prolog skipping, entity and character-reference
|
|
1298
|
+
decoding, attribute whitespace normalisation; a tag keeps its `prefix:`, as libxml2 reports it,
|
|
1299
|
+
so `<svg:rect>` is not a rect -- in OpenSCAD either) with **a port of upstream's MIT-licensed
|
|
1300
|
+
`src/libsvg`** (its copyright notice is in the file): its `d` tokenizer with every quirk (a `-`
|
|
1301
|
+
is a token, `1.5.5` is two numbers, a number with trailing junk is 0), Beziers in `max($fn, 20)`
|
|
1302
|
+
segments, arcs and circles/ellipses through `Discretizer::circular` (circles at least 40),
|
|
1303
|
+
rounded `rect`s rebuilt as path data printed at 6 digits, `transform` with `skewX`/`skewY` and
|
|
1304
|
+
libsvg's argument-count checks, `<use>` of a shape in an earlier `<defs>` only, unknown
|
|
1305
|
+
elements (`<a>`, `<symbol>`, `<switch>`) see-through with their transform ignored, and
|
|
1306
|
+
**strokes**: an open subpath, `<line>` and `<polyline>` become their stroke's outline via
|
|
1307
|
+
Clipper2's `ClipperOffset` at 2^27 per user unit (measured), with `stroke-width` (below 0.01 is
|
|
1308
|
+
1), `stroke-linecap` and `stroke-linejoin` (`bevel` maps to Clipper's Square, as libsvg has it).
|
|
1309
|
+
Each element then fills even-odd on its own and the elements union (`fill()`), which is what
|
|
1310
|
+
the reference does: separate overlapping rects union, one path's overlapping subpaths cancel.
|
|
1311
|
+
Two departures: an arc with a zero radius or coincident endpoints is a line or nothing, as the
|
|
1312
|
+
SVG spec says, where libsvg divides by zero and draws NaN vertices at the origin; and
|
|
1313
|
+
OpenSCAD's 2D pipeline drops vertices within ~1.1e-8 mm of collinear, which ours (any 2D
|
|
1314
|
+
shape, not just SVG) does not -- spec `paths-cubic02` keeps two such vertices at an S-curve's
|
|
1315
|
+
inflection. **Placement is `pageMap()`, matching the reference's `import_svg.cc` by its
|
|
1316
|
+
output**: the page's `width`/`height` to mm (a unitless length at `dpi=`,
|
|
1317
|
+
72 by default; `px` at 96; a `dpi` below 0.001 warns and is 72), the `viewBox` scaled onto the
|
|
1318
|
+
page under `preserveAspectRatio`
|
|
1298
1319
|
(default `xMidYMid meet`), and Y flipped about the page HEIGHT -- or about the drawing's centre
|
|
1299
1320
|
with `center=true`. Negating Y alone, as this did before, put a unitless 100-unit drawing in 2.8x
|
|
1300
1321
|
too large and below the X axis. Bounds match OpenSCAD 2026.02.01 (`SvgPlacement` tests).
|
|
@@ -1670,7 +1691,7 @@ the side-quad diagonal choice changes a twisted solid without changing its trian
|
|
|
1670
1691
|
default below 3, so these are an extrude warped round Z. The warp inverts the solid for a positive
|
|
1671
1692
|
angle, hence the mirror-in-Y dance.
|
|
1672
1693
|
- Kept departure: `$fa`/`$fs` <= 0 fall back to 12/2 rather than upstream's clamp-to-0.01 with a warning.
|
|
1673
|
-
- Not ported: `linear_extrude(v=)` (accepted, ignored); DXF
|
|
1694
|
+
- Not ported: `linear_extrude(v=)` (accepted, ignored); DXF import arcs don't read the discretizer.
|
|
1674
1695
|
|
|
1675
1696
|
## Cancel and the module recursion limit (#554)
|
|
1676
1697
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscad_cpp_evaluator
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.43.0
|
|
4
4
|
Summary: C++ OpenSCAD evaluator with Python bindings
|
|
5
5
|
Author: NeuSCAD Contributors
|
|
6
|
-
License-Expression: MIT
|
|
6
|
+
License-Expression: MIT AND OFL-1.1
|
|
7
7
|
License-File: LICENSE
|
|
8
|
+
License-File: resources/fonts/LICENSE
|
|
8
9
|
Classifier: Development Status :: 3 - Alpha
|
|
9
10
|
Classifier: Intended Audience :: Developers
|
|
10
11
|
Classifier: Operating System :: OS Independent
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 BelfrySCAD Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -43,6 +43,7 @@ enum class Op {
|
|
|
43
43
|
StoreLocal, // a = slot index (pops)
|
|
44
44
|
LoadDyn, // a = name pool index ($-prefixed)
|
|
45
45
|
StoreDyn, // a = name pool index (pops; also marks dynExplicit)
|
|
46
|
+
WarnDuplicateLet, // a = name pool index (pops; warns, binds nothing -- see Evaluator::warnDuplicateLet)
|
|
46
47
|
LoadFree, // a = name pool index -- Evaluator::evalIdentifier fallback (warnIfUndef=true)
|
|
47
48
|
// Same as LoadFree, but Evaluator::evalIdentifier's warnIfUndef=false --
|
|
48
49
|
// only ever emitted for a PrimaryCall's own callee probe (bytecode_
|
|
@@ -240,20 +241,6 @@ enum class Op {
|
|
|
240
241
|
// there's no branch to emit here).
|
|
241
242
|
Echo,
|
|
242
243
|
|
|
243
|
-
// Only ever emitted for a non-empty-argument AssertOp (see
|
|
244
|
-
// bytecode_compiler.cpp's own AssertOp case -- a zero-argument
|
|
245
|
-
// assert() is unconditionally true and compiles straight through with
|
|
246
|
-
// no check at all). Reached only on the condition-false path (guarded
|
|
247
|
-
// by a JumpIfTrue the compiler emits around it, mirroring LogicalOrOp's
|
|
248
|
-
// own jump-then-patch shape) -- always throws via Evaluator::error(),
|
|
249
|
-
// i.e. [[noreturn]] at runtime. a = 1 if a message Value was compiled
|
|
250
|
-
// and pushed (pop it), else 0. b = constant-pool index of condText
|
|
251
|
-
// (the condition expression's own source text, interned ONCE at
|
|
252
|
-
// compile time via its toString() -- cheaper than the interpreter,
|
|
253
|
-
// which recomputes this on every failing call). pos/node: same
|
|
254
|
-
// Evaluator::error() TRACE-walk need CheckIterLimit already has.
|
|
255
|
-
AssertFail,
|
|
256
|
-
|
|
257
244
|
// -- Module-body compilation (Stage 2) --------------------------------
|
|
258
245
|
// A call to a user module resolved to a specific ModuleDeclaration AT
|
|
259
246
|
// COMPILE TIME (see CompiledChunk::ModuleCallSite) -- the module-side
|
|
@@ -717,16 +704,10 @@ enum class Op {
|
|
|
717
704
|
StoreLetVar,
|
|
718
705
|
|
|
719
706
|
// a = index into CompiledChunk::assertSites. Pops site.argCount values
|
|
720
|
-
// (
|
|
721
|
-
// source order
|
|
722
|
-
//
|
|
723
|
-
//
|
|
724
|
-
// Evaluator::evalAssertStatement exactly: named "condition"/"message"
|
|
725
|
-
// win over positional 0/1 (resolved at COMPILE time into
|
|
726
|
-
// AssertSite::conditionArgIndex/messageArgIndex -- the argument SHAPE
|
|
727
|
-
// is static, only values vary per call), throws via Evaluator::error()
|
|
728
|
-
// on failure, otherwise runs any chained node.children natively (rare;
|
|
729
|
-
// not worth its own compiled path -- see AssertSite's own doc comment).
|
|
707
|
+
// (every argument of an assert() statement or expression, pushed in
|
|
708
|
+
// source order) and hands them to Evaluator::checkAssert; a statement
|
|
709
|
+
// then runs any chained children natively (rare; not worth its own
|
|
710
|
+
// compiled path).
|
|
730
711
|
AssertStatement,
|
|
731
712
|
// a = nativeStatements index of the AST node whose arm this is. Emitted
|
|
732
713
|
// only when the Evaluator was built with coverage on (compile-time
|
|
@@ -763,6 +744,10 @@ struct Instruction {
|
|
|
763
744
|
// applyDefaults()'s existing sibling-isolated defaultCtx; empty if that
|
|
764
745
|
// parameter has no default. `bodyCode` is the function's own expression body.
|
|
765
746
|
struct CompiledChunk {
|
|
747
|
+
// String literals whose text holds an escape OpenSCAD calls undefined,
|
|
748
|
+
// with how many: the Evaluator warns for them once, when the chunk is
|
|
749
|
+
// compiled (it has the warning channel; the compiler does not).
|
|
750
|
+
std::vector<std::pair<const oscad::StringLiteral*, int>> undefinedEscapeLiterals;
|
|
766
751
|
struct Param {
|
|
767
752
|
std::string name;
|
|
768
753
|
int slot = 0; // unused when isDyn is true -- $-params are never slot-addressed
|
|
@@ -1036,30 +1021,13 @@ struct CompiledChunk {
|
|
|
1036
1021
|
const oscad::ASTNode* node = nullptr;
|
|
1037
1022
|
};
|
|
1038
1023
|
|
|
1039
|
-
// One Op::AssertStatement site
|
|
1040
|
-
//
|
|
1041
|
-
// into the site's own argCount-sized popped-argument array (source
|
|
1042
|
-
// order), resolved at COMPILE time via the same "named wins over
|
|
1043
|
-
// positional 0/1" priority Evaluator::getArg applies at runtime --
|
|
1044
|
-
// nullopt means "no argument supplies this logical parameter" (mirrors
|
|
1045
|
-
// getArg's own defaultValue fallback: absent condition reads as
|
|
1046
|
-
// `Value{true}`, absent message means no ": ..." suffix).
|
|
1047
|
-
// `condTextConstIdx`: constants[] index of the condition argument's own
|
|
1048
|
-
// source text (or "false" when no condition argument exists, matching
|
|
1049
|
-
// evalAssertStatement's `node.arguments.empty() ? "false" : ...`),
|
|
1050
|
-
// interned once at compile time. `node`: for both Evaluator::error()'s
|
|
1051
|
-
// TRACE walk and the (rare) chained-children fallback below.
|
|
1052
|
-
//
|
|
1053
|
-
// ponytail: a script with TWO named args of the SAME name (e.g.
|
|
1054
|
-
// `assert(condition=true, condition=false)`) would resolve to the
|
|
1055
|
-
// LAST one here, not getArg's own first-match; not worth the extra
|
|
1056
|
-
// bookkeeping to fix for input that's already nonsensical.
|
|
1024
|
+
// One Op::AssertStatement site. `statement` is null for the expression
|
|
1025
|
+
// form, which has no children.
|
|
1057
1026
|
struct AssertSite {
|
|
1058
1027
|
int argCount = 0;
|
|
1059
|
-
std::
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
const oscad::ModularAssert* node = nullptr;
|
|
1028
|
+
const std::vector<std::unique_ptr<oscad::Argument>>* arguments = nullptr;
|
|
1029
|
+
const oscad::ASTNode* node = nullptr;
|
|
1030
|
+
const oscad::ModularAssert* statement = nullptr;
|
|
1063
1031
|
};
|
|
1064
1032
|
|
|
1065
1033
|
// Every distinct chunk this SPECIFIC CompiledChunk owns is either a
|
|
@@ -188,7 +188,7 @@ std::vector<ColoredBody> toRenderableBodies(const std::vector<ColoredBody>& bodi
|
|
|
188
188
|
double flatHeight = kTopLevel2dHeight);
|
|
189
189
|
|
|
190
190
|
// A 3D affine transform as it acts on the XY plane: rows x and y, columns
|
|
191
|
-
// x, y and translation -- what OpenSCAD
|
|
191
|
+
// x, y and translation -- what OpenSCAD applies to 2D
|
|
192
192
|
// geometry (z, and everything out of the plane, simply drops away).
|
|
193
193
|
manifold::mat2x3 projectTo2d(const manifold::mat3x4& m);
|
|
194
194
|
|
|
@@ -203,10 +203,10 @@ bool projectSectionXform(ColoredBody& b);
|
|
|
203
203
|
|
|
204
204
|
// Applies `m`, projected onto the plane, to a CrossSection. A singular
|
|
205
205
|
// projection -- scale([0,1]), a quarter turn about X -- empties it, as
|
|
206
|
-
//
|
|
206
|
+
// OpenSCAD does, and returns false.
|
|
207
207
|
bool transformSection(manifold::CrossSection& cs, const manifold::mat3x4& m);
|
|
208
208
|
|
|
209
|
-
//
|
|
209
|
+
// OpenSCAD's warning for that case, word for word.
|
|
210
210
|
inline constexpr const char* kZeroScale2dWarning = "Scaling a 2D object with 0 - removing object";
|
|
211
211
|
|
|
212
212
|
} // namespace oscadeval
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "openscad_cpp_evaluator/segments.hpp"
|
|
4
|
+
|
|
5
|
+
#include <array>
|
|
6
|
+
#include <optional>
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <vector>
|
|
9
|
+
|
|
10
|
+
namespace oscadeval {
|
|
11
|
+
|
|
12
|
+
using Contour2d = std::vector<std::array<double, 2>>;
|
|
13
|
+
|
|
14
|
+
// import()'s DXF arguments. `disc` carries $fn/$fa/$fs/$fe for arcs.
|
|
15
|
+
struct DxfOptions {
|
|
16
|
+
std::optional<std::string> layer;
|
|
17
|
+
double xorigin = 0.0, yorigin = 0.0, scale = 1.0;
|
|
18
|
+
Discretizer disc;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// The outlines, to be filled even-odd, and OpenSCAD's warnings about the
|
|
22
|
+
// file, in the order it prints them.
|
|
23
|
+
struct DxfImport {
|
|
24
|
+
std::vector<Contour2d> contours;
|
|
25
|
+
std::vector<std::string> warnings;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Hand-rolled DXF reader matching OpenSCAD 2026.02.01's import (see the
|
|
29
|
+
// notes atop dxf_import.cpp): LINE, CIRCLE, ARC, ELLIPSE, LWPOLYLINE,
|
|
30
|
+
// POLYLINE and INSERT, chained into closed outlines. Throws
|
|
31
|
+
// std::runtime_error on I/O failure.
|
|
32
|
+
DxfImport loadDxf(const std::string& path, const DxfOptions& opts = {});
|
|
33
|
+
|
|
34
|
+
// SVG reader, as OpenSCAD 2026.02.01 reads it (a port of its MIT-licensed
|
|
35
|
+
// libsvg): <path>, <rect>, <circle>, <ellipse>, <line>, <polygon>,
|
|
36
|
+
// <polyline> and <use>, with transforms, display:none, and strokes -- an
|
|
37
|
+
// open path, <line> or <polyline> is drawn as its stroke's outline. Curves
|
|
38
|
+
// split by `disc`. Y is flipped (SVG's is down, OpenSCAD's is up). Throws
|
|
39
|
+
// std::runtime_error on I/O/parse failure.
|
|
40
|
+
//: Which part of the drawing to import. All unset means the whole file.
|
|
41
|
+
//: `id` matches an element's `id` attribute; `cls` (not an OpenSCAD
|
|
42
|
+
//: parameter) one entry of its space-separated `class` list; either takes
|
|
43
|
+
//: everything under the element, so naming a <g> means "that group".
|
|
44
|
+
//: `layer` names an Inkscape layer (inkscape:groupmode="layer", by its
|
|
45
|
+
//: inkscape:label): alone it takes that layer, with id/cls it restricts
|
|
46
|
+
//: them to elements inside it.
|
|
47
|
+
struct SvgFilter {
|
|
48
|
+
std::optional<std::string> id;
|
|
49
|
+
std::optional<std::string> cls;
|
|
50
|
+
std::optional<std::string> layer;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// `matched`, when given, reports whether the filter found anything. A miss
|
|
54
|
+
// imports nothing rather than falling back to the whole drawing; the caller
|
|
55
|
+
// warns. Always true when no filter was set.
|
|
56
|
+
// Placed as OpenSCAD places them: page units to mm (a unitless length at
|
|
57
|
+
// `dpi`), the viewBox under preserveAspectRatio, Y flipped about the page
|
|
58
|
+
// height -- or about the drawing's centre with `center`. The result is
|
|
59
|
+
// filled: overlapping contours have already been combined.
|
|
60
|
+
std::vector<Contour2d> loadSvgContours(const std::string& path,
|
|
61
|
+
const SvgFilter& filter = {},
|
|
62
|
+
bool* matched = nullptr,
|
|
63
|
+
double dpi = 72.0,
|
|
64
|
+
bool center = false,
|
|
65
|
+
const Discretizer& disc = {});
|
|
66
|
+
|
|
67
|
+
} // namespace oscadeval
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
#include "openscad_cpp_evaluator/bound_args.hpp"
|
|
4
4
|
#include "openscad_cpp_evaluator/bytecode.hpp"
|
|
5
|
+
|
|
6
|
+
#include <unordered_set>
|
|
5
7
|
#include "openscad_cpp_evaluator/bytecode_vm.hpp"
|
|
6
8
|
#include "openscad_cpp_evaluator/call_args.hpp"
|
|
7
9
|
#include "openscad_cpp_evaluator/csg_node.hpp"
|
|
@@ -557,10 +559,39 @@ public:
|
|
|
557
559
|
// Public: builtins/import.cpp's not-manifold warning is emitted from a
|
|
558
560
|
// free function, same reasoning as tagGenerated()/builtinChildren().
|
|
559
561
|
void warn(const std::string& message, const oscad::Position* position);
|
|
562
|
+
// OpenSCAD's lexer warns "Undefined escape sequence" once per bad escape
|
|
563
|
+
// in the source. This warns for a literal the first time it is
|
|
564
|
+
// evaluated or compiled, and never again for that literal.
|
|
565
|
+
void warnUndefinedEscapes(const oscad::StringLiteral& lit, int count);
|
|
566
|
+
// let() keeps the FIRST binding of a repeated name: OpenSCAD evaluates
|
|
567
|
+
// the later right-hand side, warns with its value, and discards it.
|
|
568
|
+
// OpenSCAD's Assert::performAssert, given every argument's value in
|
|
569
|
+
// source order -- it evaluates them all, pass or fail, so a passing
|
|
570
|
+
// `assert(true, nosuch)` still warns. Warns about unexpected arguments;
|
|
571
|
+
// throws via error() when the condition is false or missing (`assert()`
|
|
572
|
+
// fails). The message prints as echo() would print it.
|
|
573
|
+
void checkAssert(const std::vector<std::unique_ptr<oscad::Argument>>& arguments, const std::vector<Value>& values,
|
|
574
|
+
const oscad::ASTNode& node);
|
|
575
|
+
void warnDuplicateLet(const std::string& name, const Value& v, const oscad::Position* position);
|
|
576
|
+
template <typename Assignments>
|
|
577
|
+
static bool repeatsEarlierLetName(const Assignments& assignments, size_t i) {
|
|
578
|
+
for (size_t j = 0; j < i; ++j)
|
|
579
|
+
if (assignments[j]->name->name == assignments[i]->name->name) return true;
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
std::unordered_set<const oscad::StringLiteral*> undefinedEscapesWarned_;
|
|
583
|
+
void warnUndefinedEscapes(const CompiledChunk& chunk) {
|
|
584
|
+
for (const auto& [lit, n] : chunk.undefinedEscapeLiterals) warnUndefinedEscapes(*lit, n);
|
|
585
|
+
}
|
|
560
586
|
// Hands one already-formatted warning line to echoFn_, recording it in
|
|
561
587
|
// warnCapture first when one is active. Every warning path goes through
|
|
562
588
|
// here, including a ManifoldCache hit replaying a cached line.
|
|
563
589
|
void emitWarning(const std::string& formatted);
|
|
590
|
+
// "ERROR: {message}{locSuffix(position)}" that does NOT stop the run:
|
|
591
|
+
// OpenSCAD logs several of its errors this way and carries on.
|
|
592
|
+
void nonFatalError(const std::string& message, const oscad::Position* position) {
|
|
593
|
+
emitWarning("ERROR: " + message + locSuffix(position));
|
|
594
|
+
}
|
|
564
595
|
|
|
565
596
|
// Applies OpenSCAD's mixed-2D/3D rules to a node's children just
|
|
566
597
|
// before its GenerateFn runs -- see csg_generate.cpp.
|
|
@@ -167,7 +167,7 @@ struct ExportSvgOptions {
|
|
|
167
167
|
void writeSvg(const std::string& path, const std::vector<ColoredBody>& bodies,
|
|
168
168
|
const ExportSvgOptions& opts = {});
|
|
169
169
|
|
|
170
|
-
// DXF, the third 2D writer: OpenSCAD's
|
|
170
|
+
// DXF, the third 2D writer: byte-compatible with OpenSCAD's layout (an AC1006
|
|
171
171
|
// header with the model's extents, one CONTINUOUS linetype, layer 0) and
|
|
172
172
|
// every contour of every body a closed LWPOLYLINE on layer 0 -- holes are
|
|
173
173
|
// contours like any other, as in OpenSCAD. A 1-vertex contour is a POINT
|
|
@@ -259,13 +259,10 @@ struct ExportPovOptions {
|
|
|
259
259
|
// POV-Ray scene description. Every object splitBodiesForExport produces is
|
|
260
260
|
// one mesh2 -- a welded vertex list, a texture per colour, and a texture
|
|
261
261
|
// index per triangle, so per-triangle colour needs no unwelding -- with
|
|
262
|
-
// inside_vector, which makes it a SOLID to POV-Ray (refraction, CSG).
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
// bounding box, its camera, and radiosity from rad_def.inc. Colour is rgbf
|
|
267
|
-
// with filter = 1 - alpha, as OpenSCAD writes it. Numbers are the shortest
|
|
268
|
-
// text that round-trips, in the classic locale.
|
|
262
|
+
// inside_vector, which makes it a SOLID to POV-Ray (refraction, CSG). The
|
|
263
|
+
// rest of the scene (material, lights, default camera) is spec section F2.
|
|
264
|
+
// Colour is rgbf with filter = 1 - alpha. Numbers are the shortest text that
|
|
265
|
+
// round-trips, in the classic locale.
|
|
269
266
|
void writePov(const std::string& path, const std::vector<ExportObject>& objects,
|
|
270
267
|
const ExportPovOptions& opts = {});
|
|
271
268
|
|
|
@@ -9,12 +9,14 @@ class ASTNode;
|
|
|
9
9
|
namespace oscadeval {
|
|
10
10
|
|
|
11
11
|
class Evaluator;
|
|
12
|
+
struct EvalContext;
|
|
12
13
|
|
|
13
14
|
// import() used as an expression (not a geometry statement): returns a VNF
|
|
14
15
|
// ([[verts],[faces]]) for a mesh file (.stl/.obj/.off/.3mf), or the JSON
|
|
15
16
|
// file's content converted to native values (.json). DXF/SVG-as-Region
|
|
16
17
|
// import lands alongside their module-context counterparts in a later
|
|
17
18
|
// phase. Mirrors Evaluator._import_as_value (minus the dxf/svg branch).
|
|
18
|
-
|
|
19
|
+
// `ctx` supplies $fn/$fa/$fs/$fe for an SVG's curves.
|
|
20
|
+
Value importAsValue(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& node, const EvalContext& ctx);
|
|
19
21
|
|
|
20
22
|
} // namespace oscadeval
|
|
@@ -11,34 +11,25 @@
|
|
|
11
11
|
|
|
12
12
|
namespace oscadeval {
|
|
13
13
|
|
|
14
|
-
// How curves become polygons:
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// $fn > $fe > $fa/$fs. $fe is the most a curve's polygon may stray from the
|
|
19
|
-
// true circle, measured along a radius to an edge's midpoint; when set (>=
|
|
20
|
-
// 2^-20) it replaces $fa/$fs entirely. Upstream reads $fe only behind
|
|
21
|
-
// --enable=discretization-by-error; this evaluator always honours it, and
|
|
22
|
-
// advertises that as supported_feature("discretization-by-error").
|
|
23
|
-
//
|
|
24
|
-
// Departures from upstream, kept from before this port: $fa/$fs <= 0 fall
|
|
25
|
-
// back to their defaults (12/2) rather than clamping to 0.01 with a warning.
|
|
14
|
+
// How curves become polygons: segment and slice counts from $fn/$fe/$fa/$fs
|
|
15
|
+
// (spec sections B7 and C6). $fe is always honoured here (OpenSCAD reads it
|
|
16
|
+
// only behind --enable=discretization-by-error), advertised as
|
|
17
|
+
// supported_feature("discretization-by-error").
|
|
26
18
|
struct Discretizer {
|
|
27
19
|
double fn = 0.0;
|
|
28
20
|
double fe = 0.0;
|
|
29
21
|
double fa = 12.0;
|
|
30
22
|
double fs = 2.0;
|
|
31
23
|
|
|
32
|
-
// `warn`, when given, receives
|
|
24
|
+
// `warn`, when given, receives the clamping warnings (spec section B7).
|
|
33
25
|
static Discretizer fromCtx(const EvalContext& ctx, const std::function<void(const std::string&)>& warn = {});
|
|
34
26
|
// Stored in, and read back from, a node's params -- they are part of its
|
|
35
27
|
// cache key, and generate has only the params to go on.
|
|
36
28
|
static Discretizer fromParams(const CSGParams& params);
|
|
37
29
|
void store(CSGParams& params) const;
|
|
38
30
|
|
|
39
|
-
// Segments for `angle` degrees of arc at radius r. nullopt where
|
|
40
|
-
//
|
|
41
|
-
// caller supplies its own fallback, as upstream's value_or() does.
|
|
31
|
+
// Segments for `angle` degrees of arc at radius r. nullopt where there is
|
|
32
|
+
// no count (spec section B7); every caller supplies its own fallback.
|
|
42
33
|
std::optional<int> circular(double r, double angleDegrees = 360.0) const;
|
|
43
34
|
|
|
44
35
|
// linear_extrude slice counts: twist without scale, twist with uniform
|
|
@@ -54,8 +45,8 @@ struct Discretizer {
|
|
|
54
45
|
double scaleX, double scaleY, unsigned slices, unsigned segments) const;
|
|
55
46
|
};
|
|
56
47
|
|
|
57
|
-
// Full-circle segment count from ctx's $fn/$fe/$fa/$fs at radius r
|
|
58
|
-
//
|
|
48
|
+
// Full-circle segment count from ctx's $fn/$fe/$fa/$fs at radius r, or 3
|
|
49
|
+
// when there is none.
|
|
59
50
|
int fnSegmentsFromCtx(const EvalContext& ctx, double r = 0.0,
|
|
60
51
|
const std::function<void(const std::string&)>& warn = {});
|
|
61
52
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <vector>
|
|
5
|
+
|
|
6
|
+
namespace oscadeval {
|
|
7
|
+
|
|
8
|
+
// Height data for surface() (spec section D3). Never throws: a file that
|
|
9
|
+
// cannot be read gives no heights and a warning, and the script carries on.
|
|
10
|
+
// `heights[row * cols + col]`; `minVal` is what the base sits 1 below.
|
|
11
|
+
struct SurfaceData {
|
|
12
|
+
std::vector<double> heights;
|
|
13
|
+
int rows = 0;
|
|
14
|
+
int cols = 0;
|
|
15
|
+
double minVal = 0;
|
|
16
|
+
std::vector<std::string> warnings;
|
|
17
|
+
};
|
|
18
|
+
SurfaceData loadSurface(const std::string& path, bool invert);
|
|
19
|
+
|
|
20
|
+
} // namespace oscadeval
|
|
@@ -268,12 +268,9 @@ Value vecSub(const Value& a, const Value& b);
|
|
|
268
268
|
// behavior in the reference implementation -- revisit only if a real
|
|
269
269
|
// script's `*` on a bool-containing vector is shown to need it.
|
|
270
270
|
//
|
|
271
|
-
// `error`, when non-null, receives the
|
|
272
|
-
//
|
|
273
|
-
//
|
|
274
|
-
// requires matching lengths (2 != 3)", "Matrix must be rectangular. Problem
|
|
275
|
-
// at row 1", and so on. applyBinaryOp warns with it; a caller that only
|
|
276
|
-
// wants the value can leave it null. It is only written on an undef result.
|
|
271
|
+
// `error`, when non-null, receives the diagnostic for whichever undefined
|
|
272
|
+
// case was hit (spec section A6); applyBinaryOp warns with it. It is only
|
|
273
|
+
// written on an undef result.
|
|
277
274
|
Value matmul(const Value& a, const Value& b, std::string* error = nullptr);
|
|
278
275
|
|
|
279
276
|
// OpenSCAD's echo()/str() number formatting: at most 6 significant digits,
|
|
@@ -306,7 +303,9 @@ std::string formatNumber(double v);
|
|
|
306
303
|
//
|
|
307
304
|
// A trailing lone backslash is kept as itself. It can only occur in an
|
|
308
305
|
// unterminated literal, which is a parse error long before this runs.
|
|
309
|
-
|
|
306
|
+
// `undefinedEscapes`, when given, counts the escapes OpenSCAD's lexer calls
|
|
307
|
+
// undefined (it warns once for each).
|
|
308
|
+
std::string unescapeStringLiteral(const std::string& raw, int* undefinedEscapes = nullptr);
|
|
310
309
|
|
|
311
310
|
// echo()/str()/assert-message display format: "undef" | "true"/"false" |
|
|
312
311
|
// "[start : step : end]" (range) | formatNumber() (number) | "[e1, e2, ...]"
|
|
@@ -4,12 +4,12 @@ build-backend = "scikit_build_core.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openscad_cpp_evaluator"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.43.0"
|
|
8
8
|
description = "C++ OpenSCAD evaluator with Python bindings"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
|
-
license = "MIT"
|
|
12
|
-
license-files = ["LICENSE"]
|
|
11
|
+
license = "MIT AND OFL-1.1"
|
|
12
|
+
license-files = ["LICENSE", "resources/fonts/LICENSE"]
|
|
13
13
|
authors = [{ name = "NeuSCAD Contributors" }]
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Development Status :: 3 - Alpha",
|
|
@@ -68,7 +68,7 @@ target_include_directories(openscad_cpp_evaluator PRIVATE ${stb_SOURCE_DIR} ${CM
|
|
|
68
68
|
add_dependencies(openscad_cpp_evaluator generate_bundled_font)
|
|
69
69
|
|
|
70
70
|
target_link_libraries(openscad_cpp_evaluator PUBLIC openscad_cpp_parser manifold Boost::polygon)
|
|
71
|
-
target_link_libraries(openscad_cpp_evaluator PRIVATE linenoise freetype harfbuzz)
|
|
71
|
+
target_link_libraries(openscad_cpp_evaluator PRIVATE linenoise freetype harfbuzz Clipper2)
|
|
72
72
|
target_compile_options(openscad_cpp_evaluator PRIVATE
|
|
73
73
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall;-Wextra>
|
|
74
74
|
)
|
|
@@ -392,8 +392,8 @@ std::vector<ColoredBody> generateCsg(Evaluator& ev, const CSGParams& params, con
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
RoleSplit split = splitByRole(stmtBodies);
|
|
395
|
-
// A `%` statement is scenery, not an operand:
|
|
396
|
-
// of the CSG entirely
|
|
395
|
+
// A `%` statement is scenery, not an operand: OpenSCAD leaves it out
|
|
396
|
+
// of the CSG entirely, so the
|
|
397
397
|
// NEXT statement is the minuend of a difference(), and an
|
|
398
398
|
// intersection() is not cancelled by it. It was taken as an empty
|
|
399
399
|
// operand, which emptied both. Only the `%` statement itself: a
|
|
@@ -271,15 +271,28 @@ std::vector<ColoredBody> generateSurface(Evaluator& ev, const CSGParams& params,
|
|
|
271
271
|
// operand (and so empties an intersection) -- see resolveCsg.
|
|
272
272
|
bool emptyStatementIsAnOperand(const oscad::ASTNode& stmt);
|
|
273
273
|
|
|
274
|
-
// OpenSCAD's sin_degrees/cos_degrees: exact at
|
|
274
|
+
// OpenSCAD's sin_degrees/cos_degrees/tan_degrees/atan2_degrees: exact at
|
|
275
|
+
// multiples of 30 and 45 degrees.
|
|
275
276
|
double sinDeg(double x);
|
|
276
277
|
double cosDeg(double x);
|
|
278
|
+
double tanDeg(double x);
|
|
279
|
+
double atan2Deg(double y, double x);
|
|
277
280
|
|
|
278
|
-
//
|
|
281
|
+
// A radius/diameter argument pair: a numeric `d` beats `r`, numbers only.
|
|
279
282
|
std::optional<double> lookupRadius(Evaluator& ev, const CallArgs& args, std::optional<int> rPos,
|
|
280
283
|
std::optional<int> dPos, const std::string& rName, const std::string& dName,
|
|
281
284
|
const oscad::Position* where);
|
|
282
285
|
|
|
286
|
+
// "ERROR: <text>" at `where`, for input a primitive repairs and carries on with.
|
|
287
|
+
void emitInputError(Evaluator& ev, const std::string& text, const oscad::Position* where);
|
|
288
|
+
|
|
289
|
+
// Reads polygon() paths or polyhedron() faces (`listName`): each entry a
|
|
290
|
+
// list of point indices. Entries that are not lists and indices that are not
|
|
291
|
+
// numbers are reported as ERRORs and skipped; out-of-range indices are
|
|
292
|
+
// WARNINGs and skipped. Every surviving entry is returned, however short.
|
|
293
|
+
std::vector<std::vector<size_t>> readIndexLists(Evaluator& ev, const ValueList& lists, const std::string& listName,
|
|
294
|
+
size_t pointCount, const oscad::Position* where);
|
|
295
|
+
|
|
283
296
|
CSGParams resolveText(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
|
|
284
297
|
|
|
285
298
|
// The font size text()/textmetrics()/fontmetrics() draw at: `size`
|
|
@@ -118,15 +118,14 @@ CSGParams resolveIntersectionFor(Evaluator& ev, const oscad::ModularIntersection
|
|
|
118
118
|
// needs `i` visible in `j`'s own range expression).
|
|
119
119
|
std::function<void(size_t, EvalContext&)> recurse = [&](size_t depth, EvalContext& parentCtx) {
|
|
120
120
|
if (depth == node.assignments.size()) {
|
|
121
|
+
if (depth == 0) return; // for() with no loop variables iterates zero times in OpenSCAD, not once.
|
|
121
122
|
// One body-entry marker per full cartesian-product iteration
|
|
122
123
|
// and nothing per individual variable binding (unlike
|
|
123
124
|
// evalFor) -- mirrors _resolve_intersection_for's single
|
|
124
125
|
// `_check_debug(body_node[0], loop_ctx, expr_level=True)`.
|
|
125
126
|
if (!bodyNodes.empty()) ev.checkDebug(*bodyNodes.front(), parentCtx, /*forced=*/false, /*exprLevel=*/true);
|
|
126
|
-
// One operand per child STATEMENT of every iteration:
|
|
127
|
-
//
|
|
128
|
-
// node (control.cc), so they are intersected flat, not
|
|
129
|
-
// unioned per iteration first.
|
|
127
|
+
// One operand per child STATEMENT of every iteration: OpenSCAD
|
|
128
|
+
// intersects them flat, not unioned per iteration first.
|
|
130
129
|
std::vector<const oscad::ASTNode*> assigns, stmts;
|
|
131
130
|
for (const oscad::ASTNode* stmt : bodyNodes) {
|
|
132
131
|
if (stmt->kind() == oscad::NodeKind::Assignment) assigns.push_back(stmt);
|