openscad-cpp-evaluator 0.1.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/.github/workflows/wheels.yml +1 -1
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/bindings/module.cpp +201 -61
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/evaluator.hpp +35 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/pyproject.toml +1 -1
- openscad_cpp_evaluator-0.3.0/python/openscad_cpp_evaluator/__init__.py +379 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/csg_generate.cpp +37 -6
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/csg_resolve.cpp +1 -0
- openscad_cpp_evaluator-0.3.0/tests/test_python_bindings.py +187 -0
- openscad_cpp_evaluator-0.1.0/python/openscad_cpp_evaluator/__init__.py +0 -207
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/bundled_font_path.hpp.in +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/text/stb_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.3.0}/tools/cli/main.cpp +0 -0
|
@@ -82,7 +82,7 @@ jobs:
|
|
|
82
82
|
# C:\msys64 (not on PATH); its bison/flex satisfy the parser
|
|
83
83
|
# submodule's grammar version requirement.
|
|
84
84
|
CIBW_BEFORE_ALL_WINDOWS: 'C:\msys64\usr\bin\bash.exe -lc "pacman -Sy --noconfirm bison flex"'
|
|
85
|
-
CIBW_TEST_COMMAND: "python
|
|
85
|
+
CIBW_TEST_COMMAND: "python {package}/tests/test_python_bindings.py"
|
|
86
86
|
|
|
87
87
|
- uses: actions/upload-artifact@v7
|
|
88
88
|
with:
|
|
@@ -13,12 +13,16 @@
|
|
|
13
13
|
|
|
14
14
|
#include <nanobind/nanobind.h>
|
|
15
15
|
#include <nanobind/ndarray.h>
|
|
16
|
+
#include <nanobind/stl/shared_ptr.h>
|
|
16
17
|
#include <nanobind/stl/string.h>
|
|
17
18
|
|
|
18
19
|
#include "openscad_cpp_evaluator/colored_body.hpp"
|
|
20
|
+
#include "openscad_cpp_evaluator/csg_node.hpp"
|
|
19
21
|
#include "openscad_cpp_evaluator/eval_context.hpp"
|
|
20
22
|
#include "openscad_cpp_evaluator/eval_use.hpp"
|
|
21
23
|
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
24
|
+
#include "openscad_cpp_evaluator/manifold_cache.hpp"
|
|
25
|
+
#include "openscad_cpp_evaluator/profile.hpp"
|
|
22
26
|
#include "openscad_cpp_evaluator/value.hpp"
|
|
23
27
|
|
|
24
28
|
#include "openscad_cpp_parser/api.hpp"
|
|
@@ -67,6 +71,44 @@ std::unordered_map<std::string, oscadeval::Value> toViewportParams(nb::dict d) {
|
|
|
67
71
|
return out;
|
|
68
72
|
}
|
|
69
73
|
|
|
74
|
+
// A facade class handle (openscad_cpp_evaluator.<name>), imported lazily at
|
|
75
|
+
// first use and leaked deliberately -- never destroyed, so no nb::object
|
|
76
|
+
// destructor runs after Python finalization (the app exits via os._exit,
|
|
77
|
+
// which skips finalizers; a normal-shutdown consumer would otherwise crash).
|
|
78
|
+
nb::object facadeAttr(const char* name) {
|
|
79
|
+
static nb::object* mod = new nb::object(nb::module_::import_("openscad_cpp_evaluator"));
|
|
80
|
+
return mod->attr(name);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
nb::object valueToPy(const oscadeval::Value& v); // recursive
|
|
84
|
+
|
|
85
|
+
nb::object valueToPy(const oscadeval::Value& v) {
|
|
86
|
+
if (std::holds_alternative<std::monostate>(v)) return nb::none();
|
|
87
|
+
if (const bool* b = std::get_if<bool>(&v)) return nb::cast(*b);
|
|
88
|
+
if (const double* d = std::get_if<double>(&v)) return nb::cast(*d);
|
|
89
|
+
if (const std::string* s = std::get_if<std::string>(&v)) return nb::cast(*s);
|
|
90
|
+
if (const oscadeval::ListPtr* lp = std::get_if<oscadeval::ListPtr>(&v)) {
|
|
91
|
+
nb::list out;
|
|
92
|
+
if (*lp)
|
|
93
|
+
for (const oscadeval::Value& item : (*lp)->items) out.append(valueToPy(item));
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
if (const oscadeval::ObjectPtr* op = std::get_if<oscadeval::ObjectPtr>(&v)) {
|
|
97
|
+
nb::dict data;
|
|
98
|
+
if (*op)
|
|
99
|
+
for (const auto& [k, val] : (*op)->items) data[nb::str(k.c_str())] = valueToPy(val);
|
|
100
|
+
return facadeAttr("OscObject")(data);
|
|
101
|
+
}
|
|
102
|
+
// OscRange / FunctionLiteral: no direct Python analog -- wrap the
|
|
103
|
+
// OpenSCAD text so the debugger displays it cleanly (unquoted).
|
|
104
|
+
return facadeAttr("_ScadValue")(oscadeval::fmtValue(v));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
nb::object posToPy(const oscad::Position* p) {
|
|
108
|
+
if (!p) return nb::none();
|
|
109
|
+
return facadeAttr("_Position")(p->line, p->column, p->origin, p->start_offset, p->end_offset);
|
|
110
|
+
}
|
|
111
|
+
|
|
70
112
|
// One evaluated body's mesh + attributes, shaped to match what the renderer
|
|
71
113
|
// already reads off a manifold3d mesh (vert_properties (nVert, numProp),
|
|
72
114
|
// tri_verts (nTri, 3), run_original_id (nRun,), run_index (nRun+1,) -- the
|
|
@@ -124,30 +166,98 @@ nb::dict idSpansToDict(const std::vector<IdSpan>& idSpans) {
|
|
|
124
166
|
return d;
|
|
125
167
|
}
|
|
126
168
|
|
|
127
|
-
//
|
|
169
|
+
// CSGNode -> a facade `_CSGNode` (kind/params/bodies/is_builtin/children),
|
|
170
|
+
// recursively, eagerly converting every field to plain Python data. No
|
|
171
|
+
// lifetime extension needed -- CSGParams (Value-only, see csg_node.hpp) and
|
|
172
|
+
// ColoredBody never hold AST pointers, so the result is fully self-contained
|
|
173
|
+
// once built, unlike CSGNode::node itself (deliberately not exposed: the AST
|
|
174
|
+
// it points into does not outlive this binding call, and the CSG-tree dump
|
|
175
|
+
// consumer only ever needs kind/params/children/bodies -- see
|
|
176
|
+
// format_csg_tree's own doc comment).
|
|
177
|
+
nb::object csgNodeToPy(const oscadeval::CSGNode& node) {
|
|
178
|
+
nb::dict params;
|
|
179
|
+
for (const auto& [k, v] : node.params) params[nb::str(k.c_str())] = valueToPy(v);
|
|
180
|
+
nb::list bodies;
|
|
181
|
+
for (const oscadeval::ColoredBody& cb : node.bodies) {
|
|
182
|
+
if (!cb.body || cb.body->IsEmpty()) continue;
|
|
183
|
+
// ColoredBody here is const in this walk (tree ownership stays with
|
|
184
|
+
// the caller) -- GetMeshGL() itself is logically read-only, so a
|
|
185
|
+
// const_cast here is safe/local, mirroring bodyToDict's mutating
|
|
186
|
+
// signature only because manifold3d's own API isn't const-qualified.
|
|
187
|
+
bodies.append(bodyToDict(const_cast<oscadeval::ColoredBody&>(cb)));
|
|
188
|
+
}
|
|
189
|
+
nb::list children;
|
|
190
|
+
for (const std::unique_ptr<oscadeval::CSGNode>& child : node.children) children.append(csgNodeToPy(*child));
|
|
191
|
+
return facadeAttr("_CSGNode")(node.kind, params, bodies, node.isBuiltin, children);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
nb::list csgTreeToPy(const std::vector<std::unique_ptr<oscadeval::CSGNode>>& tree) {
|
|
195
|
+
nb::list out;
|
|
196
|
+
for (const std::unique_ptr<oscadeval::CSGNode>& node : tree) out.append(csgNodeToPy(*node));
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
nb::object profileResultToPy(const std::optional<oscadeval::ProfileResult>& pr) {
|
|
201
|
+
if (!pr) return nb::none();
|
|
202
|
+
nb::list sites;
|
|
203
|
+
for (const oscadeval::CallSiteProfile& s : pr->callSites) {
|
|
204
|
+
sites.append(facadeAttr("CallSiteProfile")(s.kind, s.name, s.callerName, s.callOrigin, s.callLine, s.declOrigin,
|
|
205
|
+
s.declLine, s.callCount, s.selfTime, s.cumulativeTime));
|
|
206
|
+
}
|
|
207
|
+
return facadeAttr("ProfileResult")(sites, pr->resolveTime, pr->generateTime, pr->totalTime, pr->unattributedTime);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ctx.dyn / ctx.dynExplicit -> (dict[str, Any], set[str]) -- every currently-
|
|
211
|
+
// visible $-prefixed dynamic variable, and the subset the script itself
|
|
212
|
+
// assigned (vs. merely seeded by viewportParams). ctx is caller-owned in this
|
|
213
|
+
// port (see evaluate()'s own doc comment in evaluator.hpp), so this is a
|
|
214
|
+
// direct readback, not a separate tracking mechanism.
|
|
215
|
+
std::pair<nb::dict, nb::object> dynStateToPy(const oscadeval::EvalContext& ctx) {
|
|
216
|
+
nb::dict dyn;
|
|
217
|
+
for (const auto& [name, v] : ctx.dyn.items()) dyn[nb::str(name.c_str())] = valueToPy(v);
|
|
218
|
+
nb::set explicitNames;
|
|
219
|
+
for (const auto& [name, isExplicit] : ctx.dynExplicit.items())
|
|
220
|
+
if (isExplicit) explicitNames.add(nb::str(name.c_str()));
|
|
221
|
+
return {dyn, explicitNames};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// (list[body-dict], list[echo-str], dict[int, span], list[_CSGNode],
|
|
225
|
+
// ProfileResult|None, dict[str, Any], set[str]). Raises the C++ error
|
|
128
226
|
// message as a Python exception on ParseError/EvalError (nanobind maps
|
|
129
227
|
// std::exception -> RuntimeError, whose str() is the already-formatted
|
|
130
228
|
// "ERROR:..."/caret diagnostic; the facade re-raises as EvalError).
|
|
131
|
-
nb::object evaluate(const std::string& path, nb::dict viewportParams
|
|
229
|
+
nb::object evaluate(const std::string& path, nb::dict viewportParams,
|
|
230
|
+
std::shared_ptr<oscadeval::ManifoldCache> manifoldCache, bool profile) {
|
|
132
231
|
std::unordered_map<std::string, oscadeval::Value> vp = toViewportParams(viewportParams);
|
|
133
232
|
|
|
134
233
|
std::vector<oscadeval::ColoredBody> bodies;
|
|
135
234
|
std::vector<std::string> echoes;
|
|
136
235
|
std::vector<IdSpan> idSpans;
|
|
236
|
+
std::vector<std::unique_ptr<oscadeval::CSGNode>> csgTree;
|
|
237
|
+
std::optional<oscadeval::ProfileResult> profileResult;
|
|
238
|
+
nb::dict dyn;
|
|
239
|
+
nb::object dynExplicit;
|
|
137
240
|
{
|
|
138
241
|
nb::gil_scoped_release rel;
|
|
139
242
|
auto logFn = [&echoes](const std::string& m) { echoes.push_back(m); };
|
|
140
243
|
std::vector<std::unique_ptr<oscad::ASTNode>> ast = oscad::getASTFromFile(path);
|
|
141
244
|
oscadeval::ResolvedUseScopes used = oscadeval::resolveUseScopes(ast, path, logFn);
|
|
142
|
-
oscadeval::Evaluator ev(logFn);
|
|
245
|
+
oscadeval::Evaluator ev(logFn, nullptr, manifoldCache, oscadeval::DebugHooks{}, profile);
|
|
143
246
|
oscadeval::EvalContext ctx = oscadeval::EvalContext::makeRoot(used.rootScope.get());
|
|
144
247
|
bodies = oscadeval::toRenderableBodies(ev.evaluate(used.processedNodes, ctx, vp));
|
|
145
248
|
collectIdSpans(ev, idSpans);
|
|
249
|
+
csgTree = std::move(ev.csgTree);
|
|
250
|
+
profileResult = std::move(ev.profileResult);
|
|
251
|
+
{
|
|
252
|
+
nb::gil_scoped_acquire g; // building Python objects needs the GIL back
|
|
253
|
+
std::tie(dyn, dynExplicit) = dynStateToPy(ctx);
|
|
254
|
+
}
|
|
146
255
|
}
|
|
147
256
|
|
|
148
257
|
nb::list echoList;
|
|
149
258
|
for (const std::string& s : echoes) echoList.append(s);
|
|
150
|
-
return nb::make_tuple(bodiesToList(bodies), echoList, idSpansToDict(idSpans))
|
|
259
|
+
return nb::make_tuple(bodiesToList(bodies), echoList, idSpansToDict(idSpans), csgTreeToPy(csgTree),
|
|
260
|
+
profileResultToPy(profileResult), dyn, dynExplicit);
|
|
151
261
|
}
|
|
152
262
|
|
|
153
263
|
// ------------------------------------------------------------------------
|
|
@@ -155,44 +265,6 @@ nb::object evaluate(const std::string& path, nb::dict viewportParams) {
|
|
|
155
265
|
// Python conversion for locals inspection.
|
|
156
266
|
// ------------------------------------------------------------------------
|
|
157
267
|
|
|
158
|
-
// A facade class handle (openscad_cpp_evaluator.<name>), imported lazily at
|
|
159
|
-
// first use and leaked deliberately -- never destroyed, so no nb::object
|
|
160
|
-
// destructor runs after Python finalization (the app exits via os._exit,
|
|
161
|
-
// which skips finalizers; a normal-shutdown consumer would otherwise crash).
|
|
162
|
-
nb::object facadeAttr(const char* name) {
|
|
163
|
-
static nb::object* mod = new nb::object(nb::module_::import_("openscad_cpp_evaluator"));
|
|
164
|
-
return mod->attr(name);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
nb::object valueToPy(const oscadeval::Value& v); // recursive
|
|
168
|
-
|
|
169
|
-
nb::object valueToPy(const oscadeval::Value& v) {
|
|
170
|
-
if (std::holds_alternative<std::monostate>(v)) return nb::none();
|
|
171
|
-
if (const bool* b = std::get_if<bool>(&v)) return nb::cast(*b);
|
|
172
|
-
if (const double* d = std::get_if<double>(&v)) return nb::cast(*d);
|
|
173
|
-
if (const std::string* s = std::get_if<std::string>(&v)) return nb::cast(*s);
|
|
174
|
-
if (const oscadeval::ListPtr* lp = std::get_if<oscadeval::ListPtr>(&v)) {
|
|
175
|
-
nb::list out;
|
|
176
|
-
if (*lp)
|
|
177
|
-
for (const oscadeval::Value& item : (*lp)->items) out.append(valueToPy(item));
|
|
178
|
-
return out;
|
|
179
|
-
}
|
|
180
|
-
if (const oscadeval::ObjectPtr* op = std::get_if<oscadeval::ObjectPtr>(&v)) {
|
|
181
|
-
nb::dict data;
|
|
182
|
-
if (*op)
|
|
183
|
-
for (const auto& [k, val] : (*op)->items) data[nb::str(k.c_str())] = valueToPy(val);
|
|
184
|
-
return facadeAttr("OscObject")(data);
|
|
185
|
-
}
|
|
186
|
-
// OscRange / FunctionLiteral: no direct Python analog -- wrap the
|
|
187
|
-
// OpenSCAD text so the debugger displays it cleanly (unquoted).
|
|
188
|
-
return facadeAttr("_ScadValue")(oscadeval::fmtValue(v));
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
nb::object posToPy(const oscad::Position* p) {
|
|
192
|
-
if (!p) return nb::none();
|
|
193
|
-
return facadeAttr("_Position")(p->line, p->column, p->origin, p->start_offset, p->end_offset);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
268
|
// One debug frame -> {"local_scope", "outer_scope", "dyn_names"}, the shape
|
|
197
269
|
// the debugger pane's _filtered_vars consumes.
|
|
198
270
|
nb::dict frameToDict(const oscadeval::DebugFrame& f) {
|
|
@@ -220,13 +292,34 @@ nb::list callStackToPy(const std::vector<oscadeval::CallStackFrame>& cs) {
|
|
|
220
292
|
return out;
|
|
221
293
|
}
|
|
222
294
|
|
|
295
|
+
// Called from within a debug_hook/error_break callback (never after it
|
|
296
|
+
// returns) to best-effort generate a live render of whatever's been
|
|
297
|
+
// resolved so far -- see Evaluator::generatePartialTree()'s own doc
|
|
298
|
+
// comment for why this is safe to call mid-resolve.
|
|
299
|
+
using GeneratePartialFn = std::function<std::vector<oscadeval::ColoredBody>()>;
|
|
300
|
+
|
|
301
|
+
// Wraps a GeneratePartialFn as a Python callable returning a plain list of
|
|
302
|
+
// body-dicts (bodiesToList's own shape) -- the facade's _generate_partial_render
|
|
303
|
+
// converts these to ColoredBody and catches whatever exception a GenerateFn
|
|
304
|
+
// raises, the same try/except shape it already had calling generate_tree()
|
|
305
|
+
// directly. No error handling needed here: a C++ exception crossing into
|
|
306
|
+
// Python via this cpp_function is nanobind's normal std::exception ->
|
|
307
|
+
// RuntimeError mapping, which that Python try/except already catches.
|
|
308
|
+
nb::object generatePartialTrampoline(const GeneratePartialFn& generatePartial) {
|
|
309
|
+
return nb::cpp_function([&generatePartial]() -> nb::list {
|
|
310
|
+
std::vector<oscadeval::ColoredBody> bodies = generatePartial();
|
|
311
|
+
return bodiesToList(bodies);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
223
315
|
// Trampoline: C++ debug hook -> the Python DebugSession hook. Runs with the
|
|
224
|
-
// GIL held (reacquired by the caller). `getFrame`/`callStack`
|
|
225
|
-
// for this synchronous call, so the get_frames
|
|
226
|
-
// from within the Python hook, before it returns.
|
|
316
|
+
// GIL held (reacquired by the caller). `getFrame`/`callStack`/`generatePartial`
|
|
317
|
+
// are valid only for this synchronous call, so the get_frames/generate_partial
|
|
318
|
+
// closures are only ever invoked from within the Python hook, before it returns.
|
|
227
319
|
oscadeval::DebugAction callPyDebugHook(nb::handle hook, int line, int depth, bool forced, const std::string& origin,
|
|
228
320
|
const std::vector<oscadeval::CallStackFrame>& callStack,
|
|
229
|
-
const oscadeval::DebugFramesFn& getFrame
|
|
321
|
+
const oscadeval::DebugFramesFn& getFrame,
|
|
322
|
+
const GeneratePartialFn& generatePartial) {
|
|
230
323
|
auto getFramesPy = nb::cpp_function([&callStack, &getFrame]() -> nb::object {
|
|
231
324
|
std::vector<oscadeval::DebugFrame> frames = getFrame();
|
|
232
325
|
nb::list allFrameLocals;
|
|
@@ -241,9 +334,11 @@ oscadeval::DebugAction callPyDebugHook(nb::handle hook, int line, int depth, boo
|
|
|
241
334
|
}
|
|
242
335
|
return nb::make_tuple(nb::make_tuple(lastLocals, allFrameLocals), callStackToPy(callStack));
|
|
243
336
|
});
|
|
337
|
+
nb::object generatePartialPy = generatePartialTrampoline(generatePartial);
|
|
244
338
|
|
|
245
339
|
nb::object ret = hook(line, depth, nb::arg("forced") = forced, nb::arg("expr_level") = false,
|
|
246
|
-
nb::arg("expr_depth") = 0, nb::arg("origin") = origin, nb::arg("get_frames") = getFramesPy
|
|
340
|
+
nb::arg("expr_depth") = 0, nb::arg("origin") = origin, nb::arg("get_frames") = getFramesPy,
|
|
341
|
+
nb::arg("generate_partial") = generatePartialPy);
|
|
247
342
|
nb::tuple t = nb::cast<nb::tuple>(ret);
|
|
248
343
|
oscadeval::DebugAction action;
|
|
249
344
|
action.stop = (nb::cast<std::string>(t[0]) == "stop");
|
|
@@ -255,57 +350,92 @@ oscadeval::DebugAction callPyDebugHook(nb::handle hook, int line, int depth, boo
|
|
|
255
350
|
// Trampoline: C++ errorBreak -> the Python DebugSession error hook.
|
|
256
351
|
void callPyErrorBreak(nb::handle errorBreak, int line, const std::string& header, const std::string& origin,
|
|
257
352
|
const std::vector<oscadeval::CallStackFrame>& callStack,
|
|
258
|
-
const oscadeval::DebugFramesFn& getFrame) {
|
|
353
|
+
const oscadeval::DebugFramesFn& getFrame, const GeneratePartialFn& generatePartial) {
|
|
259
354
|
std::vector<oscadeval::DebugFrame> frames = getFrame();
|
|
260
355
|
nb::list allFrameLocals;
|
|
261
356
|
for (const oscadeval::DebugFrame& f : frames) allFrameLocals.append(frameToDict(f));
|
|
262
|
-
|
|
357
|
+
nb::object generatePartialPy = generatePartialTrampoline(generatePartial);
|
|
358
|
+
errorBreak(line, header, allFrameLocals, callStackToPy(callStack), nb::arg("origin") = origin,
|
|
359
|
+
nb::arg("generate_partial") = generatePartialPy);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Trampoline: C++ returnHook -> the Python DebugSession return hook. Only
|
|
363
|
+
// fires for user function/function-literal calls (never modules, never
|
|
364
|
+
// builtins -- see DebugHooks::returnHook's own doc comment).
|
|
365
|
+
void callPyReturnHook(nb::handle returnHook, const std::string& name, const oscadeval::Value& result, int depth) {
|
|
366
|
+
returnHook(name, valueToPy(result), depth);
|
|
263
367
|
}
|
|
264
368
|
|
|
265
369
|
// evaluate() with the debugger wired in. echo is delivered live via echoFn
|
|
266
370
|
// (not batched), so a paused session can still print. Returns (bodies, [],
|
|
267
|
-
// id_to_node). The GIL is released around the C++
|
|
268
|
-
// inside every callback trampoline; the actual pause
|
|
269
|
-
// side (threading.Event) so the GUI thread keeps running.
|
|
371
|
+
// id_to_node, dyn, dyn_explicit). The GIL is released around the C++
|
|
372
|
+
// evaluate and reacquired inside every callback trampoline; the actual pause
|
|
373
|
+
// blocks on the Python side (threading.Event) so the GUI thread keeps running.
|
|
270
374
|
nb::object debugEvaluate(const std::string& path, nb::dict viewportParams, nb::callable debugHook,
|
|
271
|
-
nb::callable errorBreak, nb::callable echoFn
|
|
375
|
+
nb::callable errorBreak, nb::callable echoFn,
|
|
376
|
+
std::shared_ptr<oscadeval::ManifoldCache> manifoldCache, nb::object returnHook) {
|
|
272
377
|
std::unordered_map<std::string, oscadeval::Value> vp = toViewportParams(viewportParams);
|
|
273
378
|
|
|
274
379
|
std::vector<oscadeval::ColoredBody> bodies;
|
|
275
380
|
std::vector<IdSpan> idSpans;
|
|
276
381
|
std::exception_ptr err;
|
|
382
|
+
nb::dict dyn;
|
|
383
|
+
nb::object dynExplicit;
|
|
277
384
|
{
|
|
278
385
|
nb::gil_scoped_release rel;
|
|
279
386
|
auto echoCpp = [&echoFn](const std::string& m) {
|
|
280
387
|
nb::gil_scoped_acquire g;
|
|
281
388
|
echoFn(m);
|
|
282
389
|
};
|
|
390
|
+
// Set right after `ev` is constructed below, before evaluate() runs
|
|
391
|
+
// -- every hook fires only from within that call, by which point
|
|
392
|
+
// this is always valid. Needed because `hooks` (captured by the
|
|
393
|
+
// lambdas below) must be fully built and passed into Evaluator's
|
|
394
|
+
// constructor before `ev` exists, so the lambdas can't capture `ev`
|
|
395
|
+
// itself; they capture this pointer's address instead, which DOES
|
|
396
|
+
// already exist (see generatePartial's own doc comment on why
|
|
397
|
+
// GeneratePartialFn needs a live Evaluator& at all).
|
|
398
|
+
oscadeval::Evaluator* evPtr = nullptr;
|
|
399
|
+
GeneratePartialFn generatePartial = [&evPtr]() -> std::vector<oscadeval::ColoredBody> {
|
|
400
|
+
return evPtr->generatePartialTree();
|
|
401
|
+
};
|
|
283
402
|
oscadeval::DebugHooks hooks;
|
|
284
403
|
hooks.debugHook = [&](int line, int depth, bool forced, const std::string& origin,
|
|
285
404
|
const std::vector<oscadeval::CallStackFrame>& cs,
|
|
286
405
|
const oscadeval::DebugFramesFn& gf) -> oscadeval::DebugAction {
|
|
287
406
|
nb::gil_scoped_acquire g;
|
|
288
|
-
return callPyDebugHook(debugHook, line, depth, forced, origin, cs, gf);
|
|
407
|
+
return callPyDebugHook(debugHook, line, depth, forced, origin, cs, gf, generatePartial);
|
|
289
408
|
};
|
|
290
409
|
hooks.errorBreak = [&](int line, const std::string& header, const std::string& origin,
|
|
291
410
|
const std::vector<oscadeval::CallStackFrame>& cs, const oscadeval::DebugFramesFn& gf) {
|
|
292
411
|
nb::gil_scoped_acquire g;
|
|
293
|
-
callPyErrorBreak(errorBreak, line, header, origin, cs, gf);
|
|
412
|
+
callPyErrorBreak(errorBreak, line, header, origin, cs, gf, generatePartial);
|
|
294
413
|
};
|
|
414
|
+
if (!returnHook.is_none()) {
|
|
415
|
+
hooks.returnHook = [&](const std::string& name, const oscadeval::Value& result, int depth) {
|
|
416
|
+
nb::gil_scoped_acquire g;
|
|
417
|
+
callPyReturnHook(returnHook, name, result, depth);
|
|
418
|
+
};
|
|
419
|
+
}
|
|
295
420
|
try {
|
|
296
421
|
std::vector<std::unique_ptr<oscad::ASTNode>> ast = oscad::getASTFromFile(path);
|
|
297
422
|
oscadeval::ResolvedUseScopes used = oscadeval::resolveUseScopes(ast, path, echoCpp);
|
|
298
|
-
oscadeval::Evaluator ev(echoCpp, nullptr,
|
|
423
|
+
oscadeval::Evaluator ev(echoCpp, nullptr, manifoldCache, hooks, false);
|
|
424
|
+
evPtr = &ev;
|
|
299
425
|
oscadeval::EvalContext ctx = oscadeval::EvalContext::makeRoot(used.rootScope.get());
|
|
300
426
|
bodies = oscadeval::toRenderableBodies(ev.evaluate(used.processedNodes, ctx, vp));
|
|
301
427
|
collectIdSpans(ev, idSpans);
|
|
428
|
+
{
|
|
429
|
+
nb::gil_scoped_acquire g;
|
|
430
|
+
std::tie(dyn, dynExplicit) = dynStateToPy(ctx);
|
|
431
|
+
}
|
|
302
432
|
} catch (...) {
|
|
303
433
|
err = std::current_exception();
|
|
304
434
|
}
|
|
305
435
|
}
|
|
306
436
|
if (err) std::rethrow_exception(err); // re-raised with the GIL held -> Python exception
|
|
307
437
|
|
|
308
|
-
return nb::make_tuple(bodiesToList(bodies), nb::list(), idSpansToDict(idSpans));
|
|
438
|
+
return nb::make_tuple(bodiesToList(bodies), nb::list(), idSpansToDict(idSpans), dyn, dynExplicit);
|
|
309
439
|
}
|
|
310
440
|
|
|
311
441
|
// Top-level declaration names + source spans, for the editor's completion and
|
|
@@ -358,11 +488,21 @@ nb::list parseDecls(const std::string& path) {
|
|
|
358
488
|
|
|
359
489
|
NB_MODULE(_openscad_cpp_evaluator, m) {
|
|
360
490
|
m.doc() = "C++ OpenSCAD evaluator (nanobind binding)";
|
|
361
|
-
|
|
362
|
-
|
|
491
|
+
|
|
492
|
+
// Opt-in, shared across evaluate() calls -- see manifold_cache.hpp.
|
|
493
|
+
// Only a constructor and clear() are ever called from Python (get/put
|
|
494
|
+
// are internal to generateTree()'s own C++ implementation).
|
|
495
|
+
nb::class_<oscadeval::ManifoldCache>(m, "ManifoldCache")
|
|
496
|
+
.def(nb::init<>())
|
|
497
|
+
.def("clear", &oscadeval::ManifoldCache::clear);
|
|
498
|
+
|
|
499
|
+
m.def("evaluate", &evaluate, nb::arg("path"), nb::arg("viewport_params"), nb::arg("manifold_cache") = nullptr,
|
|
500
|
+
nb::arg("profile") = false,
|
|
501
|
+
"Evaluate a .scad file; return (bodies, echoes, id_to_node, csg_tree, profile_result, dyn, dyn_explicit).");
|
|
363
502
|
m.def("parse_decls", &parseDecls, nb::arg("path"),
|
|
364
503
|
"Parse a .scad file; return top-level declaration (namespace, name, start, end, line, column, origin) tuples.");
|
|
365
504
|
m.def("debug_evaluate", &debugEvaluate, nb::arg("path"), nb::arg("viewport_params"), nb::arg("debug_hook"),
|
|
366
|
-
nb::arg("error_break"), nb::arg("echo_fn"),
|
|
367
|
-
"
|
|
505
|
+
nb::arg("error_break"), nb::arg("echo_fn"), nb::arg("manifold_cache") = nullptr,
|
|
506
|
+
nb::arg("return_hook") = nb::none(),
|
|
507
|
+
"Evaluate with the debugger wired in; returns (bodies, [], id_to_node, dyn, dyn_explicit). Callbacks fire under the GIL.");
|
|
368
508
|
}
|
|
@@ -174,6 +174,26 @@ public:
|
|
|
174
174
|
// top-level show_only filter -- see evaluate().
|
|
175
175
|
std::vector<ColoredBody> generateTree(const std::vector<std::unique_ptr<CSGNode>>& tree);
|
|
176
176
|
|
|
177
|
+
// Best-effort generate over whatever's been resolved SO FAR, for a live
|
|
178
|
+
// partial render while genuinely paused inside a debug hook mid-
|
|
179
|
+
// evaluation (resolveTree()/evaluate() haven't returned yet) -- flattens
|
|
180
|
+
// treeStack_ across every nesting level and runs the same bottom-up
|
|
181
|
+
// generate walk generateTree() uses, via generateTreeImpl(), over
|
|
182
|
+
// non-owning pointers into nodes treeStack_ (not this call) still owns.
|
|
183
|
+
// Safe to call mid-resolve: the resolve pass never reads CSGNode::bodies,
|
|
184
|
+
// only ever writes kind/params/children, so populating .bodies early
|
|
185
|
+
// here cannot corrupt or race the resolve that's paused around this
|
|
186
|
+
// call -- and if a ManifoldCache is set, the real generateTree() call at
|
|
187
|
+
// the end of evaluate() gets a cache hit for any subtree this already
|
|
188
|
+
// generated, so a debug session pays no repeated Manifold work session-
|
|
189
|
+
// wide (see manifold_cache.hpp's own doc comment on this exact use
|
|
190
|
+
// case). Only meaningful to call synchronously from within a
|
|
191
|
+
// DebugHookFn/ErrorBreakFn callback; the caller must not retain a
|
|
192
|
+
// reference into anything treeStack_ owns past that callback's return.
|
|
193
|
+
// Mirrors the reference's `ev.generate_tree(partial_nodes)` called from
|
|
194
|
+
// `_generate_partial_render`.
|
|
195
|
+
std::vector<ColoredBody> generatePartialTree();
|
|
196
|
+
|
|
177
197
|
// Provenance tables populated by tagGenerated() during generate --
|
|
178
198
|
// originalID -> the AST node that produced it / that node's own
|
|
179
199
|
// resolved color. Public, read by a caller (CLI, WYSIWYG picking) after
|
|
@@ -336,6 +356,15 @@ public:
|
|
|
336
356
|
// reference's Evaluator.profile_result.
|
|
337
357
|
std::optional<ProfileResult> profileResult;
|
|
338
358
|
|
|
359
|
+
// The resolved (and, after evaluate() runs, generated) CSG tree from the
|
|
360
|
+
// most recent evaluate() call -- moved here from evaluateImpl's local
|
|
361
|
+
// `tree` after generateTree() populates each node's own `bodies`, so a
|
|
362
|
+
// caller can inspect tree shape/params after evaluate() returns (CSG-tree
|
|
363
|
+
// dump, live partial-render). Empty for direct resolveTree()/
|
|
364
|
+
// generateTree() callers that bypass evaluate() -- same scoping as
|
|
365
|
+
// profileResult above. Mirrors the reference's Evaluator.csg_tree.
|
|
366
|
+
std::vector<std::unique_ptr<CSGNode>> csgTree;
|
|
367
|
+
|
|
339
368
|
private:
|
|
340
369
|
// Shared body for resolveTree()'s/evaluate()'s two overloads (owning vs.
|
|
341
370
|
// raw-pointer node list) -- a template rather than duplicating each
|
|
@@ -348,6 +377,12 @@ private:
|
|
|
348
377
|
std::vector<ColoredBody> evaluateImpl(const NodeList& nodes, EvalContext& ctx,
|
|
349
378
|
const std::unordered_map<std::string, Value>& viewportParams);
|
|
350
379
|
|
|
380
|
+
// Shared bottom-up generate walk behind generateTree()/generatePartialTree()
|
|
381
|
+
// -- see generatePartialTree()'s own doc comment and this function's
|
|
382
|
+
// definition (csg_generate.cpp) for why non-owning pointers, not
|
|
383
|
+
// unique_ptr, let both callers share one implementation.
|
|
384
|
+
std::vector<ColoredBody> generateTreeImpl(const std::vector<CSGNode*>& tree);
|
|
385
|
+
|
|
351
386
|
// Evaluates one top-level element of a `[...]` list literal (a plain
|
|
352
387
|
// expression, or one of the 6 list-comprehension clause kinds --
|
|
353
388
|
// for/c-for/let/if/if-else/each), appending whatever it contributes to
|