openscad-cpp-evaluator 1.22.0__tar.gz → 1.24.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +8 -3
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/CMakeLists.txt +10 -1
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/api.cpp +118 -28
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +86 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/evaluator.hpp +12 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +17 -3
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/CMakeLists.txt +34 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/function_builtins.cpp +0 -32
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/primitives_3d.cpp +49 -6
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/topology.cpp +0 -12
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/csg_generate.cpp +33 -3
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/expr_eval.cpp +7 -3
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/manifold_cache.cpp +3 -3
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/value.cpp +0 -30
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/CMakeLists.txt +4 -1
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_csg_tree.cpp +49 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_manifold_cache.cpp +63 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/uv.lock +0 -0
|
@@ -136,9 +136,14 @@ struct LibraryFileResult {
|
|
|
136
136
|
LibraryFileResult getASTFromLibraryFile(const std::string& currFile, const std::string& libFile,
|
|
137
137
|
bool includeComments = false, bool processIncludes = true);
|
|
138
138
|
|
|
139
|
-
// OpenSCAD's library search path: (1) directory of currFile,
|
|
140
|
-
// OPENSCADPATH
|
|
141
|
-
//
|
|
139
|
+
// OpenSCAD's library search path, in order: (1) directory of currFile,
|
|
140
|
+
// (2) each OPENSCADPATH entry (':'-separated on POSIX, ';' on Windows),
|
|
141
|
+
// (3) the user's own libraries folder, (4) libraries shipped beside this
|
|
142
|
+
// binary. OPENSCADPATH ADDS to (3) and (4) rather than replacing them,
|
|
143
|
+
// which is what OpenSCAD's own parser_init() does.
|
|
144
|
+
std::vector<std::string> librarySearchDirs(const std::string& currFile);
|
|
145
|
+
|
|
146
|
+
// The first entry of librarySearchDirs() that holds `libFile`.
|
|
142
147
|
std::optional<std::string> findLibraryFile(const std::string& currFile, const std::string& libFile);
|
|
143
148
|
|
|
144
149
|
// A file's statements with its `include <...>` directives resolved, where
|
|
@@ -38,7 +38,16 @@ target_include_directories(openscad_cpp_parser PRIVATE
|
|
|
38
38
|
${CMAKE_CURRENT_SOURCE_DIR}/grammar
|
|
39
39
|
${CMAKE_CURRENT_BINARY_DIR}
|
|
40
40
|
)
|
|
41
|
-
|
|
41
|
+
# CMAKE_DL_LIBS is -ldl for api.cpp's dladdr() -- empty on macOS and
|
|
42
|
+
# Windows, where it lives in libSystem/kernel32. A local macOS build
|
|
43
|
+
# therefore links fine and manylinux (glibc < 2.34, dl still a separate
|
|
44
|
+
# library) does not: caught only by a wheel build.
|
|
45
|
+
target_link_libraries(openscad_cpp_parser PUBLIC nlohmann_json::nlohmann_json ${CMAKE_DL_LIBS})
|
|
46
|
+
# SHGetFolderPathW, for the real My Documents rather than an assumed
|
|
47
|
+
# %USERPROFILE%\Documents -- see api.cpp userLibraryDir().
|
|
48
|
+
if(WIN32)
|
|
49
|
+
target_link_libraries(openscad_cpp_parser PUBLIC shell32)
|
|
50
|
+
endif()
|
|
42
51
|
target_compile_options(openscad_cpp_parser PRIVATE
|
|
43
52
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall;-Wextra>
|
|
44
53
|
)
|
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
#include <cstdlib>
|
|
9
9
|
#include <filesystem>
|
|
10
|
+
#if defined(_WIN32)
|
|
11
|
+
// NOMINMAX or windows.h's max()/min() macros eat std::max below -- MSVC
|
|
12
|
+
// caught it as "illegal token on right side of '::'", which names neither
|
|
13
|
+
// the macro nor the header.
|
|
14
|
+
#define NOMINMAX
|
|
15
|
+
#define WIN32_LEAN_AND_MEAN
|
|
16
|
+
#include <windows.h>
|
|
17
|
+
#include <shlobj.h>
|
|
18
|
+
#else
|
|
19
|
+
#include <dlfcn.h>
|
|
20
|
+
#endif
|
|
10
21
|
#include <fstream>
|
|
11
22
|
#include <set>
|
|
12
23
|
#include <system_error>
|
|
@@ -133,6 +144,22 @@ std::vector<std::unique_ptr<ASTNode>> getASTFromString(const std::string& code,
|
|
|
133
144
|
|
|
134
145
|
namespace {
|
|
135
146
|
|
|
147
|
+
// A "not found" that says where we actually looked. The old message named
|
|
148
|
+
// only the includer, so "searched relative to X" read as "only X was
|
|
149
|
+
// searched" -- which is how #503 came to be filed against a search that
|
|
150
|
+
// does cover the libraries folder.
|
|
151
|
+
std::string notFound(const char* noun, const std::string& filename, const std::string& currentFile) {
|
|
152
|
+
std::string msg = std::string(noun) + " '" + filename + "' not found. Searched:";
|
|
153
|
+
for (const auto& d : librarySearchDirs(currentFile)) {
|
|
154
|
+
msg += "\n " + d;
|
|
155
|
+
}
|
|
156
|
+
return msg;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
} // namespace
|
|
160
|
+
|
|
161
|
+
namespace {
|
|
162
|
+
|
|
136
163
|
std::string readFile(const std::string& path) {
|
|
137
164
|
std::ifstream in(path, std::ios::binary);
|
|
138
165
|
if (!in) {
|
|
@@ -163,8 +190,7 @@ std::vector<std::unique_ptr<ASTNode>> resolveIncludes(std::vector<std::unique_pt
|
|
|
163
190
|
const std::string& filename = inc.filepath->val;
|
|
164
191
|
auto libFile = findLibraryFile(currentFile, filename);
|
|
165
192
|
if (!libFile) {
|
|
166
|
-
throw std::runtime_error("Included file
|
|
167
|
-
(currentFile.empty() ? "current directory" : currentFile));
|
|
193
|
+
throw std::runtime_error(notFound("Included file", filename, currentFile));
|
|
168
194
|
}
|
|
169
195
|
std::string absLib = fs::absolute(*libFile).string();
|
|
170
196
|
if (visited.count(absLib) != 0) {
|
|
@@ -185,40 +211,98 @@ std::vector<std::unique_ptr<ASTNode>> resolveIncludes(std::vector<std::unique_pt
|
|
|
185
211
|
|
|
186
212
|
} // namespace
|
|
187
213
|
|
|
188
|
-
|
|
189
|
-
std::vector<fs::path> dirs;
|
|
190
|
-
if (!currFile.empty()) {
|
|
191
|
-
dirs.push_back(fs::absolute(currFile).parent_path());
|
|
192
|
-
}
|
|
214
|
+
namespace {
|
|
193
215
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
216
|
+
// The user's own libraries folder -- OpenSCAD's
|
|
217
|
+
// PlatformUtils::userLibraryPath(), and the one an installer or a git clone
|
|
218
|
+
// of BOSL2 lands in.
|
|
219
|
+
std::string userLibraryDir() {
|
|
197
220
|
#if defined(_WIN32)
|
|
198
|
-
|
|
221
|
+
// ASK Windows where My Documents is rather than assuming
|
|
222
|
+
// %USERPROFILE%\Documents. OneDrive's Known Folder Move -- on by default
|
|
223
|
+
// on a new machine -- relocates it to %USERPROFILE%\OneDrive\Documents,
|
|
224
|
+
// and a library OpenSCAD itself installed then sat somewhere we never
|
|
225
|
+
// looked (BelfrySCAD #503). Same call and same flag OpenSCAD makes
|
|
226
|
+
// (PlatformUtils-win.cc getFolderPath).
|
|
227
|
+
wchar_t buf[MAX_PATH] = {0};
|
|
228
|
+
if (SHGetFolderPathW(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_CURRENT, buf) == S_OK) {
|
|
229
|
+
return (fs::path(buf) / "OpenSCAD" / "libraries").string();
|
|
230
|
+
}
|
|
199
231
|
const char* userProfile = std::getenv("USERPROFILE");
|
|
200
|
-
|
|
201
|
-
|
|
232
|
+
return userProfile ? (fs::path(userProfile) / "Documents" / "OpenSCAD" / "libraries").string()
|
|
233
|
+
: std::string();
|
|
234
|
+
#else
|
|
235
|
+
const char* home = std::getenv("HOME");
|
|
236
|
+
if (!home) {
|
|
237
|
+
return {};
|
|
202
238
|
}
|
|
203
|
-
#
|
|
204
|
-
|
|
205
|
-
|
|
239
|
+
#if defined(__APPLE__)
|
|
240
|
+
return (fs::path(home) / "Documents" / "OpenSCAD" / "libraries").string();
|
|
241
|
+
#else
|
|
242
|
+
return (fs::path(home) / ".local" / "share" / "OpenSCAD" / "libraries").string();
|
|
243
|
+
#endif
|
|
244
|
+
#endif
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Libraries shipped alongside this build -- OpenSCAD's
|
|
248
|
+
// PlatformUtils::resourcePath("libraries"). "Alongside" means beside the
|
|
249
|
+
// binary this code was linked into: the CLI executable, or the Python
|
|
250
|
+
// extension inside its installed package.
|
|
251
|
+
// ponytail: one candidate directory, no ../share/openscad/libraries walk --
|
|
252
|
+
// add the walk if a packaging layout ever puts the libraries somewhere
|
|
253
|
+
// other than next to the binary.
|
|
254
|
+
std::string bundledLibraryDir() {
|
|
255
|
+
fs::path self;
|
|
256
|
+
#if defined(_WIN32)
|
|
257
|
+
HMODULE mod = nullptr;
|
|
258
|
+
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
|
259
|
+
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
|
260
|
+
reinterpret_cast<LPCWSTR>(&userLibraryDir), &mod)) {
|
|
261
|
+
wchar_t buf[MAX_PATH] = {0};
|
|
262
|
+
if (GetModuleFileNameW(mod, buf, MAX_PATH)) {
|
|
263
|
+
self = buf;
|
|
264
|
+
}
|
|
206
265
|
}
|
|
207
266
|
#else
|
|
208
|
-
|
|
209
|
-
|
|
267
|
+
Dl_info info;
|
|
268
|
+
if (dladdr(reinterpret_cast<void*>(&userLibraryDir), &info) && info.dli_fname) {
|
|
269
|
+
self = info.dli_fname;
|
|
210
270
|
}
|
|
211
271
|
#endif
|
|
272
|
+
if (self.empty()) {
|
|
273
|
+
return {};
|
|
274
|
+
}
|
|
275
|
+
std::error_code ec;
|
|
276
|
+
return (fs::absolute(self, ec).parent_path() / "libraries").string();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
} // namespace
|
|
212
280
|
|
|
281
|
+
std::vector<std::string> librarySearchDirs(const std::string& currFile) {
|
|
282
|
+
std::vector<std::string> dirs;
|
|
283
|
+
if (!currFile.empty()) {
|
|
284
|
+
dirs.push_back(fs::absolute(currFile).parent_path().string());
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#if defined(_WIN32)
|
|
288
|
+
const char pathsep = ';';
|
|
289
|
+
#else
|
|
290
|
+
const char pathsep = ':';
|
|
291
|
+
#endif
|
|
292
|
+
|
|
293
|
+
// OPENSCADPATH comes FIRST and adds to the built-in paths rather than
|
|
294
|
+
// replacing them -- exactly what OpenSCAD's parser_init() does. It used
|
|
295
|
+
// to replace them, so setting the variable for one library hid every
|
|
296
|
+
// other, including a BOSL2 sitting in the default folder (#503).
|
|
213
297
|
const char* envPath = std::getenv("OPENSCADPATH");
|
|
214
|
-
|
|
215
|
-
|
|
298
|
+
if (envPath) {
|
|
299
|
+
std::string env(envPath);
|
|
216
300
|
size_t start = 0;
|
|
217
301
|
while (start <= env.size()) {
|
|
218
302
|
size_t pos = env.find(pathsep, start);
|
|
219
303
|
std::string part = (pos == std::string::npos) ? env.substr(start) : env.substr(start, pos - start);
|
|
220
304
|
if (!part.empty()) {
|
|
221
|
-
dirs.
|
|
305
|
+
dirs.push_back(part);
|
|
222
306
|
}
|
|
223
307
|
if (pos == std::string::npos) {
|
|
224
308
|
break;
|
|
@@ -227,8 +311,17 @@ std::optional<std::string> findLibraryFile(const std::string& currFile, const st
|
|
|
227
311
|
}
|
|
228
312
|
}
|
|
229
313
|
|
|
230
|
-
for (const
|
|
231
|
-
|
|
314
|
+
for (const std::string& d : {userLibraryDir(), bundledLibraryDir()}) {
|
|
315
|
+
if (!d.empty()) {
|
|
316
|
+
dirs.push_back(d);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return dirs;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
std::optional<std::string> findLibraryFile(const std::string& currFile, const std::string& libFile) {
|
|
323
|
+
for (const auto& d : librarySearchDirs(currFile)) {
|
|
324
|
+
fs::path candidate = fs::path(d) / libFile;
|
|
232
325
|
std::error_code ec;
|
|
233
326
|
if (fs::is_regular_file(candidate, ec)) {
|
|
234
327
|
return candidate.string();
|
|
@@ -255,9 +348,7 @@ LibraryFileResult getASTFromLibraryFile(const std::string& currFile, const std::
|
|
|
255
348
|
bool processIncludes) {
|
|
256
349
|
auto found = findLibraryFile(currFile, libFile);
|
|
257
350
|
if (!found) {
|
|
258
|
-
throw std::runtime_error("Library file
|
|
259
|
-
"' not found in search paths. Searched in: current file directory, OPENSCADPATH, and "
|
|
260
|
-
"platform default paths.");
|
|
351
|
+
throw std::runtime_error(notFound("Library file", libFile, currFile));
|
|
261
352
|
}
|
|
262
353
|
auto ast = getASTFromFile(*found, includeComments, processIncludes);
|
|
263
354
|
return LibraryFileResult{std::move(ast), *found};
|
|
@@ -346,8 +437,7 @@ void collectProgram(const FileAst& nodes, const std::string& currentFile, bool i
|
|
|
346
437
|
const std::string& filename = inc.filepath->val;
|
|
347
438
|
auto libFile = findLibraryFile(currentFile, filename);
|
|
348
439
|
if (!libFile) {
|
|
349
|
-
throw std::runtime_error("Included file
|
|
350
|
-
(currentFile.empty() ? "current directory" : currentFile));
|
|
440
|
+
throw std::runtime_error(notFound("Included file", filename, currentFile));
|
|
351
441
|
}
|
|
352
442
|
std::string absLib = fs::absolute(*libFile).string();
|
|
353
443
|
if (!visited.insert(absLib).second) continue;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
#include <gtest/gtest.h>
|
|
4
4
|
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
#include <cstdlib>
|
|
5
7
|
#include <filesystem>
|
|
6
8
|
#include <fstream>
|
|
7
9
|
#include <random>
|
|
@@ -138,3 +140,87 @@ TEST(FileApi, FindLibraryFileReturnsNulloptWhenMissing) {
|
|
|
138
140
|
auto found = findLibraryFile("", "definitely_missing_file_xyz.scad");
|
|
139
141
|
EXPECT_FALSE(found.has_value());
|
|
140
142
|
}
|
|
143
|
+
|
|
144
|
+
namespace {
|
|
145
|
+
|
|
146
|
+
// RAII OPENSCADPATH, so one test's setting cannot leak into the next.
|
|
147
|
+
class ScopedOpenscadPath {
|
|
148
|
+
public:
|
|
149
|
+
explicit ScopedOpenscadPath(const std::string& value) {
|
|
150
|
+
const char* prev = std::getenv("OPENSCADPATH");
|
|
151
|
+
had_ = prev != nullptr;
|
|
152
|
+
if (had_) prev_ = prev;
|
|
153
|
+
set(value.c_str());
|
|
154
|
+
}
|
|
155
|
+
~ScopedOpenscadPath() {
|
|
156
|
+
if (had_) {
|
|
157
|
+
set(prev_.c_str());
|
|
158
|
+
} else {
|
|
159
|
+
#if defined(_WIN32)
|
|
160
|
+
_putenv_s("OPENSCADPATH", "");
|
|
161
|
+
#else
|
|
162
|
+
unsetenv("OPENSCADPATH");
|
|
163
|
+
#endif
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
private:
|
|
167
|
+
static void set(const char* v) {
|
|
168
|
+
#if defined(_WIN32)
|
|
169
|
+
_putenv_s("OPENSCADPATH", v);
|
|
170
|
+
#else
|
|
171
|
+
setenv("OPENSCADPATH", v, 1);
|
|
172
|
+
#endif
|
|
173
|
+
}
|
|
174
|
+
bool had_ = false;
|
|
175
|
+
std::string prev_;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
} // namespace
|
|
179
|
+
|
|
180
|
+
TEST(FileApi, OpenscadPathAddsToTheBuiltInDirsRatherThanReplacingThem) {
|
|
181
|
+
// BelfrySCAD #503: `env = envPath ? envPath : dfltPath` meant setting
|
|
182
|
+
// OPENSCADPATH for one library hid every library in the default folder.
|
|
183
|
+
std::vector<std::string> without = librarySearchDirs("");
|
|
184
|
+
TempDir dir;
|
|
185
|
+
ScopedOpenscadPath scoped(dir.path().string());
|
|
186
|
+
std::vector<std::string> with = librarySearchDirs("");
|
|
187
|
+
|
|
188
|
+
EXPECT_EQ(with.size(), without.size() + 1);
|
|
189
|
+
EXPECT_EQ(with.front(), dir.path().string()); // and it is searched FIRST
|
|
190
|
+
for (const auto& d : without) {
|
|
191
|
+
EXPECT_NE(std::find(with.begin(), with.end(), d), with.end()) << d;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
TEST(FileApi, FindLibraryFileSearchesOpenscadPath) {
|
|
196
|
+
TempDir libs;
|
|
197
|
+
fs::create_directories(libs.path() / "MYLIB");
|
|
198
|
+
fs::path libFile = libs.path() / "MYLIB" / "std.scad";
|
|
199
|
+
writeFile(libFile, "x = 1;\n");
|
|
200
|
+
|
|
201
|
+
TempDir docs;
|
|
202
|
+
fs::path mainFile = docs.path() / "main.scad";
|
|
203
|
+
writeFile(mainFile, "x = 1;\n");
|
|
204
|
+
|
|
205
|
+
ScopedOpenscadPath scoped(libs.path().string());
|
|
206
|
+
auto found = findLibraryFile(mainFile.string(), "MYLIB/std.scad");
|
|
207
|
+
ASSERT_TRUE(found.has_value());
|
|
208
|
+
EXPECT_EQ(fs::path(*found), libFile);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
TEST(FileApi, MissingIncludeErrorNamesEveryDirectorySearched) {
|
|
212
|
+
TempDir dir;
|
|
213
|
+
fs::path mainFile = dir.path() / "main.scad";
|
|
214
|
+
writeFile(mainFile, "include <NOPE/std.scad>\n");
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
getASTFromFile(mainFile.string());
|
|
218
|
+
FAIL() << "expected a missing-include error";
|
|
219
|
+
} catch (const std::runtime_error& e) {
|
|
220
|
+
std::string msg = e.what();
|
|
221
|
+
EXPECT_NE(msg.find("NOPE/std.scad"), std::string::npos) << msg;
|
|
222
|
+
for (const auto& d : librarySearchDirs(mainFile.string())) {
|
|
223
|
+
EXPECT_NE(msg.find(d), std::string::npos) << msg;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -398,6 +398,14 @@ public:
|
|
|
398
398
|
// than anything reentrancy-aware, since generateTreeImpl recurses
|
|
399
399
|
// depth-first on one thread.
|
|
400
400
|
const oscad::Position* generateWarnEntry = nullptr;
|
|
401
|
+
// Non-null while generateTreeImpl() is generating a subtree whose result
|
|
402
|
+
// it intends to cache: warn() appends each formatted line here as well as
|
|
403
|
+
// emitting it, so the entry can replay them on a later hit. Saved and
|
|
404
|
+
// restored around each node rather than left set, and the inner vector is
|
|
405
|
+
// merged into the outer one on the way out, so a parent's entry carries
|
|
406
|
+
// everything its whole subtree said -- which is what a parent-level hit
|
|
407
|
+
// has to reproduce, since it skips all of it. See ManifoldCache.
|
|
408
|
+
std::vector<std::string>* warnCapture = nullptr;
|
|
401
409
|
// The same republish for CSGNode::callChain, read by tagGenerated to
|
|
402
410
|
// fill idToCallChain.
|
|
403
411
|
uint32_t generateCallChain = kNoCallChain;
|
|
@@ -530,6 +538,10 @@ public:
|
|
|
530
538
|
// Public: builtins/import.cpp's not-manifold warning is emitted from a
|
|
531
539
|
// free function, same reasoning as tagGenerated()/builtinChildren().
|
|
532
540
|
void warn(const std::string& message, const oscad::Position* position);
|
|
541
|
+
// Hands one already-formatted warning line to echoFn_, recording it in
|
|
542
|
+
// warnCapture first when one is active. Every warning path goes through
|
|
543
|
+
// here, including a ManifoldCache hit replaying a cached line.
|
|
544
|
+
void emitWarning(const std::string& formatted);
|
|
533
545
|
|
|
534
546
|
// Applies OpenSCAD's mixed-2D/3D rules to a node's children just
|
|
535
547
|
// before its GenerateFn runs -- see csg_generate.cpp.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include "openscad_cpp_evaluator/csg_node.hpp"
|
|
4
4
|
|
|
5
5
|
#include <mutex>
|
|
6
|
+
#include <vector>
|
|
6
7
|
#include <optional>
|
|
7
8
|
#include <string>
|
|
8
9
|
#include <unordered_map>
|
|
@@ -22,15 +23,28 @@ namespace oscadeval {
|
|
|
22
23
|
// threading.Lock -- a host may run renders/evaluates on a background
|
|
23
24
|
// thread while another operation reads/clears the same cache). Mirrors
|
|
24
25
|
// the reference's ManifoldCache class.
|
|
26
|
+
// What one cache entry holds. The warnings matter as much as the bodies:
|
|
27
|
+
// a hit skips the whole subtree's GenerateFn, and every generate-time
|
|
28
|
+
// diagnostic is raised *inside* one of those (polyhedron's "mesh is not
|
|
29
|
+
// closed", import()'s failures, the dimension rules). Cached without them,
|
|
30
|
+
// a second render of unchanged source silently dropped every warning the
|
|
31
|
+
// first one raised, so a real defect looked intermittent and the author
|
|
32
|
+
// went hunting for a phantom. A cache has to be transparent; that includes
|
|
33
|
+
// what it says, not only what it draws. See BelfrySCAD issue #521.
|
|
34
|
+
struct CachedSubtree {
|
|
35
|
+
std::vector<ColoredBody> bodies;
|
|
36
|
+
std::vector<std::string> warnings; // already formatted, replayed verbatim
|
|
37
|
+
};
|
|
38
|
+
|
|
25
39
|
class ManifoldCache {
|
|
26
40
|
public:
|
|
27
|
-
std::optional<
|
|
28
|
-
void put(std::string key, std::vector<ColoredBody> bodies);
|
|
41
|
+
std::optional<CachedSubtree> get(const std::string& key) const;
|
|
42
|
+
void put(std::string key, std::vector<ColoredBody> bodies, std::vector<std::string> warnings);
|
|
29
43
|
void clear();
|
|
30
44
|
|
|
31
45
|
private:
|
|
32
46
|
mutable std::mutex mutex_;
|
|
33
|
-
std::unordered_map<std::string,
|
|
47
|
+
std::unordered_map<std::string, CachedSubtree> entries_;
|
|
34
48
|
};
|
|
35
49
|
|
|
36
50
|
// Structural content-hash key for `node`, used by generateTree()'s
|
|
@@ -69,3 +69,37 @@ target_link_libraries(openscad_cpp_evaluator PRIVATE linenoise freetype harfbuzz
|
|
|
69
69
|
target_compile_options(openscad_cpp_evaluator PRIVATE
|
|
70
70
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall;-Wextra>
|
|
71
71
|
)
|
|
72
|
+
|
|
73
|
+
# -Wall -Wextra above is about OUR code, but two TUs pull a vendored header
|
|
74
|
+
# in wholesale and inherit its warnings: 27 from Boost.Polygon's voronoi
|
|
75
|
+
# headers and 9 from stb_image_write's implementation, against 5 that were
|
|
76
|
+
# real. Silenced per source file, per warning.
|
|
77
|
+
#
|
|
78
|
+
# Deliberately NOT -isystem, which looks like the tidier fix and is a trap:
|
|
79
|
+
# clang searches -isystem AFTER /usr/local/include, so a Homebrew Boost
|
|
80
|
+
# 1.90 silently won over the pinned 1.86 (measured, not assumed). Keeping
|
|
81
|
+
# -I keeps the fetched copy winning.
|
|
82
|
+
include(CheckCXXCompilerFlag)
|
|
83
|
+
foreach(_w deprecated-enum-float-conversion missing-field-initializers deprecated-declarations)
|
|
84
|
+
check_cxx_compiler_flag("-Wno-${_w}" OSCAD_HAS_WNO_${_w})
|
|
85
|
+
endforeach()
|
|
86
|
+
|
|
87
|
+
if(OSCAD_HAS_WNO_deprecated-enum-float-conversion)
|
|
88
|
+
# <boost/polygon/voronoi.hpp> does floating-point arithmetic on an
|
|
89
|
+
# unnamed enum, deprecated in C++20.
|
|
90
|
+
set_source_files_properties(builtins/roof.cpp PROPERTIES
|
|
91
|
+
COMPILE_OPTIONS "-Wno-deprecated-enum-float-conversion")
|
|
92
|
+
endif()
|
|
93
|
+
|
|
94
|
+
# zip_stored.cpp defines STB_IMAGE_WRITE_IMPLEMENTATION, so stb's C compiles
|
|
95
|
+
# as ours: `= { 0 }` partial initializers, and one sprintf().
|
|
96
|
+
set(_stb_quiet "")
|
|
97
|
+
if(OSCAD_HAS_WNO_missing-field-initializers)
|
|
98
|
+
list(APPEND _stb_quiet "-Wno-missing-field-initializers")
|
|
99
|
+
endif()
|
|
100
|
+
if(OSCAD_HAS_WNO_deprecated-declarations)
|
|
101
|
+
list(APPEND _stb_quiet "-Wno-deprecated-declarations")
|
|
102
|
+
endif()
|
|
103
|
+
if(_stb_quiet)
|
|
104
|
+
set_source_files_properties(zip_stored.cpp PROPERTIES COMPILE_OPTIONS "${_stb_quiet}")
|
|
105
|
+
endif()
|
{openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -837,38 +837,6 @@ Value builtinFontmetrics(Evaluator& ev, const CallArgs& args) {
|
|
|
837
837
|
});
|
|
838
838
|
}
|
|
839
839
|
|
|
840
|
-
// Take only scalar numbers, mapped to how many leading positional
|
|
841
|
-
// arguments must each actually BE a number. Anything else there (undef, a
|
|
842
|
-
// string, a list, a bool, an object) is a type error yielding undef, and
|
|
843
|
-
// so is supplying fewer arguments than the arity -- matching the
|
|
844
|
-
// reference, which rejects the call outright rather than coercing.
|
|
845
|
-
//
|
|
846
|
-
// This has to be checked up front rather than left to each case below:
|
|
847
|
-
// toDoubleLenient() silently turns undef/string/list into 0.0, which
|
|
848
|
-
// would make `cos(misspelled_var)` quietly 1 instead of undef, and a
|
|
849
|
-
// typo'd variable then produces plausible-looking geometry instead of an
|
|
850
|
-
// obvious failure. Arity is deliberately a floor, not an exact match --
|
|
851
|
-
// the reference also rejects EXTRA arguments, but tightening that too
|
|
852
|
-
// risks breaking working library code for no correctness gain here.
|
|
853
|
-
const std::unordered_map<std::string, size_t>& scalarNumericArity() {
|
|
854
|
-
static const std::unordered_map<std::string, size_t> arity = {
|
|
855
|
-
{"abs", 1}, {"sign", 1}, {"ceil", 1}, {"floor", 1}, {"round", 1}, {"sqrt", 1},
|
|
856
|
-
{"ln", 1}, {"log", 1}, {"exp", 1}, {"sin", 1}, {"cos", 1}, {"tan", 1},
|
|
857
|
-
{"asin", 1}, {"acos", 1}, {"atan", 1}, {"atan2", 2}, {"pow", 2}, {"rands", 3},
|
|
858
|
-
};
|
|
859
|
-
return arity;
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
// Numeric functions that legitimately take a LIST argument, so the
|
|
863
|
-
// all-arguments-must-be-numbers rule above can't apply -- each validates
|
|
864
|
-
// its own operands, and only needs the bool case caught here (Value's
|
|
865
|
-
// bool and double are distinct alternatives, but the reference rejects
|
|
866
|
-
// `max(true, 1)` as a type error rather than treating true as 1).
|
|
867
|
-
const std::unordered_set<std::string>& numericOnlyNames() {
|
|
868
|
-
static const std::unordered_set<std::string> names = {"max", "min", "norm", "cross"};
|
|
869
|
-
return names;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
840
|
} // namespace
|
|
873
841
|
|
|
874
842
|
bool isBuiltinFunctionName(const std::string& name) {
|
{openscad_cpp_evaluator-1.22.0 → openscad_cpp_evaluator-1.24.0}/src/builtins/primitives_3d.cpp
RENAMED
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
#include <cstdint>
|
|
12
12
|
#include <map>
|
|
13
13
|
#include <numbers>
|
|
14
|
+
#include <optional>
|
|
14
15
|
#include <set>
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <utility>
|
|
15
18
|
|
|
16
19
|
namespace oscadeval {
|
|
17
20
|
|
|
@@ -42,8 +45,18 @@ bool isDrawableFailure(const manifold::Manifold& body, const M& mesh) {
|
|
|
42
45
|
[](float v) { return std::isfinite(v); });
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
struct BoundaryEdges {
|
|
49
|
+
size_t count = 0;
|
|
50
|
+
// Vertex indices of one representative open edge, or nullopt when the
|
|
51
|
+
// mesh is closed. A count alone is enough on a hand-written face list,
|
|
52
|
+
// where you can just read it; it is useless on generated geometry --
|
|
53
|
+
// three bad edges in a few thousand triangles cannot be found by eye,
|
|
54
|
+
// which is what happened in BelfrySCAD #521 / issue #187.
|
|
55
|
+
std::optional<std::pair<uint32_t, uint32_t>> first;
|
|
56
|
+
};
|
|
57
|
+
|
|
45
58
|
template <typename M>
|
|
46
|
-
|
|
59
|
+
BoundaryEdges findBoundaryEdges(const M& mesh) {
|
|
47
60
|
std::map<std::pair<uint32_t, uint32_t>, int> uses;
|
|
48
61
|
for (size_t i = 0; i + 2 < mesh.triVerts.size(); i += 3) {
|
|
49
62
|
const uint32_t v[3] = {static_cast<uint32_t>(mesh.triVerts[i]),
|
|
@@ -54,11 +67,34 @@ size_t countBoundaryEdges(const M& mesh) {
|
|
|
54
67
|
++uses[{std::min(a, b), std::max(a, b)}];
|
|
55
68
|
}
|
|
56
69
|
}
|
|
57
|
-
|
|
70
|
+
BoundaryEdges out;
|
|
71
|
+
// std::map iterates in vertex-index order, which is arbitrary from the
|
|
72
|
+
// author's point of view but DETERMINISTIC: the same mesh names the same
|
|
73
|
+
// edge on every run. That matters more than which edge gets picked --
|
|
74
|
+
// an identifier that moves between renders is worse than no identifier.
|
|
75
|
+
// A cluster of open edges is nearly always one hole, so the first is
|
|
76
|
+
// usually representative of the rest.
|
|
58
77
|
for (const auto& [edge, count] : uses) {
|
|
59
|
-
if (count % 2
|
|
78
|
+
if (count % 2 == 0) continue;
|
|
79
|
+
++out.count;
|
|
80
|
+
if (!out.first) out.first = edge;
|
|
60
81
|
}
|
|
61
|
-
return
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// "[1, 2.5, 0] - [1, 3, 0]" for one edge, using the same number formatting
|
|
86
|
+
// echo() uses, so a coordinate can be pasted straight back into a script.
|
|
87
|
+
template <typename M>
|
|
88
|
+
std::string describeEdge(const M& mesh, std::pair<uint32_t, uint32_t> edge) {
|
|
89
|
+
const size_t stride = mesh.numProp > 0 ? static_cast<size_t>(mesh.numProp) : 3;
|
|
90
|
+
auto point = [&](uint32_t v) {
|
|
91
|
+
const size_t base = static_cast<size_t>(v) * stride;
|
|
92
|
+
if (base + 2 >= mesh.vertProperties.size()) return std::string("?");
|
|
93
|
+
return "[" + formatNumber(static_cast<double>(mesh.vertProperties[base])) + ", " +
|
|
94
|
+
formatNumber(static_cast<double>(mesh.vertProperties[base + 1])) + ", " +
|
|
95
|
+
formatNumber(static_cast<double>(mesh.vertProperties[base + 2])) + "]";
|
|
96
|
+
};
|
|
97
|
+
return point(edge.first) + " - " + point(edge.second);
|
|
62
98
|
}
|
|
63
99
|
} // namespace
|
|
64
100
|
|
|
@@ -810,8 +846,15 @@ std::vector<ColoredBody> generatePolyhedron(Evaluator& ev, const CSGParams& para
|
|
|
810
846
|
// self-intersections builds perfectly well, and only an OPEN one
|
|
811
847
|
// reaches this branch. The count points straight at the problem.
|
|
812
848
|
if (!ev.insideHull) {
|
|
813
|
-
|
|
814
|
-
|
|
849
|
+
const BoundaryEdges open = findBoundaryEdges(mesh);
|
|
850
|
+
// Name one of them. Where the hole IS is the only part of this
|
|
851
|
+
// message an author can act on; the count alone just says to go
|
|
852
|
+
// looking, across the whole mesh.
|
|
853
|
+
const std::string where =
|
|
854
|
+
open.first ? ", first at " + describeEdge(mesh, *open.first) : std::string();
|
|
855
|
+
ev.warn("polyhedron: mesh is not closed -- " + std::to_string(open.count) +
|
|
856
|
+
" boundary edge(s)" + where +
|
|
857
|
+
"; drawing it as a surface. hull() can still "
|
|
815
858
|
"use its points, but it cannot take part in union/difference/intersection",
|
|
816
859
|
&node.position());
|
|
817
860
|
}
|
|
@@ -621,18 +621,6 @@ double bandDistance(double v, double lo, double hi, bool invert) {
|
|
|
621
621
|
return invert ? -d : d;
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
std::optional<std::array<double, 3>> readVec3(const Value& v) {
|
|
625
|
-
const ListPtr* l = std::get_if<ListPtr>(&v);
|
|
626
|
-
if (!l || !*l || (*l)->items.size() != 3) return std::nullopt;
|
|
627
|
-
std::array<double, 3> out{};
|
|
628
|
-
for (size_t i = 0; i < 3; ++i) {
|
|
629
|
-
const double* d = std::get_if<double>(&(*l)->items[i]);
|
|
630
|
-
if (!d || !std::isfinite(*d)) return std::nullopt;
|
|
631
|
-
out[i] = *d;
|
|
632
|
-
}
|
|
633
|
-
return out;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
624
|
} // namespace
|
|
637
625
|
|
|
638
626
|
// -- 2D: marching squares --------------------------------------------------
|