openscad-cpp-evaluator 1.35.0__tar.gz → 1.36.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 (228) hide show
  1. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/CLAUDE.md +8 -1
  2. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/CMakeLists.txt +3 -0
  3. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/PKG-INFO +1 -1
  4. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/bindings/module.cpp +1 -1
  5. openscad_cpp_evaluator-1.36.0/cmake/patch_manifold.cmake +31 -0
  6. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +1 -1
  7. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/value.hpp +41 -15
  8. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/pyproject.toml +1 -1
  9. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/booleans.cpp +2 -2
  10. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/call_args.cpp +2 -2
  11. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/control.cpp +1 -1
  12. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/dxf_dim.cpp +1 -1
  13. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/function_builtins.cpp +1 -1
  14. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/import.cpp +11 -12
  15. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/primitives_2d.cpp +4 -4
  16. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/primitives_3d.cpp +7 -7
  17. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/surface.cpp +2 -2
  18. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/text.cpp +2 -3
  19. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/bytecode_vm.cpp +9 -10
  20. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/colored_body.cpp +1 -1
  21. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/eval_context.cpp +2 -2
  22. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/expr_eval.cpp +15 -4
  23. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/measure_geometry.cpp +1 -1
  24. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/value.cpp +62 -21
  25. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_control_flow.cpp +91 -24
  26. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_expr_eval.cpp +26 -13
  27. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_value.cpp +34 -19
  28. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_viewport_params.cpp +2 -2
  29. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/uv.lock +1 -1
  30. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/.github/workflows/ci.yml +0 -0
  31. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/.github/workflows/wheels.yml +0 -0
  32. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/.gitignore +0 -0
  33. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/.gitmodules +0 -0
  34. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/LICENSE +0 -0
  35. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/README.md +0 -0
  36. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/bindings/CMakeLists.txt +0 -0
  37. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/bindings/ast_to_py.cpp +0 -0
  38. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/cmake/embed_font.cmake +0 -0
  39. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/examples/CMakeLists.txt +0 -0
  40. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/examples/eval_perf_benchmark.cpp +0 -0
  41. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/examples/manifold_cache_reuse.cpp +0 -0
  42. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/examples/minimal_debugger.cpp +0 -0
  43. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
  44. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/.gitignore +0 -0
  45. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
  46. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
  47. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/README.md +0 -0
  48. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
  49. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
  50. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
  51. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
  52. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
  53. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
  54. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
  55. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
  56. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
  57. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
  58. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
  59. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
  60. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
  61. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
  62. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
  63. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
  64. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/.DS_Store +0 -0
  65. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
  66. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
  67. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
  68. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
  69. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
  70. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
  71. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
  72. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
  73. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
  74. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
  75. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
  76. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
  77. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
  78. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
  79. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
  80. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
  81. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
  82. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
  83. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
  84. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
  85. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
  86. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
  87. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
  88. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
  89. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
  90. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
  91. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
  92. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
  93. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
  94. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
  95. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
  96. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
  97. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
  98. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
  99. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
  100. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
  101. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
  102. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
  103. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
  104. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
  105. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
  106. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
  107. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
  108. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
  109. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
  110. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
  111. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
  112. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
  113. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
  114. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
  115. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
  116. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
  117. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
  118. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
  119. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
  120. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
  121. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
  122. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
  123. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
  124. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
  125. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
  126. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
  127. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
  128. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
  129. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
  130. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
  131. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
  132. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
  133. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
  134. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
  135. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
  136. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
  137. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
  138. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
  139. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
  140. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
  141. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
  142. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
  143. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
  144. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
  145. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
  146. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
  147. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
  148. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
  149. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/resources/fonts/LICENSE +0 -0
  150. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
  151. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
  152. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
  153. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
  154. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/CMakeLists.txt +0 -0
  155. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/builtins.hpp +0 -0
  156. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/color.cpp +0 -0
  157. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/extrude.cpp +0 -0
  158. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/modifiers.cpp +0 -0
  159. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/registry.cpp +0 -0
  160. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/roof.cpp +0 -0
  161. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/segments.cpp +0 -0
  162. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/topology.cpp +0 -0
  163. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/builtins/transforms.cpp +0 -0
  164. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/bytecode_compiler.cpp +0 -0
  165. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/coverage.cpp +0 -0
  166. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/csg_generate.cpp +0 -0
  167. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/csg_resolve.cpp +0 -0
  168. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/css_colors.cpp +0 -0
  169. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/debug/debug_repl.cpp +0 -0
  170. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/debug_profile.cpp +0 -0
  171. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/eval_error.cpp +0 -0
  172. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/eval_use.cpp +0 -0
  173. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/export.cpp +0 -0
  174. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/format_closure.cpp +0 -0
  175. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/import/dxf_import.cpp +0 -0
  176. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/import/mesh_import.cpp +0 -0
  177. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/import/scene_import.cpp +0 -0
  178. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/import/surface_load.cpp +0 -0
  179. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/import/svg_import.cpp +0 -0
  180. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/manifold_cache.cpp +0 -0
  181. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/mesh_check.cpp +0 -0
  182. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/stmt_eval.cpp +0 -0
  183. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/text/font_match.cpp +0 -0
  184. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/text/freetype_font_provider.cpp +0 -0
  185. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/text/text_metrics.cpp +0 -0
  186. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/user_calls.cpp +0 -0
  187. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/utf8.cpp +0 -0
  188. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/xkcd_colors.cpp +0 -0
  189. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/xkcd_colors.hpp +0 -0
  190. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/src/zip_stored.cpp +0 -0
  191. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/CMakeLists.txt +0 -0
  192. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_booleans.cpp +0 -0
  193. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_bytecode_compiler.cpp +0 -0
  194. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_children_separate.cpp +0 -0
  195. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_cli.cpp +0 -0
  196. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_coverage.cpp +0 -0
  197. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_csg_tree.cpp +0 -0
  198. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_debug_hooks.cpp +0 -0
  199. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_discretizer.cpp +0 -0
  200. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_dxf_svg_import.cpp +0 -0
  201. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_eval_context.cpp +0 -0
  202. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_export.cpp +0 -0
  203. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_extrude_roof.cpp +0 -0
  204. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_feature_detection.cpp +0 -0
  205. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_function_builtins.cpp +0 -0
  206. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_helpers.hpp +0 -0
  207. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_import_export.cpp +0 -0
  208. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_include_cache.cpp +0 -0
  209. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_manifold_cache.cpp +0 -0
  210. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_mesh_check.cpp +0 -0
  211. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_multi_color_merge.cpp +0 -0
  212. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_primitives.cpp +0 -0
  213. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_profiling.cpp +0 -0
  214. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_python_bindings.py +0 -0
  215. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_render_expr.cpp +0 -0
  216. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_scope_trail.cpp +0 -0
  217. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_scoping.cpp +0 -0
  218. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_surface.cpp +0 -0
  219. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_tail_calls.cpp +0 -0
  220. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_text.cpp +0 -0
  221. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_transforms.cpp +0 -0
  222. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_unexpected_args.cpp +0 -0
  223. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_use.cpp +0 -0
  224. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tests/test_zip_stored.cpp +0 -0
  225. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tools/cli/CMakeLists.txt +0 -0
  226. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tools/cli/cli_lib.cpp +0 -0
  227. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tools/cli/cli_lib.hpp +0 -0
  228. {openscad_cpp_evaluator-1.35.0 → openscad_cpp_evaluator-1.36.0}/tools/cli/main.cpp +0 -0
@@ -9,7 +9,14 @@ OpenSCAD AST and produces Manifold CSG geometry. This port builds on two depende
9
9
 
10
10
  - `openscad_cpp_parser` (git submodule, `external/openscad_cpp_parser`) for lexing/parsing/AST/scope
11
11
  - Manifold (https://github.com/elalish/manifold) v3.5.2, pulled in via CMake `FetchContent` (pinned
12
- tag, not vendored) — wired in as of Phase 2
12
+ tag, not vendored) — wired in as of Phase 2. **Patched at fetch time** by
13
+ `cmake/patch_manifold.cmake`: it deletes the `combined.RemoveDegenerates()` call in
14
+ `CsgLeafNode::Compose`, which on some inputs leaves the face data inconsistent so the sort after
15
+ it reads past an array (heap-buffer-overflow under ASan, reached by
16
+ `MinkowskiDifference.ShrinksANonConvexBodyOnEverySide`). Bisected with a Manifold-only repro to
17
+ upstream #1789 (969b1417), which fixes it by deleting the same call; unreleased as of 3.5.4.
18
+ The script fails the configure if the source around the call has changed, so **drop the patch
19
+ when bumping past #1789** rather than letting it rot
13
20
  - Boost.Polygon (`boostorg/polygon` + `boostorg/config`, fetched individually — not the full Boost
14
21
  superproject) for `roof()`'s Voronoi-diagram construction — wired in as of Phase 6, see below
15
22
  - `nothings/stb` (`stb_image.h`; header-only, no build step) for `surface()`'s PNG loader — wired
@@ -137,6 +137,9 @@ FetchContent_Declare(
137
137
  GIT_REPOSITORY https://github.com/elalish/manifold.git
138
138
  GIT_TAG v3.5.2
139
139
  GIT_SHALLOW TRUE
140
+ # Backports the one line of upstream #1789 that fixes a heap overflow in
141
+ # CsgLeafNode::Compose -- see cmake/patch_manifold.cmake.
142
+ PATCH_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch_manifold.cmake
140
143
  )
141
144
  FetchContent_MakeAvailable(manifold)
142
145
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscad_cpp_evaluator
3
- Version: 1.35.0
3
+ Version: 1.36.0
4
4
  Summary: C++ OpenSCAD evaluator with Python bindings
5
5
  Author: NeuSCAD Contributors
6
6
  License-Expression: MIT
@@ -76,7 +76,7 @@ oscadeval::Value pyToValue(nb::handle v) {
76
76
  std::vector<oscadeval::Value> items;
77
77
  for (nb::handle item : nb::borrow<nb::sequence>(v)) items.push_back(pyToValue(item));
78
78
  return oscadeval::Value{oscadeval::ListPtr(
79
- std::make_shared<const oscadeval::ValueList>(oscadeval::ValueList{std::move(items)}))};
79
+ oscadeval::makeList(std::move(items)))};
80
80
  }
81
81
  return oscadeval::Value{}; // monostate = undef
82
82
  }
@@ -0,0 +1,31 @@
1
+ # Patches the fetched Manifold v3.5.2 source; run as its FetchContent
2
+ # PATCH_COMMAND, in the source directory.
3
+ #
4
+ # CsgLeafNode::Compose calls RemoveDegenerates() on the combined mesh and
5
+ # then sorts it, and on some inputs the cleanup leaves the face data
6
+ # inconsistent: SortGeometry -> GatherFaces then reads past the end of an
7
+ # array (a heap-buffer-overflow under AddressSanitizer). Our
8
+ # MinkowskiDifference.ShrinksANonConvexBodyOnEverySide test reaches it;
9
+ # reproduced with Manifold alone, and bisected upstream to elalish/manifold
10
+ # #1789 ("Improved decimation", 969b1417), which fixes it by deleting this
11
+ # same call -- the only part of that commit the fix needs. Not in any
12
+ # release yet; drop this patch when Manifold is bumped past it.
13
+ #
14
+ # Idempotent: a re-run on already-patched source changes nothing. Anything
15
+ # else -- the call or its surroundings changed -- is an error, so a version
16
+ # bump can never silently skip the patch.
17
+ set(file src/csg_tree.cpp)
18
+ file(READ ${file} src)
19
+ set(call " // required to remove parts that are smaller than the tolerance\n combined.RemoveDegenerates();\n")
20
+ string(FIND "${src}" "${call}" at)
21
+ if(at EQUAL -1)
22
+ string(FIND "${src}" "combined.RemoveDegenerates();" any)
23
+ if(NOT any EQUAL -1)
24
+ message(FATAL_ERROR "patch_manifold.cmake: ${file} changed around RemoveDegenerates(); update the patch")
25
+ endif()
26
+ message(STATUS "patch_manifold.cmake: already applied")
27
+ return()
28
+ endif()
29
+ string(REPLACE "${call}" "" src "${src}")
30
+ file(WRITE ${file} "${src}")
31
+ message(STATUS "patch_manifold.cmake: removed RemoveDegenerates() from CsgLeafNode::Compose")
@@ -170,7 +170,7 @@ struct VmFrame {
170
170
  std::vector<Value> slots;
171
171
  std::vector<Value> stack;
172
172
  std::vector<bool> bound;
173
- std::vector<std::vector<Value>> accumStack;
173
+ std::vector<ListBuilder> accumStack;
174
174
  std::vector<IterList> iterLists;
175
175
  // std::deque, NOT vector: Evaluator::enterUserCall stores
176
176
  // CallStackFrame::bodyCtx as a pointer to ctxChain.back() (see
@@ -3,6 +3,7 @@
3
3
  #include "openscad_cpp_evaluator/osc_range.hpp"
4
4
 
5
5
  #include <atomic>
6
+ #include <cstdint>
6
7
  #include <functional>
7
8
  #include <initializer_list>
8
9
  #include <memory>
@@ -114,41 +115,46 @@ inline std::shared_ptr<TrailView<Value>> capturedLetTrail(const Closure& c) {
114
115
  // with one compare-and-swap, so two lists sharing a prefix can never write
115
116
  // the same slot (the loser copies).
116
117
  struct ListBuffer {
117
- std::vector<Value> v;
118
- std::atomic<size_t> used;
118
+ std::vector<Value> v; // never reallocated once a list views it
119
+ std::atomic<uint32_t> used{0}; // with fromAppend, packs into one word
119
120
  // Set when this buffer came from appending: a list that was appended
120
121
  // to once is likely to be again, so ITS copies grow geometrically,
121
122
  // while a one-off concat's result is allocated at exactly its size.
122
123
  bool fromAppend = false;
123
- explicit ListBuffer(std::vector<Value>&& items) : v(std::move(items)), used(v.size()) {}
124
124
  };
125
125
 
126
+ // A list's elements: the first `size()` of a buffer. A list made by
127
+ // makeList keeps its buffer in its own allocation (keep_ empty); one made by
128
+ // appending in place views the buffer of the list it extends, and keep_
129
+ // holds that list's allocation alive. The element pointer is cached, so a
130
+ // read is one hop, as with a plain vector. Neither copyable nor movable:
131
+ // an own-buffer view must never outlive the allocation it sits in.
126
132
  class ListItems {
127
133
  public:
128
134
  ListItems() = default;
129
- ListItems(std::vector<Value>&& items) // NOLINT: implicit, as the old vector was
130
- : buf_(std::make_shared<ListBuffer>(std::move(items))), n_(buf_->v.size()) {}
131
- ListItems(const std::vector<Value>& items) : ListItems(std::vector<Value>(items)) {} // NOLINT
132
- ListItems(std::initializer_list<Value> items) : ListItems(std::vector<Value>(items)) {}
135
+ ListItems(const ListItems&) = delete;
136
+ ListItems& operator=(const ListItems&) = delete;
133
137
 
134
138
  size_t size() const { return n_; }
135
139
  bool empty() const { return n_ == 0; }
136
- const Value* data() const { return buf_ ? buf_->v.data() : nullptr; }
137
- const Value* begin() const { return data(); }
138
- const Value* end() const { return data() + n_; }
139
- const Value& operator[](size_t i) const { return data()[i]; }
140
+ const Value* data() const { return data_; }
141
+ const Value* begin() const { return data_; }
142
+ const Value* end() const { return data_ + n_; }
143
+ const Value& operator[](size_t i) const { return data_[i]; }
140
144
  const Value& at(size_t i) const;
141
- const Value& front() const { return data()[0]; }
142
- const Value& back() const { return data()[n_ - 1]; }
145
+ const Value& front() const { return data_[0]; }
146
+ const Value& back() const { return data_[n_ - 1]; }
143
147
  // A copy as a plain vector, for the few callers that build on one.
144
148
  // Explicit, so a copy is never made by accident binding a reference.
145
149
  explicit operator std::vector<Value>() const { return std::vector<Value>(begin(), end()); }
146
150
  std::vector<Value> toVector() const { return std::vector<Value>(begin(), end()); }
147
151
 
148
152
  private:
149
- ListItems(std::shared_ptr<ListBuffer> buf, size_t n) : buf_(std::move(buf)), n_(n) {}
150
- std::shared_ptr<ListBuffer> buf_;
153
+ std::shared_ptr<const void> keep_;
154
+ ListBuffer* buf_ = nullptr;
155
+ const Value* data_ = nullptr;
151
156
  size_t n_ = 0;
157
+ friend ListPtr makeList(std::vector<Value> items);
152
158
  friend ListPtr listAppend(const ListPtr& base, std::vector<Value>&& extra);
153
159
  };
154
160
 
@@ -156,6 +162,13 @@ struct ValueList {
156
162
  ListItems items;
157
163
  };
158
164
 
165
+ // A new list holding `items` (adopted, not copied): one allocation for the
166
+ // list and its buffer together, plus the elements' own -- as many as a list
167
+ // that was a plain vector cost.
168
+ ListPtr makeList(std::vector<Value> items);
169
+ inline ListPtr makeList() { return makeList(std::vector<Value>{}); }
170
+
171
+
159
172
  // `base` followed by `extra`, sharing base's buffer whenever base is the
160
173
  // longest list using it and the buffer has room: amortized O(|extra|)
161
174
  // rather than O(|base| + |extra|), which is what turns the idiomatic
@@ -164,6 +177,19 @@ struct ValueList {
164
177
  // its own elements.
165
178
  ListPtr listAppend(const ListPtr& base, std::vector<Value>&& extra);
166
179
 
180
+ // Builds a list literal or comprehension result from its contributions. When
181
+ // the first contribution is `each <a list>`, the result starts AS that list
182
+ // and everything after it is appended with listAppend -- so the other
183
+ // accumulator idiom, f(i, [each acc, x]), extends acc in place just as
184
+ // concat(acc, [x]) does, instead of copying it.
185
+ struct ListBuilder {
186
+ ListPtr seed; // the list an `each` started from, if any
187
+ std::vector<Value> rest; // everything contributed after it
188
+ void push(Value v) { rest.push_back(std::move(v)); }
189
+ void appendEach(const Value& v); // as appendEachInto
190
+ ListPtr finish();
191
+ };
192
+
167
193
  // Insertion-ordered key/value pairs, not a map: object()'s iteration order
168
194
  // and `==` are order-sensitive (doc: openscad_evaluator/docs/evaluator.md,
169
195
  // the object() entry).
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "openscad_cpp_evaluator"
7
- version = "1.35.0"
7
+ version = "1.36.0"
8
8
  description = "C++ OpenSCAD evaluator with Python bindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -143,9 +143,9 @@ CSGParams resolveCsg(Evaluator& ev, const oscad::ModularCall& node, EvalContext&
143
143
 
144
144
  CSGParams params;
145
145
  params["op"] = Value{op};
146
- params["group_sizes"] = Value{std::make_shared<const ValueList>(ValueList{std::move(groupSizes)})};
146
+ params["group_sizes"] = Value{makeList(std::move(groupSizes))};
147
147
  params["empty_is_a_group"] =
148
- Value{std::make_shared<const ValueList>(ValueList{std::move(emptyIsAGroup)})};
148
+ Value{makeList(std::move(emptyIsAGroup))};
149
149
  return params;
150
150
  }
151
151
 
@@ -93,10 +93,10 @@ Value callArgsToValue(const CallArgs& args) {
93
93
  std::vector<std::pair<std::string, Value>> namedVec(args.named.begin(), args.named.end());
94
94
 
95
95
  std::vector<Value> outer = {
96
- Value{std::make_shared<const ValueList>(ValueList{std::move(posVec)})},
96
+ Value{makeList(std::move(posVec))},
97
97
  Value{std::make_shared<const ValueObject>(ValueObject{std::move(namedVec)})},
98
98
  };
99
- return Value{std::make_shared<const ValueList>(ValueList{std::move(outer)})};
99
+ return Value{makeList(std::move(outer))};
100
100
  }
101
101
 
102
102
  const oscad::Expression* argExpr(const oscad::Argument& arg) {
@@ -141,7 +141,7 @@ CSGParams resolveIntersectionFor(Evaluator& ev, const oscad::ModularIntersection
141
141
  recurse(0, ctx);
142
142
 
143
143
  CSGParams params;
144
- params["group_sizes"] = Value{std::make_shared<const ValueList>(ValueList{std::move(groupSizes)})};
144
+ params["group_sizes"] = Value{makeList(std::move(groupSizes))};
145
145
  return params;
146
146
  }
147
147
 
@@ -234,7 +234,7 @@ Value builtinDxfCross(Evaluator& ev, const CallArgs& args, const oscad::ASTNode&
234
234
  if (dem == 0.0) break; // parallel: no cross, same as the reference
235
235
  const double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / dem;
236
236
  std::vector<Value> xy{Value{x1 + ua * (x2 - x1)}, Value{y1 + ua * (y2 - y1)}};
237
- return Value{std::make_shared<const ValueList>(ValueList{std::move(xy)})};
237
+ return Value{makeList(std::move(xy))};
238
238
  }
239
239
  }
240
240
  ev.warn("Can't find cross in '" + c.rawFile + "', layer '" + c.layer + "'!", &node.position());
@@ -48,7 +48,7 @@ std::optional<std::vector<double>> allNumericList(const Value& v) {
48
48
  return out;
49
49
  }
50
50
 
51
- Value listOf(std::vector<Value> items) { return Value{std::make_shared<const ValueList>(ValueList{std::move(items)})}; }
51
+ Value listOf(std::vector<Value> items) { return Value{makeList(std::move(items))}; }
52
52
  Value numList(const std::vector<double>& xs) {
53
53
  std::vector<Value> items;
54
54
  items.reserve(xs.size());
@@ -66,7 +66,7 @@ Value jsonToValue(const nlohmann::ordered_json& j) {
66
66
  std::vector<Value> items;
67
67
  items.reserve(j.size());
68
68
  for (const auto& el : j) items.push_back(jsonToValue(el));
69
- return Value{std::make_shared<const ValueList>(ValueList{std::move(items)})};
69
+ return Value{makeList(std::move(items))};
70
70
  }
71
71
  if (j.is_object()) {
72
72
  std::vector<std::pair<std::string, Value>> items;
@@ -102,20 +102,19 @@ Value meshToVnf(const LoadedMesh& mesh) {
102
102
  if (it == vertMap.end()) {
103
103
  idx = static_cast<int>(vertsOut.size());
104
104
  vertMap.emplace(v, idx);
105
- vertsOut.push_back(Value{std::make_shared<const ValueList>(
106
- ValueList{{Value{v[0]}, Value{v[1]}, Value{v[2]}}})});
105
+ vertsOut.push_back(Value{makeList({Value{v[0]}, Value{v[1]}, Value{v[2]}})});
107
106
  } else {
108
107
  idx = it->second;
109
108
  }
110
109
  face.push_back(Value{static_cast<double>(idx)});
111
110
  }
112
- facesOut.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(face)})});
111
+ facesOut.push_back(Value{makeList(std::move(face))});
113
112
  }
114
113
  std::vector<Value> outer = {
115
- Value{std::make_shared<const ValueList>(ValueList{std::move(vertsOut)})},
116
- Value{std::make_shared<const ValueList>(ValueList{std::move(facesOut)})},
114
+ Value{makeList(std::move(vertsOut))},
115
+ Value{makeList(std::move(facesOut))},
117
116
  };
118
- return Value{std::make_shared<const ValueList>(ValueList{std::move(outer)})};
117
+ return Value{makeList(std::move(outer))};
119
118
  }
120
119
 
121
120
  } // namespace
@@ -152,10 +151,10 @@ Value contoursToValue(const std::vector<Contour2d>& contours) {
152
151
  for (const auto& c : contours) {
153
152
  std::vector<Value> pts;
154
153
  pts.reserve(c.size());
155
- for (const auto& p : c) pts.push_back(Value{std::make_shared<const ValueList>(ValueList{{Value{p[0]}, Value{p[1]}}})});
156
- outer.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(pts)})});
154
+ for (const auto& p : c) pts.push_back(Value{makeList({Value{p[0]}, Value{p[1]}})});
155
+ outer.push_back(Value{makeList(std::move(pts))});
157
156
  }
158
- return Value{std::make_shared<const ValueList>(ValueList{std::move(outer)})};
157
+ return Value{makeList(std::move(outer))};
159
158
  }
160
159
 
161
160
  std::vector<Contour2d> valueToContours(const Value& v) {
@@ -284,8 +283,8 @@ CSGParams resolveImport(Evaluator& ev, const oscad::ModularCall& node, EvalConte
284
283
  params["kind"] = Value{std::string("mesh")};
285
284
  params["repair"] = Value{repair};
286
285
  params["tolerance"] = toleranceArg;
287
- params["verts"] = Value{std::make_shared<const ValueList>(ValueList{std::move(vertsFlat)})};
288
- params["tris"] = Value{std::make_shared<const ValueList>(ValueList{std::move(trisFlat)})};
286
+ params["verts"] = Value{makeList(std::move(vertsFlat))};
287
+ params["tris"] = Value{makeList(std::move(trisFlat))};
289
288
  return params;
290
289
  }
291
290
  if (ext == ".json") {
@@ -79,9 +79,9 @@ CSGParams resolve2d(Evaluator& ev, const oscad::ModularCall& node, EvalContext&
79
79
  const double x = (pl && *pl && !(*pl)->items.empty()) ? toDoubleLenient((*pl)->items[0]) : 0.0;
80
80
  const double y = (pl && *pl && (*pl)->items.size() > 1) ? toDoubleLenient((*pl)->items[1]) : 0.0;
81
81
  std::vector<Value> xy = {Value{x}, Value{y}};
82
- pts.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(xy)})});
82
+ pts.push_back(Value{makeList(std::move(xy))});
83
83
  }
84
- params["pts"] = Value{std::make_shared<const ValueList>(ValueList{std::move(pts)})};
84
+ params["pts"] = Value{makeList(std::move(pts))};
85
85
 
86
86
  if (const ListPtr* pathsList = std::get_if<ListPtr>(&pathsArg); pathsList && *pathsList) {
87
87
  std::vector<Value> paths;
@@ -91,9 +91,9 @@ CSGParams resolve2d(Evaluator& ev, const oscad::ModularCall& node, EvalContext&
91
91
  if (pathIdxList && *pathIdxList) {
92
92
  for (const Value& idx : (*pathIdxList)->items) idxVals.push_back(Value{toDoubleLenient(idx)});
93
93
  }
94
- paths.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(idxVals)})});
94
+ paths.push_back(Value{makeList(std::move(idxVals))});
95
95
  }
96
- params["paths"] = Value{std::make_shared<const ValueList>(ValueList{std::move(paths)})};
96
+ params["paths"] = Value{makeList(std::move(paths))};
97
97
  } else {
98
98
  params["paths"] = Value{}; // undef == "no paths given" -- pts is one single contour
99
99
  }
@@ -141,7 +141,7 @@ CSGParams resolveCube(Evaluator& ev, const oscad::ModularCall& node, EvalContext
141
141
  }
142
142
 
143
143
  CSGParams params;
144
- params["size"] = Value{std::make_shared<const ValueList>(ValueList{std::move(sizeVec)})};
144
+ params["size"] = Value{makeList(std::move(sizeVec))};
145
145
  params["center"] = Value{center};
146
146
  params["color"] = colorToValue(effCtx.color);
147
147
  return params;
@@ -402,8 +402,8 @@ CSGParams resolveSphere(Evaluator& ev, const oscad::ModularCall& node, EvalConte
402
402
  // Manifold::Sphere IS a subdivided octahedron (Shape::Octahedron,
403
403
  // then Subdivide), so this needs no mesh of our own -- generate
404
404
  // calls it directly.
405
- params["verts"] = Value{std::make_shared<const ValueList>(ValueList{})};
406
- params["tris"] = Value{std::make_shared<const ValueList>(ValueList{})};
405
+ params["verts"] = Value{makeList()};
406
+ params["tris"] = Value{makeList()};
407
407
  return params;
408
408
  }
409
409
 
@@ -418,8 +418,8 @@ CSGParams resolveSphere(Evaluator& ev, const oscad::ModularCall& node, EvalConte
418
418
  std::vector<Value> trisValues;
419
419
  trisValues.reserve(m.tris.size());
420
420
  for (int t : m.tris) trisValues.push_back(Value{static_cast<double>(t)});
421
- params["verts"] = Value{std::make_shared<const ValueList>(ValueList{std::move(vertsValues)})};
422
- params["tris"] = Value{std::make_shared<const ValueList>(ValueList{std::move(trisValues)})};
421
+ params["verts"] = Value{makeList(std::move(vertsValues))};
422
+ params["tris"] = Value{makeList(std::move(trisValues))};
423
423
  return params;
424
424
  }
425
425
 
@@ -832,8 +832,8 @@ CSGParams resolvePolyhedron(Evaluator& ev, const oscad::ModularCall& node, EvalC
832
832
  for (uint32_t t : tris) trisValues.push_back(Value{static_cast<double>(t)});
833
833
 
834
834
  CSGParams params;
835
- params["verts"] = Value{std::make_shared<const ValueList>(ValueList{std::move(vertsValues)})};
836
- params["tris"] = Value{std::make_shared<const ValueList>(ValueList{std::move(trisValues)})};
835
+ params["verts"] = Value{makeList(std::move(vertsValues))};
836
+ params["tris"] = Value{makeList(std::move(trisValues))};
837
837
  params["color"] = colorToValue(effCtx.color);
838
838
  return params;
839
839
  }
@@ -44,9 +44,9 @@ CSGParams resolveSurface(Evaluator& ev, const oscad::ModularCall& node, EvalCont
44
44
  std::vector<Value> rowVals;
45
45
  rowVals.reserve(row.size());
46
46
  for (double v : row) rowVals.push_back(Value{v});
47
- rows.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(rowVals)})});
47
+ rows.push_back(Value{makeList(std::move(rowVals))});
48
48
  }
49
- params["heights"] = Value{std::make_shared<const ValueList>(ValueList{std::move(rows)})};
49
+ params["heights"] = Value{makeList(std::move(rows))};
50
50
  return params;
51
51
  }
52
52
 
@@ -69,8 +69,7 @@ CSGParams resolveText(Evaluator& ev, const oscad::ModularCall& node, EvalContext
69
69
  std::vector<Value> glyphs;
70
70
  glyphs.reserve(m.glyphs.size());
71
71
  for (const TextMeasurement::Placed& g : m.glyphs) {
72
- glyphs.push_back(Value{std::make_shared<const ValueList>(
73
- ValueList{{Value{static_cast<double>(g.glyph)}, Value{g.x}, Value{g.y}}})});
72
+ glyphs.push_back(Value{makeList({Value{static_cast<double>(g.glyph)}, Value{g.x}, Value{g.y}})});
74
73
  }
75
74
 
76
75
  CSGParams params;
@@ -89,7 +88,7 @@ CSGParams resolveText(Evaluator& ev, const oscad::ModularCall& node, EvalContext
89
88
  params["segs"] = Value{static_cast<double>(segs)};
90
89
  params["offset_x"] = Value{offsetX};
91
90
  params["offset_y"] = Value{offsetY};
92
- params["glyphs"] = Value{std::make_shared<const ValueList>(ValueList{std::move(glyphs)})};
91
+ params["glyphs"] = Value{makeList(std::move(glyphs))};
93
92
  params["color"] = colorToValue(effCtx.color);
94
93
  return params;
95
94
  }
@@ -792,7 +792,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
792
792
  items[count - 1 - i] = std::move(f.stack.back());
793
793
  f.stack.pop_back();
794
794
  }
795
- f.stack.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(items)})});
795
+ f.stack.push_back(Value{makeList(std::move(items))});
796
796
  ++f.pc;
797
797
  break;
798
798
  }
@@ -803,28 +803,28 @@ Value driveVm(Evaluator& ev, size_t floor) {
803
803
  case Op::AccumAppendOne: {
804
804
  Value v = std::move(f.stack.back());
805
805
  f.stack.pop_back();
806
- f.accumStack.back().push_back(std::move(v));
806
+ f.accumStack.back().push(std::move(v));
807
807
  ++f.pc;
808
808
  break;
809
809
  }
810
810
  case Op::AccumAppendEach: {
811
811
  Value v = std::move(f.stack.back());
812
812
  f.stack.pop_back();
813
- appendEachInto(f.accumStack.back(), v);
813
+ f.accumStack.back().appendEach(v);
814
814
  ++f.pc;
815
815
  break;
816
816
  }
817
817
  case Op::AccumClose: {
818
- std::vector<Value> items = std::move(f.accumStack.back());
818
+ ListPtr list = f.accumStack.back().finish();
819
819
  f.accumStack.pop_back();
820
- f.stack.push_back(Value{std::make_shared<const ValueList>(ValueList{std::move(items)})});
820
+ f.stack.push_back(Value{std::move(list)});
821
821
  ++f.pc;
822
822
  break;
823
823
  }
824
824
  case Op::AccumMergeEach: {
825
- std::vector<Value> inner = std::move(f.accumStack.back());
825
+ const ListPtr inner = f.accumStack.back().finish();
826
826
  f.accumStack.pop_back();
827
- for (const Value& item : inner) appendEachInto(f.accumStack.back(), item);
827
+ for (const Value& item : inner->items) f.accumStack.back().appendEach(item);
828
828
  ++f.pc;
829
829
  break;
830
830
  }
@@ -1492,9 +1492,8 @@ Value driveVm(Evaluator& ev, size_t floor) {
1492
1492
  CSGParams params;
1493
1493
  if (site.includeOpParam) params["op"] = Value{pending.op};
1494
1494
  params["group_sizes"] =
1495
- Value{std::make_shared<const ValueList>(ValueList{std::move(pending.groupSizes)})};
1496
- params["empty_is_a_group"] = Value{std::make_shared<const ValueList>(
1497
- ValueList{std::move(pending.emptyIsAGroup)})};
1495
+ Value{makeList(std::move(pending.groupSizes))};
1496
+ params["empty_is_a_group"] = Value{makeList(std::move(pending.emptyIsAGroup))};
1498
1497
  // Mirrors Evaluator::buildTreeNode's own post-
1499
1498
  // resolveBody() half exactly (csg_resolve.cpp).
1500
1499
  const bool uncacheable =
@@ -5,7 +5,7 @@ namespace oscadeval {
5
5
  Value colorToValue(const std::optional<std::array<double, 4>>& color) {
6
6
  if (!color) return Value{};
7
7
  std::vector<Value> items = {Value{(*color)[0]}, Value{(*color)[1]}, Value{(*color)[2]}, Value{(*color)[3]}};
8
- return Value{std::make_shared<const ValueList>(ValueList{std::move(items)})};
8
+ return Value{makeList(std::move(items))};
9
9
  }
10
10
 
11
11
  std::optional<std::array<float, 4>> valueToColor(const Value& v) {
@@ -63,9 +63,9 @@ EvalContext EvalContext::makeRoot(const oscad::Scope* rootScope, const oscad::Sc
63
63
  // same script starts working there with no edit.
64
64
  ctx.dyn->set("$_SUPPORTED_FEATURE", Value{true});
65
65
  ctx.dyn->set("$_BELFRYSCAD",
66
- Value{std::make_shared<const ValueList>(ValueList{{Value{double{OSCAD_EVAL_VERSION_MAJOR}},
66
+ Value{makeList({Value{double{OSCAD_EVAL_VERSION_MAJOR}},
67
67
  Value{double{OSCAD_EVAL_VERSION_MINOR}},
68
- Value{double{OSCAD_EVAL_VERSION_PATCH}}}})});
68
+ Value{double{OSCAD_EVAL_VERSION_PATCH}}})});
69
69
  ctx.let_ = TrailView<Value>::makeRoot();
70
70
  ctx.dynPositions = TrailView<const oscad::Position*>::makeRoot();
71
71
  ctx.childrenNodes = emptyChildrenNodes();
@@ -350,10 +350,21 @@ std::vector<Value> Evaluator::evalListCompBody(const oscad::ASTNode& body, EvalC
350
350
  }
351
351
 
352
352
  Value Evaluator::evalListLiteral(const oscad::ListComprehension& node, EvalContext& ctx) {
353
- std::vector<Value> items;
354
- items.reserve(node.elements.size());
355
- for (const auto& elemPtr : node.elements) evalListElement(*elemPtr, ctx, items);
356
- return Value{std::make_shared<const ValueList>(ValueList{std::move(items)})};
353
+ ListBuilder list;
354
+ list.rest.reserve(node.elements.size());
355
+ size_t first = 0;
356
+ // `[each acc, ...]`: start from acc itself (see ListBuilder), so the
357
+ // accumulator idiom appends in place rather than copying acc.
358
+ if (!node.elements.empty() && node.elements[0]->kind() == oscad::NodeKind::ListCompEach) {
359
+ auto& n = static_cast<const oscad::ListCompEach&>(*node.elements[0]);
360
+ if (!isListCompClauseKind(n.body->kind())) {
361
+ checkDebug(n, ctx, /*forced=*/false, /*exprLevel=*/true);
362
+ list.appendEach(evalExpr(static_cast<const oscad::Expression&>(*n.body), ctx));
363
+ first = 1;
364
+ }
365
+ }
366
+ for (size_t i = first; i < node.elements.size(); ++i) evalListElement(*node.elements[i], ctx, list.rest);
367
+ return Value{list.finish()};
357
368
  }
358
369
 
359
370
  Value Evaluator::evalRangeLiteral(const oscad::RangeLiteral& node, EvalContext& ctx) {
@@ -32,7 +32,7 @@ namespace oscadeval {
32
32
  namespace {
33
33
 
34
34
  Value listOf(std::vector<Value> items) {
35
- return Value{std::make_shared<const ValueList>(ValueList{std::move(items)})};
35
+ return Value{makeList(std::move(items))};
36
36
  }
37
37
 
38
38
  Value pointOf(double x, double y, double z) { return listOf({Value{x}, Value{y}, Value{z}}); }