openscad-cpp-evaluator 0.13.3__tar.gz → 0.13.4__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.13.3 → openscad_cpp_evaluator-0.13.4}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/bytecode.hpp +46 -2
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/evaluator.hpp +69 -5
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/scope_trail.hpp +19 -1
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/bytecode_compiler.cpp +19 -6
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/bytecode_vm.cpp +108 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/user_calls.cpp +36 -12
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_bytecode_compiler.cpp +82 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_scope_trail.cpp +30 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/README.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/text/stb_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tools/cli/main.cpp +0 -0
|
@@ -325,8 +325,50 @@ enum class Op {
|
|
|
325
325
|
// same seam, now a counter).
|
|
326
326
|
PopBuiltinWrap,
|
|
327
327
|
|
|
328
|
+
// A `children()` / `children(N)` statement -- the runtime-varying
|
|
329
|
+
// sibling of Op::CallModule/Op::PushBuiltinWrap, closing the LAST
|
|
330
|
+
// dominant native-reentry source (BOSL2's attachable() calls
|
|
331
|
+
// children() at nearly every wrapper level; measured 85 of 93 native
|
|
332
|
+
// reentries in a real script). Unlike PushBuiltinWrap's constructs,
|
|
333
|
+
// the forwarded children aren't known at compile time (they're the
|
|
334
|
+
// CALLER's own call-site statements, carried on ctx.childrenNodes/
|
|
335
|
+
// childrenCallerCtx -- see Evaluator::buildModuleChildCtx), so they
|
|
336
|
+
// can't compile inline; instead the handler resolves the list at
|
|
337
|
+
// RUNTIME, looks up/compiles its chunk (the same
|
|
338
|
+
// childrenListChunkCache_ tryRunCompiledChildren uses, via
|
|
339
|
+
// lookupOrCompileChildrenListChunk -- gated on useBytecodeVm() &&
|
|
340
|
+
// inResolvePass_, the cache is pass-scoped), and pushes it onto
|
|
341
|
+
// vmCallStack_ directly, mirroring Op::CallModule's own zero-native-
|
|
342
|
+
// call push -- but with a THIRD frame shape: splice-owning like a
|
|
343
|
+
// module frame (ownsModuleSplice=true, mirroring evalModularCall's
|
|
344
|
+
// own unconditional splice branch for "children"), yet bracketless
|
|
345
|
+
// like a bare frame (children() never gets a callStack_/profiling
|
|
346
|
+
// entry natively either -- only enterUserCall pushes those, and
|
|
347
|
+
// resolveChildren/builtinChildren never call it). driveVm's existing
|
|
348
|
+
// completion branch and teardownVmCallStackDownTo both already
|
|
349
|
+
// handle that combination (their bracket and splice concerns are
|
|
350
|
+
// independent).
|
|
351
|
+
//
|
|
352
|
+
// Handler ordering is load-bearing: checkDebug fires in-handler
|
|
353
|
+
// against the scope-wrapped ctx (byte-for-byte what Op::
|
|
354
|
+
// NativeStatement does -- NOT via an emitted Op::CheckDebugStatement,
|
|
355
|
+
// whose handler passes the un-wrapped ctx); randsBefore is captured
|
|
356
|
+
// BEFORE argument resolution (rands-in-args taint, same lesson
|
|
357
|
+
// PushBuiltinWrap already encodes); and treeStack_ is pushed LAST,
|
|
358
|
+
// immediately before the frame push / native fallback (an early-out
|
|
359
|
+
// or a throw during arg resolution then has nothing to clean up --
|
|
360
|
+
// the native path's own catch{pop;throw} has no equivalent here, so
|
|
361
|
+
// the reorder IS the exception-safety mechanism). The not-eligible
|
|
362
|
+
// fallback reuses the ALREADY-resolved args (never evalStatement,
|
|
363
|
+
// which would re-resolve them: double rands(), double side effects)
|
|
364
|
+
// by inlining evalModularCall's own children branch around a native
|
|
365
|
+
// evalChildren call. a = index into CompiledChunk::nativeStatements
|
|
366
|
+
// (the ModularCall node -- arguments, error position, splice node;
|
|
367
|
+
// no separate site table needed).
|
|
368
|
+
CallChildren,
|
|
369
|
+
|
|
328
370
|
// A single "native passthrough" statement -- intersection_for,
|
|
329
|
-
//
|
|
371
|
+
// union/difference/intersection and every other builtin
|
|
330
372
|
// module call NOT covered by Op::PushBuiltinWrap (see that op's own
|
|
331
373
|
// doc comment for exactly which builtins ARE covered), the `*`
|
|
332
374
|
// modifier's own no-op case, or a user-module call that didn't
|
|
@@ -344,7 +386,9 @@ enum class Op {
|
|
|
344
386
|
// pattern that made this op's own native reentry a genuine Windows
|
|
345
387
|
// crash risk in practice, not just a missed optimization. See
|
|
346
388
|
// Op::PushBuiltinWrap's own doc comment for the real story and the
|
|
347
|
-
// fix.)
|
|
389
|
+
// fix. children() fell here too, and was the LAST and largest such
|
|
390
|
+
// reentry source once PushBuiltinWrap's own set was covered -- it
|
|
391
|
+
// now has Op::CallChildren, above.)
|
|
348
392
|
// a = index into CompiledChunk::nativeStatements. Runtime just does
|
|
349
393
|
// what Evaluator::evalChildren's own per-statement loop already does
|
|
350
394
|
// for one node: derive childCtx via ctx.withScope(...), checkDebug,
|
|
@@ -271,6 +271,25 @@ public:
|
|
|
271
271
|
// _builtin_children/_eval_children_lazy.
|
|
272
272
|
void builtinChildren(const CallArgs& args, EvalContext& ctx);
|
|
273
273
|
|
|
274
|
+
// The "which nodes, evaluated against what context" half of
|
|
275
|
+
// builtinChildren, shared with Op::CallChildren's runtime handler
|
|
276
|
+
// (bytecode_vm.cpp) so the native and compiled paths cannot drift on
|
|
277
|
+
// any of the subtle parts: the caller-ctx re-derivation, the
|
|
278
|
+
// $-forwarding loop (which must read the post-resolveCallArgs effCtx
|
|
279
|
+
// -- a children($fn=12) named-$ override lives only there), and the
|
|
280
|
+
// children(N) statement-index filtering/bounds-check. nullopt means
|
|
281
|
+
// "nothing to evaluate" (no forwarded children in scope, empty list,
|
|
282
|
+
// or index out of range) -- a silent no-op in every existing caller,
|
|
283
|
+
// exactly matching builtinChildren's own early returns. `ctx` must be
|
|
284
|
+
// the effCtx resolveCallArgs returned, same as builtinChildren's own
|
|
285
|
+
// parameter today. Public for the same free-function reasoning as
|
|
286
|
+
// builtinChildren itself.
|
|
287
|
+
struct ChildrenForward {
|
|
288
|
+
EvalContext evalCtx;
|
|
289
|
+
std::vector<const oscad::ASTNode*> nodes;
|
|
290
|
+
};
|
|
291
|
+
std::optional<ChildrenForward> prepareChildrenForward(const CallArgs& args, EvalContext& ctx);
|
|
292
|
+
|
|
274
293
|
// "WARNING: {message}{locSuffix(position)}" via echoFn_, no-op if unset.
|
|
275
294
|
// Public: builtins/import.cpp's not-manifold warning is emitted from a
|
|
276
295
|
// free function, same reasoning as tagGenerated()/builtinChildren().
|
|
@@ -532,6 +551,17 @@ private:
|
|
|
532
551
|
// into the caller's scope exactly the way the native per-statement
|
|
533
552
|
// loop's own writes already do.
|
|
534
553
|
bool tryRunCompiledChildren(const std::vector<const oscad::ASTNode*>& children, EvalContext& ctx);
|
|
554
|
+
public:
|
|
555
|
+
// The cache-lookup half of tryRunCompiledChildren, shared with
|
|
556
|
+
// Op::CallChildren's runtime handler (bytecode_vm.cpp, a free
|
|
557
|
+
// function -- public for the same no-friend-declaration reasoning as
|
|
558
|
+
// vmCallStack_/treeStack_). Returns the eligible compiled chunk for
|
|
559
|
+
// `children` or nullptr. Caller owns the useBytecodeVm()/
|
|
560
|
+
// inResolvePass_ gate -- the pass gate is load-bearing
|
|
561
|
+
// (childrenListChunkCache_ is pass-scoped, see its own doc comment),
|
|
562
|
+
// not defensive.
|
|
563
|
+
const CompiledChunk* lookupOrCompileChildrenListChunk(const std::vector<const oscad::ASTNode*>& children);
|
|
564
|
+
private:
|
|
535
565
|
void evalModularCall(const oscad::ModularCall& node, EvalContext& ctx);
|
|
536
566
|
void evalFor(const oscad::ModularFor& node, EvalContext& ctx);
|
|
537
567
|
void evalLetBlock(const oscad::ModularLet& node, EvalContext& ctx);
|
|
@@ -951,15 +981,38 @@ private:
|
|
|
951
981
|
// body -- so a resolvable module call anywhere in that list gets
|
|
952
982
|
// Op::CallModule bytecode, and any if/for control flow around it gets
|
|
953
983
|
// real Jump-based bytecode too, instead of falling through to the
|
|
954
|
-
// native per-statement loop.
|
|
955
|
-
//
|
|
956
|
-
//
|
|
957
|
-
//
|
|
984
|
+
// native per-statement loop.
|
|
985
|
+
//
|
|
986
|
+
// Keyed by (FIRST element, list SIZE) -- NOT the first element alone,
|
|
987
|
+
// the original convention borrowed from assignBlockChunkCache_
|
|
988
|
+
// (where it IS sufficient: a leading-assignment run's first member
|
|
989
|
+
// uniquely determines the run). Here it wasn't: children()'s
|
|
990
|
+
// forwarding produces two DIFFERENT lists sharing a first element --
|
|
991
|
+
// bare `children()` forwards the caller's whole list, `children(0)`
|
|
992
|
+
// a single-element slice of it -- and keying by front alone made
|
|
993
|
+
// whichever form ran first poison the cache for the other (caught
|
|
994
|
+
// for real: `module m() { children(); children(0); }\n
|
|
995
|
+
// m() { cube(); sphere(); }` made children(0) emit BOTH shapes,
|
|
996
|
+
// or bare children() emit only one, depending on statement order).
|
|
997
|
+
// (front, size) fully disambiguates every real producer: fixed AST
|
|
998
|
+
// lists have unique fronts per call site, and the only same-front
|
|
999
|
+
// pair (bare vs indexed forwarding) always differs in size except
|
|
1000
|
+
// when the lists are literally identical anyway. Same nullopt-means-
|
|
958
1001
|
// tried-and-failed convention, same dangling-pointer hazard, same
|
|
959
1002
|
// two-part fix (cleared alongside stmtExprChunkCache_ at the top of
|
|
960
1003
|
// every resolveTreeImpl call, only read/written while inResolvePass_)
|
|
961
1004
|
// as stmtExprChunkCache_ itself.
|
|
962
|
-
|
|
1005
|
+
struct ChildrenListKeyHash {
|
|
1006
|
+
size_t operator()(const std::pair<const oscad::ASTNode*, size_t>& k) const {
|
|
1007
|
+
// Standard hash-combine (boost-style golden-ratio mix) --
|
|
1008
|
+
// either half alone collides by construction here.
|
|
1009
|
+
const size_t h1 = std::hash<const oscad::ASTNode*>{}(k.first);
|
|
1010
|
+
const size_t h2 = std::hash<size_t>{}(k.second);
|
|
1011
|
+
return h1 ^ (h2 + 0x9e3779b97f4a7c15ULL + (h1 << 6) + (h1 >> 2));
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
std::unordered_map<std::pair<const oscad::ASTNode*, size_t>, std::optional<CompiledChunk>, ChildrenListKeyHash>
|
|
1015
|
+
childrenListChunkCache_;
|
|
963
1016
|
|
|
964
1017
|
// See stmtExprChunkCache_'s own doc comment, immediately above, for why
|
|
965
1018
|
// this exists. Not a reentrancy guard (resolveTreeImpl is never called
|
|
@@ -1115,6 +1168,17 @@ public:
|
|
|
1115
1168
|
return bytecodeVmEnabled() && (!debugHooks_.debugHook || fastContinueBreakpoints_.has_value());
|
|
1116
1169
|
}
|
|
1117
1170
|
|
|
1171
|
+
// Read accessor for inResolvePass_ (private, below) -- Op::CallChildren's
|
|
1172
|
+
// runtime handler (bytecode_vm.cpp, a free function) must gate its
|
|
1173
|
+
// childrenListChunkCache_ access on it, exactly like
|
|
1174
|
+
// tryRunCompiledChildren's own self-gate: the cache is pass-scoped
|
|
1175
|
+
// (cleared per resolveTreeImpl, AST-address-reuse hazard -- see
|
|
1176
|
+
// stmtExprChunkCache_'s own doc comment), and driveVm CAN run outside
|
|
1177
|
+
// the resolve pass (a host calling evalChildren directly reaches
|
|
1178
|
+
// module opcodes via lookupOrCompileModuleChunk, which is NOT
|
|
1179
|
+
// pass-scoped).
|
|
1180
|
+
bool inResolvePass() const { return inResolvePass_; }
|
|
1181
|
+
|
|
1118
1182
|
private:
|
|
1119
1183
|
// The fine-grained half of the check above: even when useBytecodeVm()
|
|
1120
1184
|
// says compiling/using bytecode is on the table at all, a SPECIFIC
|
|
@@ -368,12 +368,30 @@ public:
|
|
|
368
368
|
dirty_[level].push_back(id);
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
+
// Level-aware, NOT a blind pop_back() -- the exact fix
|
|
372
|
+
// ScopeTrailStorage::popLevel (above) already carries, for the exact
|
|
373
|
+
// out-of-order-pop bug class its own doc comment describes; this
|
|
374
|
+
// indexed twin never got the same fix because nothing violated LIFO
|
|
375
|
+
// view destruction on the dyn trail until Op::CallChildren's
|
|
376
|
+
// forwarding frame (bytecode_vm.cpp): its evalCtx (a dyn level opened
|
|
377
|
+
// AFTER the call's own effCtx level) is moved into a VmFrame and
|
|
378
|
+
// OUTLIVES effCtx, so effCtx's pop runs while evalCtx's later entry
|
|
379
|
+
// is still physically on top of the same name's stack -- the blind
|
|
380
|
+
// pop_back() silently removed the still-live forwarded value instead
|
|
381
|
+
// of the one actually being popped (caught for real: a
|
|
382
|
+
// children($fn=9) named-$ override read back as the root default 0
|
|
383
|
+
// inside the forwarded child).
|
|
371
384
|
void popLevel(int level) {
|
|
372
385
|
auto it = dirty_.find(level);
|
|
373
386
|
if (it != dirty_.end()) {
|
|
374
387
|
for (int id : it->second) {
|
|
375
388
|
auto& stack = stacks_[static_cast<size_t>(id)];
|
|
376
|
-
|
|
389
|
+
for (auto rit = stack.rbegin(); rit != stack.rend(); ++rit) {
|
|
390
|
+
if (rit->level == level) {
|
|
391
|
+
stack.erase(std::next(rit).base());
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
377
395
|
}
|
|
378
396
|
dirty_.erase(it);
|
|
379
397
|
}
|
|
@@ -1420,12 +1420,25 @@ public:
|
|
|
1420
1420
|
emitBuiltinWrap(*wrapKind, call.name->name, call, children, out);
|
|
1421
1421
|
return;
|
|
1422
1422
|
}
|
|
1423
|
-
//
|
|
1424
|
-
//
|
|
1425
|
-
//
|
|
1426
|
-
//
|
|
1427
|
-
//
|
|
1428
|
-
//
|
|
1423
|
+
// children() -- the runtime-varying forwarding builtin,
|
|
1424
|
+
// detected by the same function-pointer-identity pattern
|
|
1425
|
+
// as Transform/Color above. Deliberately NO preceding
|
|
1426
|
+
// Op::CheckDebugStatement (unlike emitBuiltinWrap's own
|
|
1427
|
+
// emission): CallChildren's handler fires checkDebug
|
|
1428
|
+
// itself against the SCOPE-WRAPPED ctx, byte-for-byte
|
|
1429
|
+
// matching Op::NativeStatement's own handler -- the
|
|
1430
|
+
// CheckDebugStatement handler passes the un-wrapped ctx,
|
|
1431
|
+
// which would be a subtle behavior change for this node.
|
|
1432
|
+
// See Op::CallChildren's own doc comment (bytecode.hpp).
|
|
1433
|
+
if (dispatchIt != dispatch.end() && dispatchIt->second == &resolveChildren) {
|
|
1434
|
+
out.push_back({Op::CallChildren, internNativeStatement(&stmt), 0, &stmt.position()});
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
// Every other builtin, or a name that didn't resolve to a
|
|
1438
|
+
// user module statically -- native passthrough, exactly
|
|
1439
|
+
// like echo/assert/etc. below. Never the recursion-depth
|
|
1440
|
+
// risk this compiler targets for THESE (see
|
|
1441
|
+
// NativeStatement's own doc comment, bytecode.hpp).
|
|
1429
1442
|
out.push_back({Op::NativeStatement, internNativeStatement(&stmt), 0, &stmt.position()});
|
|
1430
1443
|
return;
|
|
1431
1444
|
}
|
|
@@ -329,6 +329,49 @@ void pushBracketedModuleFrame(Evaluator& ev, const CompiledChunk& chunk, const o
|
|
|
329
329
|
ev.vmCallBrackets_.push_back(std::move(handle));
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
// Op::CallChildren's own push -- a THIRD frame shape, distinct from both
|
|
333
|
+
// existing helpers: splice-owning like pushBracketedModuleFrame's
|
|
334
|
+
// (ownsModuleSplice=true, mirroring evalModularCall's own unconditional
|
|
335
|
+
// splice branch for "children", csg_resolve.cpp) but BRACKETLESS like
|
|
336
|
+
// pushBareFrame's (nullopt in vmCallBrackets_ -- children() never gets a
|
|
337
|
+
// callStack_/profiling entry natively either: only enterUserCall pushes
|
|
338
|
+
// those, and resolveChildren/builtinChildren never call it, so no TRACE
|
|
339
|
+
// frame, no profile site, no $parent_modules bump, exactly matching the
|
|
340
|
+
// native path). driveVm's completion branch and teardownVmCallStackDownTo
|
|
341
|
+
// both already handle this combination -- their bracket (`if (bracket)`)
|
|
342
|
+
// and splice (`if (ownsModuleSplice)`) concerns are independent at both
|
|
343
|
+
// sites. `evalCtx` is prepareChildrenForward's result (the caller-derived,
|
|
344
|
+
// $-forwarded context the children must run under -- see that helper's
|
|
345
|
+
// own doc comment, evaluator.hpp). hopEligible set explicitly false --
|
|
346
|
+
// pushBracketedModuleFrame itself omits the reset (benign there only
|
|
347
|
+
// because module chunks never contain tail-call opcodes); don't inherit
|
|
348
|
+
// a pooled function frame's stale true here either.
|
|
349
|
+
void pushChildrenForwardFrame(Evaluator& ev, const CompiledChunk& chunk, EvalContext evalCtx,
|
|
350
|
+
std::uint64_t randsBefore, const oscad::ASTNode& callNode) {
|
|
351
|
+
if (ev.vmCallStack_.size() >= Evaluator::kMaxVmCallStackDepth) {
|
|
352
|
+
ev.error("Recursion too deep while forwarding children()", callNode);
|
|
353
|
+
}
|
|
354
|
+
auto frame = ev.acquireVmFrame();
|
|
355
|
+
frame->chunk = &chunk;
|
|
356
|
+
frame->code = &chunk.bodyCode;
|
|
357
|
+
frame->pc = 0;
|
|
358
|
+
frame->slots.assign(static_cast<size_t>(chunk.numSlots), Value{});
|
|
359
|
+
frame->stack.clear();
|
|
360
|
+
frame->bound.clear();
|
|
361
|
+
frame->accumStack.clear();
|
|
362
|
+
frame->iterLists.assign(static_cast<size_t>(chunk.numIterLists), IterList{});
|
|
363
|
+
frame->ctxChain.clear();
|
|
364
|
+
frame->ctxChain.push_back(std::move(evalCtx));
|
|
365
|
+
frame->tailHopGuard = 0;
|
|
366
|
+
frame->logicalName.clear();
|
|
367
|
+
frame->hopEligible = false;
|
|
368
|
+
frame->ownsModuleSplice = true;
|
|
369
|
+
frame->moduleRandsBefore = randsBefore;
|
|
370
|
+
frame->moduleSpliceCallNode = &callNode;
|
|
371
|
+
ev.vmCallStack_.push_back(std::move(frame));
|
|
372
|
+
ev.vmCallBrackets_.emplace_back(std::nullopt);
|
|
373
|
+
}
|
|
374
|
+
|
|
332
375
|
// Tears down every frame from vmCallStack_'s own top down to (but not
|
|
333
376
|
// including) `floor`, on the exception path -- releases each VmFrame to
|
|
334
377
|
// the pool, tears down its ctxChain back-to-front (never relying on
|
|
@@ -933,6 +976,71 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
933
976
|
}
|
|
934
977
|
break;
|
|
935
978
|
}
|
|
979
|
+
case Op::CallChildren: {
|
|
980
|
+
// Ordering is load-bearing throughout -- see this op's
|
|
981
|
+
// own doc comment (bytecode.hpp): checkDebug against
|
|
982
|
+
// the SCOPE-WRAPPED ctx (byte-for-byte what Op::
|
|
983
|
+
// NativeStatement does for this same node today);
|
|
984
|
+
// randsBefore BEFORE argument resolution (rands-in-args
|
|
985
|
+
// taint); treeStack_ pushed LAST, immediately before
|
|
986
|
+
// the frame push / native fallback, so an early-out or
|
|
987
|
+
// a throw during arg resolution has nothing to clean
|
|
988
|
+
// up (the native path's own catch{pop;throw} has no
|
|
989
|
+
// equivalent out here -- this reorder IS the
|
|
990
|
+
// exception-safety mechanism; arg resolution never
|
|
991
|
+
// appends CSG nodes, so pushing after it is
|
|
992
|
+
// unobservable).
|
|
993
|
+
const auto* callNode =
|
|
994
|
+
static_cast<const oscad::ModularCall*>(f.chunk->nativeStatements[static_cast<size_t>(ins.a)]);
|
|
995
|
+
EvalContext scopedCtx = ctx.withScope(callNode->scope() ? callNode->scope() : ctx.scope);
|
|
996
|
+
ev.checkDebug(*callNode, scopedCtx);
|
|
997
|
+
const std::uint64_t randsBefore = ev.randsCallCount();
|
|
998
|
+
auto [args, effCtx] = resolveCallArgs(ev, callNode->arguments, scopedCtx);
|
|
999
|
+
std::optional<Evaluator::ChildrenForward> fwd = ev.prepareChildrenForward(args, effCtx);
|
|
1000
|
+
if (!fwd) {
|
|
1001
|
+
// No forwarded children in scope / empty / index
|
|
1002
|
+
// out of range -- a silent no-op, exactly matching
|
|
1003
|
+
// builtinChildren's own early returns.
|
|
1004
|
+
++f.pc;
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
// Pass gate is load-bearing, not defensive -- the
|
|
1008
|
+
// chunk cache is pass-scoped; see inResolvePass()'s
|
|
1009
|
+
// own doc comment (evaluator.hpp).
|
|
1010
|
+
const CompiledChunk* chunk = (ev.useBytecodeVm() && ev.inResolvePass())
|
|
1011
|
+
? ev.lookupOrCompileChildrenListChunk(fwd->nodes)
|
|
1012
|
+
: nullptr;
|
|
1013
|
+
if (chunk) {
|
|
1014
|
+
ev.treeStack_.emplace_back();
|
|
1015
|
+
pushChildrenForwardFrame(ev, *chunk, std::move(fwd->evalCtx), randsBefore, *callNode);
|
|
1016
|
+
// f.pc deliberately NOT advanced -- resumes when
|
|
1017
|
+
// the pushed frame completes; driveVm's completion
|
|
1018
|
+
// branch runs the splice (isModule &&
|
|
1019
|
+
// ownsModuleSplice), mirroring evalModularCall's
|
|
1020
|
+
// own "children" splice branch exactly.
|
|
1021
|
+
} else {
|
|
1022
|
+
// Fallback reuses the ALREADY-resolved args --
|
|
1023
|
+
// never evalStatement, which would re-resolve them
|
|
1024
|
+
// (double rands(), double echo/assert side
|
|
1025
|
+
// effects, double expr-level debug stops).
|
|
1026
|
+
// Inlines evalModularCall's own children branch:
|
|
1027
|
+
// push accumulator, run natively, pop, splice.
|
|
1028
|
+
// The native evalChildren still self-gates and
|
|
1029
|
+
// retries tryRunCompiledChildren internally.
|
|
1030
|
+
ev.treeStack_.emplace_back();
|
|
1031
|
+
try {
|
|
1032
|
+
ev.evalChildren(fwd->nodes, fwd->evalCtx);
|
|
1033
|
+
} catch (...) {
|
|
1034
|
+
ev.treeStack_.pop_back();
|
|
1035
|
+
throw;
|
|
1036
|
+
}
|
|
1037
|
+
std::vector<std::unique_ptr<CSGNode>> children = std::move(ev.treeStack_.back());
|
|
1038
|
+
ev.treeStack_.pop_back();
|
|
1039
|
+
ev.spliceModuleChildren(std::move(children), randsBefore, *callNode);
|
|
1040
|
+
++f.pc;
|
|
1041
|
+
}
|
|
1042
|
+
break;
|
|
1043
|
+
}
|
|
936
1044
|
case Op::PushBuiltinWrap: {
|
|
937
1045
|
const CompiledChunk::BuiltinWrapSite& site = f.chunk->builtinWrapSites[static_cast<size_t>(ins.a)];
|
|
938
1046
|
// Captured BEFORE any argument resolution -- mirrors
|
|
@@ -84,15 +84,29 @@ bool Evaluator::tryRunCompiledAssignmentBlock(const std::vector<const oscad::AST
|
|
|
84
84
|
|
|
85
85
|
bool Evaluator::tryRunCompiledChildren(const std::vector<const oscad::ASTNode*>& children, EvalContext& ctx) {
|
|
86
86
|
if (children.empty() || !useBytecodeVm() || !inResolvePass_) return false;
|
|
87
|
+
const CompiledChunk* chunk = lookupOrCompileChildrenListChunk(children);
|
|
88
|
+
if (!chunk) return false;
|
|
89
|
+
runCompiledModuleBody(*this, *chunk, ctx);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// The cache-lookup half of tryRunCompiledChildren, shared with
|
|
94
|
+
// Op::CallChildren's own runtime handler (bytecode_vm.cpp) -- both need
|
|
95
|
+
// exactly this "list -> eligible chunk or nullptr" step, differing only
|
|
96
|
+
// in how they then RUN the chunk (native runCompiledModuleBody reentry
|
|
97
|
+
// here, a direct vmCallStack_ push there). Caller is responsible for the
|
|
98
|
+
// useBytecodeVm()/inResolvePass_ gate (see childrenListChunkCache_'s own
|
|
99
|
+
// doc comment for why the pass gate is load-bearing, not defensive).
|
|
100
|
+
const CompiledChunk* Evaluator::lookupOrCompileChildrenListChunk(const std::vector<const oscad::ASTNode*>& children) {
|
|
87
101
|
const oscad::ASTNode* first = children.front();
|
|
88
|
-
auto
|
|
102
|
+
const auto key = std::make_pair(first, children.size());
|
|
103
|
+
auto it = childrenListChunkCache_.find(key);
|
|
89
104
|
if (it == childrenListChunkCache_.end()) {
|
|
90
|
-
it = childrenListChunkCache_.emplace(
|
|
105
|
+
it = childrenListChunkCache_.emplace(key, tryCompileChildrenList(children, first->scope())).first;
|
|
91
106
|
if (it->second) flattenNestedLiterals(*it->second);
|
|
92
107
|
}
|
|
93
|
-
if (!it->second || !chunkEligibleNow(*it->second)) return
|
|
94
|
-
|
|
95
|
-
return true;
|
|
108
|
+
if (!it->second || !chunkEligibleNow(*it->second)) return nullptr;
|
|
109
|
+
return &*it->second;
|
|
96
110
|
}
|
|
97
111
|
|
|
98
112
|
const Value* Evaluator::findUpvalue(const oscad::ASTNode* targetDecl, int slot) const {
|
|
@@ -897,15 +911,20 @@ Value Evaluator::parentModuleName(int idx) const {
|
|
|
897
911
|
return Value{modules[static_cast<size_t>(revIdx)]};
|
|
898
912
|
}
|
|
899
913
|
|
|
900
|
-
|
|
914
|
+
std::optional<Evaluator::ChildrenForward> Evaluator::prepareChildrenForward(const CallArgs& args, EvalContext& ctx) {
|
|
901
915
|
Value idxArg = getArg(args, 0, "index", Value{});
|
|
902
|
-
if (!ctx.childrenNodes || ctx.childrenNodes->empty()) return;
|
|
916
|
+
if (!ctx.childrenNodes || ctx.childrenNodes->empty()) return std::nullopt;
|
|
903
917
|
const EvalContext* callerCtx = ctx.childrenCallerCtx;
|
|
904
|
-
if (!callerCtx) return;
|
|
918
|
+
if (!callerCtx) return std::nullopt;
|
|
905
919
|
|
|
906
920
|
// A children() forwarding chain's own dyn/let_/etc. must alias the
|
|
907
921
|
// *caller's* (not this ctx's) -- see EvalContext::withScope's rationale.
|
|
908
922
|
EvalContext evalCtx = callerCtx->childCtx(nullptr, std::nullopt, callerCtx->childrenNodes, callerCtx->childrenCallerCtx);
|
|
923
|
+
// `ctx` here is the post-resolveCallArgs effCtx, deliberately: a
|
|
924
|
+
// `children($fn=12)`-style named-$ override lives only at effCtx's own
|
|
925
|
+
// trail level, and TrailView::items() is ancestry-visible, so reading
|
|
926
|
+
// from effCtx forwards both the call's own overrides AND everything
|
|
927
|
+
// the wrapper module's body set (`$fn = 100; children();`).
|
|
909
928
|
for (const auto& [k, v] : ctx.dyn->items()) {
|
|
910
929
|
if (!k.empty() && k[0] == '$') evalCtx.dyn->set(k, v);
|
|
911
930
|
}
|
|
@@ -914,8 +933,7 @@ void Evaluator::builtinChildren(const CallArgs& args, EvalContext& ctx) {
|
|
|
914
933
|
}
|
|
915
934
|
|
|
916
935
|
if (std::holds_alternative<std::monostate>(idxArg)) {
|
|
917
|
-
|
|
918
|
-
return;
|
|
936
|
+
return ChildrenForward{std::move(evalCtx), *ctx.childrenNodes};
|
|
919
937
|
}
|
|
920
938
|
|
|
921
939
|
// children(N) indexes child *statements*, not output bodies -- a
|
|
@@ -930,8 +948,14 @@ void Evaluator::builtinChildren(const CallArgs& args, EvalContext& ctx) {
|
|
|
930
948
|
geoNodes.push_back(c);
|
|
931
949
|
}
|
|
932
950
|
}
|
|
933
|
-
if (idx < 0 || static_cast<size_t>(idx) >= geoNodes.size()) return;
|
|
934
|
-
|
|
951
|
+
if (idx < 0 || static_cast<size_t>(idx) >= geoNodes.size()) return std::nullopt;
|
|
952
|
+
return ChildrenForward{std::move(evalCtx), {geoNodes[static_cast<size_t>(idx)]}};
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
void Evaluator::builtinChildren(const CallArgs& args, EvalContext& ctx) {
|
|
956
|
+
std::optional<ChildrenForward> fwd = prepareChildrenForward(args, ctx);
|
|
957
|
+
if (!fwd) return;
|
|
958
|
+
evalChildren(fwd->nodes, fwd->evalCtx);
|
|
935
959
|
}
|
|
936
960
|
|
|
937
961
|
} // namespace oscadeval
|
{openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/tests/test_bytecode_compiler.cpp
RENAMED
|
@@ -1299,6 +1299,35 @@ TEST(ModuleBodyCompiles, ReassignmentInsideForLoopBodyDoesNotSpuriouslyWarn) {
|
|
|
1299
1299
|
for (const std::string& w : warnings) EXPECT_EQ(w.find("overwritten"), std::string::npos) << w;
|
|
1300
1300
|
}
|
|
1301
1301
|
|
|
1302
|
+
// Regression test for a real cache-collision bug: childrenListChunkCache_
|
|
1303
|
+
// was keyed by the list's FIRST element alone (a convention borrowed from
|
|
1304
|
+
// assignBlockChunkCache_, where it IS sufficient) -- but children()'s
|
|
1305
|
+
// forwarding produces two DIFFERENT lists sharing a first element: bare
|
|
1306
|
+
// `children()` forwards the caller's whole list, `children(0)` a single-
|
|
1307
|
+
// element slice of it. Whichever form ran first poisoned the cache for
|
|
1308
|
+
// the other: here, bare children() cached a two-statement chunk keyed by
|
|
1309
|
+
// &cubeStmt, then children(0)'s single-element {&cubeStmt} lookup HIT
|
|
1310
|
+
// that key and emitted BOTH shapes. Fixed by keying on (front, size).
|
|
1311
|
+
TEST(ModuleBodyCompiles, BareAndIndexedChildrenForwardingDoNotShareACachedChunk) {
|
|
1312
|
+
ScopedVm vm(true);
|
|
1313
|
+
// m() emits: children() -> cube+sphere, then children(0) -> cube only.
|
|
1314
|
+
// 3 bodies total; the collision bug produced 4 (children(0) emitting
|
|
1315
|
+
// sphere too).
|
|
1316
|
+
Evaluated e = evalSrc("module m() { children(); children(0); }\n"
|
|
1317
|
+
"m() { cube(1); sphere(r=1, $fn=8); }");
|
|
1318
|
+
EXPECT_EQ(e.bodies.size(), 3u);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// Same collision, opposite statement order -- children(0) caching its
|
|
1322
|
+
// single-element chunk first used to TRUNCATE the later bare children()
|
|
1323
|
+
// (2 bodies where 3 belong).
|
|
1324
|
+
TEST(ModuleBodyCompiles, IndexedThenBareChildrenForwardingDoNotShareACachedChunk) {
|
|
1325
|
+
ScopedVm vm(true);
|
|
1326
|
+
Evaluated e = evalSrc("module m() { children(0); children(); }\n"
|
|
1327
|
+
"m() { cube(1); sphere(r=1, $fn=8); }");
|
|
1328
|
+
EXPECT_EQ(e.bodies.size(), 3u);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1302
1331
|
TEST(ModuleBodyCompiles, RecursiveModuleWithIfSucceedsWellPastTheOldNativeLimitCompiled) {
|
|
1303
1332
|
ScopedVm vm(true);
|
|
1304
1333
|
Evaluated e = evalSrc("module recur(n) { if (n > 0) { recur(n - 1); } else { cube(1); } }\nrecur(10000);");
|
|
@@ -1390,6 +1419,59 @@ TEST(ModuleBodyCompiles, UnionWrappedRecursionStillHitsTheNativeReentryGuardCont
|
|
|
1390
1419
|
}
|
|
1391
1420
|
}
|
|
1392
1421
|
|
|
1422
|
+
// The BOSL2 attachable() shape this whole effort targets: a wrapper module
|
|
1423
|
+
// whose body is just `children();`, applied at every level of a recursive
|
|
1424
|
+
// chain. children() used to fall to Op::NativeStatement -- one genuine
|
|
1425
|
+
// native C++ reentry (evalStatement -> evalModularCall -> builtinChildren
|
|
1426
|
+
// -> evalChildren -> runCompiledModuleBody -> a fresh nested driveVm) per
|
|
1427
|
+
// level, measured as 85 of 93 native-reentry hits in a real BOSL2 script.
|
|
1428
|
+
// Op::CallChildren resolves the forwarded list at runtime and pushes its
|
|
1429
|
+
// chunk onto vmCallStack_ directly (zero native frames), so this now
|
|
1430
|
+
// SUCCEEDS well past the old ~40-level Windows-safe ceiling. Depth 1500:
|
|
1431
|
+
// same figure the PushBuiltinWrap per-construct tests use -- comfortably
|
|
1432
|
+
// past the old ceiling, and tree depth stays flat regardless (children()
|
|
1433
|
+
// and user-module calls both splice, no kMaxCsgTreeDepth interaction).
|
|
1434
|
+
TEST(ModuleBodyCompiles, RecursiveChildrenForwardingChainSucceedsWellPastTheOldNativeReentryLimit) {
|
|
1435
|
+
ScopedVm vm(true);
|
|
1436
|
+
Evaluated e = evalSrc("module wrap() { children(); }\n"
|
|
1437
|
+
"module recur(n) { if (n > 0) { wrap() recur(n - 1); } else { cube(1); } }\n"
|
|
1438
|
+
"recur(1500);");
|
|
1439
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
// Same chain through the INDEXED form -- children(0) shares Op::
|
|
1443
|
+
// CallChildren with the bare form (the index is resolved at runtime by
|
|
1444
|
+
// the same prepareChildrenForward helper the native path uses), so it
|
|
1445
|
+
// gets the same zero-native-reentry treatment, not just bare children().
|
|
1446
|
+
TEST(ModuleBodyCompiles, RecursiveIndexedChildrenForwardingChainSucceedsWellPastTheOldNativeReentryLimit) {
|
|
1447
|
+
ScopedVm vm(true);
|
|
1448
|
+
Evaluated e = evalSrc("module wrap() { children(0); }\n"
|
|
1449
|
+
"module recur(n) { if (n > 0) { wrap() recur(n - 1); } else { cube(1); } }\n"
|
|
1450
|
+
"recur(1500);");
|
|
1451
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// $-forwarding parity for the compiled children() path: a wrapper module's
|
|
1455
|
+
// own $-writes (`$fn = 7; children();`) and a children($fn=9)-style
|
|
1456
|
+
// named-$ override must both reach the forwarded child, exactly as the
|
|
1457
|
+
// native builtinChildren path forwards them (prepareChildrenForward's own
|
|
1458
|
+
// $-loop, shared by both paths precisely so they can't drift -- these
|
|
1459
|
+
// tests are the proof it actually holds end-to-end through the compiled
|
|
1460
|
+
// opcode, not just by construction).
|
|
1461
|
+
TEST(ModuleBodyCompiles, ChildrenForwardingCarriesWrapperDollarWritesCompiled) {
|
|
1462
|
+
ScopedVm vm(true);
|
|
1463
|
+
EXPECT_EQ(runCapturingEcho("module w() { $fn = 7; children(); }\n"
|
|
1464
|
+
"w() echo($fn);"),
|
|
1465
|
+
"ECHO: 7");
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
TEST(ModuleBodyCompiles, ChildrenForwardingCarriesNamedDollarArgCompiled) {
|
|
1469
|
+
ScopedVm vm(true);
|
|
1470
|
+
EXPECT_EQ(runCapturingEcho("module w() { children($fn = 9); }\n"
|
|
1471
|
+
"w() echo($fn);"),
|
|
1472
|
+
"ECHO: 9");
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1393
1475
|
// Regression test for a real bug this same investigation caught:
|
|
1394
1476
|
// enterUserCall's own depth guard used to check callStack_.size()
|
|
1395
1477
|
// directly -- but callStack_ also grows from cheap, zero-native-cost
|
|
@@ -75,6 +75,36 @@ TEST(IndexedScopeTrailStorage, SetAtSameLevelDoesNotAccumulateEntries) {
|
|
|
75
75
|
EXPECT_EQ(*storage.lookup("$fn", level), 999);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// popLevel must remove the entry belonging to THE LEVEL BEING POPPED, not
|
|
79
|
+
// blindly pop_back() whatever happens to be physically last -- the exact
|
|
80
|
+
// out-of-order-pop bug class ScopeTrailStorage::popLevel's own doc comment
|
|
81
|
+
// already describes (and fixed) for the non-indexed twin; this indexed
|
|
82
|
+
// variant kept the blind pop until Op::CallChildren's forwarding frame
|
|
83
|
+
// (bytecode_vm.cpp) became the first real caller to violate LIFO view
|
|
84
|
+
// destruction on the dyn trail. Level shape mirrors that real scenario
|
|
85
|
+
// exactly: E (a children() call's own effCtx, opened first) and L (the
|
|
86
|
+
// forwarding evalCtx, opened later, moved into a VmFrame) both set the
|
|
87
|
+
// same name; E pops FIRST while L is still live. The blind pop removed
|
|
88
|
+
// L's entry -- the still-live forwarded value -- leaving a lookup from L
|
|
89
|
+
// falling through to the root default (caught for real: children($fn=9)
|
|
90
|
+
// read back as 0 inside the forwarded child).
|
|
91
|
+
TEST(IndexedScopeTrailStorage, PopLevelRemovesItsOwnEntryNotThePhysicallyLastOne) {
|
|
92
|
+
auto intern = std::make_shared<DynNameIntern>();
|
|
93
|
+
IndexedScopeTrailStorage<int> storage(intern);
|
|
94
|
+
const int root = storage.openLevel(0);
|
|
95
|
+
storage.set("$fn", 0, root);
|
|
96
|
+
const int e = storage.openLevel(root); // effCtx's own level
|
|
97
|
+
storage.set("$fn", 9, e);
|
|
98
|
+
const int l = storage.openLevel(root); // forwarding evalCtx's level, opened AFTER e
|
|
99
|
+
storage.set("$fn", 9, l);
|
|
100
|
+
storage.popLevel(e); // e dies while l is still live -- non-LIFO
|
|
101
|
+
ASSERT_NE(storage.lookup("$fn", l), nullptr);
|
|
102
|
+
EXPECT_EQ(*storage.lookup("$fn", l), 9);
|
|
103
|
+
storage.popLevel(l);
|
|
104
|
+
ASSERT_NE(storage.lookup("$fn", root), nullptr);
|
|
105
|
+
EXPECT_EQ(*storage.lookup("$fn", root), 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
78
108
|
// A captured (closure) level's own ancestor must stay alive even after
|
|
79
109
|
// EVERY other TrailView referencing that ancestor has gone out of scope --
|
|
80
110
|
// see TrailView::openChild's own doc comment (parentView_) for why. This
|
|
File without changes
|
{openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/.github/workflows/wheels.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.4}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|