openscad-cpp-evaluator 0.27.1__tar.gz → 0.28.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 (199) hide show
  1. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/PKG-INFO +1 -1
  2. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/grammar/lexer.l +9 -0
  3. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +37 -0
  4. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/value.hpp +20 -0
  5. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/pyproject.toml +1 -1
  6. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/bytecode_compiler.cpp +4 -1
  7. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/expr_eval.cpp +1 -1
  8. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/value.cpp +34 -0
  9. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_bytecode_compiler.cpp +2 -2
  10. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_dxf_svg_import.cpp +29 -29
  11. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_import_export.cpp +13 -13
  12. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_surface.cpp +8 -8
  13. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_value.cpp +62 -0
  14. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/.github/workflows/ci.yml +0 -0
  15. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/.github/workflows/wheels.yml +0 -0
  16. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/.gitignore +0 -0
  17. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/.gitmodules +0 -0
  18. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/CLAUDE.md +0 -0
  19. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/CMakeLists.txt +0 -0
  20. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/LICENSE +0 -0
  21. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/README.md +0 -0
  22. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/bindings/CMakeLists.txt +0 -0
  23. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/bindings/ast_to_py.cpp +0 -0
  24. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/bindings/module.cpp +0 -0
  25. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/cmake/embed_font.cmake +0 -0
  26. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/examples/CMakeLists.txt +0 -0
  27. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/examples/eval_perf_benchmark.cpp +0 -0
  28. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/examples/manifold_cache_reuse.cpp +0 -0
  29. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/examples/minimal_debugger.cpp +0 -0
  30. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
  31. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/.gitignore +0 -0
  32. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
  33. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
  34. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/README.md +0 -0
  35. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
  36. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
  37. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
  38. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
  39. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
  40. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
  41. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
  42. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
  43. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
  44. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
  45. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
  46. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
  47. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
  48. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
  49. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
  50. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
  51. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
  52. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
  53. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
  54. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
  55. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
  56. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
  57. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
  58. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
  59. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
  60. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
  61. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
  62. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
  63. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
  64. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
  65. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
  66. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
  67. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
  68. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
  69. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
  70. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
  71. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
  72. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
  73. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
  74. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
  75. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
  76. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
  77. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
  78. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
  79. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
  80. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
  81. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
  82. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
  83. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
  84. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
  85. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
  86. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
  87. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
  88. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
  89. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
  90. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
  91. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
  92. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
  93. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
  94. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
  95. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
  96. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
  97. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
  98. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
  99. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
  100. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
  101. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
  102. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
  103. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
  104. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
  105. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
  106. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
  107. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
  108. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
  109. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
  110. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
  111. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
  112. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
  113. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
  114. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
  115. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
  116. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
  117. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
  118. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
  119. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
  120. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
  121. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
  122. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
  123. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
  124. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
  125. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
  126. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/resources/fonts/LICENSE +0 -0
  127. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
  128. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/CMakeLists.txt +0 -0
  129. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/booleans.cpp +0 -0
  130. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/builtins.hpp +0 -0
  131. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/call_args.cpp +0 -0
  132. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/color.cpp +0 -0
  133. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/control.cpp +0 -0
  134. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/extrude.cpp +0 -0
  135. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/function_builtins.cpp +0 -0
  136. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/import.cpp +0 -0
  137. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/modifiers.cpp +0 -0
  138. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/primitives_2d.cpp +0 -0
  139. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/primitives_3d.cpp +0 -0
  140. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/registry.cpp +0 -0
  141. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/roof.cpp +0 -0
  142. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/segments.cpp +0 -0
  143. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/surface.cpp +0 -0
  144. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/text.cpp +0 -0
  145. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/topology.cpp +0 -0
  146. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/builtins/transforms.cpp +0 -0
  147. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/bytecode_vm.cpp +0 -0
  148. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/colored_body.cpp +0 -0
  149. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/csg_generate.cpp +0 -0
  150. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/csg_resolve.cpp +0 -0
  151. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/css_colors.cpp +0 -0
  152. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/debug/debug_repl.cpp +0 -0
  153. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/debug_profile.cpp +0 -0
  154. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/eval_context.cpp +0 -0
  155. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/eval_error.cpp +0 -0
  156. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/eval_use.cpp +0 -0
  157. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/export.cpp +0 -0
  158. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/import/dxf_import.cpp +0 -0
  159. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/import/mesh_import.cpp +0 -0
  160. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/import/surface_load.cpp +0 -0
  161. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/import/svg_import.cpp +0 -0
  162. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/manifold_cache.cpp +0 -0
  163. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/mesh_check.cpp +0 -0
  164. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/stmt_eval.cpp +0 -0
  165. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/text/stb_font_provider.cpp +0 -0
  166. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/text/text_metrics.cpp +0 -0
  167. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/user_calls.cpp +0 -0
  168. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/src/zip_stored.cpp +0 -0
  169. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/CMakeLists.txt +0 -0
  170. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_booleans.cpp +0 -0
  171. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_cli.cpp +0 -0
  172. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_control_flow.cpp +0 -0
  173. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_csg_tree.cpp +0 -0
  174. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_debug_hooks.cpp +0 -0
  175. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_eval_context.cpp +0 -0
  176. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_export.cpp +0 -0
  177. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_expr_eval.cpp +0 -0
  178. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_extrude_roof.cpp +0 -0
  179. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_function_builtins.cpp +0 -0
  180. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_helpers.hpp +0 -0
  181. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_manifold_cache.cpp +0 -0
  182. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_mesh_check.cpp +0 -0
  183. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_multi_color_merge.cpp +0 -0
  184. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_primitives.cpp +0 -0
  185. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_profiling.cpp +0 -0
  186. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_python_bindings.py +0 -0
  187. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_scope_trail.cpp +0 -0
  188. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_scoping.cpp +0 -0
  189. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_tail_calls.cpp +0 -0
  190. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_text.cpp +0 -0
  191. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_transforms.cpp +0 -0
  192. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_use.cpp +0 -0
  193. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_viewport_params.cpp +0 -0
  194. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tests/test_zip_stored.cpp +0 -0
  195. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tools/cli/CMakeLists.txt +0 -0
  196. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tools/cli/cli_lib.cpp +0 -0
  197. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tools/cli/cli_lib.hpp +0 -0
  198. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/tools/cli/main.cpp +0 -0
  199. {openscad_cpp_evaluator-0.27.1 → openscad_cpp_evaluator-0.28.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscad_cpp_evaluator
3
- Version: 0.27.1
3
+ Version: 0.28.0
4
4
  Summary: C++ OpenSCAD evaluator with Python bindings
5
5
  Author: NeuSCAD Contributors
6
6
  License-Expression: MIT
@@ -99,6 +99,15 @@ NUMLIT 0[xX][0-9A-Fa-f]+|[0-9]+([.][0-9]*)?([eE][+-]?[0-9]+)?|[.][0-9]+([eE][+-
99
99
  driver.stringStart = driver.tokenStart;
100
100
  BEGIN(STR);
101
101
  }
102
+ /* A backslash escaping the end of the line. Flex's `.` never matches a
103
+ newline, so without this rule the backslash matched nothing, fell to
104
+ flex's default ECHO and was printed to stdout -- a stray `\` on every
105
+ parse of such a file -- while the newline was picked up as ordinary
106
+ content by the run rule below and ended up inside the string.
107
+ Kept verbatim rather than dropped here: the value is cooked when the
108
+ literal is evaluated, so the AST keeps text that reproduces the
109
+ source exactly, which is what the pretty-printer round-trips. */
110
+ <STR>\\\r?\n { driver.stringBuffer.append(yytext, yyleng); }
102
111
  <STR>\\. { driver.stringBuffer.append(yytext, yyleng); }
103
112
  <STR>[^"\\]+ { driver.stringBuffer.append(yytext, yyleng); }
104
113
  <STR>\" {
@@ -436,3 +436,40 @@ TEST(SourceSpans, MultiLineStringReportsItsStartingLine) {
436
436
  EXPECT_EQ(assign->expr->position().line, 2);
437
437
  EXPECT_EQ(spanned(src, *assign->expr), "\"one\ntwo\"");
438
438
  }
439
+
440
+ // -- Backslash at end of line inside a string ---------------------------
441
+
442
+ // The lexer had no rule for a backslash followed by a newline: flex's `.`
443
+ // never matches a newline, so `\\.` could not, and the backslash fell
444
+ // through to flex's DEFAULT ECHO rule -- printed straight to stdout, a
445
+ // stray `\` on every parse of such a file. The newline was then swallowed
446
+ // by the content-run rule and became part of the string.
447
+ //
448
+ // The literal keeps both characters. Cooking happens where the literal is
449
+ // evaluated, not here, so a StringLiteral's text still reproduces the
450
+ // source it was parsed from -- which is what pretty-printing relies on.
451
+ TEST(LexicalStrings, BackslashNewlineIsKeptVerbatimInTheLiteral) {
452
+ struct Case { std::string src; std::string want; const char* what; };
453
+ const Case cases[] = {
454
+ {"a = \"x \\\ny\";", "x \\\ny", "LF"},
455
+ {"a = \"x \\\r\ny\";", "x \\\r\ny", "CRLF"},
456
+ };
457
+ for (const Case& c : cases) {
458
+ auto ast = parseSrc(c.src);
459
+ ASSERT_EQ(ast.size(), 1u) << c.what;
460
+ auto* assign = dynamic_cast<Assignment*>(ast[0].get());
461
+ ASSERT_NE(assign, nullptr) << c.what;
462
+ auto* str = dynamic_cast<StringLiteral*>(assign->expr.get());
463
+ ASSERT_NE(str, nullptr) << c.what;
464
+ EXPECT_EQ(str->val, c.want) << c.what;
465
+ }
466
+ }
467
+
468
+ // The continued line still counts, or every position after a multi-line
469
+ // string would be reported one line short.
470
+ TEST(LexicalStrings, BackslashNewlineStillAdvancesTheLineNumber) {
471
+ auto ast = parseSrc("a = \"x \\\ny\";\nb = 2;\n");
472
+ ASSERT_EQ(ast.size(), 2u);
473
+ EXPECT_EQ(ast[0]->position().line, 1);
474
+ EXPECT_EQ(ast[1]->position().line, 3) << "the continuation consumed a line";
475
+ }
@@ -181,6 +181,26 @@ Value matmul(const Value& a, const Value& b);
181
181
  // script's output is shown to land on one.
182
182
  std::string formatNumber(double v);
183
183
 
184
+ // Resolve the escape sequences in a string literal's source text.
185
+ //
186
+ // The parser stores a StringLiteral's text exactly as written, backslashes
187
+ // and all, so that a literal still reproduces the source it came from and
188
+ // pretty-printing round-trips. Cooking is therefore this side's job, and
189
+ // until this existed every escape reached scripts intact: "a\nb" was four
190
+ // characters, a backslash and an 'n' among them, rather than three.
191
+ //
192
+ // \\ \" \n \t \r the character they name
193
+ // \<newline> nothing at all -- a line continuation, so the string
194
+ // carries on with no break in it. A CRLF goes whole:
195
+ // leaving the CR behind, as the reference
196
+ // implementation does, puts a stray control character
197
+ // into the value of any script written on Windows.
198
+ // \<anything else> that character, with the backslash dropped
199
+ //
200
+ // A trailing lone backslash is kept as itself. It can only occur in an
201
+ // unterminated literal, which is a parse error long before this runs.
202
+ std::string unescapeStringLiteral(const std::string& raw);
203
+
184
204
  // echo()/str()/assert-message display format: "undef" | "true"/"false" |
185
205
  // "[start : step : end]" (range) | formatNumber() (number) | "[e1, e2, ...]"
186
206
  // (list, recursive) | "object(k1 = v1, ...)" ("object()" if empty) |
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "openscad_cpp_evaluator"
7
- version = "0.27.1"
7
+ version = "0.28.0"
8
8
  description = "C++ OpenSCAD evaluator with Python bindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -324,7 +324,10 @@ public:
324
324
  out.push_back({Op::PushBool, static_cast<const oscad::BooleanLiteral&>(node).val ? 1 : 0, 0, nullptr});
325
325
  return;
326
326
  case NodeKind::StringLiteral:
327
- out.push_back({Op::PushConst, internConst(Value{static_cast<const oscad::StringLiteral&>(node).val}), 0,
327
+ out.push_back({Op::PushConst,
328
+ internConst(Value{unescapeStringLiteral(
329
+ static_cast<const oscad::StringLiteral&>(node).val)}),
330
+ 0,
328
331
  nullptr});
329
332
  return;
330
333
  case NodeKind::UndefinedLiteral:
@@ -396,7 +396,7 @@ Value Evaluator::evalExpr(const oscad::Expression& node, EvalContext& ctx) {
396
396
  case NodeKind::BooleanLiteral:
397
397
  return Value{static_cast<const oscad::BooleanLiteral&>(node).val};
398
398
  case NodeKind::StringLiteral:
399
- return Value{static_cast<const oscad::StringLiteral&>(node).val};
399
+ return Value{unescapeStringLiteral(static_cast<const oscad::StringLiteral&>(node).val)};
400
400
  case NodeKind::UndefinedLiteral:
401
401
  return Value{};
402
402
  case NodeKind::CommentedExpr:
@@ -268,6 +268,40 @@ Value matmul(const Value& a, const Value& b) {
268
268
  return makeList(std::move(out));
269
269
  }
270
270
 
271
+ std::string unescapeStringLiteral(const std::string& raw) {
272
+ // Most strings carry no escape at all, and this runs on every
273
+ // evaluation of a literal on the tree-walking path -- so don't build a
274
+ // second copy of the string unless there is something to change.
275
+ const size_t first = raw.find('\\');
276
+ if (first == std::string::npos) return raw;
277
+
278
+ std::string out;
279
+ out.reserve(raw.size());
280
+ out.append(raw, 0, first);
281
+ for (size_t i = first; i < raw.size(); ++i) {
282
+ if (raw[i] != '\\' || i + 1 >= raw.size()) {
283
+ out.push_back(raw[i]); // a trailing lone backslash stands for itself
284
+ continue;
285
+ }
286
+ const char next = raw[i + 1];
287
+ switch (next) {
288
+ case 'n': out.push_back('\n'); ++i; break;
289
+ case 't': out.push_back('\t'); ++i; break;
290
+ case 'r': out.push_back('\r'); ++i; break;
291
+ case '\n': ++i; break; // line continuation: contributes nothing
292
+ case '\r':
293
+ // Only a CRLF pair is a line continuation; a lone CR is an
294
+ // ordinary escaped character like any other.
295
+ if (i + 2 < raw.size() && raw[i + 2] == '\n') { i += 2; break; }
296
+ out.push_back('\r');
297
+ ++i;
298
+ break;
299
+ default: out.push_back(next); ++i; break; // \\ and \" land here too
300
+ }
301
+ }
302
+ return out;
303
+ }
304
+
271
305
  std::string formatNumber(double v) {
272
306
  if (std::isnan(v)) return "nan";
273
307
  if (std::isinf(v)) return v > 0 ? "inf" : "-inf";
@@ -1044,7 +1044,7 @@ TEST(BytecodeCompiler, ImportCompilesAsTailPositionBody) {
1044
1044
  std::ofstream out(path);
1045
1045
  out << R"({"a": 1, "b": 2})";
1046
1046
  }
1047
- EXPECT_EQ(runCapturingEcho("function f() = import(\"" + path.string() + "\");\necho(f());"),
1047
+ EXPECT_EQ(runCapturingEcho("function f() = import(\"" + path.generic_string() + "\");\necho(f());"),
1048
1048
  "ECHO: object(a = 1, b = 2)");
1049
1049
  std::filesystem::remove(path);
1050
1050
  }
@@ -1073,7 +1073,7 @@ TEST(BytecodeCompiler, VmOffAndVmOnAgreeOnEchoAssertImportObjectCases) {
1073
1073
  const std::string script = "function withEcho(x) = echo(\"trace\", x) x + 1;\n"
1074
1074
  "function withAssert(x) = assert(x >= 0, \"must be non-negative\") x * 2;\n"
1075
1075
  "function withImport() = import(\"" +
1076
- path.string() +
1076
+ path.generic_string() +
1077
1077
  "\");\n"
1078
1078
  "existing = object(m = 1);\n"
1079
1079
  "function withObject() = object(n = 2, existing, m = 3);\n"
@@ -38,7 +38,7 @@ const char* kMinimalDxfSquare =
38
38
  TEST(DxfImport, ClosedLwpolylineProducesExpectedBoundingBox) {
39
39
  const auto path = tempPath("square.dxf");
40
40
  writeFile(path, kMinimalDxfSquare);
41
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
41
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
42
42
  ASSERT_EQ(e.bodies.size(), 1u);
43
43
  ASSERT_TRUE(e.bodies[0].section.has_value());
44
44
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6); // 4x3 square
@@ -49,7 +49,7 @@ TEST(DxfImport, ExpressionContextReturnsRegion) {
49
49
  const auto path = tempPath("square_expr.dxf");
50
50
  writeFile(path, kMinimalDxfSquare);
51
51
  Evaluator ev;
52
- Value v = asExpr("import(\"" + path.string() + "\")", ev);
52
+ Value v = asExpr("import(\"" + path.generic_string() + "\")", ev);
53
53
  const auto& contours = std::get<ListPtr>(v)->items;
54
54
  ASSERT_EQ(contours.size(), 1u);
55
55
  const auto& pts = std::get<ListPtr>(contours[0])->items;
@@ -68,7 +68,7 @@ TEST(DxfImport, LayerFilterExcludesOtherLayers) {
68
68
  "0\nENDSEC\n0\nEOF\n";
69
69
  const auto path = tempPath("layered.dxf");
70
70
  writeFile(path, dxf);
71
- Evaluated e = evalSrc("import(file=\"" + path.string() + "\", layer=\"keep\");");
71
+ Evaluated e = evalSrc("import(file=\"" + path.generic_string() + "\", layer=\"keep\");");
72
72
  ASSERT_EQ(e.bodies.size(), 1u);
73
73
  ASSERT_TRUE(e.bodies[0].section.has_value());
74
74
  EXPECT_NEAR(e.bodies[0].section->Area(), 1.0, 1e-6);
@@ -90,7 +90,7 @@ TEST(DxfImport, ClosedPolylineVertexEntityProducesExpectedArea) {
90
90
  "0\nENDSEC\n0\nEOF\n";
91
91
  const auto path = tempPath("polyline.dxf");
92
92
  writeFile(path, dxf);
93
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
93
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
94
94
  ASSERT_EQ(e.bodies.size(), 1u);
95
95
  ASSERT_TRUE(e.bodies[0].section.has_value());
96
96
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
@@ -111,7 +111,7 @@ TEST(DxfImport, OpenPolylineIsIgnored) {
111
111
  const auto path = tempPath("open_polyline.dxf");
112
112
  writeFile(path, dxf);
113
113
  Evaluator ev;
114
- auto ast = parseSrc("import(\"" + path.string() + "\");");
114
+ auto ast = parseSrc("import(\"" + path.generic_string() + "\");");
115
115
  auto scope = oscad::buildScopes(ast);
116
116
  EvalContext ctx = EvalContext::makeRoot(scope.get());
117
117
  EXPECT_THROW(ev.resolveTree(ast, ctx), EvalError);
@@ -131,7 +131,7 @@ TEST(DxfImport, UnrecognizedEntityIsSkipped) {
131
131
  "0\nENDSEC\n0\nEOF\n";
132
132
  const auto path = tempPath("unrecognized.dxf");
133
133
  writeFile(path, dxf);
134
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
134
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
135
135
  ASSERT_EQ(e.bodies.size(), 1u);
136
136
  ASSERT_TRUE(e.bodies[0].section.has_value());
137
137
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
@@ -143,7 +143,7 @@ TEST(DxfImport, NoClosedContoursErrors) {
143
143
  const auto path = tempPath("empty.dxf");
144
144
  writeFile(path, dxf);
145
145
  Evaluator ev;
146
- auto ast = parseSrc("import(\"" + path.string() + "\");");
146
+ auto ast = parseSrc("import(\"" + path.generic_string() + "\");");
147
147
  auto scope = oscad::buildScopes(ast);
148
148
  EvalContext ctx = EvalContext::makeRoot(scope.get());
149
149
  EXPECT_THROW(ev.resolveTree(ast, ctx), EvalError);
@@ -155,7 +155,7 @@ TEST(DxfImport, NoClosedContoursErrors) {
155
155
  TEST(SvgImport, RectProducesExpectedArea) {
156
156
  const auto path = tempPath("rect.svg");
157
157
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><rect x="0" y="0" width="4" height="3"/></svg>)");
158
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
158
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
159
159
  ASSERT_EQ(e.bodies.size(), 1u);
160
160
  ASSERT_TRUE(e.bodies[0].section.has_value());
161
161
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
@@ -167,7 +167,7 @@ TEST(SvgImport, PathWithGroupTransformIsTranslatedAndYFlipped) {
167
167
  writeFile(path, R"svg(<svg xmlns="http://www.w3.org/2000/svg">
168
168
  <g transform="translate(10,0)"><path d="M0,0 L4,0 L4,3 L0,3 Z"/></g>
169
169
  </svg>)svg");
170
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
170
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
171
171
  ASSERT_EQ(e.bodies.size(), 1u);
172
172
  ASSERT_TRUE(e.bodies[0].section.has_value());
173
173
  manifold::Rect bounds = e.bodies[0].section->Bounds();
@@ -183,7 +183,7 @@ TEST(SvgImport, PathWithGroupTransformIsTranslatedAndYFlipped) {
183
183
  TEST(SvgImport, CircleApproximatesAnalyticArea) {
184
184
  const auto path = tempPath("circle.svg");
185
185
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><circle cx="0" cy="0" r="5"/></svg>)");
186
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
186
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
187
187
  ASSERT_TRUE(e.bodies[0].section.has_value());
188
188
  EXPECT_NEAR(e.bodies[0].section->Area(), 3.14159265 * 25.0, 1.0); // 32-segment approximation
189
189
  std::filesystem::remove(path);
@@ -192,7 +192,7 @@ TEST(SvgImport, CircleApproximatesAnalyticArea) {
192
192
  TEST(SvgImport, CubicBezierPathIsWatertight) {
193
193
  const auto path = tempPath("bezier.svg");
194
194
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 C2,5 8,5 10,0 L10,-5 L0,-5 Z"/></svg>)");
195
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
195
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
196
196
  ASSERT_EQ(e.bodies.size(), 1u);
197
197
  ASSERT_TRUE(e.bodies[0].section.has_value());
198
198
  EXPECT_GT(e.bodies[0].section->Area(), 0.0);
@@ -203,7 +203,7 @@ TEST(SvgImport, NoShapesErrors) {
203
203
  const auto path = tempPath("noshapes.svg");
204
204
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><defs><rect x="0" y="0" width="1" height="1"/></defs></svg>)");
205
205
  Evaluator ev;
206
- auto ast = parseSrc("import(\"" + path.string() + "\");");
206
+ auto ast = parseSrc("import(\"" + path.generic_string() + "\");");
207
207
  auto scope = oscad::buildScopes(ast);
208
208
  EvalContext ctx = EvalContext::makeRoot(scope.get());
209
209
  EXPECT_THROW(ev.resolveTree(ast, ctx), EvalError);
@@ -220,7 +220,7 @@ TEST(SvgImport, EntityReferencesInAttributeValueDecodedWithoutCorruptingParse) {
220
220
  // area would come out wrong (or parsing would throw).
221
221
  const auto path = tempPath("entities.svg");
222
222
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><rect id="a&amp;b&lt;c&gt;d&quot;e&apos;f" x="0" y="0" width="4" height="3"/></svg>)");
223
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
223
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
224
224
  ASSERT_EQ(e.bodies.size(), 1u);
225
225
  ASSERT_TRUE(e.bodies[0].section.has_value());
226
226
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
@@ -241,7 +241,7 @@ TEST(SvgImport, CommentCdataPrologAndDoctypeAreSkipped) {
241
241
  <rect x="0" y="0" width="4" height="3"/>
242
242
  </svg>
243
243
  )");
244
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
244
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
245
245
  ASSERT_EQ(e.bodies.size(), 1u);
246
246
  ASSERT_TRUE(e.bodies[0].section.has_value());
247
247
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
@@ -253,7 +253,7 @@ TEST(SvgImport, TransformMatrixIsApplied) {
253
253
  writeFile(path, R"svg(<svg xmlns="http://www.w3.org/2000/svg">
254
254
  <g transform="matrix(2,0,0,2,5,0)"><rect x="0" y="0" width="4" height="3"/></g>
255
255
  </svg>)svg");
256
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
256
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
257
257
  ASSERT_TRUE(e.bodies[0].section.has_value());
258
258
  EXPECT_NEAR(e.bodies[0].section->Area(), 48.0, 1e-6); // 2x scale in both axes -> 4x area
259
259
  manifold::Rect bounds = e.bodies[0].section->Bounds();
@@ -267,7 +267,7 @@ TEST(SvgImport, TransformScaleWithSeparateXyIsApplied) {
267
267
  writeFile(path, R"svg(<svg xmlns="http://www.w3.org/2000/svg">
268
268
  <g transform="scale(2,3)"><rect x="0" y="0" width="4" height="3"/></g>
269
269
  </svg>)svg");
270
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
270
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
271
271
  ASSERT_TRUE(e.bodies[0].section.has_value());
272
272
  EXPECT_NEAR(e.bodies[0].section->Area(), 72.0, 1e-6); // 2x * 3x -> 6x area
273
273
  std::filesystem::remove(path);
@@ -278,7 +278,7 @@ TEST(SvgImport, TransformRotateAboutOriginIsApplied) {
278
278
  writeFile(path, R"svg(<svg xmlns="http://www.w3.org/2000/svg">
279
279
  <g transform="rotate(90)"><rect x="0" y="0" width="4" height="3"/></g>
280
280
  </svg>)svg");
281
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
281
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
282
282
  ASSERT_TRUE(e.bodies[0].section.has_value());
283
283
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6); // rotation preserves area
284
284
  manifold::Rect bounds = e.bodies[0].section->Bounds();
@@ -294,7 +294,7 @@ TEST(SvgImport, TransformRotateAboutOriginIsApplied) {
294
294
  TEST(SvgImport, HorizontalAndVerticalLineCommands) {
295
295
  const auto path = tempPath("hv.svg");
296
296
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 H4 V3 H0 Z"/></svg>)");
297
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
297
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
298
298
  ASSERT_TRUE(e.bodies[0].section.has_value());
299
299
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
300
300
  std::filesystem::remove(path);
@@ -303,7 +303,7 @@ TEST(SvgImport, HorizontalAndVerticalLineCommands) {
303
303
  TEST(SvgImport, SmoothCubicCommandFollowsCubic) {
304
304
  const auto path = tempPath("smoothcubic.svg");
305
305
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 C1,4 3,4 4,0 S7,-4 8,0 L8,-6 L0,-6 Z"/></svg>)");
306
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
306
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
307
307
  ASSERT_EQ(e.bodies.size(), 1u);
308
308
  ASSERT_TRUE(e.bodies[0].section.has_value());
309
309
  EXPECT_GT(e.bodies[0].section->Area(), 0.0);
@@ -313,7 +313,7 @@ TEST(SvgImport, SmoothCubicCommandFollowsCubic) {
313
313
  TEST(SvgImport, SmoothQuadraticCommandFollowsQuadratic) {
314
314
  const auto path = tempPath("smoothquad.svg");
315
315
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 Q2,4 4,0 T8,0 L8,-4 L0,-4 Z"/></svg>)");
316
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
316
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
317
317
  ASSERT_EQ(e.bodies.size(), 1u);
318
318
  ASSERT_TRUE(e.bodies[0].section.has_value());
319
319
  EXPECT_GT(e.bodies[0].section->Area(), 0.0);
@@ -323,7 +323,7 @@ TEST(SvgImport, SmoothQuadraticCommandFollowsQuadratic) {
323
323
  TEST(SvgImport, EllipticalArcCommand) {
324
324
  const auto path = tempPath("arc.svg");
325
325
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 A5,5 0 0,1 10,0 L10,-10 L0,-10 Z"/></svg>)");
326
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
326
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
327
327
  ASSERT_EQ(e.bodies.size(), 1u);
328
328
  ASSERT_TRUE(e.bodies[0].section.has_value());
329
329
  EXPECT_GT(e.bodies[0].section->Area(), 0.0);
@@ -333,7 +333,7 @@ TEST(SvgImport, EllipticalArcCommand) {
333
333
  TEST(SvgImport, PolygonPointsAttribute) {
334
334
  const auto path = tempPath("polygon.svg");
335
335
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><polygon points="0,0 4,0 4,3 0,3"/></svg>)");
336
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
336
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
337
337
  ASSERT_TRUE(e.bodies[0].section.has_value());
338
338
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
339
339
  std::filesystem::remove(path);
@@ -342,7 +342,7 @@ TEST(SvgImport, PolygonPointsAttribute) {
342
342
  TEST(SvgImport, PolylinePointsAttribute) {
343
343
  const auto path = tempPath("polyline.svg");
344
344
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><polyline points="0,0 4,0 4,3 0,3"/></svg>)");
345
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
345
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
346
346
  ASSERT_TRUE(e.bodies[0].section.has_value());
347
347
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
348
348
  std::filesystem::remove(path);
@@ -351,7 +351,7 @@ TEST(SvgImport, PolylinePointsAttribute) {
351
351
  TEST(SvgImport, StrayCharacterInPointsListIsSkipped) {
352
352
  const auto path = tempPath("straypoints.svg");
353
353
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><polygon points="0,0 x 4,0 4,3 0,3"/></svg>)");
354
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
354
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
355
355
  ASSERT_TRUE(e.bodies[0].section.has_value());
356
356
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
357
357
  std::filesystem::remove(path);
@@ -360,7 +360,7 @@ TEST(SvgImport, StrayCharacterInPointsListIsSkipped) {
360
360
  TEST(SvgImport, StrayCharacterInPathDataIsSkipped) {
361
361
  const auto path = tempPath("straypath.svg");
362
362
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 L4,0 @ L4,3 L0,3 Z"/></svg>)");
363
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
363
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
364
364
  ASSERT_TRUE(e.bodies[0].section.has_value());
365
365
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
366
366
  std::filesystem::remove(path);
@@ -374,7 +374,7 @@ TEST(SvgImport, TransformNumberWithExponentIsParsed) {
374
374
  writeFile(path, R"svg(<svg xmlns="http://www.w3.org/2000/svg">
375
375
  <g transform="translate(1e1,0)"><rect x="0" y="0" width="4" height="3"/></g>
376
376
  </svg>)svg");
377
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
377
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
378
378
  ASSERT_TRUE(e.bodies[0].section.has_value());
379
379
  manifold::Rect bounds = e.bodies[0].section->Bounds();
380
380
  EXPECT_NEAR(bounds.min.x, 10.0, 1e-6);
@@ -386,7 +386,7 @@ TEST(SvgImport, PathNumberWithExponentIsParsed) {
386
386
  // path `d` attribute rather than a transform argument list.
387
387
  const auto path = tempPath("exponent_path.svg");
388
388
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 L4e0,0 L4,3 L0,3 Z"/></svg>)");
389
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
389
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
390
390
  ASSERT_TRUE(e.bodies[0].section.has_value());
391
391
  EXPECT_NEAR(e.bodies[0].section->Area(), 12.0, 1e-6);
392
392
  std::filesystem::remove(path);
@@ -400,7 +400,7 @@ TEST(SvgImport, EllipticalArcWithOutOfRangeRadiiIsScaledUp) {
400
400
  // never hit this path.
401
401
  const auto path = tempPath("arc_scaled.svg");
402
402
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 A1,1 0 0,1 10,0 L10,-10 L0,-10 Z"/></svg>)");
403
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
403
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
404
404
  ASSERT_EQ(e.bodies.size(), 1u);
405
405
  ASSERT_TRUE(e.bodies[0].section.has_value());
406
406
  EXPECT_GT(e.bodies[0].section->Area(), 0.0);
@@ -413,7 +413,7 @@ TEST(SvgImport, MultipleSubpathsInOnePathProduceMultipleContours) {
413
413
  // starting a new one, distinct from an explicit `Z`.
414
414
  const auto path = tempPath("multisubpath.svg");
415
415
  writeFile(path, R"(<svg xmlns="http://www.w3.org/2000/svg"><path d="M0,0 L4,0 L4,3 L0,3 Z M10,0 L14,0 L14,3 L10,3 Z"/></svg>)");
416
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
416
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
417
417
  ASSERT_EQ(e.bodies.size(), 1u);
418
418
  ASSERT_TRUE(e.bodies[0].section.has_value());
419
419
  EXPECT_NEAR(e.bodies[0].section->Area(), 24.0, 1e-6); // two disjoint 4x3 squares
@@ -40,7 +40,7 @@ Value asExpr(const std::string& code, Evaluator& ev) {
40
40
  TEST(ImportModuleContext, StlRoundTripPreservesVolume) {
41
41
  const auto path = tempPath("cube.stl");
42
42
  writeCubeAs(path, &writeStl);
43
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
43
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
44
44
  ASSERT_EQ(e.bodies.size(), 1u);
45
45
  ASSERT_TRUE(e.bodies[0].body.has_value());
46
46
  EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
@@ -50,7 +50,7 @@ TEST(ImportModuleContext, StlRoundTripPreservesVolume) {
50
50
  TEST(ImportModuleContext, ObjRoundTripPreservesVolume) {
51
51
  const auto path = tempPath("cube.obj");
52
52
  writeCubeAs(path, &writeObj);
53
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
53
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
54
54
  ASSERT_EQ(e.bodies.size(), 1u);
55
55
  ASSERT_TRUE(e.bodies[0].body.has_value());
56
56
  EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
@@ -60,7 +60,7 @@ TEST(ImportModuleContext, ObjRoundTripPreservesVolume) {
60
60
  TEST(ImportModuleContext, OffRoundTripPreservesVolume) {
61
61
  const auto path = tempPath("cube.off");
62
62
  writeCubeAs(path, &writeOff);
63
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
63
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
64
64
  ASSERT_EQ(e.bodies.size(), 1u);
65
65
  ASSERT_TRUE(e.bodies[0].body.has_value());
66
66
  EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
@@ -70,7 +70,7 @@ TEST(ImportModuleContext, OffRoundTripPreservesVolume) {
70
70
  TEST(ImportModuleContext, ThreeMfRoundTripPreservesVolume) {
71
71
  const auto path = tempPath("cube.3mf");
72
72
  writeCubeAs(path, &writeThreeMf);
73
- Evaluated e = evalSrc("import(\"" + path.string() + "\");");
73
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");");
74
74
  ASSERT_EQ(e.bodies.size(), 1u);
75
75
  ASSERT_TRUE(e.bodies[0].body.has_value());
76
76
  EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
@@ -100,7 +100,7 @@ TEST(ImportModuleContext, JsonExtensionErrorsAsGeometryStatement) {
100
100
  out << R"({"a": 1})";
101
101
  }
102
102
  Evaluator ev;
103
- auto ast = parseSrc("import(\"" + path.string() + "\");");
103
+ auto ast = parseSrc("import(\"" + path.generic_string() + "\");");
104
104
  auto scope = oscad::buildScopes(ast);
105
105
  EvalContext ctx = EvalContext::makeRoot(scope.get());
106
106
  EXPECT_THROW(ev.resolveTree(ast, ctx), EvalError);
@@ -118,7 +118,7 @@ TEST(ImportModuleContext, MalformedMeshFileErrors) {
118
118
  out << "this is not a valid STL file at all";
119
119
  }
120
120
  Evaluator ev;
121
- auto ast = parseSrc("import(\"" + path.string() + "\");");
121
+ auto ast = parseSrc("import(\"" + path.generic_string() + "\");");
122
122
  auto scope = oscad::buildScopes(ast);
123
123
  EvalContext ctx = EvalContext::makeRoot(scope.get());
124
124
  EXPECT_THROW(ev.resolveTree(ast, ctx), EvalError);
@@ -136,7 +136,7 @@ TEST(ImportModuleContext, NonManifoldMeshWarns) {
136
136
  out << "OFF\n3 1 0\n0 0 0\n1 0 0\n0 1 0\n3 0 1 2\n";
137
137
  }
138
138
  std::string lastWarning;
139
- Evaluated e = evalSrc("import(\"" + path.string() + "\");", [&](const std::string& msg) { lastWarning = msg; });
139
+ Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");", [&](const std::string& msg) { lastWarning = msg; });
140
140
  EXPECT_NE(lastWarning.find("import: mesh is not a closed solid"), std::string::npos);
141
141
  // The triangle is now handed back for display rather than dropped: a
142
142
  // file that warns once and then shows nothing gives no way to see what
@@ -158,7 +158,7 @@ TEST(ImportModuleContext, EmptyMeshHasNoTrianglesErrors) {
158
158
  std::ofstream out(path);
159
159
  out << "OFF\n0 0 0\n";
160
160
  }
161
- EXPECT_THROW(evalSrc("import(\"" + path.string() + "\");"), EvalError);
161
+ EXPECT_THROW(evalSrc("import(\"" + path.generic_string() + "\");"), EvalError);
162
162
  std::filesystem::remove(path);
163
163
  }
164
164
 
@@ -168,7 +168,7 @@ TEST(ImportExpressionContext, StlReturnsVnfShape) {
168
168
  const auto path = tempPath("cube_vnf.stl");
169
169
  writeCubeAs(path, &writeStl);
170
170
  Evaluator ev;
171
- Value v = asExpr("import(\"" + path.string() + "\")", ev);
171
+ Value v = asExpr("import(\"" + path.generic_string() + "\")", ev);
172
172
  const auto& outer = std::get<ListPtr>(v)->items;
173
173
  ASSERT_EQ(outer.size(), 2u);
174
174
  const auto& verts = std::get<ListPtr>(outer[0])->items;
@@ -185,7 +185,7 @@ TEST(ImportExpressionContext, JsonReturnsNativeValues) {
185
185
  out << R"({"name": "x", "n": 3, "nested": {"a": 1, "b": 2}, "list": [1, 2, 3]})";
186
186
  }
187
187
  Evaluator ev;
188
- Value v = asExpr("import(\"" + path.string() + "\")", ev);
188
+ Value v = asExpr("import(\"" + path.generic_string() + "\")", ev);
189
189
  const auto& obj = std::get<ObjectPtr>(v)->items;
190
190
  ASSERT_EQ(obj.size(), 4u);
191
191
  EXPECT_EQ(obj[0].first, "name");
@@ -211,7 +211,7 @@ TEST(ImportExpressionContext, JsonNullValueBecomesUndef) {
211
211
  out << R"({"x": null})";
212
212
  }
213
213
  Evaluator ev;
214
- Value v = asExpr("import(\"" + path.string() + "\")", ev);
214
+ Value v = asExpr("import(\"" + path.generic_string() + "\")", ev);
215
215
  const auto& obj = std::get<ObjectPtr>(v)->items;
216
216
  ASSERT_EQ(obj.size(), 1u);
217
217
  EXPECT_TRUE(std::holds_alternative<std::monostate>(obj[0].second));
@@ -227,7 +227,7 @@ TEST(ImportExpressionContext, DxfReturnsRegionContours) {
227
227
  "0\nENDSEC\n0\nEOF\n";
228
228
  }
229
229
  Evaluator ev;
230
- Value v = asExpr("import(\"" + path.string() + "\")", ev);
230
+ Value v = asExpr("import(\"" + path.generic_string() + "\")", ev);
231
231
  const auto& contours = std::get<ListPtr>(v)->items;
232
232
  ASSERT_EQ(contours.size(), 1u);
233
233
  std::filesystem::remove(path);
@@ -250,7 +250,7 @@ TEST(ImportExpressionContext, MalformedMeshFileErrors) {
250
250
  out << "not a valid STL file";
251
251
  }
252
252
  Evaluator ev;
253
- EXPECT_THROW(asExpr("import(\"" + path.string() + "\")", ev), EvalError);
253
+ EXPECT_THROW(asExpr("import(\"" + path.generic_string() + "\")", ev), EvalError);
254
254
  std::filesystem::remove(path);
255
255
  }
256
256
 
@@ -46,7 +46,7 @@ TEST(Surface, DatFileHeightsMatchExactVertexPositions) {
46
46
  // reference on this shape (12 triangles, bbox [0,0,0]-[2,2,5]).
47
47
  const auto path = tempPath("terrain.dat");
48
48
  writeDat(path, {{0, 0, 0}, {0, 5, 0}, {0, 0, 0}});
49
- Evaluated e = evalSrc("surface(file=\"" + path.string() + "\", center=false);");
49
+ Evaluated e = evalSrc("surface(file=\"" + path.generic_string() + "\", center=false);");
50
50
  ASSERT_EQ(e.bodies.size(), 1u);
51
51
  ASSERT_TRUE(e.bodies[0].body.has_value());
52
52
  manifold::Box bbox = e.bodies[0].body->BoundingBox();
@@ -60,7 +60,7 @@ TEST(Surface, DatFileHeightsMatchExactVertexPositions) {
60
60
  TEST(Surface, CenterTrueOffsetsXyAroundOrigin) {
61
61
  const auto path = tempPath("terrain_center.dat");
62
62
  writeDat(path, {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}});
63
- Evaluated e = evalSrc("surface(file=\"" + path.string() + "\", center=true);");
63
+ Evaluated e = evalSrc("surface(file=\"" + path.generic_string() + "\", center=true);");
64
64
  manifold::Box bbox = e.bodies[0].body->BoundingBox();
65
65
  EXPECT_NEAR(bbox.min.x, -1.0, 1e-9); // (cols-1)/2 = 1
66
66
  EXPECT_NEAR(bbox.max.x, 1.0, 1e-9);
@@ -70,7 +70,7 @@ TEST(Surface, CenterTrueOffsetsXyAroundOrigin) {
70
70
  TEST(Surface, FlatGridVolumeMatchesFootprintTimesHeight) {
71
71
  const auto path = tempPath("flat.dat");
72
72
  writeDat(path, {{3, 3, 3}, {3, 3, 3}, {3, 3, 3}});
73
- Evaluated e = evalSrc("surface(file=\"" + path.string() + "\");");
73
+ Evaluated e = evalSrc("surface(file=\"" + path.generic_string() + "\");");
74
74
  ASSERT_TRUE(e.bodies[0].body.has_value());
75
75
  EXPECT_NEAR(e.bodies[0].body->Volume(), 2.0 * 2.0 * 3.0, 1e-6); // (cols-1)*(rows-1)*height
76
76
  std::filesystem::remove(path);
@@ -80,7 +80,7 @@ TEST(Surface, EmptyFileErrors) {
80
80
  const auto path = tempPath("empty.dat");
81
81
  writeDat(path, {});
82
82
  Evaluator ev;
83
- auto ast = parseSrc("surface(file=\"" + path.string() + "\");");
83
+ auto ast = parseSrc("surface(file=\"" + path.generic_string() + "\");");
84
84
  auto scope = oscad::buildScopes(ast);
85
85
  EvalContext ctx = EvalContext::makeRoot(scope.get());
86
86
  EXPECT_THROW(ev.resolveTree(ast, ctx), EvalError);
@@ -92,7 +92,7 @@ TEST(Surface, EmptyFileErrors) {
92
92
  TEST(Surface, UniformGrayImageVolumeMatchesLuminanceFormula) {
93
93
  const auto path = tempPath("flat.png");
94
94
  writeGrayscalePng(path, 3, 3, std::vector<unsigned char>(9, 128));
95
- Evaluated e = evalSrc("surface(file=\"" + path.string() + "\");");
95
+ Evaluated e = evalSrc("surface(file=\"" + path.generic_string() + "\");");
96
96
  ASSERT_TRUE(e.bodies[0].body.has_value());
97
97
  // gray=128 (r=g=b, so the weighted luminance formula reduces to the
98
98
  // input value exactly) -> height = 128/255*100.
@@ -104,8 +104,8 @@ TEST(Surface, UniformGrayImageVolumeMatchesLuminanceFormula) {
104
104
  TEST(Surface, InvertFlipsTheHeightMapping) {
105
105
  const auto path = tempPath("flat2.png");
106
106
  writeGrayscalePng(path, 3, 3, std::vector<unsigned char>(9, 200));
107
- Evaluated normal = evalSrc("surface(file=\"" + path.string() + "\", invert=false);");
108
- Evaluated inverted = evalSrc("surface(file=\"" + path.string() + "\", invert=true);");
107
+ Evaluated normal = evalSrc("surface(file=\"" + path.generic_string() + "\", invert=false);");
108
+ Evaluated inverted = evalSrc("surface(file=\"" + path.generic_string() + "\", invert=true);");
109
109
  const double heightNormal = 200.0 / 255.0 * 100.0;
110
110
  const double heightInverted = (255.0 - 200.0) / 255.0 * 100.0;
111
111
  EXPECT_NEAR(normal.bodies[0].body->Volume(), 2.0 * 2.0 * heightNormal, heightNormal * 2e-3);
@@ -121,7 +121,7 @@ TEST(Surface, ImageRowOrderMatchesBottomRowIsYZero) {
121
121
  const auto path = tempPath("rowcheck.png");
122
122
  std::vector<unsigned char> px = {0, 0, 255, 255}; // row0: black,black ; row1: white,white
123
123
  writeGrayscalePng(path, 2, 2, px);
124
- Evaluated e = evalSrc("surface(file=\"" + path.string() + "\");");
124
+ Evaluated e = evalSrc("surface(file=\"" + path.generic_string() + "\");");
125
125
  ASSERT_TRUE(e.bodies[0].body.has_value());
126
126
  // Slice a thin box at low Y (y in [0,0.5]) and confirm it reaches the
127
127
  // white row's full height (100), not the black row's height (0).