openscad-cpp-evaluator 0.51.1__tar.gz → 0.52.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-0.51.1 → openscad_cpp_evaluator-0.52.0}/.github/workflows/wheels.yml +18 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/CLAUDE.md +27 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/bytecode.hpp +4 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +11 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/evaluator.hpp +16 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/booleans.cpp +8 -3
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/color.cpp +3 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/control.cpp +3 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/extrude.cpp +12 -4
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/roof.cpp +3 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/topology.cpp +18 -6
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/transforms.cpp +3 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/bytecode_compiler.cpp +29 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/bytecode_vm.cpp +6 -3
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/measure_geometry.cpp +3 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/stmt_eval.cpp +30 -2
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_control_flow.cpp +204 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_debug_hooks.cpp +42 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_profiling.cpp +24 -3
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_render_expr.cpp +9 -2
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/uv.lock +1 -1
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/tools/cli/main.cpp +0 -0
{openscad_cpp_evaluator-0.51.1 → openscad_cpp_evaluator-0.52.0}/.github/workflows/wheels.yml
RENAMED
|
@@ -85,9 +85,26 @@ jobs:
|
|
|
85
85
|
# grammar requires %require "3.8". No newer bison package is
|
|
86
86
|
# available via dnf on this base image, so build one from source
|
|
87
87
|
# (fast: a few seconds) rather than switching manylinux images.
|
|
88
|
+
# Mirrors first, ftp.gnu.org last: ftp.gnu.org went unreachable
|
|
89
|
+
# (curl 7, connection timed out on 443) on both architectures for
|
|
90
|
+
# two consecutive runs of the v0.51.3 release, and it is a single
|
|
91
|
+
# point of failure for every Linux wheel we ship.
|
|
92
|
+
# ftpmirror.gnu.org is GNU's own redirector to a nearby mirror.
|
|
93
|
+
# Every line stays at THIS indent on purpose -- a more-indented
|
|
94
|
+
# line in a `>-` folded scalar keeps its newline instead of
|
|
95
|
+
# folding to a space, which would split a URL from its curl.
|
|
96
|
+
# CURL FLAG CEILING: this runs against AlmaLinux 8's curl 7.61,
|
|
97
|
+
# NOT the host's. --retry (7.12.3), --retry-connrefused (7.52)
|
|
98
|
+
# and --connect-timeout (7.7) are fine; --retry-all-errors is
|
|
99
|
+
# 7.71 and made every Linux wheel fail with
|
|
100
|
+
# "option --retry-all-errors: is unknown". Check `Added:` in
|
|
101
|
+
# curl/docs/cmdline-opts/<opt>.md before adding a flag here --
|
|
102
|
+
# testing the command on a Mac proves nothing about this curl.
|
|
88
103
|
CIBW_BEFORE_ALL_LINUX: >-
|
|
89
104
|
dnf install -y flex &&
|
|
90
|
-
curl -fsSL https://
|
|
105
|
+
{ curl -fsSL --retry 3 --retry-connrefused --connect-timeout 20 https://ftpmirror.gnu.org/bison/bison-3.8.2.tar.gz -o /tmp/bison.tar.gz ||
|
|
106
|
+
curl -fsSL --retry 3 --retry-connrefused --connect-timeout 20 https://mirrors.kernel.org/gnu/bison/bison-3.8.2.tar.gz -o /tmp/bison.tar.gz ||
|
|
107
|
+
curl -fsSL --retry 3 --retry-connrefused --connect-timeout 20 https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz -o /tmp/bison.tar.gz ; } &&
|
|
91
108
|
cd /tmp && tar xzf bison.tar.gz && cd bison-3.8.2 &&
|
|
92
109
|
./configure --prefix=/usr/local && make -j$(nproc) && make install
|
|
93
110
|
# Mirrors ci.yml's macOS step: the hosted runner image ships an
|
|
@@ -584,7 +584,33 @@ grep for `ponytail:`.
|
|
|
584
584
|
mutable state threaded through recursive evaluation. `dyn`/`let_`/`dynPositions`/`dynExplicit`
|
|
585
585
|
are `shared_ptr`-wrapped, not plain value members — `withScope()` relies on that aliasing to
|
|
586
586
|
give sibling statements in the same block correct assignment visibility (see the header comment
|
|
587
|
-
before reworking this; it's not an arbitrary choice).
|
|
587
|
+
before reworking this; it's not an arbitrary choice). **An `if`/`else` branch body is its own
|
|
588
|
+
scope**: assignments (including `$`-var assignments) inside it are visible for the rest of the
|
|
589
|
+
branch but must not survive the closing brace, so both engines evaluate a taken branch against
|
|
590
|
+
`childCtx()` — `branchScope()` in `stmt_eval.cpp`, `Op::OpenLetScope`/`Op::CloseExprScope`
|
|
591
|
+
around each branch on the compiled path. `let_`/`dyn` open a non-isolated child (the branch
|
|
592
|
+
reads everything outside, writes only inside) while `dynPositions` opens an **isolated** one, so
|
|
593
|
+
shadowing an outer name is not mistaken for reassigning it — two assignments to the same name
|
|
594
|
+
*within* one branch still warn, because they share that fresh level. Getting this wrong is not
|
|
595
|
+
just a spurious warning: before the fix a branch's writes escaped and silently changed later
|
|
596
|
+
geometry (BOSL2's `half_of()` reassigns `v` inside an `else if`, clobbering the outer `v`).
|
|
597
|
+
**A builtin operator's braced child block (`translate() { a = 1; }`) is its own scope by the
|
|
598
|
+
same rule.** Each builtin resolve function derives one `Evaluator::blockScope()` context for its
|
|
599
|
+
children (`booleans.cpp` derives ONE spanning both of `resolveCsg`'s passes, since the assignment
|
|
600
|
+
pass writes what the geometry pass reads); `emitBuiltinWrap`/`emitCsgWrap` bracket their inline
|
|
601
|
+
children with `Op::OpenLetScope`/`Op::CloseExprScope`. The bracket goes *inside* Push/Pop, because
|
|
602
|
+
`Op::PopBuiltinWrap` re-resolves the call's arguments and those must still see the OUTER ctx — an
|
|
603
|
+
assignment in the block must never feed back into the operator's own arguments.
|
|
604
|
+
**Do not "simplify" this into `resolveCallArgs`** by having it always return a child ctx, however
|
|
605
|
+
tempting — every builtin's child context does come from there, but so does every *user*-module
|
|
606
|
+
call's and every pure argument resolution, and the extra dyn level breaks BOSL2's `$`-var
|
|
607
|
+
propagation outright (`$tags_shown`/`$attach_to`/`$transform`/`$anchor_override` stop resolving).
|
|
608
|
+
That was tried: the whole unit suite passed and 130 of ~390 BOSL2 doc examples failed. Scope the
|
|
609
|
+
CHILDREN, not the call. `for`/`let`/`intersection_for` bodies, and a *user* module's child block (evaluated
|
|
610
|
+
through `childrenCallerCtx`), were already correct. `tests/test_control_flow.cpp`'s
|
|
611
|
+
`IfBranchScope.*` and `OperatorBlockScope.*` pin every case under both engines. One older test
|
|
612
|
+
(`RenderExpr.MeasuredSubtreeUsesItsOwnCoordinates`) had encoded the leak by reading a block's
|
|
613
|
+
variable from outside it, and was corrected.
|
|
588
614
|
- `include/openscad_cpp_evaluator/eval_error.hpp`, `src/eval_error.cpp` — `EvalError` and the
|
|
589
615
|
exact ERROR/TRACE string formatting real OpenSCAD produces. Also the **unexpected-argument
|
|
590
616
|
warnings** (`warnUnexpectedNamedArg`/`warnTooManyPositionalArgs`/`warnUnexpectedArgs`), the port
|
|
@@ -687,7 +687,10 @@ enum class Op {
|
|
|
687
687
|
// just "pop the current ctx level", identical either way.
|
|
688
688
|
CloseExprScope,
|
|
689
689
|
|
|
690
|
-
// ModularLet's own (statement-form) child scope
|
|
690
|
+
// ModularLet's own (statement-form) child scope, ALSO used to bracket
|
|
691
|
+
// an if/else branch body (see ModularIf/ModularIfElse in
|
|
692
|
+
// bytecode_compiler.cpp) -- a branch is its own scope in OpenSCAD and
|
|
693
|
+
// needs exactly this same child ctx, so one opcode covers both -- mirrors
|
|
691
694
|
// Evaluator::evalLetBlock's own `ctx.childCtx(nullptr, std::nullopt,
|
|
692
695
|
// ctx.childrenNodes, ctx.childrenCallerCtx)` call exactly, pushed onto
|
|
693
696
|
// f.ctxChain (Op::CloseExprScope, above, pops it back off once the
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include <cstdint>
|
|
13
13
|
#include <memory>
|
|
14
14
|
#include <optional>
|
|
15
|
+
#include <deque>
|
|
15
16
|
#include <vector>
|
|
16
17
|
|
|
17
18
|
namespace oscadeval {
|
|
@@ -155,7 +156,16 @@ struct VmFrame {
|
|
|
155
156
|
std::vector<bool> bound;
|
|
156
157
|
std::vector<std::vector<Value>> accumStack;
|
|
157
158
|
std::vector<IterList> iterLists;
|
|
158
|
-
std::vector
|
|
159
|
+
// std::deque, NOT vector: Evaluator::enterUserCall stores
|
|
160
|
+
// CallStackFrame::bodyCtx as a pointer to ctxChain.back() (see
|
|
161
|
+
// pushBracketedCallFrame/pushBracketedModuleFrame), and that pointer is
|
|
162
|
+
// read LATER, by any checkDebug() that walks the whole call stack to
|
|
163
|
+
// build per-frame debugger locals. A vector reallocates on the next
|
|
164
|
+
// push -- which every transform inside a compiled body does, via
|
|
165
|
+
// Op::PushBuiltinWrap -- leaving bodyCtx pointing at the moved-from
|
|
166
|
+
// element (null let_) and segfaulting buildDebugFrame. deque never
|
|
167
|
+
// invalidates references to existing elements on push_back/pop_back.
|
|
168
|
+
std::deque<EvalContext> ctxChain;
|
|
159
169
|
// Still-open Op::PushBuiltinWrap brackets, LIFO, scoped to THIS frame's
|
|
160
170
|
// own instruction stream -- mirrors accumStack/iterLists' own role for
|
|
161
171
|
// their respective bracket pairs. Normal execution always drains this
|
|
@@ -144,6 +144,22 @@ public:
|
|
|
144
144
|
// sub-groups of an existing children list without needing ownership.
|
|
145
145
|
void evalChildren(const std::vector<const oscad::ASTNode*>& children, EvalContext& ctx);
|
|
146
146
|
|
|
147
|
+
// The child context a BRACED BLOCK's statements run in. A `{ ... }`
|
|
148
|
+
// block is a scope in OpenSCAD: assignments (and `$`-var assignments)
|
|
149
|
+
// inside it are visible for the rest of the block but must not survive
|
|
150
|
+
// the closing brace. Every builtin operator's resolve function derives
|
|
151
|
+
// one of these for its children; the compiled path does the same with
|
|
152
|
+
// an Op::OpenLetScope/Op::CloseExprScope bracket.
|
|
153
|
+
//
|
|
154
|
+
// Deliberately NOT folded into resolveCallArgs, though that is the one
|
|
155
|
+
// place every builtin's child context comes from: resolveCallArgs also
|
|
156
|
+
// serves user-module calls and pure argument resolution, and giving
|
|
157
|
+
// those an extra dyn level breaks BOSL2's `$`-var propagation
|
|
158
|
+
// ($tags_shown/$attach_to/$transform all stop resolving). Measured, not
|
|
159
|
+
// reasoned: 130 of ~390 BOSL2 doc examples failed that way. Scope the
|
|
160
|
+
// CHILDREN, not the call.
|
|
161
|
+
EvalContext blockScope(const EvalContext& ctx) const;
|
|
162
|
+
|
|
147
163
|
// Top-level entry point: resolveTree() + generateTree(), then the
|
|
148
164
|
// top-level `!` (show_only) filter -- if any returned body has
|
|
149
165
|
// BodyRole::ShowOnly, the result is filtered down to just
|
|
@@ -91,22 +91,27 @@ CSGParams resolveCsg(Evaluator& ev, const oscad::ModularCall& node, EvalContext&
|
|
|
91
91
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
92
92
|
(void)args;
|
|
93
93
|
|
|
94
|
+
// ONE scope around both passes -- see Evaluator::blockScope. The
|
|
95
|
+
// assignment pass writes into the same block scope the geometry pass
|
|
96
|
+
// then reads from, so it cannot be scoped per-pass.
|
|
97
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
98
|
+
|
|
94
99
|
std::vector<const oscad::ASTNode*> assignNodes;
|
|
95
100
|
std::vector<const oscad::ASTNode*> geoNodes;
|
|
96
|
-
for (const oscad::ASTNode* c : ev.expandChildStatements(node.children,
|
|
101
|
+
for (const oscad::ASTNode* c : ev.expandChildStatements(node.children, blockCtx)) {
|
|
97
102
|
if (c->kind() == oscad::NodeKind::Assignment) {
|
|
98
103
|
assignNodes.push_back(c);
|
|
99
104
|
} else if (c->kind() != oscad::NodeKind::ModuleDeclaration && c->kind() != oscad::NodeKind::FunctionDeclaration) {
|
|
100
105
|
geoNodes.push_back(c);
|
|
101
106
|
}
|
|
102
107
|
}
|
|
103
|
-
if (!assignNodes.empty()) ev.evalChildren(assignNodes,
|
|
108
|
+
if (!assignNodes.empty()) ev.evalChildren(assignNodes, blockCtx);
|
|
104
109
|
|
|
105
110
|
std::vector<Value> groupSizes;
|
|
106
111
|
groupSizes.reserve(geoNodes.size());
|
|
107
112
|
for (const oscad::ASTNode* geoNode : geoNodes) {
|
|
108
113
|
const size_t before = ev.currentTreeFrameSize();
|
|
109
|
-
ev.evalChildren(std::vector<const oscad::ASTNode*>{geoNode},
|
|
114
|
+
ev.evalChildren(std::vector<const oscad::ASTNode*>{geoNode}, blockCtx);
|
|
110
115
|
groupSizes.push_back(Value{static_cast<double>(ev.currentTreeFrameSize() - before)});
|
|
111
116
|
}
|
|
112
117
|
|
|
@@ -44,7 +44,9 @@ CSGParams resolveColor(Evaluator& ev, const oscad::ModularCall& node, EvalContex
|
|
|
44
44
|
// under the color-tagged context -- the returned bodies themselves are
|
|
45
45
|
// unused here; generate reads them back via each child's own .bodies
|
|
46
46
|
// and stamps `rgba` onto all of them. Mirrors _resolve_color.
|
|
47
|
-
|
|
47
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
48
|
+
EvalContext blockCtx = ev.blockScope(result.ctx);
|
|
49
|
+
ev.evalChildren(node.children, blockCtx);
|
|
48
50
|
return std::move(result.params);
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -31,7 +31,9 @@ std::vector<ColoredBody> generateChildren(Evaluator&, const CSGParams&, const st
|
|
|
31
31
|
CSGParams resolveRender(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
32
32
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
33
33
|
(void)args;
|
|
34
|
-
|
|
34
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
35
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
36
|
+
ev.evalChildren(node.children, blockCtx);
|
|
35
37
|
return CSGParams{};
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -56,7 +56,9 @@ BuiltinWrapParams computeLinearExtrudeParams(Evaluator& ev, const oscad::Modular
|
|
|
56
56
|
|
|
57
57
|
CSGParams resolveLinearExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
58
58
|
BuiltinWrapParams result = computeLinearExtrudeParams(ev, node, ctx);
|
|
59
|
-
|
|
59
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
60
|
+
EvalContext blockCtx = ev.blockScope(result.ctx);
|
|
61
|
+
ev.evalChildren(node.children, blockCtx);
|
|
60
62
|
return std::move(result.params);
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -107,7 +109,9 @@ BuiltinWrapParams computeRotateExtrudeParams(Evaluator& ev, const oscad::Modular
|
|
|
107
109
|
|
|
108
110
|
CSGParams resolveRotateExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
109
111
|
BuiltinWrapParams result = computeRotateExtrudeParams(ev, node, ctx);
|
|
110
|
-
|
|
112
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
113
|
+
EvalContext blockCtx = ev.blockScope(result.ctx);
|
|
114
|
+
ev.evalChildren(node.children, blockCtx);
|
|
111
115
|
return std::move(result.params);
|
|
112
116
|
}
|
|
113
117
|
|
|
@@ -143,7 +147,9 @@ BuiltinWrapParams computeProjectionParams(Evaluator& ev, const oscad::ModularCal
|
|
|
143
147
|
|
|
144
148
|
CSGParams resolveProjection(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
145
149
|
BuiltinWrapParams result = computeProjectionParams(ev, node, ctx);
|
|
146
|
-
|
|
150
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
151
|
+
EvalContext blockCtx = ev.blockScope(result.ctx);
|
|
152
|
+
ev.evalChildren(node.children, blockCtx);
|
|
147
153
|
return std::move(result.params);
|
|
148
154
|
}
|
|
149
155
|
|
|
@@ -209,7 +215,9 @@ BuiltinWrapParams computeOffsetParams(Evaluator& ev, const oscad::ModularCall& n
|
|
|
209
215
|
|
|
210
216
|
CSGParams resolveOffset(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
211
217
|
BuiltinWrapParams result = computeOffsetParams(ev, node, ctx);
|
|
212
|
-
|
|
218
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
219
|
+
EvalContext blockCtx = ev.blockScope(result.ctx);
|
|
220
|
+
ev.evalChildren(node.children, blockCtx);
|
|
213
221
|
return std::move(result.params);
|
|
214
222
|
}
|
|
215
223
|
|
|
@@ -464,7 +464,9 @@ CSGParams computeRoofParams(Evaluator& ev, const CallArgs& args, EvalContext& ef
|
|
|
464
464
|
|
|
465
465
|
CSGParams resolveRoof(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
466
466
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
467
|
-
|
|
467
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
468
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
469
|
+
ev.evalChildren(node.children, blockCtx);
|
|
468
470
|
return computeRoofParams(ev, args, effCtx);
|
|
469
471
|
}
|
|
470
472
|
|
|
@@ -23,7 +23,9 @@ static constexpr double kDefaultSimplifyFraction = 0.001;
|
|
|
23
23
|
CSGParams resolveHull(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
24
24
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
25
25
|
(void)args;
|
|
26
|
-
|
|
26
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
27
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
28
|
+
ev.evalChildren(node.children, blockCtx);
|
|
27
29
|
return CSGParams{};
|
|
28
30
|
}
|
|
29
31
|
|
|
@@ -85,7 +87,9 @@ std::vector<ColoredBody> generateHull(Evaluator&, const CSGParams&, const std::v
|
|
|
85
87
|
CSGParams resolveFill(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
86
88
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
87
89
|
(void)args;
|
|
88
|
-
|
|
90
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
91
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
92
|
+
ev.evalChildren(node.children, blockCtx);
|
|
89
93
|
return CSGParams{};
|
|
90
94
|
}
|
|
91
95
|
|
|
@@ -146,7 +150,9 @@ std::vector<ColoredBody> generateFill(Evaluator& ev, const CSGParams&,
|
|
|
146
150
|
CSGParams resolveMinkowski(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
147
151
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
148
152
|
(void)args;
|
|
149
|
-
|
|
153
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
154
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
155
|
+
ev.evalChildren(node.children, blockCtx);
|
|
150
156
|
return CSGParams{};
|
|
151
157
|
}
|
|
152
158
|
|
|
@@ -334,7 +340,9 @@ std::vector<ColoredBody> generateMinkowski(Evaluator& ev, const CSGParams&, cons
|
|
|
334
340
|
CSGParams resolveMinkowskiDifference(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
335
341
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
336
342
|
(void)args;
|
|
337
|
-
|
|
343
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
344
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
345
|
+
ev.evalChildren(node.children, blockCtx);
|
|
338
346
|
return CSGParams{};
|
|
339
347
|
}
|
|
340
348
|
|
|
@@ -394,7 +402,9 @@ CSGParams resolveSimplify(Evaluator& ev, const oscad::ModularCall& node, EvalCon
|
|
|
394
402
|
CSGParams params;
|
|
395
403
|
// Position 0 so simplify(0.1) reads naturally.
|
|
396
404
|
params["tolerance"] = getArg(args, 0, "tolerance", Value{});
|
|
397
|
-
|
|
405
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
406
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
407
|
+
ev.evalChildren(node.children, blockCtx);
|
|
398
408
|
return params;
|
|
399
409
|
}
|
|
400
410
|
|
|
@@ -715,7 +725,9 @@ CSGParams resolveLevelSet(Evaluator& ev, const oscad::ModularCall& node, EvalCon
|
|
|
715
725
|
params["isovalue"] = getArg(args, 2, "isovalue", Value{0.0});
|
|
716
726
|
params["invert"] = getArg(args, 3, "invert", Value{false});
|
|
717
727
|
params["edge"] = getArg(args, 4, "edge", Value{});
|
|
718
|
-
|
|
728
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
729
|
+
EvalContext blockCtx = ev.blockScope(effCtx);
|
|
730
|
+
ev.evalChildren(node.children, blockCtx);
|
|
719
731
|
return params;
|
|
720
732
|
}
|
|
721
733
|
|
|
@@ -219,7 +219,9 @@ BuiltinWrapParams computeTransformParams(Evaluator& ev, const oscad::ModularCall
|
|
|
219
219
|
|
|
220
220
|
CSGParams resolveTransform(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
221
221
|
BuiltinWrapParams result = computeTransformParams(ev, node, ctx);
|
|
222
|
-
|
|
222
|
+
// The child block is its own scope -- see Evaluator::blockScope.
|
|
223
|
+
EvalContext blockCtx = ev.blockScope(result.ctx);
|
|
224
|
+
ev.evalChildren(node.children, blockCtx);
|
|
223
225
|
return std::move(result.params);
|
|
224
226
|
}
|
|
225
227
|
|
|
@@ -1289,7 +1289,15 @@ public:
|
|
|
1289
1289
|
chunk_.builtinWrapSites.push_back(std::move(site));
|
|
1290
1290
|
const int idx = static_cast<int>(chunk_.builtinWrapSites.size()) - 1;
|
|
1291
1291
|
out.push_back({Op::PushBuiltinWrap, idx, 0, &wrapperNode.position()});
|
|
1292
|
+
// The child block is its own scope -- same rule as an if-branch, and
|
|
1293
|
+
// the interpreter gets it from resolveCallArgs' child ctx (see
|
|
1294
|
+
// call_args.cpp). Opened INSIDE the Push/Pop bracket so that
|
|
1295
|
+
// Op::PopBuiltinWrap's own resolveCallArgs call still sees the
|
|
1296
|
+
// OUTER ctx: an assignment in the block must not feed back into the
|
|
1297
|
+
// operator's own arguments.
|
|
1298
|
+
out.push_back({Op::OpenLetScope, 0, 0, nullptr});
|
|
1292
1299
|
compileStatementList(children, out);
|
|
1300
|
+
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1293
1301
|
out.push_back({Op::PopBuiltinWrap, idx, 0, &wrapperNode.position()});
|
|
1294
1302
|
}
|
|
1295
1303
|
|
|
@@ -1312,6 +1320,10 @@ public:
|
|
|
1312
1320
|
chunk_.csgWrapSites.push_back(std::move(site));
|
|
1313
1321
|
const int idx = static_cast<int>(chunk_.csgWrapSites.size()) - 1;
|
|
1314
1322
|
out.push_back({Op::PushCsgWrap, idx, 0, &call.position()});
|
|
1323
|
+
// One scope around BOTH passes -- see emitBuiltinWrap's own note.
|
|
1324
|
+
// The assignment pass must write into the same block scope the
|
|
1325
|
+
// geometry pass then reads from, so it cannot be bracketed per-pass.
|
|
1326
|
+
out.push_back({Op::OpenLetScope, 0, 0, nullptr});
|
|
1315
1327
|
|
|
1316
1328
|
std::vector<const oscad::ASTNode*> assignNodes;
|
|
1317
1329
|
std::vector<const oscad::ASTNode*> geoNodes;
|
|
@@ -1335,6 +1347,7 @@ public:
|
|
|
1335
1347
|
compileStatementList(std::vector<const oscad::ASTNode*>{geoNode}, out);
|
|
1336
1348
|
out.push_back({Op::CsgGroupEnd, 0, 0, nullptr});
|
|
1337
1349
|
}
|
|
1350
|
+
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1338
1351
|
out.push_back({Op::PopCsgWrap, idx, 0, &call.position()});
|
|
1339
1352
|
}
|
|
1340
1353
|
|
|
@@ -1688,13 +1701,25 @@ public:
|
|
|
1688
1701
|
emitBuiltinWrap(CompiledChunk::BuiltinWrapSite::Kind::Modifier, "show_only", n, {n.child.get()}, out);
|
|
1689
1702
|
return;
|
|
1690
1703
|
}
|
|
1704
|
+
// Both if-forms bracket the taken branch in Op::OpenLetScope /
|
|
1705
|
+
// Op::CloseExprScope. An if-branch body is its own scope in
|
|
1706
|
+
// OpenSCAD -- assignments inside must not survive the closing
|
|
1707
|
+
// brace -- and the child ctx a let-BLOCK gets is exactly the
|
|
1708
|
+
// one a branch needs, so the same opcode serves both (see
|
|
1709
|
+
// branchScope, stmt_eval.cpp, for the interpreter's identical
|
|
1710
|
+
// rule and the full reasoning). The scope is opened INSIDE the
|
|
1711
|
+
// conditional jump's target range, so a branch that is not
|
|
1712
|
+
// taken never opens one, and each branch's own Close is the
|
|
1713
|
+
// last thing before the jump past its sibling.
|
|
1691
1714
|
case NodeKind::ModularIf: {
|
|
1692
1715
|
auto& n = static_cast<const oscad::ModularIf&>(stmt);
|
|
1693
1716
|
const int jumpFalseIdx = static_cast<int>(out.size());
|
|
1694
1717
|
out.push_back({Op::NativeCondJumpIfFalse, internNativeExpr(n.condition.get()), 0, &n.condition->position()});
|
|
1695
1718
|
const oscad::ASTNode* marker = n.trueBranch.empty() ? &stmt : n.trueBranch.front().get();
|
|
1696
1719
|
out.push_back({Op::NativeCheckDebugExprLevel, internNativeStatement(marker), 0, nullptr});
|
|
1720
|
+
out.push_back({Op::OpenLetScope, 0, 0, nullptr});
|
|
1697
1721
|
compileStatementList(n.trueBranch, out);
|
|
1722
|
+
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1698
1723
|
out[static_cast<size_t>(jumpFalseIdx)].b = static_cast<int>(out.size());
|
|
1699
1724
|
return;
|
|
1700
1725
|
}
|
|
@@ -1704,13 +1729,17 @@ public:
|
|
|
1704
1729
|
out.push_back({Op::NativeCondJumpIfFalse, internNativeExpr(n.condition.get()), 0, &n.condition->position()});
|
|
1705
1730
|
const oscad::ASTNode* trueMarker = n.trueBranch.empty() ? &stmt : n.trueBranch.front().get();
|
|
1706
1731
|
out.push_back({Op::NativeCheckDebugExprLevel, internNativeStatement(trueMarker), 0, nullptr});
|
|
1732
|
+
out.push_back({Op::OpenLetScope, 0, 0, nullptr});
|
|
1707
1733
|
compileStatementList(n.trueBranch, out);
|
|
1734
|
+
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1708
1735
|
const int jumpEndIdx = static_cast<int>(out.size());
|
|
1709
1736
|
out.push_back({Op::Jump, 0, 0, nullptr});
|
|
1710
1737
|
out[static_cast<size_t>(jumpFalseIdx)].b = static_cast<int>(out.size());
|
|
1711
1738
|
const oscad::ASTNode* falseMarker = n.falseBranch.empty() ? &stmt : n.falseBranch.front().get();
|
|
1712
1739
|
out.push_back({Op::NativeCheckDebugExprLevel, internNativeStatement(falseMarker), 0, nullptr});
|
|
1740
|
+
out.push_back({Op::OpenLetScope, 0, 0, nullptr});
|
|
1713
1741
|
compileStatementList(n.falseBranch, out);
|
|
1742
|
+
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1714
1743
|
out[static_cast<size_t>(jumpEndIdx)].a = static_cast<int>(out.size());
|
|
1715
1744
|
return;
|
|
1716
1745
|
}
|
|
@@ -270,8 +270,11 @@ void pushBracketedCallFrame(Evaluator& ev, const CompiledChunk& chunk, const osc
|
|
|
270
270
|
applyCompiledDefaultsToFrame(ev, chunk, *frame);
|
|
271
271
|
|
|
272
272
|
// enterUserCall's own bodyCtx must point at frame->ctxChain's OWN
|
|
273
|
-
// storage (stable: this VmFrame lives behind a
|
|
274
|
-
// address never moves even if vmCallStack_ itself
|
|
273
|
+
// storage (stable on two counts: this VmFrame lives behind a
|
|
274
|
+
// unique_ptr, so its address never moves even if vmCallStack_ itself
|
|
275
|
+
// reallocates, AND ctxChain is a std::deque, so a later push onto it
|
|
276
|
+
// never moves the element handed over here -- see its own doc comment,
|
|
277
|
+
// bytecode_vm.hpp, for the segfault a vector caused), not
|
|
275
278
|
// a plain local -- a local `childCtx` here would be destroyed the
|
|
276
279
|
// instant this function returns, but CallStackFrame::bodyCtx is read
|
|
277
280
|
// LATER, by ANY subsequent checkDebug() call (this call's own nested
|
|
@@ -328,7 +331,7 @@ void pushBracketedModuleFrame(Evaluator& ev, const CompiledChunk& chunk, const o
|
|
|
328
331
|
frame->logicalName = decl.name->name;
|
|
329
332
|
frame->ownsModuleSplice = true;
|
|
330
333
|
// enterUserCall's own bodyCtx must point at frame->ctxChain's OWN
|
|
331
|
-
// storage, not the caller's own (about-to-be-destroyed) local
|
|
334
|
+
// (deque-stable) storage, not the caller's own (about-to-be-destroyed) local
|
|
332
335
|
// `childCtx` -- see pushBracketedCallFrame's own doc comment, above,
|
|
333
336
|
// for the full dangling-pointer hazard this avoids (same fix, same
|
|
334
337
|
// root cause, module side).
|
|
@@ -228,7 +228,9 @@ Value Evaluator::evalRenderExpr(const oscad::RenderExpression& node, EvalContext
|
|
|
228
228
|
treeStack_.emplace_back();
|
|
229
229
|
std::vector<std::unique_ptr<CSGNode>> sub;
|
|
230
230
|
try {
|
|
231
|
-
|
|
231
|
+
// The child block is its own scope -- see blockScope.
|
|
232
|
+
EvalContext blockCtx = blockScope(effCtx);
|
|
233
|
+
evalChildren(node.children, blockCtx);
|
|
232
234
|
sub = std::move(treeStack_.back());
|
|
233
235
|
treeStack_.pop_back();
|
|
234
236
|
} catch (...) {
|
|
@@ -6,6 +6,32 @@
|
|
|
6
6
|
|
|
7
7
|
namespace oscadeval {
|
|
8
8
|
|
|
9
|
+
// A braced block is its own scope in OpenSCAD: assignments (and `$`-var
|
|
10
|
+
// assignments) inside it are visible to the rest of the block and to
|
|
11
|
+
// anything it calls, but must NOT survive the closing brace.
|
|
12
|
+
//
|
|
13
|
+
// a = 1;
|
|
14
|
+
// if (true) { a = 2; }
|
|
15
|
+
// echo(a); // 1 in OpenSCAD -- was 2 here
|
|
16
|
+
//
|
|
17
|
+
// Evaluating a block against the enclosing ctx let those writes escape,
|
|
18
|
+
// which silently changed geometry (BOSL2's half_of() reassigns `v` inside
|
|
19
|
+
// an `else if`, clobbering the outer `v` for everything after it) and also
|
|
20
|
+
// produced a bogus "assigned on line N but was overwritten" warning for
|
|
21
|
+
// what is really a shadow, not an overwrite. Verified against OpenSCAD
|
|
22
|
+
// 2026.02.01 for values, `$`-vars, nesting, and the same-scope warning
|
|
23
|
+
// that must still fire.
|
|
24
|
+
//
|
|
25
|
+
// This is exactly the child context a let-BLOCK gets (evalLetBlock, and
|
|
26
|
+
// Op::OpenLetScope on the compiled path): let_/dyn open a non-isolated
|
|
27
|
+
// child so the block reads everything outside and writes only inside,
|
|
28
|
+
// while dynPositions opens an ISOLATED one so shadowing an outer name is
|
|
29
|
+
// not mistaken for reassigning it -- two assignments to the same name
|
|
30
|
+
// within the one block still warn, because they share this fresh level.
|
|
31
|
+
EvalContext Evaluator::blockScope(const EvalContext& ctx) const {
|
|
32
|
+
return ctx.childCtx(nullptr, std::nullopt, ctx.childrenNodes, ctx.childrenCallerCtx);
|
|
33
|
+
}
|
|
34
|
+
|
|
9
35
|
void Evaluator::evalAssignment(const oscad::Assignment& node, EvalContext& ctx) {
|
|
10
36
|
const std::string& name = node.name->name;
|
|
11
37
|
if (!name.empty() && name[0] == '$') {
|
|
@@ -196,7 +222,8 @@ void Evaluator::evalStatement(const oscad::ASTNode& node, EvalContext& ctx) {
|
|
|
196
222
|
if (truthy(evalExprMaybeCompiled(*n.condition, ctx))) {
|
|
197
223
|
checkDebug(n.trueBranch.empty() ? node : *n.trueBranch.front(), ctx, /*forced=*/false,
|
|
198
224
|
/*exprLevel=*/true);
|
|
199
|
-
|
|
225
|
+
EvalContext branchCtx = blockScope(ctx);
|
|
226
|
+
evalChildren(n.trueBranch, branchCtx);
|
|
200
227
|
}
|
|
201
228
|
return;
|
|
202
229
|
}
|
|
@@ -204,7 +231,8 @@ void Evaluator::evalStatement(const oscad::ASTNode& node, EvalContext& ctx) {
|
|
|
204
231
|
auto& n = static_cast<const oscad::ModularIfElse&>(node);
|
|
205
232
|
const auto& branch = truthy(evalExprMaybeCompiled(*n.condition, ctx)) ? n.trueBranch : n.falseBranch;
|
|
206
233
|
checkDebug(branch.empty() ? node : *branch.front(), ctx, /*forced=*/false, /*exprLevel=*/true);
|
|
207
|
-
|
|
234
|
+
EvalContext branchCtx = blockScope(ctx);
|
|
235
|
+
evalChildren(branch, branchCtx);
|
|
208
236
|
return;
|
|
209
237
|
}
|
|
210
238
|
case oscad::NodeKind::ModularFor:
|