openscad-cpp-evaluator 0.13.4__tar.gz → 0.13.7__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.13.4 → openscad_cpp_evaluator-0.13.7}/PKG-INFO +1 -1
  2. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/bytecode.hpp +240 -52
  3. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/bytecode_vm.hpp +37 -0
  4. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/pyproject.toml +1 -1
  5. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/builtins.hpp +17 -0
  6. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/extrude.cpp +51 -13
  7. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/roof.cpp +21 -4
  8. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/bytecode_compiler.cpp +153 -18
  9. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/bytecode_vm.cpp +145 -1
  10. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_bytecode_compiler.cpp +260 -11
  11. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/.github/workflows/ci.yml +0 -0
  12. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/.github/workflows/wheels.yml +0 -0
  13. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/.gitignore +0 -0
  14. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/.gitmodules +0 -0
  15. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/CLAUDE.md +0 -0
  16. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/CMakeLists.txt +0 -0
  17. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/LICENSE +0 -0
  18. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/README.md +0 -0
  19. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/bindings/CMakeLists.txt +0 -0
  20. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/bindings/module.cpp +0 -0
  21. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/cmake/embed_font.cmake +0 -0
  22. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/examples/CMakeLists.txt +0 -0
  23. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/examples/eval_perf_benchmark.cpp +0 -0
  24. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/examples/manifold_cache_reuse.cpp +0 -0
  25. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/examples/minimal_debugger.cpp +0 -0
  26. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
  27. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/.gitignore +0 -0
  28. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/CLAUDE.md +0 -0
  29. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
  30. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/README.md +0 -0
  31. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
  32. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
  33. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
  34. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
  35. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
  36. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
  37. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
  38. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
  39. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
  40. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
  41. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
  42. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
  43. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
  44. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
  45. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
  46. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
  47. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/api.cpp +0 -0
  48. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
  49. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
  50. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
  51. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
  52. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
  53. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
  54. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
  55. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
  56. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/comments.cpp +0 -0
  57. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
  58. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
  59. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
  60. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
  61. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
  62. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
  63. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
  64. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/position.cpp +0 -0
  65. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
  66. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/scope.cpp +0 -0
  67. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
  68. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
  69. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
  70. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
  71. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
  72. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
  73. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
  74. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
  75. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
  76. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
  77. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
  78. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
  79. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
  80. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
  81. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
  82. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
  83. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
  84. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
  85. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
  86. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
  87. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
  88. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
  89. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
  90. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
  91. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
  92. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
  93. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
  94. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
  95. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
  96. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
  97. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
  98. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
  99. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
  100. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
  101. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
  102. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
  103. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
  104. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
  105. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
  106. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/export.hpp +0 -0
  107. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
  108. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
  109. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
  110. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
  111. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
  112. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
  113. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/profile.hpp +0 -0
  114. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
  115. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/segments.hpp +0 -0
  116. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
  117. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
  118. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
  119. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/value.hpp +0 -0
  120. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
  121. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/python/openscad_cpp_evaluator/__init__.py +0 -0
  122. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/resources/fonts/LICENSE +0 -0
  123. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/resources/fonts/LiberationSans-Regular.ttf +0 -0
  124. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/CMakeLists.txt +0 -0
  125. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/booleans.cpp +0 -0
  126. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/call_args.cpp +0 -0
  127. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/color.cpp +0 -0
  128. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/control.cpp +0 -0
  129. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/function_builtins.cpp +0 -0
  130. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/import.cpp +0 -0
  131. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/modifiers.cpp +0 -0
  132. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/primitives_2d.cpp +0 -0
  133. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/primitives_3d.cpp +0 -0
  134. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/registry.cpp +0 -0
  135. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/segments.cpp +0 -0
  136. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/surface.cpp +0 -0
  137. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/text.cpp +0 -0
  138. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/topology.cpp +0 -0
  139. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/builtins/transforms.cpp +0 -0
  140. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/colored_body.cpp +0 -0
  141. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/csg_generate.cpp +0 -0
  142. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/csg_resolve.cpp +0 -0
  143. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/css_colors.cpp +0 -0
  144. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/debug/debug_repl.cpp +0 -0
  145. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/debug_profile.cpp +0 -0
  146. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/eval_context.cpp +0 -0
  147. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/eval_error.cpp +0 -0
  148. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/eval_use.cpp +0 -0
  149. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/export.cpp +0 -0
  150. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/expr_eval.cpp +0 -0
  151. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/import/dxf_import.cpp +0 -0
  152. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/import/mesh_import.cpp +0 -0
  153. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/import/surface_load.cpp +0 -0
  154. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/import/svg_import.cpp +0 -0
  155. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/manifold_cache.cpp +0 -0
  156. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/stmt_eval.cpp +0 -0
  157. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/text/stb_font_provider.cpp +0 -0
  158. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/text/text_metrics.cpp +0 -0
  159. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/user_calls.cpp +0 -0
  160. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/value.cpp +0 -0
  161. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/src/zip_stored.cpp +0 -0
  162. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/CMakeLists.txt +0 -0
  163. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_booleans.cpp +0 -0
  164. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_cli.cpp +0 -0
  165. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_control_flow.cpp +0 -0
  166. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_csg_tree.cpp +0 -0
  167. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_debug_hooks.cpp +0 -0
  168. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_dxf_svg_import.cpp +0 -0
  169. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_eval_context.cpp +0 -0
  170. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_export.cpp +0 -0
  171. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_expr_eval.cpp +0 -0
  172. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_extrude_roof.cpp +0 -0
  173. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_function_builtins.cpp +0 -0
  174. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_helpers.hpp +0 -0
  175. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_import_export.cpp +0 -0
  176. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_manifold_cache.cpp +0 -0
  177. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_multi_color_merge.cpp +0 -0
  178. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_primitives.cpp +0 -0
  179. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_profiling.cpp +0 -0
  180. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_python_bindings.py +0 -0
  181. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_scope_trail.cpp +0 -0
  182. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_scoping.cpp +0 -0
  183. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_surface.cpp +0 -0
  184. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_tail_calls.cpp +0 -0
  185. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_text.cpp +0 -0
  186. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_transforms.cpp +0 -0
  187. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_use.cpp +0 -0
  188. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_value.cpp +0 -0
  189. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_viewport_params.cpp +0 -0
  190. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tests/test_zip_stored.cpp +0 -0
  191. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tools/cli/CMakeLists.txt +0 -0
  192. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tools/cli/cli_lib.cpp +0 -0
  193. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tools/cli/cli_lib.hpp +0 -0
  194. {openscad_cpp_evaluator-0.13.4 → openscad_cpp_evaluator-0.13.7}/tools/cli/main.cpp +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscad_cpp_evaluator
3
- Version: 0.13.4
3
+ Version: 0.13.7
4
4
  Summary: C++ OpenSCAD evaluator with Python bindings
5
5
  Author: NeuSCAD Contributors
6
6
  License-Expression: MIT
@@ -261,7 +261,9 @@ enum class Op {
261
261
  CallModule,
262
262
 
263
263
  // -- Builtin-wrap compilation (closes the "NativeStatement gap" for ----
264
- // -- translate/rotate/scale/mirror/multmatrix/resize/color/#/%/!) ------
264
+ // -- translate/rotate/scale/mirror/multmatrix/resize/color/#/%/!, ------
265
+ // -- hull/minkowski/render/linear_extrude/rotate_extrude/projection/ ---
266
+ // -- offset/roof) --------------------------------------------------------
265
267
  // A builtin-with-children statement that isn't a "call" the way
266
268
  // Op::CallModule's target is (no callStack_/profiling participation,
267
269
  // no named scope with upvalue semantics -- see CompiledChunk::
@@ -284,31 +286,41 @@ enum class Op {
284
286
  // (mirrors Evaluator::buildTreeNode's own ordering exactly -- doing
285
287
  // this AFTER would silently drop uncacheable/ManifoldCache taint
286
288
  // tracking for a rands() call embedded in the wrapper's own
287
- // arguments), computes this site's own params (and, for Transform/
288
- // Color kinds, a possibly-$-scoped child EvalContext, pushed onto
289
- // f.ctxChain unconditionally -- Modifier kind needs neither params
290
- // nor a ctx push), pushes a fresh ev.treeStack_ frame, and stashes
291
- // {params, randsBefore, siteIdx} onto VmFrame::builtinWrapStack (a
292
- // real per-frame LIFO stack, not a single slot: Push/PopBuiltinWrap
293
- // pairs can nest or sequence within one frame's own instruction
294
- // stream, e.g. `translate(a) translate(b) recur();`). The compiler
295
- // always emits a plain Op::CheckDebugStatement immediately before
296
- // this (see emitBuiltinWrap, bytecode_compiler.cpp), mirroring
297
- // ModularEcho/ModularAssert's own pattern -- NOT skipped the way
298
- // Op::CallModule's own call site skips one: this is a genuine
299
- // statement doing real work here, unlike a module call (which
300
- // transfers control to a declaration whose OWN body statements each
301
- // get their own check instead).
289
+ // arguments), computes this site's own params for every kind except
290
+ // Modifier (empty, no ctx push) and Roof (deferred to Pop -- see
291
+ // BuiltinWrapSite's own doc comment) via that kind's own native
292
+ // compute function (computeTransformParams/computeColorParams/etc.,
293
+ // builtins.hpp) -- always a possibly-$-scoped child EvalContext,
294
+ // pushed onto f.ctxChain unconditionally for every non-Modifier kind
295
+ // (Roof pushes it too, params or not) -- pushes a fresh ev.treeStack_
296
+ // frame, and stashes {params, randsBefore, siteIdx, (Roof only)
297
+ // deferredArgs} onto VmFrame::builtinWrapStack (a real per-frame LIFO
298
+ // stack, not a single slot: Push/PopBuiltinWrap pairs can nest or
299
+ // sequence within one frame's own instruction stream, e.g.
300
+ // `translate(a) translate(b) recur();`). The compiler always emits a
301
+ // plain Op::CheckDebugStatement immediately before this (see
302
+ // emitBuiltinWrap, bytecode_compiler.cpp), mirroring ModularEcho/
303
+ // ModularAssert's own pattern -- NOT skipped the way Op::CallModule's
304
+ // own call site skips one: this is a genuine statement doing real
305
+ // work here, unlike a module call (which transfers control to a
306
+ // declaration whose OWN body statements each get their own check
307
+ // instead).
302
308
  PushBuiltinWrap,
303
309
 
304
310
  // Closes the matching Op::PushBuiltinWrap bracket: pops
305
311
  // VmFrame::builtinWrapStack's own top entry FIRST (before anything
306
312
  // that can itself throw, e.g. Evaluator::setTreeDepthOrThrow below --
307
313
  // so the exception-teardown path's own pending count is already
308
- // correct if THIS throws), pops the ctx push Push made (Transform/
309
- // Color kinds only), pops ev.treeStack_ to retrieve the children this
310
- // bracket's own body produced, and builds the tagged CSGNode exactly
311
- // like Evaluator::buildTreeNode's own post-resolveBody() half does
314
+ // correct if THIS throws); for Roof only, computes `pending.params`
315
+ // HERE via computeRoofParams(ev, pending.deferredArgs, ctx) -- the one
316
+ // kind whose params computation has an observable side effect
317
+ // (ev.warn()) that must stay ordered AFTER children, unlike every
318
+ // other kind's params (computed at Push, before children, since
319
+ // nothing else in this group has an order-sensitive side effect); pops
320
+ // the ctx Push made (every kind except Modifier); pops ev.treeStack_
321
+ // to retrieve the children this bracket's own body produced, and
322
+ // builds the tagged CSGNode exactly like Evaluator::buildTreeNode's
323
+ // own post-resolveBody() half does
312
324
  // (kind/node/isBuiltin=true/children/params/uncacheable/
313
325
  // setTreeDepthOrThrow), pushing it onto the new top of treeStack_. a
314
326
  // = index into CompiledChunk::builtinWrapSites (same site Push used).
@@ -325,6 +337,112 @@ enum class Op {
325
337
  // same seam, now a counter).
326
338
  PopBuiltinWrap,
327
339
 
340
+ // -- CSG-wrap compilation (closes the LAST native-reentry source in ----
341
+ // -- the original NativeStatement gap: union()/difference()/ -
342
+ // -- intersection()/intersection_for) -----------------------------------
343
+ // union()/difference()/intersection() weren't covered by the original
344
+ // Op::PushBuiltinWrap (see that op's own doc comment) because they need
345
+ // bespoke bookkeeping PushBuiltinWrap's single all-children bracket
346
+ // doesn't do: Evaluator's own resolveCsg (booleans.cpp) evaluates each
347
+ // TOP-LEVEL child statement of the block SEPARATELY and records how
348
+ // many CSGNodes it individually contributed ("group_sizes") -- e.g.
349
+ // `difference(){ A; B; C; }` = A - (B u C), preserving A's own group
350
+ // even when A itself expands to more than one body (an attachable()-
351
+ // style call returning parent+children as one operand). A flat
352
+ // all-children bracket the way Transform/Color/Modifier use would lose
353
+ // that grouping entirely. This op pair (PushCsgWrap/PopCsgWrap) plus
354
+ // Op::CsgGroupStart/CsgGroupEnd (below) replicate resolveCsg's exact
355
+ // two-pass shape (all assignments first, THEN one evalChildren-per-
356
+ // geometry-statement) as inline compiled bytecode instead, exactly as
357
+ // PushBuiltinWrap already did for translate/rotate/scale/mirror/
358
+ // multmatrix/resize/color/#/%/! -- same rationale (a recursive
359
+ // union()/difference()/intersection()-wrapped module chain was still a
360
+ // real Windows native-reentry depth risk, just never independently
361
+ // fixed when PushBuiltinWrap's own set was).
362
+ //
363
+ // a = index into CompiledChunk::csgWrapSites. Runtime handler: captures
364
+ // ev.randsCallCount() BEFORE argument resolution (same rands-in-args
365
+ // taint reasoning as PushBuiltinWrap); for a `hasArgs` site (union/
366
+ // difference/intersection) resolves the (rare, $-only) arguments via
367
+ // resolveCallArgs exactly like resolveCsg itself does (discarding the
368
+ // positional/named result -- these take no real parameters -- keeping
369
+ // only the possibly-$-scoped child ctx) and pushes that ctx onto
370
+ // f.ctxChain unconditionally (mirrors Transform/Color's own
371
+ // unconditional push -- a bare `union() {...}` with no `$fn=...`
372
+ // override still pushes a ctx that's merely a copy, cheap and uniform
373
+ // rather than a special-cased branch); intersection_for (`hasArgs`
374
+ // false -- it isn't a call, has no `.arguments`) skips both entirely,
375
+ // matching resolveIntersectionFor's own use of its caller's ctx
376
+ // unchanged (its per-ITERATION child ctxs are a completely separate
377
+ // concern, handled by the compiled cartesian loop's own Op::
378
+ // ForIterNext, not by this bracket). Either way: pushes a fresh
379
+ // ev.treeStack_ frame (every child statement's/iteration's own
380
+ // CSGNode(s) land flat in this ONE frame -- mirrors Evaluator::
381
+ // buildTreeNode/evalModularCall's own single treeStack_.emplace_back()
382
+ // around the whole call, not one per group), and stashes {op,
383
+ // randsBefore, siteIdx, empty groupSizes} onto VmFrame::csgWrapStack (a
384
+ // real per-frame LIFO, same reasoning as builtinWrapStack: nested/
385
+ // sequenced CSG wraps within one frame's own instruction stream, e.g.
386
+ // `union() { difference() {...} }`). The compiler always emits a plain
387
+ // Op::CheckDebugStatement immediately before this (see emitCsgWrap/
388
+ // compileIntersectionForLoop, bytecode_compiler.cpp), mirroring
389
+ // emitBuiltinWrap's own pattern -- this is a genuine statement doing
390
+ // real work here, not a call transferring control to a declaration.
391
+ PushCsgWrap,
392
+
393
+ // Opens one "group" within an already-open Op::PushCsgWrap bracket --
394
+ // emitted immediately before each top-level GEOMETRY child statement's
395
+ // own inline-compiled bytecode (compileStatementList of exactly that
396
+ // one statement). Records ev.treeStack_.back().size() into
397
+ // csgWrapStack.back().groupStartSize -- always operates on the
398
+ // TOPMOST (innermost still-open) csgWrapStack entry, matching
399
+ // PopBuiltinWrap's own back()-is-always-mine LIFO discipline, so no
400
+ // operand is needed. Assignments among the block's children are
401
+ // compiled separately, BEFORE any CsgGroupStart/End pair at all (see
402
+ // emitCsgWrap) -- mirrors resolveCsg's own two-pass split exactly
403
+ // (Evaluator::evalChildren(assignNodes, effCtx) always runs to
404
+ // completion before the per-geoNode loop starts).
405
+ CsgGroupStart,
406
+
407
+ // Closes the matching Op::CsgGroupStart: computes
408
+ // ev.treeStack_.back().size() - csgWrapStack.back().groupStartSize
409
+ // (how many CSGNodes THIS one top-level statement just contributed,
410
+ // however many that turned out to be -- 0 for a statement whose own
411
+ // evaluation spliced nothing, e.g. a no-op unknown-module warning; >1
412
+ // for an attachable()-style multi-body operand) and appends it, as a
413
+ // Value, onto csgWrapStack.back().groupSizes -- exactly one entry per
414
+ // top-level geometry statement, in source order, mirroring resolveCsg's
415
+ // own `groupSizes.push_back(Value{...})` loop.
416
+ CsgGroupEnd,
417
+
418
+ // Closes the matching Op::PushCsgWrap bracket: pops
419
+ // VmFrame::csgWrapStack's own top entry FIRST (before anything that can
420
+ // itself throw, e.g. setTreeDepthOrThrow below -- same "exception-
421
+ // teardown's own pending count must already be right" reasoning as
422
+ // PopBuiltinWrap), pops the ctx Push pushed (only when `hasArgs`),
423
+ // pops ev.treeStack_ to retrieve every group's own CSGNode(s) (flat,
424
+ // exactly like resolveCsg's own `children` result -- group boundaries
425
+ // live only in group_sizes, never in the CSGNode list's own shape), and
426
+ // builds the tagged CSGNode exactly like Evaluator::buildTreeNode's own
427
+ // post-resolveBody() half does, with params = {"group_sizes":
428
+ // ValueList(pending.groupSizes)} plus, only when `includeOpParam`,
429
+ // "op": site.op -- byte-for-byte what native resolveCsg returns for
430
+ // union/difference/intersection (generateCsg needs "op" to
431
+ // disambiguate the ONE function it shares across all 3) and what
432
+ // native resolveIntersectionFor returns (no "op" key at all --
433
+ // generateIntersectionFor is its own dedicated, separately-registered
434
+ // function, never needs one) -- pushing the result onto the new top of
435
+ // treeStack_. a = index into CompiledChunk::csgWrapSites (same site
436
+ // Push used).
437
+ //
438
+ // teardownVmCallStackDownTo's own exception path (bytecode_vm.cpp) pops
439
+ // frame->csgWrapStack.size() additional treeStack_ entries per
440
+ // torn-down frame, alongside its existing builtinWrapStack/
441
+ // ownsModuleSplice accounting -- same reasoning as PopBuiltinWrap's own
442
+ // doc comment: an exception can leave N of these brackets open in one
443
+ // frame.
444
+ PopCsgWrap,
445
+
328
446
  // A `children()` / `children(N)` statement -- the runtime-varying
329
447
  // sibling of Op::CallModule/Op::PushBuiltinWrap, closing the LAST
330
448
  // dominant native-reentry source (BOSL2's attachable() calls
@@ -367,38 +485,58 @@ enum class Op {
367
485
  // no separate site table needed).
368
486
  CallChildren,
369
487
 
370
- // A single "native passthrough" statement -- intersection_for,
371
- // union/difference/intersection and every other builtin
372
- // module call NOT covered by Op::PushBuiltinWrap (see that op's own
373
- // doc comment for exactly which builtins ARE covered), the `*`
374
- // modifier's own no-op case, or a user-module call that didn't
375
- // resolve at compile time (shadowed, forward-declared, or otherwise
376
- // not statically known) -- anything compileStatementList doesn't give
377
- // its own real bytecode. (Assignment/ModularEcho/ModularAssert/
378
- // ModularLet used to fall here too; they now have their own real
379
- // bytecode -- Op::StoreModuleVar/Op::Echo/Op::AssertStatement/
380
- // Op::OpenLetScope+StoreLetVar -- purely a throughput change, since
381
- // none of these were ever the recursion-depth risk this compiler
382
- // targets. `#`/`%`/`!` modifiers and translate/rotate/scale/mirror/
383
- // multmatrix/resize/color used to fall here too, for the SAME
384
- // throughput reasoning -- WRONG in that one specific case: a
385
- // recursive module call wrapped in one of these is exactly the
386
- // pattern that made this op's own native reentry a genuine Windows
387
- // crash risk in practice, not just a missed optimization. See
388
- // Op::PushBuiltinWrap's own doc comment for the real story and the
389
- // fix. children() fell here too, and was the LAST and largest such
390
- // reentry source once PushBuiltinWrap's own set was covered -- it
391
- // now has Op::CallChildren, above.)
488
+ // A single "native passthrough" statement -- every builtin module call
489
+ // not covered by Op::PushBuiltinWrap/Op::PushCsgWrap (see those ops'
490
+ // own doc comments for exactly which builtins ARE covered -- cube/
491
+ // sphere/import/text/surface/etc., the true LEAVES that never take a
492
+ // `children` block at all, so wrapping a recursive call inside one
493
+ // isn't even syntactically possible), the `*` modifier's own no-op
494
+ // case, or a user-module call that didn't resolve at compile time
495
+ // (shadowed, forward-declared, or otherwise not statically known) --
496
+ // anything compileStatementList doesn't give its own real bytecode.
497
+ // (Assignment/ModularEcho/ModularAssert/ModularLet used to fall here
498
+ // too; they now have their own real bytecode -- Op::StoreModuleVar/
499
+ // Op::Echo/Op::AssertStatement/Op::OpenLetScope+StoreLetVar -- purely
500
+ // a throughput change, since none of these were ever the recursion-
501
+ // depth risk this compiler targets. `#`/`%`/`!` modifiers and
502
+ // translate/rotate/scale/mirror/multmatrix/resize/color used to fall
503
+ // here too, for the SAME throughput reasoning -- WRONG in that one
504
+ // specific case: a recursive module call wrapped in one of these is
505
+ // exactly the pattern that made this op's own native reentry a
506
+ // genuine Windows crash risk in practice, not just a missed
507
+ // optimization. See Op::PushBuiltinWrap's own doc comment for the
508
+ // real story and the fix. children() fell here too, and was the LAST
509
+ // and largest such reentry source once PushBuiltinWrap's own set was
510
+ // covered -- it now has Op::CallChildren, above. union()/difference()/
511
+ // intersection() fell here too, and were the last remaining REAL
512
+ // native-reentry risk among ModularCall-shaped statements (bespoke
513
+ // group_sizes bookkeeping meant they couldn't just reuse
514
+ // PushBuiltinWrap's own bracket) -- they now have Op::PushCsgWrap,
515
+ // above. hull()/minkowski()/render()/linear_extrude()/rotate_extrude()/
516
+ // projection()/offset()/roof() fell here too, closing out every
517
+ // remaining non-leaf builtin whose OWN children can wrap a recursive
518
+ // call in an idiomatic script (a rounded-hull chain, a recursive
519
+ // extrude, etc.) -- they now share Op::PushBuiltinWrap's own bracket
520
+ // via 6 new Kind values (Passthrough/LinearExtrude/RotateExtrude/
521
+ // Projection/Offset/Roof), reusing the exact same mechanism rather
522
+ // than inventing another. intersection_for -- NOT a ModularCall at
523
+ // all, its own NodeKind -- fell here too and was the true LAST
524
+ // native-reentry gap; it now shares Op::PushCsgWrap's own bracket
525
+ // (CsgWrapSite::hasArgs/includeOpParam both false for it) wrapped
526
+ // around a compiled cartesian-product loop reusing Op::ForIterNext/
527
+ // ForIterEnd/NativeIterMaterialize verbatim (see
528
+ // compileIntersectionForLoop, bytecode_compiler.cpp) -- one Op::
529
+ // CsgGroupStart/CsgGroupEnd pair per full iteration instead of per
530
+ // source statement. Every non-leaf builtin construct is covered now.)
392
531
  // a = index into CompiledChunk::nativeStatements. Runtime just does
393
532
  // what Evaluator::evalChildren's own per-statement loop already does
394
533
  // for one node: derive childCtx via ctx.withScope(...), checkDebug,
395
534
  // evalStatement. These are still "leaf-shaped" for what's left here
396
- // after Op::PushBuiltinWrap peeled off the proven-risky subset: real
397
- // recursion safety for a recursive module chain is covered by
398
- // CallModule/PushBuiltinWrap/ForIterNext/the Jump-based if/for control
399
- // flow, not by how many of THESE sit alongside them in the same body
400
- // -- true again now that the one construct that violated it
401
- // (translate()-wrapped recursion) has its own real bytecode instead.
535
+ // now that Op::PushBuiltinWrap/Op::PushCsgWrap have peeled off every
536
+ // proven-risky construct: real recursion safety for a recursive module
537
+ // chain is covered by CallModule/PushBuiltinWrap/PushCsgWrap/
538
+ // ForIterNext/the Jump-based if/for control flow, not by how many of
539
+ // THESE sit alongside them in the same body.
402
540
  NativeStatement,
403
541
 
404
542
  // If/if-else's own condition, evaluated NATIVELY (Evaluator::
@@ -714,8 +852,8 @@ struct CompiledChunk {
714
852
  // replay the native param-resolution step and rebuild the tagged
715
853
  // CSGNode at Pop time.
716
854
  //
717
- // `node`'s concrete type depends on `kind`: Transform/Color sites are
718
- // genuine `ModularCall`s (down-cast to read `.name`/`.arguments`/
855
+ // `node`'s concrete type depends on `kind`: every kind except Modifier
856
+ // is a genuine `ModularCall` (down-cast to read `.name`/`.arguments`/
719
857
  // `.children`); Modifier sites are the wrapper node itself
720
858
  // (`ModularModifierHighlight`/`Background`/`ShowOnly` -- `!`/`#`/`%`;
721
859
  // `*`/Disable never reaches here, its child never evaluates at all,
@@ -727,10 +865,59 @@ struct CompiledChunk {
727
865
  // union of concrete pointers) because that's all Op::PopBuiltinWrap
728
866
  // itself ever needs `node` for: the resulting CSGNode's own
729
867
  // `node`/error-position field.
868
+ //
869
+ // Passthrough/LinearExtrude/RotateExtrude/Projection/Offset/Roof
870
+ // (added for hull()/minkowski()/render()/linear_extrude()/
871
+ // rotate_extrude()/projection()/offset()/roof()) share Transform/
872
+ // Color's exact push-time-computed-params shape, just via a different
873
+ // native compute function each (Op::PushBuiltinWrap's own runtime
874
+ // handler switches on `kind` to pick it) -- see that op's own doc
875
+ // comment for the one exception (Roof, whose params computation has
876
+ // to run at POP time instead, after children, to preserve an
877
+ // observable warn() ordering).
730
878
  struct BuiltinWrapSite {
731
- enum class Kind { Transform, Color, Modifier };
879
+ enum class Kind {
880
+ Transform,
881
+ Color,
882
+ Modifier,
883
+ Passthrough, // hull()/minkowski()/render() -- empty params, no compute function needed
884
+ LinearExtrude,
885
+ RotateExtrude,
886
+ Projection,
887
+ Offset,
888
+ Roof, // computed at POP time, not PUSH -- see this struct's own doc comment
889
+ };
732
890
  Kind kind;
733
- std::string tagName; // "translate"/"rotate"/.../"color"/"highlight"/"background"/"show_only"
891
+ std::string tagName; // "translate"/"rotate"/.../"color"/"highlight"/"background"/"show_only"/"hull"/...
892
+ const oscad::ASTNode* node = nullptr;
893
+ };
894
+
895
+ // One Op::PushCsgWrap/PopCsgWrap site pair -- see those ops' own doc
896
+ // comments for the full "why union/difference/intersection need
897
+ // bespoke group_sizes bookkeeping instead of just reusing
898
+ // BuiltinWrapSite" rationale. `op` is "union"/"difference"/
899
+ // "intersection" (the 3 names resolveDispatch() maps to resolveCsg,
900
+ // always a genuine ModularCall) OR "intersection_for" (NOT a
901
+ // ModularCall -- a distinct NodeKind/ModuleInstantiation subtype with
902
+ // its own `.assignments`/`.body`, see compileIntersectionForLoop,
903
+ // bytecode_compiler.cpp) -- `node` is therefore the generic ASTNode*
904
+ // BuiltinWrapSite's own Modifier kind already established this pattern
905
+ // for, down-cast to ModularCall only when `hasArgs` is true.
906
+ //
907
+ // `hasArgs`/`includeOpParam` are both true for union/difference/
908
+ // intersection, both false for intersection_for: it isn't a call at
909
+ // all (no `.arguments`, so Op::PushCsgWrap's handler must skip
910
+ // resolveCallArgs/the ctx push entirely -- matches native
911
+ // resolveIntersectionFor, which uses the SAME ctx its caller passed in
912
+ // unchanged, never a $-scoped child of its own), and its own
913
+ // CSGParams has no "op" key at all (generateIntersectionFor is a
914
+ // dedicated, separately-registered generate function, unlike
915
+ // generateCsg which needs "op" in params to disambiguate union/
916
+ // difference/intersection from ONE shared function).
917
+ struct CsgWrapSite {
918
+ std::string op;
919
+ bool hasArgs = true;
920
+ bool includeOpParam = true;
734
921
  const oscad::ASTNode* node = nullptr;
735
922
  };
736
923
 
@@ -796,6 +983,7 @@ struct CompiledChunk {
796
983
  // own doc comments, above) -- always empty for a function chunk.
797
984
  std::vector<ModuleCallSite> moduleCallSites;
798
985
  std::vector<BuiltinWrapSite> builtinWrapSites;
986
+ std::vector<CsgWrapSite> csgWrapSites;
799
987
  std::vector<AssertSite> assertSites;
800
988
  std::vector<const oscad::Expression*> nativeExprs;
801
989
  std::vector<const oscad::ASTNode*> nativeStatements;
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "openscad_cpp_evaluator/bound_args.hpp"
4
4
  #include "openscad_cpp_evaluator/bytecode.hpp"
5
+ #include "openscad_cpp_evaluator/call_args.hpp"
5
6
  #include "openscad_cpp_evaluator/csg_node.hpp"
6
7
  #include "openscad_cpp_evaluator/eval_context.hpp"
7
8
  #include "openscad_cpp_evaluator/value.hpp"
@@ -28,6 +29,33 @@ struct PendingBuiltinWrap {
28
29
  CSGParams params;
29
30
  std::uint64_t randsBefore = 0;
30
31
  int siteIdx = -1;
32
+ // Only populated for BuiltinWrapSite::Kind::Roof -- the already-
33
+ // resolved call arguments, retained across the whole bracket so
34
+ // Op::PopBuiltinWrap's handler can compute roof()'s own params AFTER
35
+ // children finish (computeRoofParams needs them; re-running
36
+ // resolveCallArgs at Pop time instead would re-evaluate every argument
37
+ // expression a second time -- double rands()/side effects). Every
38
+ // other kind computes its params at Push time and leaves this default-
39
+ // empty.
40
+ CallArgs deferredArgs;
41
+ };
42
+
43
+ // One still-open Op::PushCsgWrap bracket's own state -- see that op's own
44
+ // doc comment (bytecode.hpp) for the full contract. `groupSizes` is built
45
+ // up incrementally, one entry per Op::CsgGroupStart/CsgGroupEnd pair (one
46
+ // per top-level GEOMETRY child statement); `groupStartSize` is scratch
47
+ // space for the CURRENTLY OPEN group only (set by CsgGroupStart, consumed
48
+ // by the matching CsgGroupEnd) -- safe as a single scalar, not a stack of
49
+ // its own, because groups within one CSG wrap are siblings in sequence,
50
+ // never nested (unlike PushCsgWrap brackets themselves, which CAN nest,
51
+ // e.g. `union() { difference() {...} }` -- that's what makes
52
+ // VmFrame::csgWrapStack itself a real LIFO, below).
53
+ struct PendingCsgWrap {
54
+ std::string op;
55
+ std::uint64_t randsBefore = 0;
56
+ int siteIdx = -1;
57
+ std::vector<Value> groupSizes;
58
+ size_t groupStartSize = 0;
31
59
  };
32
60
 
33
61
  // One ListCompFor/statement-for assignment's own materialized iteration
@@ -127,6 +155,15 @@ struct VmFrame {
127
155
  // existing invariant ("whoever pops this frame drains its own open
128
156
  // brackets first") already covers it.
129
157
  std::vector<PendingBuiltinWrap> builtinWrapStack;
158
+ // Op::PushCsgWrap's own per-frame LIFO -- same role/lifetime/teardown
159
+ // discipline as builtinWrapStack, just for union()/difference()/
160
+ // intersection() (see PendingCsgWrap's own doc comment, above, and
161
+ // Op::PushCsgWrap's, bytecode.hpp). Not explicitly cleared in
162
+ // releaseVmFrame, same as builtinWrapStack/accumStack/ctxChain -- the
163
+ // existing invariant ("whoever pops this frame drains its own open
164
+ // brackets first", normally via matched Push/Pop, or via
165
+ // teardownVmCallStackDownTo on the exception path) already covers it.
166
+ std::vector<PendingCsgWrap> csgWrapStack;
130
167
  // The ORIGINAL callee name at push time, used by
131
168
  // Evaluator::exitUserCallSuccess's own returnHook call when this frame
132
169
  // carries a bracket -- deliberately NOT updated by a later tail hop
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "openscad_cpp_evaluator"
7
- version = "0.13.4"
7
+ version = "0.13.7"
8
8
  description = "C++ OpenSCAD evaluator with Python bindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include "openscad_cpp_evaluator/call_args.hpp"
3
4
  #include "openscad_cpp_evaluator/dispatch.hpp"
4
5
 
5
6
  #include <optional>
@@ -153,21 +154,30 @@ std::vector<ColoredBody> generateMinkowski(Evaluator& ev, const CSGParams& param
153
154
  const oscad::ASTNode& node);
154
155
 
155
156
  // linear_extrude()/rotate_extrude()/projection() -- extrude.cpp.
157
+ // computeXParams: the pure "resolve args, build params" half, split out
158
+ // like computeTransformParams/computeColorParams so Op::PushBuiltinWrap's
159
+ // own runtime handler can call it directly (bytecode_vm.cpp) instead of
160
+ // through the whole resolve function, whose OTHER half (evalChildren) is
161
+ // exactly the native reentry that split exists to avoid.
162
+ BuiltinWrapParams computeLinearExtrudeParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
156
163
  CSGParams resolveLinearExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
157
164
  std::vector<ColoredBody> generateLinearExtrude(Evaluator& ev, const CSGParams& params,
158
165
  const std::vector<std::unique_ptr<CSGNode>>& children,
159
166
  const oscad::ASTNode& node);
160
167
 
168
+ BuiltinWrapParams computeRotateExtrudeParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
161
169
  CSGParams resolveRotateExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
162
170
  std::vector<ColoredBody> generateRotateExtrude(Evaluator& ev, const CSGParams& params,
163
171
  const std::vector<std::unique_ptr<CSGNode>>& children,
164
172
  const oscad::ASTNode& node);
165
173
 
174
+ BuiltinWrapParams computeProjectionParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
166
175
  CSGParams resolveProjection(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
167
176
  std::vector<ColoredBody> generateProjection(Evaluator& ev, const CSGParams& params,
168
177
  const std::vector<std::unique_ptr<CSGNode>>& children,
169
178
  const oscad::ASTNode& node);
170
179
 
180
+ BuiltinWrapParams computeOffsetParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
171
181
  CSGParams resolveOffset(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
172
182
  std::vector<ColoredBody> generateOffset(Evaluator& ev, const CSGParams& params,
173
183
  const std::vector<std::unique_ptr<CSGNode>>& children, const oscad::ASTNode& node);
@@ -176,6 +186,13 @@ std::vector<ColoredBody> generateOffset(Evaluator& ev, const CSGParams& params,
176
186
  // contour polygons) + Tier 3 (SDF/level-set fallback) only, per the plan --
177
187
  // Tier 2 (general multi-contour/hole straight skeleton) is a named,
178
188
  // documented follow-up, not silently dropped (see CLAUDE.md).
189
+ // computeRoofParams: UNLIKE computeLinearExtrudeParams and friends above,
190
+ // this is the params-computation half taken from AFTER evalChildren (it
191
+ // calls ev.warn(), an observable side effect that must stay ordered after
192
+ // any child's own echo/warn output) -- takes already-resolved CallArgs,
193
+ // not a raw node+ctx, since Op::PushBuiltinWrap's own runtime handler
194
+ // calls this at POP time. See its own doc comment (roof.cpp).
195
+ CSGParams computeRoofParams(Evaluator& ev, const CallArgs& args, EvalContext& effCtx);
179
196
  CSGParams resolveRoof(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
180
197
  std::vector<ColoredBody> generateRoof(Evaluator& ev, const CSGParams& params,
181
198
  const std::vector<std::unique_ptr<CSGNode>>& children, const oscad::ASTNode& node);
@@ -13,10 +13,21 @@ namespace oscadeval {
13
13
  // mirrors _resolve_linear_extrude/_generate_linear_extrude. `scale` is
14
14
  // either a single number (applied to both X/Y) or a [x,y] pair for the top
15
15
  // face; the bottom face is always full-size.
16
-
17
- CSGParams resolveLinearExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
16
+ //
17
+ // Split into computeLinearExtrudeParams (pure, no children-evaluation side
18
+ // effect) + resolveLinearExtrude (adds the evalChildren call) so Op::
19
+ // PushBuiltinWrap's own runtime handler (bytecode_vm.cpp) can call the pure
20
+ // half directly instead of going through the whole resolve function --
21
+ // exactly the same split computeTransformParams/computeColorParams already
22
+ // use, extended to this builtin. Params computation here has no observable
23
+ // side effect of its own (no warn()/echo()/rands() call), so moving it
24
+ // before evalChildren (unlike this function's own former single-body
25
+ // shape, which computed params AFTER children like every other builtin
26
+ // still not covered by PushBuiltinWrap) is behaviorally unobservable --
27
+ // see computeRoofParams's own doc comment (roof.cpp) for the one builtin
28
+ // in this group where that ISN'T true and a different split was needed.
29
+ BuiltinWrapParams computeLinearExtrudeParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
18
30
  auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
19
- ev.evalChildren(node.children, effCtx);
20
31
 
21
32
  const double height = toDoubleLenient(getArg(args, 0, "height", Value{1.0}));
22
33
  const bool center = truthy(getArg(args, std::nullopt, "center", Value{false}));
@@ -40,7 +51,13 @@ CSGParams resolveLinearExtrude(Evaluator& ev, const oscad::ModularCall& node, Ev
40
51
  params["scale_x"] = Value{scaleX};
41
52
  params["scale_y"] = Value{scaleY};
42
53
  params["color"] = colorToValue(effCtx.color);
43
- return params;
54
+ return BuiltinWrapParams{std::move(params), std::move(effCtx)};
55
+ }
56
+
57
+ CSGParams resolveLinearExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
58
+ BuiltinWrapParams result = computeLinearExtrudeParams(ev, node, ctx);
59
+ ev.evalChildren(node.children, result.ctx);
60
+ return std::move(result.params);
44
61
  }
45
62
 
46
63
  std::vector<ColoredBody> generateLinearExtrude(Evaluator& ev, const CSGParams& params,
@@ -65,9 +82,10 @@ std::vector<ColoredBody> generateLinearExtrude(Evaluator& ev, const CSGParams& p
65
82
  // so resolve only caches $fn/$fa/$fs for generate to call fnSegments()
66
83
  // with once the real max-x bound exists.
67
84
 
68
- CSGParams resolveRotateExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
85
+ // Split the same way as computeLinearExtrudeParams, above -- see its own
86
+ // doc comment.
87
+ BuiltinWrapParams computeRotateExtrudeParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
69
88
  auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
70
- ev.evalChildren(node.children, effCtx);
71
89
 
72
90
  const double angle = toDoubleLenient(getArg(args, 0, "angle", Value{360.0}));
73
91
 
@@ -84,7 +102,13 @@ CSGParams resolveRotateExtrude(Evaluator& ev, const oscad::ModularCall& node, Ev
84
102
  params["fa"] = Value{dynOr("$fa", 12.0)};
85
103
  params["fs"] = Value{dynOr("$fs", 2.0)};
86
104
  params["color"] = colorToValue(effCtx.color);
87
- return params;
105
+ return BuiltinWrapParams{std::move(params), std::move(effCtx)};
106
+ }
107
+
108
+ CSGParams resolveRotateExtrude(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
109
+ BuiltinWrapParams result = computeRotateExtrudeParams(ev, node, ctx);
110
+ ev.evalChildren(node.children, result.ctx);
111
+ return std::move(result.params);
88
112
  }
89
113
 
90
114
  std::vector<ColoredBody> generateRotateExtrude(Evaluator& ev, const CSGParams& params,
@@ -108,12 +132,19 @@ std::vector<ColoredBody> generateRotateExtrude(Evaluator& ev, const CSGParams& p
108
132
  // FillRule::Positive to clean up self-intersections Manifold's own
109
133
  // Project() can produce.
110
134
 
111
- CSGParams resolveProjection(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
135
+ // Split the same way as computeLinearExtrudeParams, above -- see its own
136
+ // doc comment.
137
+ BuiltinWrapParams computeProjectionParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
112
138
  auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
113
- ev.evalChildren(node.children, effCtx);
114
139
  CSGParams params;
115
140
  params["cut"] = Value{truthy(getArg(args, std::nullopt, "cut", Value{false}))};
116
- return params;
141
+ return BuiltinWrapParams{std::move(params), std::move(effCtx)};
142
+ }
143
+
144
+ CSGParams resolveProjection(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
145
+ BuiltinWrapParams result = computeProjectionParams(ev, node, ctx);
146
+ ev.evalChildren(node.children, result.ctx);
147
+ return std::move(result.params);
117
148
  }
118
149
 
119
150
  std::vector<ColoredBody> generateProjection(Evaluator&, const CSGParams& params,
@@ -145,9 +176,10 @@ std::vector<ColoredBody> generateProjection(Evaluator&, const CSGParams& params,
145
176
  // (JoinType::Square, or Miter if chamfer=true) are mutually exclusive;
146
177
  // neither given passes the first child through unchanged.
147
178
 
148
- CSGParams resolveOffset(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
179
+ // Split the same way as computeLinearExtrudeParams, above -- see its own
180
+ // doc comment.
181
+ BuiltinWrapParams computeOffsetParams(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
149
182
  auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
150
- ev.evalChildren(node.children, effCtx);
151
183
 
152
184
  const Value rArg = getArg(args, std::nullopt, "r", Value{});
153
185
  const Value deltaArg = getArg(args, std::nullopt, "delta", Value{});
@@ -161,7 +193,13 @@ CSGParams resolveOffset(Evaluator& ev, const oscad::ModularCall& node, EvalConte
161
193
  params["segs"] = Value{static_cast<double>(fnSegmentsFromCtx(effCtx, std::fabs(toDoubleLenient(rArg))))};
162
194
  }
163
195
  params["color"] = colorToValue(effCtx.color);
164
- return params;
196
+ return BuiltinWrapParams{std::move(params), std::move(effCtx)};
197
+ }
198
+
199
+ CSGParams resolveOffset(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
200
+ BuiltinWrapParams result = computeOffsetParams(ev, node, ctx);
201
+ ev.evalChildren(node.children, result.ctx);
202
+ return std::move(result.params);
165
203
  }
166
204
 
167
205
  std::vector<ColoredBody> generateOffset(Evaluator&, const CSGParams& params, const std::vector<std::unique_ptr<CSGNode>>& children,