openscad-cpp-evaluator 0.1.0__tar.gz → 0.2.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.
Files changed (194) hide show
  1. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/.github/workflows/wheels.yml +1 -1
  2. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/PKG-INFO +1 -1
  3. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/bindings/module.cpp +154 -52
  4. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/evaluator.hpp +9 -0
  5. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/pyproject.toml +1 -1
  6. openscad_cpp_evaluator-0.2.0/python/openscad_cpp_evaluator/__init__.py +370 -0
  7. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/csg_resolve.cpp +1 -0
  8. openscad_cpp_evaluator-0.2.0/tests/test_python_bindings.py +140 -0
  9. openscad_cpp_evaluator-0.1.0/python/openscad_cpp_evaluator/__init__.py +0 -207
  10. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/.github/workflows/ci.yml +0 -0
  11. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/.gitignore +0 -0
  12. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/.gitmodules +0 -0
  13. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/CLAUDE.md +0 -0
  14. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/CMakeLists.txt +0 -0
  15. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/LICENSE +0 -0
  16. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/README.md +0 -0
  17. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/bindings/CMakeLists.txt +0 -0
  18. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/examples/CMakeLists.txt +0 -0
  19. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/examples/eval_perf_benchmark.cpp +0 -0
  20. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/examples/manifold_cache_reuse.cpp +0 -0
  21. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/examples/minimal_debugger.cpp +0 -0
  22. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
  23. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/.gitignore +0 -0
  24. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
  25. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
  26. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/README.md +0 -0
  27. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
  28. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
  29. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
  30. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
  31. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
  32. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
  33. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
  34. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
  35. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
  36. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
  37. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
  38. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
  39. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
  40. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
  41. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
  42. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
  43. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
  44. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
  45. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
  46. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
  47. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
  48. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
  49. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
  50. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
  51. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
  52. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
  53. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
  54. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
  55. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
  56. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
  57. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
  58. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
  59. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
  60. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
  61. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
  62. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
  63. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
  64. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
  65. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
  66. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
  67. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
  68. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
  69. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
  70. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
  71. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
  72. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
  73. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
  74. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
  75. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
  76. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
  77. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
  78. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
  79. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
  80. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
  81. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
  82. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
  83. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
  84. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
  85. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
  86. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
  87. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
  88. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
  89. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/bundled_font_path.hpp.in +0 -0
  90. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
  91. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
  92. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
  93. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
  94. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
  95. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
  96. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
  97. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
  98. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
  99. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
  100. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
  101. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
  102. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
  103. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
  104. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
  105. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
  106. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
  107. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
  108. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
  109. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
  110. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
  111. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
  112. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
  113. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
  114. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
  115. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
  116. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
  117. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
  118. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
  119. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/resources/fonts/LICENSE +0 -0
  120. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
  121. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/CMakeLists.txt +0 -0
  122. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/booleans.cpp +0 -0
  123. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/builtins.hpp +0 -0
  124. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/call_args.cpp +0 -0
  125. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/color.cpp +0 -0
  126. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/control.cpp +0 -0
  127. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/extrude.cpp +0 -0
  128. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/function_builtins.cpp +0 -0
  129. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/import.cpp +0 -0
  130. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/modifiers.cpp +0 -0
  131. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/primitives_2d.cpp +0 -0
  132. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/primitives_3d.cpp +0 -0
  133. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/registry.cpp +0 -0
  134. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/roof.cpp +0 -0
  135. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/segments.cpp +0 -0
  136. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/surface.cpp +0 -0
  137. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/text.cpp +0 -0
  138. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/topology.cpp +0 -0
  139. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/builtins/transforms.cpp +0 -0
  140. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/bytecode_compiler.cpp +0 -0
  141. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/bytecode_vm.cpp +0 -0
  142. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/colored_body.cpp +0 -0
  143. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/csg_generate.cpp +0 -0
  144. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/css_colors.cpp +0 -0
  145. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/debug/debug_repl.cpp +0 -0
  146. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/debug_profile.cpp +0 -0
  147. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/eval_context.cpp +0 -0
  148. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/eval_error.cpp +0 -0
  149. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/eval_use.cpp +0 -0
  150. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/export.cpp +0 -0
  151. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/expr_eval.cpp +0 -0
  152. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/import/dxf_import.cpp +0 -0
  153. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/import/mesh_import.cpp +0 -0
  154. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/import/surface_load.cpp +0 -0
  155. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/import/svg_import.cpp +0 -0
  156. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/manifold_cache.cpp +0 -0
  157. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/stmt_eval.cpp +0 -0
  158. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/text/stb_font_provider.cpp +0 -0
  159. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/text/text_metrics.cpp +0 -0
  160. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/user_calls.cpp +0 -0
  161. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/value.cpp +0 -0
  162. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/src/zip_stored.cpp +0 -0
  163. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/CMakeLists.txt +0 -0
  164. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_booleans.cpp +0 -0
  165. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_bytecode_compiler.cpp +0 -0
  166. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_cli.cpp +0 -0
  167. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_control_flow.cpp +0 -0
  168. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_csg_tree.cpp +0 -0
  169. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_debug_hooks.cpp +0 -0
  170. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_dxf_svg_import.cpp +0 -0
  171. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_eval_context.cpp +0 -0
  172. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_export.cpp +0 -0
  173. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_expr_eval.cpp +0 -0
  174. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_extrude_roof.cpp +0 -0
  175. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_function_builtins.cpp +0 -0
  176. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_helpers.hpp +0 -0
  177. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_import_export.cpp +0 -0
  178. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_manifold_cache.cpp +0 -0
  179. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_multi_color_merge.cpp +0 -0
  180. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_primitives.cpp +0 -0
  181. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_profiling.cpp +0 -0
  182. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_scoping.cpp +0 -0
  183. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_surface.cpp +0 -0
  184. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_tail_calls.cpp +0 -0
  185. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_text.cpp +0 -0
  186. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_transforms.cpp +0 -0
  187. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_use.cpp +0 -0
  188. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_value.cpp +0 -0
  189. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_viewport_params.cpp +0 -0
  190. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tests/test_zip_stored.cpp +0 -0
  191. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tools/cli/CMakeLists.txt +0 -0
  192. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tools/cli/cli_lib.cpp +0 -0
  193. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.0}/tools/cli/cli_lib.hpp +0 -0
  194. {openscad_cpp_evaluator-0.1.0 → openscad_cpp_evaluator-0.2.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 -c \"import openscad_cpp_evaluator\""
85
+ CIBW_TEST_COMMAND: "python {package}/tests/test_python_bindings.py"
86
86
 
87
87
  - uses: actions/upload-artifact@v7
88
88
  with:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscad_cpp_evaluator
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: C++ OpenSCAD evaluator with Python bindings
5
5
  Author: NeuSCAD Contributors
6
6
  License-Expression: MIT
@@ -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
- // (list[body-dict], list[echo-str], dict[int, span]). Raises the C++ error
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) {
@@ -262,18 +334,28 @@ void callPyErrorBreak(nb::handle errorBreak, int line, const std::string& header
262
334
  errorBreak(line, header, allFrameLocals, callStackToPy(callStack), nb::arg("origin") = origin);
263
335
  }
264
336
 
337
+ // Trampoline: C++ returnHook -> the Python DebugSession return hook. Only
338
+ // fires for user function/function-literal calls (never modules, never
339
+ // builtins -- see DebugHooks::returnHook's own doc comment).
340
+ void callPyReturnHook(nb::handle returnHook, const std::string& name, const oscadeval::Value& result, int depth) {
341
+ returnHook(name, valueToPy(result), depth);
342
+ }
343
+
265
344
  // evaluate() with the debugger wired in. echo is delivered live via echoFn
266
345
  // (not batched), so a paused session can still print. Returns (bodies, [],
267
- // id_to_node). The GIL is released around the C++ evaluate and reacquired
268
- // inside every callback trampoline; the actual pause blocks on the Python
269
- // side (threading.Event) so the GUI thread keeps running.
346
+ // id_to_node, dyn, dyn_explicit). The GIL is released around the C++
347
+ // evaluate and reacquired inside every callback trampoline; the actual pause
348
+ // blocks on the Python side (threading.Event) so the GUI thread keeps running.
270
349
  nb::object debugEvaluate(const std::string& path, nb::dict viewportParams, nb::callable debugHook,
271
- nb::callable errorBreak, nb::callable echoFn) {
350
+ nb::callable errorBreak, nb::callable echoFn,
351
+ std::shared_ptr<oscadeval::ManifoldCache> manifoldCache, nb::object returnHook) {
272
352
  std::unordered_map<std::string, oscadeval::Value> vp = toViewportParams(viewportParams);
273
353
 
274
354
  std::vector<oscadeval::ColoredBody> bodies;
275
355
  std::vector<IdSpan> idSpans;
276
356
  std::exception_ptr err;
357
+ nb::dict dyn;
358
+ nb::object dynExplicit;
277
359
  {
278
360
  nb::gil_scoped_release rel;
279
361
  auto echoCpp = [&echoFn](const std::string& m) {
@@ -292,20 +374,30 @@ nb::object debugEvaluate(const std::string& path, nb::dict viewportParams, nb::c
292
374
  nb::gil_scoped_acquire g;
293
375
  callPyErrorBreak(errorBreak, line, header, origin, cs, gf);
294
376
  };
377
+ if (!returnHook.is_none()) {
378
+ hooks.returnHook = [&](const std::string& name, const oscadeval::Value& result, int depth) {
379
+ nb::gil_scoped_acquire g;
380
+ callPyReturnHook(returnHook, name, result, depth);
381
+ };
382
+ }
295
383
  try {
296
384
  std::vector<std::unique_ptr<oscad::ASTNode>> ast = oscad::getASTFromFile(path);
297
385
  oscadeval::ResolvedUseScopes used = oscadeval::resolveUseScopes(ast, path, echoCpp);
298
- oscadeval::Evaluator ev(echoCpp, nullptr, nullptr, hooks, false);
386
+ oscadeval::Evaluator ev(echoCpp, nullptr, manifoldCache, hooks, false);
299
387
  oscadeval::EvalContext ctx = oscadeval::EvalContext::makeRoot(used.rootScope.get());
300
388
  bodies = oscadeval::toRenderableBodies(ev.evaluate(used.processedNodes, ctx, vp));
301
389
  collectIdSpans(ev, idSpans);
390
+ {
391
+ nb::gil_scoped_acquire g;
392
+ std::tie(dyn, dynExplicit) = dynStateToPy(ctx);
393
+ }
302
394
  } catch (...) {
303
395
  err = std::current_exception();
304
396
  }
305
397
  }
306
398
  if (err) std::rethrow_exception(err); // re-raised with the GIL held -> Python exception
307
399
 
308
- return nb::make_tuple(bodiesToList(bodies), nb::list(), idSpansToDict(idSpans));
400
+ return nb::make_tuple(bodiesToList(bodies), nb::list(), idSpansToDict(idSpans), dyn, dynExplicit);
309
401
  }
310
402
 
311
403
  // Top-level declaration names + source spans, for the editor's completion and
@@ -358,11 +450,21 @@ nb::list parseDecls(const std::string& path) {
358
450
 
359
451
  NB_MODULE(_openscad_cpp_evaluator, m) {
360
452
  m.doc() = "C++ OpenSCAD evaluator (nanobind binding)";
361
- m.def("evaluate", &evaluate, nb::arg("path"), nb::arg("viewport_params"),
362
- "Evaluate a .scad file; return (list of body dicts with raw mesh arrays, list of echo strings).");
453
+
454
+ // Opt-in, shared across evaluate() calls -- see manifold_cache.hpp.
455
+ // Only a constructor and clear() are ever called from Python (get/put
456
+ // are internal to generateTree()'s own C++ implementation).
457
+ nb::class_<oscadeval::ManifoldCache>(m, "ManifoldCache")
458
+ .def(nb::init<>())
459
+ .def("clear", &oscadeval::ManifoldCache::clear);
460
+
461
+ m.def("evaluate", &evaluate, nb::arg("path"), nb::arg("viewport_params"), nb::arg("manifold_cache") = nullptr,
462
+ nb::arg("profile") = false,
463
+ "Evaluate a .scad file; return (bodies, echoes, id_to_node, csg_tree, profile_result, dyn, dyn_explicit).");
363
464
  m.def("parse_decls", &parseDecls, nb::arg("path"),
364
465
  "Parse a .scad file; return top-level declaration (namespace, name, start, end, line, column, origin) tuples.");
365
466
  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
- "Evaluate with the debugger wired in; returns (bodies, [], id_to_node). Callbacks fire under the GIL.");
467
+ nb::arg("error_break"), nb::arg("echo_fn"), nb::arg("manifold_cache") = nullptr,
468
+ nb::arg("return_hook") = nb::none(),
469
+ "Evaluate with the debugger wired in; returns (bodies, [], id_to_node, dyn, dyn_explicit). Callbacks fire under the GIL.");
368
470
  }
@@ -336,6 +336,15 @@ public:
336
336
  // reference's Evaluator.profile_result.
337
337
  std::optional<ProfileResult> profileResult;
338
338
 
339
+ // The resolved (and, after evaluate() runs, generated) CSG tree from the
340
+ // most recent evaluate() call -- moved here from evaluateImpl's local
341
+ // `tree` after generateTree() populates each node's own `bodies`, so a
342
+ // caller can inspect tree shape/params after evaluate() returns (CSG-tree
343
+ // dump, live partial-render). Empty for direct resolveTree()/
344
+ // generateTree() callers that bypass evaluate() -- same scoping as
345
+ // profileResult above. Mirrors the reference's Evaluator.csg_tree.
346
+ std::vector<std::unique_ptr<CSGNode>> csgTree;
347
+
339
348
  private:
340
349
  // Shared body for resolveTree()'s/evaluate()'s two overloads (owning vs.
341
350
  // raw-pointer node list) -- a template rather than duplicating each
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "openscad_cpp_evaluator"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "C++ OpenSCAD evaluator with Python bindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"