openscad-cpp-evaluator 0.13.3__tar.gz → 0.13.5__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.5}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/bytecode.hpp +168 -11
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/bytecode_vm.hpp +27 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/evaluator.hpp +69 -5
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/scope_trail.hpp +19 -1
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/bytecode_compiler.cpp +65 -6
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/bytecode_vm.cpp +177 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/user_calls.cpp +36 -12
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_bytecode_compiler.cpp +188 -11
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_scope_trail.cpp +30 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/README.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/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.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/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.5}/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.5}/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.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/text/stb_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.13.3 → openscad_cpp_evaluator-0.13.5}/tools/cli/main.cpp +0 -0
|
@@ -325,10 +325,148 @@ enum class Op {
|
|
|
325
325
|
// same seam, now a counter).
|
|
326
326
|
PopBuiltinWrap,
|
|
327
327
|
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
//
|
|
328
|
+
// -- CSG-wrap compilation (closes the LAST native-reentry source in ----
|
|
329
|
+
// -- the original NativeStatement gap: union()/difference()/ -
|
|
330
|
+
// -- intersection()) ----------------------------------------------------
|
|
331
|
+
// union()/difference()/intersection() weren't covered by the original
|
|
332
|
+
// Op::PushBuiltinWrap (see that op's own doc comment) because they need
|
|
333
|
+
// bespoke bookkeeping PushBuiltinWrap's single all-children bracket
|
|
334
|
+
// doesn't do: Evaluator's own resolveCsg (booleans.cpp) evaluates each
|
|
335
|
+
// TOP-LEVEL child statement of the block SEPARATELY and records how
|
|
336
|
+
// many CSGNodes it individually contributed ("group_sizes") -- e.g.
|
|
337
|
+
// `difference(){ A; B; C; }` = A - (B u C), preserving A's own group
|
|
338
|
+
// even when A itself expands to more than one body (an attachable()-
|
|
339
|
+
// style call returning parent+children as one operand). A flat
|
|
340
|
+
// all-children bracket the way Transform/Color/Modifier use would lose
|
|
341
|
+
// that grouping entirely. This op pair (PushCsgWrap/PopCsgWrap) plus
|
|
342
|
+
// Op::CsgGroupStart/CsgGroupEnd (below) replicate resolveCsg's exact
|
|
343
|
+
// two-pass shape (all assignments first, THEN one evalChildren-per-
|
|
344
|
+
// geometry-statement) as inline compiled bytecode instead, exactly as
|
|
345
|
+
// PushBuiltinWrap already did for translate/rotate/scale/mirror/
|
|
346
|
+
// multmatrix/resize/color/#/%/! -- same rationale (a recursive
|
|
347
|
+
// union()/difference()/intersection()-wrapped module chain was still a
|
|
348
|
+
// real Windows native-reentry depth risk, just never independently
|
|
349
|
+
// fixed when PushBuiltinWrap's own set was).
|
|
350
|
+
//
|
|
351
|
+
// a = index into CompiledChunk::csgWrapSites. Runtime handler: captures
|
|
352
|
+
// ev.randsCallCount() BEFORE argument resolution (same rands-in-args
|
|
353
|
+
// taint reasoning as PushBuiltinWrap), resolves the (rare, $-only)
|
|
354
|
+
// arguments via resolveCallArgs exactly like resolveCsg itself does
|
|
355
|
+
// (discarding the positional/named result -- union/difference/
|
|
356
|
+
// intersection take no real parameters -- keeping only the possibly-
|
|
357
|
+
// $-scoped child ctx), pushes that ctx onto f.ctxChain unconditionally
|
|
358
|
+
// (mirrors Transform/Color's own unconditional push -- a bare
|
|
359
|
+
// `union() {...}` with no `$fn=...` override still pushes a ctx that's
|
|
360
|
+
// merely a copy, cheap and uniform rather than a special-cased branch),
|
|
361
|
+
// pushes a fresh ev.treeStack_ frame (every child statement's own
|
|
362
|
+
// CSGNode(s), across every group, land flat in this ONE frame --
|
|
363
|
+
// mirrors Evaluator::buildTreeNode/evalModularCall's own single
|
|
364
|
+
// treeStack_.emplace_back() around the whole call, not one per group),
|
|
365
|
+
// and stashes {op, randsBefore, siteIdx, empty groupSizes} onto
|
|
366
|
+
// VmFrame::csgWrapStack (a real per-frame LIFO, same reasoning as
|
|
367
|
+
// builtinWrapStack: nested/sequenced CSG wraps within one frame's own
|
|
368
|
+
// instruction stream, e.g. `union() { difference() {...} }`). The
|
|
369
|
+
// compiler always emits a plain Op::CheckDebugStatement immediately
|
|
370
|
+
// before this (see emitCsgWrap, bytecode_compiler.cpp), mirroring
|
|
371
|
+
// emitBuiltinWrap's own pattern -- this is a genuine statement doing
|
|
372
|
+
// real work here, not a call transferring control to a declaration.
|
|
373
|
+
PushCsgWrap,
|
|
374
|
+
|
|
375
|
+
// Opens one "group" within an already-open Op::PushCsgWrap bracket --
|
|
376
|
+
// emitted immediately before each top-level GEOMETRY child statement's
|
|
377
|
+
// own inline-compiled bytecode (compileStatementList of exactly that
|
|
378
|
+
// one statement). Records ev.treeStack_.back().size() into
|
|
379
|
+
// csgWrapStack.back().groupStartSize -- always operates on the
|
|
380
|
+
// TOPMOST (innermost still-open) csgWrapStack entry, matching
|
|
381
|
+
// PopBuiltinWrap's own back()-is-always-mine LIFO discipline, so no
|
|
382
|
+
// operand is needed. Assignments among the block's children are
|
|
383
|
+
// compiled separately, BEFORE any CsgGroupStart/End pair at all (see
|
|
384
|
+
// emitCsgWrap) -- mirrors resolveCsg's own two-pass split exactly
|
|
385
|
+
// (Evaluator::evalChildren(assignNodes, effCtx) always runs to
|
|
386
|
+
// completion before the per-geoNode loop starts).
|
|
387
|
+
CsgGroupStart,
|
|
388
|
+
|
|
389
|
+
// Closes the matching Op::CsgGroupStart: computes
|
|
390
|
+
// ev.treeStack_.back().size() - csgWrapStack.back().groupStartSize
|
|
391
|
+
// (how many CSGNodes THIS one top-level statement just contributed,
|
|
392
|
+
// however many that turned out to be -- 0 for a statement whose own
|
|
393
|
+
// evaluation spliced nothing, e.g. a no-op unknown-module warning; >1
|
|
394
|
+
// for an attachable()-style multi-body operand) and appends it, as a
|
|
395
|
+
// Value, onto csgWrapStack.back().groupSizes -- exactly one entry per
|
|
396
|
+
// top-level geometry statement, in source order, mirroring resolveCsg's
|
|
397
|
+
// own `groupSizes.push_back(Value{...})` loop.
|
|
398
|
+
CsgGroupEnd,
|
|
399
|
+
|
|
400
|
+
// Closes the matching Op::PushCsgWrap bracket: pops
|
|
401
|
+
// VmFrame::csgWrapStack's own top entry FIRST (before anything that can
|
|
402
|
+
// itself throw, e.g. setTreeDepthOrThrow below -- same "exception-
|
|
403
|
+
// teardown's own pending count must already be right" reasoning as
|
|
404
|
+
// PopBuiltinWrap), pops the ctx PushCsgWrap unconditionally pushed,
|
|
405
|
+
// pops ev.treeStack_ to retrieve every group's own CSGNode(s) (flat,
|
|
406
|
+
// exactly like resolveCsg's own `children` result -- group boundaries
|
|
407
|
+
// live only in group_sizes, never in the CSGNode list's own shape), and
|
|
408
|
+
// builds the tagged CSGNode exactly like Evaluator::buildTreeNode's own
|
|
409
|
+
// post-resolveBody() half does, with params = {"op": site.op,
|
|
410
|
+
// "group_sizes": ValueList(pending.groupSizes)} -- byte-for-byte what
|
|
411
|
+
// native resolveCsg returns -- pushing the result onto the new top of
|
|
412
|
+
// treeStack_. a = index into CompiledChunk::csgWrapSites (same site
|
|
413
|
+
// Push used).
|
|
414
|
+
//
|
|
415
|
+
// teardownVmCallStackDownTo's own exception path (bytecode_vm.cpp) pops
|
|
416
|
+
// frame->csgWrapStack.size() additional treeStack_ entries per
|
|
417
|
+
// torn-down frame, alongside its existing builtinWrapStack/
|
|
418
|
+
// ownsModuleSplice accounting -- same reasoning as PopBuiltinWrap's own
|
|
419
|
+
// doc comment: an exception can leave N of these brackets open in one
|
|
420
|
+
// frame.
|
|
421
|
+
PopCsgWrap,
|
|
422
|
+
|
|
423
|
+
// A `children()` / `children(N)` statement -- the runtime-varying
|
|
424
|
+
// sibling of Op::CallModule/Op::PushBuiltinWrap, closing the LAST
|
|
425
|
+
// dominant native-reentry source (BOSL2's attachable() calls
|
|
426
|
+
// children() at nearly every wrapper level; measured 85 of 93 native
|
|
427
|
+
// reentries in a real script). Unlike PushBuiltinWrap's constructs,
|
|
428
|
+
// the forwarded children aren't known at compile time (they're the
|
|
429
|
+
// CALLER's own call-site statements, carried on ctx.childrenNodes/
|
|
430
|
+
// childrenCallerCtx -- see Evaluator::buildModuleChildCtx), so they
|
|
431
|
+
// can't compile inline; instead the handler resolves the list at
|
|
432
|
+
// RUNTIME, looks up/compiles its chunk (the same
|
|
433
|
+
// childrenListChunkCache_ tryRunCompiledChildren uses, via
|
|
434
|
+
// lookupOrCompileChildrenListChunk -- gated on useBytecodeVm() &&
|
|
435
|
+
// inResolvePass_, the cache is pass-scoped), and pushes it onto
|
|
436
|
+
// vmCallStack_ directly, mirroring Op::CallModule's own zero-native-
|
|
437
|
+
// call push -- but with a THIRD frame shape: splice-owning like a
|
|
438
|
+
// module frame (ownsModuleSplice=true, mirroring evalModularCall's
|
|
439
|
+
// own unconditional splice branch for "children"), yet bracketless
|
|
440
|
+
// like a bare frame (children() never gets a callStack_/profiling
|
|
441
|
+
// entry natively either -- only enterUserCall pushes those, and
|
|
442
|
+
// resolveChildren/builtinChildren never call it). driveVm's existing
|
|
443
|
+
// completion branch and teardownVmCallStackDownTo both already
|
|
444
|
+
// handle that combination (their bracket and splice concerns are
|
|
445
|
+
// independent).
|
|
446
|
+
//
|
|
447
|
+
// Handler ordering is load-bearing: checkDebug fires in-handler
|
|
448
|
+
// against the scope-wrapped ctx (byte-for-byte what Op::
|
|
449
|
+
// NativeStatement does -- NOT via an emitted Op::CheckDebugStatement,
|
|
450
|
+
// whose handler passes the un-wrapped ctx); randsBefore is captured
|
|
451
|
+
// BEFORE argument resolution (rands-in-args taint, same lesson
|
|
452
|
+
// PushBuiltinWrap already encodes); and treeStack_ is pushed LAST,
|
|
453
|
+
// immediately before the frame push / native fallback (an early-out
|
|
454
|
+
// or a throw during arg resolution then has nothing to clean up --
|
|
455
|
+
// the native path's own catch{pop;throw} has no equivalent here, so
|
|
456
|
+
// the reorder IS the exception-safety mechanism). The not-eligible
|
|
457
|
+
// fallback reuses the ALREADY-resolved args (never evalStatement,
|
|
458
|
+
// which would re-resolve them: double rands(), double side effects)
|
|
459
|
+
// by inlining evalModularCall's own children branch around a native
|
|
460
|
+
// evalChildren call. a = index into CompiledChunk::nativeStatements
|
|
461
|
+
// (the ModularCall node -- arguments, error position, splice node;
|
|
462
|
+
// no separate site table needed).
|
|
463
|
+
CallChildren,
|
|
464
|
+
|
|
465
|
+
// A single "native passthrough" statement -- intersection_for, every
|
|
466
|
+
// OTHER builtin module call not covered by Op::PushBuiltinWrap/
|
|
467
|
+
// Op::PushCsgWrap (see those ops' own doc comments for exactly which
|
|
468
|
+
// builtins ARE covered -- cube/sphere/hull/linear_extrude/etc., the
|
|
469
|
+
// ones that never wrap a recursive call in idiomatic OpenSCAD), the `*`
|
|
332
470
|
// modifier's own no-op case, or a user-module call that didn't
|
|
333
471
|
// resolve at compile time (shadowed, forward-declared, or otherwise
|
|
334
472
|
// not statically known) -- anything compileStatementList doesn't give
|
|
@@ -344,17 +482,22 @@ enum class Op {
|
|
|
344
482
|
// pattern that made this op's own native reentry a genuine Windows
|
|
345
483
|
// crash risk in practice, not just a missed optimization. See
|
|
346
484
|
// Op::PushBuiltinWrap's own doc comment for the real story and the
|
|
347
|
-
// fix.)
|
|
485
|
+
// fix. children() fell here too, and was the LAST and largest such
|
|
486
|
+
// reentry source once PushBuiltinWrap's own set was covered -- it now
|
|
487
|
+
// has Op::CallChildren, above. union()/difference()/intersection()
|
|
488
|
+
// fell here too, and were the last remaining REAL native-reentry risk
|
|
489
|
+
// (bespoke group_sizes bookkeeping meant they couldn't just reuse
|
|
490
|
+
// PushBuiltinWrap's own bracket) -- they now have Op::PushCsgWrap,
|
|
491
|
+
// above.)
|
|
348
492
|
// a = index into CompiledChunk::nativeStatements. Runtime just does
|
|
349
493
|
// what Evaluator::evalChildren's own per-statement loop already does
|
|
350
494
|
// for one node: derive childCtx via ctx.withScope(...), checkDebug,
|
|
351
495
|
// evalStatement. These are still "leaf-shaped" for what's left here
|
|
352
|
-
//
|
|
353
|
-
// recursion safety for a recursive module
|
|
354
|
-
// CallModule/PushBuiltinWrap/
|
|
355
|
-
// flow, not by how many of
|
|
356
|
-
//
|
|
357
|
-
// (translate()-wrapped recursion) has its own real bytecode instead.
|
|
496
|
+
// now that Op::PushBuiltinWrap/Op::PushCsgWrap have peeled off every
|
|
497
|
+
// proven-risky construct: real recursion safety for a recursive module
|
|
498
|
+
// chain is covered by CallModule/PushBuiltinWrap/PushCsgWrap/
|
|
499
|
+
// ForIterNext/the Jump-based if/for control flow, not by how many of
|
|
500
|
+
// THESE sit alongside them in the same body.
|
|
358
501
|
NativeStatement,
|
|
359
502
|
|
|
360
503
|
// If/if-else's own condition, evaluated NATIVELY (Evaluator::
|
|
@@ -690,6 +833,19 @@ struct CompiledChunk {
|
|
|
690
833
|
const oscad::ASTNode* node = nullptr;
|
|
691
834
|
};
|
|
692
835
|
|
|
836
|
+
// One Op::PushCsgWrap/PopCsgWrap site pair -- see those ops' own doc
|
|
837
|
+
// comments for the full "why union/difference/intersection need
|
|
838
|
+
// bespoke group_sizes bookkeeping instead of just reusing
|
|
839
|
+
// BuiltinWrapSite" rationale. `op` is always "union"/"difference"/
|
|
840
|
+
// "intersection" (the only 3 names resolveDispatch() maps to
|
|
841
|
+
// resolveCsg) -- always a genuine ModularCall (unlike BuiltinWrapSite's
|
|
842
|
+
// Modifier kind, this construct has no non-ModularCall variant), so
|
|
843
|
+
// `node` is typed precisely rather than a generic ASTNode*.
|
|
844
|
+
struct CsgWrapSite {
|
|
845
|
+
std::string op;
|
|
846
|
+
const oscad::ModularCall* node = nullptr;
|
|
847
|
+
};
|
|
848
|
+
|
|
693
849
|
// One Op::AssertStatement site -- see that op's own doc comment for
|
|
694
850
|
// the full contract. `conditionArgIndex`/`messageArgIndex` are indices
|
|
695
851
|
// into the site's own argCount-sized popped-argument array (source
|
|
@@ -752,6 +908,7 @@ struct CompiledChunk {
|
|
|
752
908
|
// own doc comments, above) -- always empty for a function chunk.
|
|
753
909
|
std::vector<ModuleCallSite> moduleCallSites;
|
|
754
910
|
std::vector<BuiltinWrapSite> builtinWrapSites;
|
|
911
|
+
std::vector<CsgWrapSite> csgWrapSites;
|
|
755
912
|
std::vector<AssertSite> assertSites;
|
|
756
913
|
std::vector<const oscad::Expression*> nativeExprs;
|
|
757
914
|
std::vector<const oscad::ASTNode*> nativeStatements;
|
|
@@ -30,6 +30,24 @@ struct PendingBuiltinWrap {
|
|
|
30
30
|
int siteIdx = -1;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
// One still-open Op::PushCsgWrap bracket's own state -- see that op's own
|
|
34
|
+
// doc comment (bytecode.hpp) for the full contract. `groupSizes` is built
|
|
35
|
+
// up incrementally, one entry per Op::CsgGroupStart/CsgGroupEnd pair (one
|
|
36
|
+
// per top-level GEOMETRY child statement); `groupStartSize` is scratch
|
|
37
|
+
// space for the CURRENTLY OPEN group only (set by CsgGroupStart, consumed
|
|
38
|
+
// by the matching CsgGroupEnd) -- safe as a single scalar, not a stack of
|
|
39
|
+
// its own, because groups within one CSG wrap are siblings in sequence,
|
|
40
|
+
// never nested (unlike PushCsgWrap brackets themselves, which CAN nest,
|
|
41
|
+
// e.g. `union() { difference() {...} }` -- that's what makes
|
|
42
|
+
// VmFrame::csgWrapStack itself a real LIFO, below).
|
|
43
|
+
struct PendingCsgWrap {
|
|
44
|
+
std::string op;
|
|
45
|
+
std::uint64_t randsBefore = 0;
|
|
46
|
+
int siteIdx = -1;
|
|
47
|
+
std::vector<Value> groupSizes;
|
|
48
|
+
size_t groupStartSize = 0;
|
|
49
|
+
};
|
|
50
|
+
|
|
33
51
|
// One ListCompFor/statement-for assignment's own materialized iteration
|
|
34
52
|
// state -- see Op::IterMaterialize/IterReset/IterNext's own doc comments
|
|
35
53
|
// (bytecode.hpp). Lives in the header (not bytecode_vm.cpp's own anonymous
|
|
@@ -127,6 +145,15 @@ struct VmFrame {
|
|
|
127
145
|
// existing invariant ("whoever pops this frame drains its own open
|
|
128
146
|
// brackets first") already covers it.
|
|
129
147
|
std::vector<PendingBuiltinWrap> builtinWrapStack;
|
|
148
|
+
// Op::PushCsgWrap's own per-frame LIFO -- same role/lifetime/teardown
|
|
149
|
+
// discipline as builtinWrapStack, just for union()/difference()/
|
|
150
|
+
// intersection() (see PendingCsgWrap's own doc comment, above, and
|
|
151
|
+
// Op::PushCsgWrap's, bytecode.hpp). Not explicitly cleared in
|
|
152
|
+
// releaseVmFrame, same as builtinWrapStack/accumStack/ctxChain -- the
|
|
153
|
+
// existing invariant ("whoever pops this frame drains its own open
|
|
154
|
+
// brackets first", normally via matched Push/Pop, or via
|
|
155
|
+
// teardownVmCallStackDownTo on the exception path) already covers it.
|
|
156
|
+
std::vector<PendingCsgWrap> csgWrapStack;
|
|
130
157
|
// The ORIGINAL callee name at push time, used by
|
|
131
158
|
// Evaluator::exitUserCallSuccess's own returnHook call when this frame
|
|
132
159
|
// carries a bracket -- deliberately NOT updated by a later tail hop
|
|
@@ -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
|
}
|
|
@@ -1202,6 +1202,45 @@ public:
|
|
|
1202
1202
|
out.push_back({Op::PopBuiltinWrap, idx, 0, &wrapperNode.position()});
|
|
1203
1203
|
}
|
|
1204
1204
|
|
|
1205
|
+
// union()/difference()/intersection() -- see Op::PushCsgWrap's own doc
|
|
1206
|
+
// comment (bytecode.hpp) for why these can't just reuse emitBuiltinWrap:
|
|
1207
|
+
// resolveCsg (booleans.cpp) needs per-top-level-child-statement
|
|
1208
|
+
// "group_sizes" bookkeeping, replicated here as one Op::CsgGroupStart/
|
|
1209
|
+
// CsgGroupEnd pair per GEOMETRY child, with every ASSIGNMENT child
|
|
1210
|
+
// compiled first, unconditionally, regardless of interleaving in
|
|
1211
|
+
// source -- mirrors resolveCsg's own two-pass split (`assignNodes`
|
|
1212
|
+
// fully evaluated, THEN one evalChildren call per `geoNodes` entry)
|
|
1213
|
+
// exactly, including its ModuleDeclaration/FunctionDeclaration
|
|
1214
|
+
// exclusion (a nested declaration inside a CSG block contributes to
|
|
1215
|
+
// neither pass -- already hoisted into scope, nothing to run here).
|
|
1216
|
+
void emitCsgWrap(const oscad::ModularCall& call, std::vector<Instruction>& out) {
|
|
1217
|
+
out.push_back({Op::CheckDebugStatement, internNativeStatement(&call), 0, nullptr});
|
|
1218
|
+
CompiledChunk::CsgWrapSite site;
|
|
1219
|
+
site.op = call.name->name;
|
|
1220
|
+
site.node = &call;
|
|
1221
|
+
chunk_.csgWrapSites.push_back(std::move(site));
|
|
1222
|
+
const int idx = static_cast<int>(chunk_.csgWrapSites.size()) - 1;
|
|
1223
|
+
out.push_back({Op::PushCsgWrap, idx, 0, &call.position()});
|
|
1224
|
+
|
|
1225
|
+
std::vector<const oscad::ASTNode*> assignNodes;
|
|
1226
|
+
std::vector<const oscad::ASTNode*> geoNodes;
|
|
1227
|
+
for (const auto& c : call.children) {
|
|
1228
|
+
if (c->kind() == oscad::NodeKind::Assignment) {
|
|
1229
|
+
assignNodes.push_back(c.get());
|
|
1230
|
+
} else if (c->kind() != oscad::NodeKind::ModuleDeclaration &&
|
|
1231
|
+
c->kind() != oscad::NodeKind::FunctionDeclaration) {
|
|
1232
|
+
geoNodes.push_back(c.get());
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
compileStatementList(assignNodes, out);
|
|
1236
|
+
for (const oscad::ASTNode* geoNode : geoNodes) {
|
|
1237
|
+
out.push_back({Op::CsgGroupStart, 0, 0, nullptr});
|
|
1238
|
+
compileStatementList(std::vector<const oscad::ASTNode*>{geoNode}, out);
|
|
1239
|
+
out.push_back({Op::CsgGroupEnd, 0, 0, nullptr});
|
|
1240
|
+
}
|
|
1241
|
+
out.push_back({Op::PopCsgWrap, idx, 0, &call.position()});
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1205
1244
|
void compileOneStatement(const oscad::ASTNode& stmt, std::vector<Instruction>& out) {
|
|
1206
1245
|
using oscad::NodeKind;
|
|
1207
1246
|
trackSpan(stmt);
|
|
@@ -1420,12 +1459,32 @@ public:
|
|
|
1420
1459
|
emitBuiltinWrap(*wrapKind, call.name->name, call, children, out);
|
|
1421
1460
|
return;
|
|
1422
1461
|
}
|
|
1423
|
-
//
|
|
1424
|
-
//
|
|
1425
|
-
//
|
|
1426
|
-
//
|
|
1427
|
-
//
|
|
1428
|
-
//
|
|
1462
|
+
// children() -- the runtime-varying forwarding builtin,
|
|
1463
|
+
// detected by the same function-pointer-identity pattern
|
|
1464
|
+
// as Transform/Color above. Deliberately NO preceding
|
|
1465
|
+
// Op::CheckDebugStatement (unlike emitBuiltinWrap's own
|
|
1466
|
+
// emission): CallChildren's handler fires checkDebug
|
|
1467
|
+
// itself against the SCOPE-WRAPPED ctx, byte-for-byte
|
|
1468
|
+
// matching Op::NativeStatement's own handler -- the
|
|
1469
|
+
// CheckDebugStatement handler passes the un-wrapped ctx,
|
|
1470
|
+
// which would be a subtle behavior change for this node.
|
|
1471
|
+
// See Op::CallChildren's own doc comment (bytecode.hpp).
|
|
1472
|
+
if (dispatchIt != dispatch.end() && dispatchIt->second == &resolveChildren) {
|
|
1473
|
+
out.push_back({Op::CallChildren, internNativeStatement(&stmt), 0, &stmt.position()});
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
// union()/difference()/intersection() -- see emitCsgWrap's
|
|
1477
|
+
// own doc comment for why these need their own bespoke
|
|
1478
|
+
// bracket rather than emitBuiltinWrap's.
|
|
1479
|
+
if (dispatchIt != dispatch.end() && dispatchIt->second == &resolveCsg) {
|
|
1480
|
+
emitCsgWrap(call, out);
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
// Every other builtin, or a name that didn't resolve to a
|
|
1484
|
+
// user module statically -- native passthrough, exactly
|
|
1485
|
+
// like echo/assert/etc. below. Never the recursion-depth
|
|
1486
|
+
// risk this compiler targets for THESE (see
|
|
1487
|
+
// NativeStatement's own doc comment, bytecode.hpp).
|
|
1429
1488
|
out.push_back({Op::NativeStatement, internNativeStatement(&stmt), 0, &stmt.position()});
|
|
1430
1489
|
return;
|
|
1431
1490
|
}
|