openscad-cpp-evaluator 0.29.3__tar.gz → 0.31.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-0.29.3 → openscad_cpp_evaluator-0.31.0}/CLAUDE.md +23 -1
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/bindings/module.cpp +48 -2
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/dispatch.hpp +19 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/eval_error.hpp +35 -0
- openscad_cpp_evaluator-0.31.0/include/openscad_cpp_evaluator/export.hpp +144 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/python/openscad_cpp_evaluator/__init__.py +44 -1
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/function_builtins.cpp +13 -0
- openscad_cpp_evaluator-0.31.0/src/builtins/registry.cpp +142 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/bytecode_vm.cpp +20 -6
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/csg_resolve.cpp +1 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/eval_error.cpp +37 -0
- openscad_cpp_evaluator-0.31.0/src/export.cpp +974 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/user_calls.cpp +8 -1
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/CMakeLists.txt +1 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_cli.cpp +71 -2
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_import_export.cpp +12 -8
- openscad_cpp_evaluator-0.31.0/tests/test_unexpected_args.cpp +151 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tools/cli/cli_lib.cpp +16 -15
- openscad_cpp_evaluator-0.29.3/include/openscad_cpp_evaluator/export.hpp +0 -51
- openscad_cpp_evaluator-0.29.3/src/builtins/registry.cpp +0 -81
- openscad_cpp_evaluator-0.29.3/src/export.cpp +0 -242
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/text/stb_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/uv.lock +0 -0
|
@@ -424,7 +424,29 @@ grep for `ponytail:`.
|
|
|
424
424
|
give sibling statements in the same block correct assignment visibility (see the header comment
|
|
425
425
|
before reworking this; it's not an arbitrary choice).
|
|
426
426
|
- `include/openscad_cpp_evaluator/eval_error.hpp`, `src/eval_error.cpp` — `EvalError` and the
|
|
427
|
-
exact ERROR/TRACE string formatting real OpenSCAD produces.
|
|
427
|
+
exact ERROR/TRACE string formatting real OpenSCAD produces. Also the **unexpected-argument
|
|
428
|
+
warnings** (`warnUnexpectedNamedArg`/`warnTooManyPositionalArgs`/`warnUnexpectedArgs`), the port
|
|
429
|
+
of real OpenSCAD's `Parameters.cc` `parse_without_defaults`: `variable X not specified as
|
|
430
|
+
parameter` for a named argument the callee doesn't declare, and `Too many unnamed arguments
|
|
431
|
+
supplied` once per call for positional arguments past the last parameter. `$`-prefixed names
|
|
432
|
+
other than `$children` are exempt (`isConfigVariable`, mirroring
|
|
433
|
+
`ContextFrame::is_config_variable` — a `$`-name is a dynamic-scope override, never a parameter).
|
|
434
|
+
The check has to be repeated at **every** argument-binding path, since there are five and none of
|
|
435
|
+
them share a choke point: `bindArgs` (interpreter, `user_calls.cpp`),
|
|
436
|
+
`buildBoundArgs`/`bindAstArgsIntoFrame` (bytecode VM, `bytecode_vm.cpp`), `evalModularCall`
|
|
437
|
+
(builtin modules, `csg_resolve.cpp`) and the VM's own `Op::PushBuiltinWrap`/`Op::PushCsgWrap`
|
|
438
|
+
handlers — the transform/color/hull/minkowski/render/extrude/projection/offset/roof/CSG family
|
|
439
|
+
bypasses `evalModularCall` entirely once compiled, which is exactly the gap
|
|
440
|
+
`tests/test_unexpected_args.cpp` runs every case twice (VM off and on) to catch. Builtin
|
|
441
|
+
parameter names live in `builtinParamNames` (`registry.cpp`): each list is the union of real
|
|
442
|
+
OpenSCAD's own `Parameters::parse` declaration and any extra name this port reads via `getArg`,
|
|
443
|
+
so the port never warns about an argument it goes on to honour — **add to it whenever a builtin
|
|
444
|
+
gains a parameter**, or that parameter starts warning. Builtin *functions* deliberately have no
|
|
445
|
+
entries beyond `textmetrics`/`fontmetrics`: upstream reads their arguments positionally without
|
|
446
|
+
`Parameters::parse`, so `sin(bogus=30)` warns about nothing there (verified against 2022.08.22)
|
|
447
|
+
and warning here would be a divergence. Not ported: the reference's `argument X supplied more
|
|
448
|
+
than once` / `argument X overrides positional argument`, separate conditions this port's simpler
|
|
449
|
+
positional-matching rule doesn't track.
|
|
428
450
|
- `include/openscad_cpp_evaluator/evaluator.hpp`, `src/expr_eval.cpp`, `src/stmt_eval.cpp`,
|
|
429
451
|
`src/user_calls.cpp` — the `Evaluator` class. Expression/statement dispatch is a `switch` on
|
|
430
452
|
`NodeKind` (matches `openscad_cpp_parser`'s own dispatch convention, not a visitor).
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
#include "openscad_cpp_evaluator/eval_context.hpp"
|
|
23
23
|
#include "openscad_cpp_evaluator/eval_use.hpp"
|
|
24
24
|
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
25
|
+
#include "openscad_cpp_evaluator/export.hpp"
|
|
25
26
|
#include "openscad_cpp_evaluator/mesh_check.hpp"
|
|
26
27
|
#include "openscad_cpp_evaluator/manifold_cache.hpp"
|
|
27
28
|
#include "openscad_cpp_evaluator/profile.hpp"
|
|
@@ -340,6 +341,36 @@ std::pair<nb::dict, nb::object> dynStateToPy(const oscadeval::EvalContext& ctx)
|
|
|
340
341
|
// message as a Python exception on ParseError/EvalError (nanobind maps
|
|
341
342
|
// std::exception -> RuntimeError, whose str() is the already-formatted
|
|
342
343
|
// "ERROR:..."/caret diagnostic; the facade re-raises as EvalError).
|
|
344
|
+
// The evaluated bodies, kept on the C++ side.
|
|
345
|
+
//
|
|
346
|
+
// bodyToDict flattens every Manifold into numpy arrays for the renderer,
|
|
347
|
+
// which is all the renderer needs -- but export has to do real CSG (the
|
|
348
|
+
// union, the per-colour claim, decompose), and rebuilding Manifolds from
|
|
349
|
+
// those arrays to do it costs ~146ms on a 224k-triangle model and throws
|
|
350
|
+
// away Manifold's own provenance. Handing back an opaque handle instead
|
|
351
|
+
// means geometry never round-trips through Python at all.
|
|
352
|
+
struct Geometry {
|
|
353
|
+
std::vector<oscadeval::ColoredBody> bodies;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// exportModel, with the path/format/warnings marshalling. Releases the GIL:
|
|
357
|
+
// a large export is seconds of Manifold work with no Python involved.
|
|
358
|
+
nb::list exportModelPy(const std::string& path, const Geometry& geom, const std::string& format, bool asciiStl,
|
|
359
|
+
bool stripSlivers) {
|
|
360
|
+
std::vector<std::string> warnings;
|
|
361
|
+
{
|
|
362
|
+
nb::gil_scoped_release rel;
|
|
363
|
+
oscadeval::ExportOptions opts;
|
|
364
|
+
opts.format = format;
|
|
365
|
+
opts.asciiStl = asciiStl;
|
|
366
|
+
opts.stripSlivers = stripSlivers;
|
|
367
|
+
warnings = oscadeval::exportModel(path, geom.bodies, opts);
|
|
368
|
+
}
|
|
369
|
+
nb::list out;
|
|
370
|
+
for (const std::string& w : warnings) out.append(w);
|
|
371
|
+
return out;
|
|
372
|
+
}
|
|
373
|
+
|
|
343
374
|
nb::object evaluate(const std::string& path, nb::dict viewportParams,
|
|
344
375
|
std::shared_ptr<oscadeval::ManifoldCache> manifoldCache, bool profile) {
|
|
345
376
|
std::unordered_map<std::string, oscadeval::Value> vp = toViewportParams(viewportParams);
|
|
@@ -370,8 +401,10 @@ nb::object evaluate(const std::string& path, nb::dict viewportParams,
|
|
|
370
401
|
|
|
371
402
|
nb::list echoList;
|
|
372
403
|
for (const std::string& s : echoes) echoList.append(s);
|
|
373
|
-
|
|
374
|
-
|
|
404
|
+
auto geom = std::make_shared<Geometry>();
|
|
405
|
+
geom->bodies = std::move(bodies);
|
|
406
|
+
return nb::make_tuple(bodiesToList(geom->bodies), echoList, idSpansToDict(idSpans), csgTreeToPy(csgTree),
|
|
407
|
+
profileResultToPy(profileResult), dyn, dynExplicit, geom);
|
|
375
408
|
}
|
|
376
409
|
|
|
377
410
|
// ------------------------------------------------------------------------
|
|
@@ -721,6 +754,19 @@ NB_MODULE(_openscad_cpp_evaluator, m) {
|
|
|
721
754
|
.def(nb::init<>())
|
|
722
755
|
.def("request", &FastContinueSignal::request);
|
|
723
756
|
|
|
757
|
+
nb::class_<Geometry>(m, "Geometry",
|
|
758
|
+
"Opaque handle to the evaluated bodies, kept on the C++ side so export never has to "
|
|
759
|
+
"rebuild Manifolds from the renderer's flattened arrays. Hand it to export_model().")
|
|
760
|
+
.def("__len__", [](const Geometry& g) { return g.bodies.size(); })
|
|
761
|
+
.def("is_empty", [](const Geometry& g) { return g.bodies.empty(); });
|
|
762
|
+
|
|
763
|
+
m.def("export_model", &exportModelPy, nb::arg("path"), nb::arg("geometry"), nb::arg("format") = std::string(),
|
|
764
|
+
nb::arg("ascii_stl") = false, nb::arg("strip_slivers") = true,
|
|
765
|
+
"Write `geometry` to `path`, format taken from the extension unless `format` says otherwise. "
|
|
766
|
+
"Returns the warnings to surface (open shells, mesh problems, slivers removed) rather than "
|
|
767
|
+
"logging them. Raises RuntimeError when there is no geometry, the format is unknown, or the "
|
|
768
|
+
"file cannot be opened.");
|
|
769
|
+
|
|
724
770
|
m.def("evaluate", &evaluate, nb::arg("path"), nb::arg("viewport_params"), nb::arg("manifold_cache") = nullptr,
|
|
725
771
|
nb::arg("profile") = false,
|
|
726
772
|
"Evaluate a .scad file; return (bodies, echoes, id_to_node, csg_tree, profile_result, dyn, dyn_explicit).");
|
|
@@ -54,6 +54,25 @@ using GenerateFn = std::vector<ColoredBody> (*)(Evaluator&, const CSGParams&, co
|
|
|
54
54
|
const std::unordered_map<std::string_view, ResolveFn>& resolveDispatch();
|
|
55
55
|
const std::unordered_map<std::string_view, GenerateFn>& generateDispatch();
|
|
56
56
|
|
|
57
|
+
// Every parameter name a builtin accepts, for the unexpected-argument
|
|
58
|
+
// warning (see eval_error.hpp). Returns nullptr for a name with no entry,
|
|
59
|
+
// which suppresses the check rather than warning about everything.
|
|
60
|
+
//
|
|
61
|
+
// Each list is the UNION of real OpenSCAD's own Parameters::parse
|
|
62
|
+
// declaration for that builtin (2022.08.22 -- the authority on what warns
|
|
63
|
+
// upstream) and any extra name this port itself reads via getArg, so this
|
|
64
|
+
// port never warns about an argument it goes on to honour.
|
|
65
|
+
const std::vector<std::string>* builtinParamNames(const std::string& name);
|
|
66
|
+
|
|
67
|
+
// builtinParamNames + warnUnexpectedArgs for one builtin module call. Must
|
|
68
|
+
// be invoked from EVERY path a builtin call can take: evalModularCall
|
|
69
|
+
// (interpreter, and Op::NativeStatement) plus the bytecode VM's own
|
|
70
|
+
// Op::PushBuiltinWrap/Op::PushCsgWrap handlers, which bypass
|
|
71
|
+
// evalModularCall entirely for the transform/color/hull/extrude/CSG family.
|
|
72
|
+
// Silently does nothing for a node that isn't a ModularCall (a `#`/`%`/`!`
|
|
73
|
+
// modifier shares BuiltinWrapSite but carries no arguments).
|
|
74
|
+
void warnUnexpectedBuiltinArgs(Evaluator& ev, const oscad::ASTNode& callNode);
|
|
75
|
+
|
|
57
76
|
// Concatenates every top-level node's already-generated `.bodies` (does NOT
|
|
58
77
|
// recurse into `.children` -- a parent's `.bodies` is already the fully
|
|
59
78
|
// combined result of its children). Mirrors the reference's
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
#include "openscad_cpp_parser/position.hpp"
|
|
4
4
|
|
|
5
|
+
#include <memory>
|
|
5
6
|
#include <stdexcept>
|
|
6
7
|
#include <string>
|
|
7
8
|
#include <vector>
|
|
8
9
|
|
|
9
10
|
namespace oscad {
|
|
10
11
|
class ASTNode;
|
|
12
|
+
class Argument;
|
|
13
|
+
class ParameterDeclaration;
|
|
11
14
|
} // namespace oscad
|
|
12
15
|
|
|
13
16
|
namespace oscadeval {
|
|
@@ -129,4 +132,36 @@ std::string formatError(const std::string& msg, const oscad::Position* nodePosit
|
|
|
129
132
|
std::string formatWarning(const std::string& msg, const oscad::Position* nodePosition,
|
|
130
133
|
const std::vector<CallStackFrame>& callStack);
|
|
131
134
|
|
|
135
|
+
// -- Unexpected-argument warnings -----------------------------------------
|
|
136
|
+
//
|
|
137
|
+
// Real OpenSCAD (Parameters.cc's parse_without_defaults) warns for a named
|
|
138
|
+
// argument the callee doesn't declare, and once per call for positional
|
|
139
|
+
// arguments past the last parameter. Both are silently dropped otherwise,
|
|
140
|
+
// which makes a typo'd argument name invisible -- the call still runs, the
|
|
141
|
+
// parameter just keeps its default. Wording is verbatim from the reference
|
|
142
|
+
// (2022.08.22, which quotes neither name nor message).
|
|
143
|
+
//
|
|
144
|
+
// NOT covered here (separate reference warnings, separate conditions):
|
|
145
|
+
// "argument X supplied more than once" and "argument X overrides positional
|
|
146
|
+
// argument".
|
|
147
|
+
class Evaluator;
|
|
148
|
+
|
|
149
|
+
// ContextFrame::is_config_variable: a $-prefixed name other than $children
|
|
150
|
+
// is a dynamic-scope override, never a declared parameter, so it is exempt.
|
|
151
|
+
bool isConfigVariable(const std::string& name);
|
|
152
|
+
|
|
153
|
+
// Linear scan -- ponytail: parameter lists are single-digit in practice, so
|
|
154
|
+
// a per-call set/map would cost more than it saves.
|
|
155
|
+
bool declaresParam(const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& params, const std::string& name);
|
|
156
|
+
|
|
157
|
+
void warnUnexpectedNamedArg(Evaluator& ev, const std::string& name, const oscad::Position* pos);
|
|
158
|
+
void warnTooManyPositionalArgs(Evaluator& ev, const oscad::Position* pos);
|
|
159
|
+
|
|
160
|
+
// Both warnings at once for a callee whose parameter names are a fixed list
|
|
161
|
+
// rather than a declaration -- i.e. a builtin (see builtinParamNames,
|
|
162
|
+
// dispatch.hpp). Reports against each argument's own position, which is the
|
|
163
|
+
// call's own line in every case that isn't a multi-line argument list.
|
|
164
|
+
void warnUnexpectedArgs(Evaluator& ev, const std::vector<std::string>& params,
|
|
165
|
+
const std::vector<std::unique_ptr<oscad::Argument>>& arguments);
|
|
166
|
+
|
|
132
167
|
} // namespace oscadeval
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "openscad_cpp_evaluator/colored_body.hpp"
|
|
4
|
+
|
|
5
|
+
#include <array>
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <vector>
|
|
9
|
+
|
|
10
|
+
namespace oscadeval {
|
|
11
|
+
|
|
12
|
+
// The colour every object falls back to when the script gave none.
|
|
13
|
+
inline constexpr std::array<float, 4> kDefaultExportColor = {0.8f, 0.8f, 0.8f, 1.0f};
|
|
14
|
+
|
|
15
|
+
// One object in a file format that can hold more than one -- 3MF, OBJ,
|
|
16
|
+
// VRML, X3D. `triColors` is empty for the ordinary flat-coloured object,
|
|
17
|
+
// or one RGBA per triangle when the surface came out of a multi-colour CSG
|
|
18
|
+
// merge (see splitBodiesForExport).
|
|
19
|
+
struct ExportObject {
|
|
20
|
+
std::vector<float> verts; // xyz triples
|
|
21
|
+
std::vector<uint32_t> tris; // vertex-index triples
|
|
22
|
+
std::array<float, 4> color = kDefaultExportColor;
|
|
23
|
+
std::vector<std::array<float, 4>> triColors;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// The implicit top-level union, cut into objects that never overlap.
|
|
27
|
+
//
|
|
28
|
+
// Top level in OpenSCAD is an implicit union, so `cube(100); cube(100,
|
|
29
|
+
// center=true);` is ONE solid -- writing the bodies as they arrive put both
|
|
30
|
+
// cubes in the file separately, overlapping, with their interior faces
|
|
31
|
+
// intact. Three rules, in order:
|
|
32
|
+
//
|
|
33
|
+
// 1. Union, never concatenate. Concatenating is only right while the
|
|
34
|
+
// bodies are disjoint; where two touch, each writes its own copy of
|
|
35
|
+
// the shared face and the result is non-manifold.
|
|
36
|
+
// 2. One object per colour, and no two objects share volume. Where
|
|
37
|
+
// differently-coloured solids overlap the LATER one owns the shared
|
|
38
|
+
// volume and the earlier is notched around it -- painter's order, so
|
|
39
|
+
// `color("red") body(); color("blue") detail();` leaves the detail
|
|
40
|
+
// whole. Only the invisible interior is affected: the visible surface
|
|
41
|
+
// is identical either way.
|
|
42
|
+
// 3. One object per connected component.
|
|
43
|
+
//
|
|
44
|
+
// A body Manifold rejected (an open shell is not a solid) can take part in
|
|
45
|
+
// none of that: it keeps its own triangles and its own object, and its
|
|
46
|
+
// 1-based index is appended to `openParts` for the caller to warn about.
|
|
47
|
+
std::vector<ExportObject> splitBodiesForExport(const std::vector<ColoredBody>& bodies,
|
|
48
|
+
std::vector<int>* openParts = nullptr);
|
|
49
|
+
|
|
50
|
+
// Writes a binary STL: composes every body's mesh into one solid (bodies
|
|
51
|
+
// with no `.body` -- 2D-only sections -- or an empty Manifold are
|
|
52
|
+
// skipped), per-triangle normals computed from vertex winding. Mirrors
|
|
53
|
+
// export.py's write_stl exactly (80-byte zero header, uint32 LE triangle
|
|
54
|
+
// count, 50 bytes/triangle: 3x float32 normal, 3x3 float32 vertices,
|
|
55
|
+
// uint16 attr=0). Throws std::runtime_error if there's no 3D geometry to
|
|
56
|
+
// export, or if the file can't be opened for writing.
|
|
57
|
+
//
|
|
58
|
+
// 3MF and format-from-extension dispatch land in Phase 5 per the plan's
|
|
59
|
+
// phased build order.
|
|
60
|
+
// One message per body that is not a closed manifold solid, ready to print.
|
|
61
|
+
// Empty when everything is sound.
|
|
62
|
+
//
|
|
63
|
+
// Returned rather than logged so each front end can surface it its own way,
|
|
64
|
+
// and so export.cpp needs no logging dependency. Nothing here refuses to
|
|
65
|
+
// write: a deliberately open surface is a legitimate thing to export, and
|
|
66
|
+
// silently blocking a save would be worse than an honest warning.
|
|
67
|
+
std::vector<std::string> checkExportBodies(const std::vector<ColoredBody>& bodies);
|
|
68
|
+
|
|
69
|
+
void writeStl(const std::string& path, const std::vector<ColoredBody>& bodies);
|
|
70
|
+
|
|
71
|
+
// OpenSCAD-compatible ASCII STL -- "solid OpenSCAD_Model" / one "facet
|
|
72
|
+
// normal .. outer loop .. vertex x3 .. endloop endfacet" per triangle /
|
|
73
|
+
// "endsolid". Format confirmed against real OpenSCAD's own -o out.stl.
|
|
74
|
+
void writeStlAscii(const std::string& path, const std::vector<ColoredBody>& bodies);
|
|
75
|
+
|
|
76
|
+
// Wavefront OBJ: one `o` group per object, `usemtl` naming a material in a
|
|
77
|
+
// companion .mtl written alongside (so an OBJ export produces TWO files).
|
|
78
|
+
// A multi-coloured surface becomes runs of faces with a `usemtl` between
|
|
79
|
+
// them, in triangle order -- the only per-face colour OBJ has.
|
|
80
|
+
void writeObj(const std::string& path, const std::vector<ExportObject>& objects);
|
|
81
|
+
|
|
82
|
+
// Binary little-endian PLY, one flat mesh with per-vertex colour. PLY has
|
|
83
|
+
// no object concept, so the objects are concatenated; an object carrying
|
|
84
|
+
// per-triangle colour is unwelded (three vertices per triangle), since a
|
|
85
|
+
// vertex shared by two differently-coloured triangles has no single answer.
|
|
86
|
+
void writePly(const std::string& path, const std::vector<ExportObject>& objects);
|
|
87
|
+
|
|
88
|
+
// VRML97 ("#VRML V2.0 utf8"), one Shape per object. Per-face colour rides
|
|
89
|
+
// on a Color node with `colorPerVertex FALSE`. Neither this nor X3D can
|
|
90
|
+
// carry per-triangle alpha, so the object's base alpha applies to the whole
|
|
91
|
+
// shape through Material.transparency (which is 1 - alpha).
|
|
92
|
+
void writeVrml(const std::string& path, const std::vector<ExportObject>& objects);
|
|
93
|
+
|
|
94
|
+
// X3D 3.3, Interchange profile -- the XML encoding of what writeVrml emits,
|
|
95
|
+
// node for node. Interchange is the accurate claim: per Annex B it is
|
|
96
|
+
// Geometry3D level 2 (IndexedFaceSet), Rendering level 3 (Coordinate,
|
|
97
|
+
// Color) and Shape level 1 (Appearance, Material), exactly the nodes used.
|
|
98
|
+
void writeX3d(const std::string& path, const std::vector<ExportObject>& objects);
|
|
99
|
+
|
|
100
|
+
// OFF (Object File Format): header "OFF", "$verts $tris 0", vertex lines,
|
|
101
|
+
// then "3 i j k" per triangle (0-indexed, count-prefixed). Mirrors
|
|
102
|
+
// export.py's write_off.
|
|
103
|
+
void writeOff(const std::string& path, const std::vector<ColoredBody>& bodies);
|
|
104
|
+
|
|
105
|
+
// 3MF: one mesh object + a base-color colorgroup per body (skipping empty
|
|
106
|
+
// bodies), written as a DEFLATE-compressed ZIP (writeDeflateZip, see
|
|
107
|
+
// zip_stored.hpp) -- the XML is highly compressible, so storing it would
|
|
108
|
+
// make the file several times larger for nothing. An entry that does not
|
|
109
|
+
// actually shrink is stored raw, as any ZIP writer would.
|
|
110
|
+
// Mirrors export.py's write_3mf's XML shape exactly (core + material
|
|
111
|
+
// namespaces, %.6g vertex formatting); throws std::runtime_error if there's
|
|
112
|
+
// no geometry to export.
|
|
113
|
+
void writeThreeMf(const std::string& path, const std::vector<ExportObject>& objects);
|
|
114
|
+
|
|
115
|
+
// -- one entry point ------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
struct ExportOptions {
|
|
118
|
+
// Empty means "decide from the path's extension".
|
|
119
|
+
std::string format;
|
|
120
|
+
// .stl only; binary otherwise.
|
|
121
|
+
bool asciiStl = false;
|
|
122
|
+
// Remove zero-area faces before writing the single-mesh formats. They
|
|
123
|
+
// break no topology, but slicers commonly discard them and are then
|
|
124
|
+
// left with the holes their removal opens.
|
|
125
|
+
bool stripSlivers = true;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Writes `bodies` to `path`, choosing the writer from the extension (or
|
|
129
|
+
// opts.format) and applying the same repair/verification policy the GUI
|
|
130
|
+
// used to apply itself. Returns the warnings to surface -- open shells,
|
|
131
|
+
// mesh problems, sliver removal -- rather than logging them, so each front
|
|
132
|
+
// end can present them its own way.
|
|
133
|
+
//
|
|
134
|
+
// Nothing here refuses to write: a deliberately open surface is a
|
|
135
|
+
// legitimate export, and blocking a save the user asked for would be worse
|
|
136
|
+
// than saying so. Throws std::runtime_error only when there is no geometry
|
|
137
|
+
// at all, the format is unknown, or the file cannot be opened.
|
|
138
|
+
std::vector<std::string> exportModel(const std::string& path, const std::vector<ColoredBody>& bodies,
|
|
139
|
+
const ExportOptions& opts = {});
|
|
140
|
+
|
|
141
|
+
// The extensions exportModel understands, lower-case and dot-prefixed.
|
|
142
|
+
const std::vector<std::string>& exportExtensions();
|
|
143
|
+
|
|
144
|
+
} // namespace oscadeval
|
|
@@ -19,6 +19,7 @@ __all__ = [
|
|
|
19
19
|
"Evaluator", "ColoredBody", "EvalError", "ParseError", "OscObject", "parse", "to_renderable_bodies",
|
|
20
20
|
"ManifoldCache", "CallSiteProfile", "ProfileResult", "format_csg_tree", "bodies_from_dicts",
|
|
21
21
|
"FastContinueSignal", "parse_ast", "parse_ast_string", "check_mesh", "strip_slivers",
|
|
22
|
+
"export_model", "export_extensions",
|
|
22
23
|
]
|
|
23
24
|
|
|
24
25
|
|
|
@@ -288,6 +289,36 @@ def strip_slivers(verts, tris):
|
|
|
288
289
|
return _ext.strip_slivers([float(v) for v in verts], [int(t) for t in tris])
|
|
289
290
|
|
|
290
291
|
|
|
292
|
+
def export_model(path: str, geometry, format: str = "", ascii_stl: bool = False,
|
|
293
|
+
strip_slivers: bool = True) -> list:
|
|
294
|
+
"""Write `geometry` to `path`. Returns the warnings to surface.
|
|
295
|
+
|
|
296
|
+
`geometry` is the handle an Evaluator stashes on itself as
|
|
297
|
+
`.geometry` -- the evaluated bodies, still on the C++ side. Export has
|
|
298
|
+
to do real CSG (the implicit top-level union, the per-colour volume
|
|
299
|
+
claim, the connected-component split), and going through the flattened
|
|
300
|
+
arrays the renderer gets would mean rebuilding every Manifold first:
|
|
301
|
+
~146ms on a 224k-triangle model, and Manifold's own provenance lost
|
|
302
|
+
along the way.
|
|
303
|
+
|
|
304
|
+
Format comes from the extension unless `format` overrides it. Warnings
|
|
305
|
+
-- open shells, mesh problems, slivers removed -- are returned rather
|
|
306
|
+
than logged so each front end can present them its own way. Nothing
|
|
307
|
+
here refuses to write: a deliberately open surface is a legitimate
|
|
308
|
+
export. Raises EvalError when there is no geometry, the format is
|
|
309
|
+
unknown, or the file cannot be opened.
|
|
310
|
+
"""
|
|
311
|
+
try:
|
|
312
|
+
return list(_ext.export_model(path, geometry, format, ascii_stl, strip_slivers))
|
|
313
|
+
except Exception as e:
|
|
314
|
+
raise EvalError(str(e)) from e
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def export_extensions() -> list:
|
|
318
|
+
"""The file extensions export_model understands, dot-prefixed."""
|
|
319
|
+
return [".3mf", ".stl", ".obj", ".off", ".ply", ".wrl", ".x3d"]
|
|
320
|
+
|
|
321
|
+
|
|
291
322
|
def check_mesh(verts, tris) -> dict:
|
|
292
323
|
"""Diagnose a triangle mesh against the manifoldness conditions.
|
|
293
324
|
|
|
@@ -448,9 +479,21 @@ class Evaluator:
|
|
|
448
479
|
self._manifold_cache, self._return_hook, self._fast_continue_signal)
|
|
449
480
|
self.csg_tree = []
|
|
450
481
|
self.profile_result = None
|
|
482
|
+
# The debugger path has no geometry handle: debug_evaluate
|
|
483
|
+
# returns bodies for display only, and a paused session is
|
|
484
|
+
# not something to export from.
|
|
485
|
+
self.geometry = None
|
|
451
486
|
else:
|
|
452
|
-
body_dicts, echoes, id_spans, csg_tree, profile_result, dyn,
|
|
487
|
+
(body_dicts, echoes, id_spans, csg_tree, profile_result, dyn,
|
|
488
|
+
dyn_explicit, geometry) = _ext.evaluate(
|
|
453
489
|
source_path, vp, self._manifold_cache, self._profile)
|
|
490
|
+
# The evaluated bodies, still on the C++ side. Stashed like
|
|
491
|
+
# csg_tree/profile_result rather than returned, so
|
|
492
|
+
# evaluate()'s own 2-tuple result is unchanged -- callers
|
|
493
|
+
# that only render never need to know this exists. Hand it
|
|
494
|
+
# to export_model(); see its docstring for why export does
|
|
495
|
+
# not just rebuild from the arrays the renderer gets.
|
|
496
|
+
self.geometry = geometry
|
|
454
497
|
if self._echo_fn:
|
|
455
498
|
for line in echoes:
|
|
456
499
|
self._echo_fn(line)
|
{openscad_cpp_evaluator-0.29.3 → openscad_cpp_evaluator-0.31.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "openscad_cpp_evaluator/function_builtins.hpp"
|
|
2
2
|
|
|
3
|
+
#include "openscad_cpp_evaluator/dispatch.hpp"
|
|
3
4
|
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
4
5
|
#include "openscad_cpp_evaluator/segments.hpp"
|
|
5
6
|
#include "openscad_cpp_evaluator/text_metrics.hpp"
|
|
@@ -509,6 +510,18 @@ Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs
|
|
|
509
510
|
// elsewhere before reaching here) -- mirrors the old chain's fallthrough.
|
|
510
511
|
if (idIt == ids.end()) return Value{};
|
|
511
512
|
|
|
513
|
+
// Only textmetrics/fontmetrics have an entry -- every other builtin
|
|
514
|
+
// function reads its arguments positionally upstream and warns about
|
|
515
|
+
// nothing. See builtinParamNames (registry.cpp).
|
|
516
|
+
if (const std::vector<std::string>* declared = builtinParamNames(name)) {
|
|
517
|
+
for (const auto& [argName, _] : args.named) {
|
|
518
|
+
if (!isConfigVariable(argName) &&
|
|
519
|
+
std::find(declared->begin(), declared->end(), argName) == declared->end()) {
|
|
520
|
+
warnUnexpectedNamedArg(ev, argName, &node.position());
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
512
525
|
if (const auto arityIt = scalarNumericArity().find(name); arityIt != scalarNumericArity().end()) {
|
|
513
526
|
const std::vector<Value> positional = allPositional(args);
|
|
514
527
|
if (positional.size() < arityIt->second) return Value{};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#include "builtins.hpp"
|
|
2
|
+
|
|
3
|
+
#include "openscad_cpp_evaluator/dispatch.hpp"
|
|
4
|
+
#include "openscad_cpp_evaluator/eval_error.hpp"
|
|
5
|
+
|
|
6
|
+
namespace oscadeval {
|
|
7
|
+
|
|
8
|
+
const std::unordered_map<std::string_view, ResolveFn>& resolveDispatch() {
|
|
9
|
+
static const std::unordered_map<std::string_view, ResolveFn> table = {
|
|
10
|
+
{"cube", &resolveCube},
|
|
11
|
+
{"sphere", &resolveSphere},
|
|
12
|
+
{"cylinder", &resolveCylinder},
|
|
13
|
+
{"polyhedron", &resolvePolyhedron},
|
|
14
|
+
{"circle", &resolve2d},
|
|
15
|
+
{"square", &resolve2d},
|
|
16
|
+
{"polygon", &resolve2d},
|
|
17
|
+
{"translate", &resolveTransform},
|
|
18
|
+
{"rotate", &resolveTransform},
|
|
19
|
+
{"scale", &resolveTransform},
|
|
20
|
+
{"mirror", &resolveTransform},
|
|
21
|
+
{"multmatrix", &resolveTransform},
|
|
22
|
+
{"resize", &resolveTransform},
|
|
23
|
+
{"color", &resolveColor},
|
|
24
|
+
{"union", &resolveCsg},
|
|
25
|
+
{"difference", &resolveCsg},
|
|
26
|
+
{"intersection", &resolveCsg},
|
|
27
|
+
{"children", &resolveChildren},
|
|
28
|
+
{"render", &resolveRender},
|
|
29
|
+
{"breakpoint", &resolveBreakpoint},
|
|
30
|
+
{"import", &resolveImport},
|
|
31
|
+
{"hull", &resolveHull},
|
|
32
|
+
{"minkowski", &resolveMinkowski},
|
|
33
|
+
{"linear_extrude", &resolveLinearExtrude},
|
|
34
|
+
{"rotate_extrude", &resolveRotateExtrude},
|
|
35
|
+
{"projection", &resolveProjection},
|
|
36
|
+
{"roof", &resolveRoof},
|
|
37
|
+
{"offset", &resolveOffset},
|
|
38
|
+
{"surface", &resolveSurface},
|
|
39
|
+
{"text", &resolveText},
|
|
40
|
+
};
|
|
41
|
+
return table;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const std::unordered_map<std::string_view, GenerateFn>& generateDispatch() {
|
|
45
|
+
static const std::unordered_map<std::string_view, GenerateFn> table = {
|
|
46
|
+
{"cube", &generateCube},
|
|
47
|
+
{"sphere", &generateSphere},
|
|
48
|
+
{"cylinder", &generateCylinder},
|
|
49
|
+
{"polyhedron", &generatePolyhedron},
|
|
50
|
+
{"circle", &generate2d},
|
|
51
|
+
{"square", &generate2d},
|
|
52
|
+
{"polygon", &generate2d},
|
|
53
|
+
{"translate", &generateTransform},
|
|
54
|
+
{"rotate", &generateTransform},
|
|
55
|
+
{"scale", &generateTransform},
|
|
56
|
+
{"mirror", &generateTransform},
|
|
57
|
+
{"multmatrix", &generateTransform},
|
|
58
|
+
{"resize", &generateTransform},
|
|
59
|
+
{"color", &generateColor},
|
|
60
|
+
{"union", &generateCsg},
|
|
61
|
+
{"difference", &generateCsg},
|
|
62
|
+
{"intersection", &generateCsg},
|
|
63
|
+
{"highlight", &generateHighlight},
|
|
64
|
+
{"background", &generateBackground},
|
|
65
|
+
{"show_only", &generateShowOnly},
|
|
66
|
+
{"children", &generateChildren},
|
|
67
|
+
{"intersection_for", &generateIntersectionFor},
|
|
68
|
+
{"import", &generateImport},
|
|
69
|
+
{"hull", &generateHull},
|
|
70
|
+
{"minkowski", &generateMinkowski},
|
|
71
|
+
{"linear_extrude", &generateLinearExtrude},
|
|
72
|
+
{"rotate_extrude", &generateRotateExtrude},
|
|
73
|
+
{"projection", &generateProjection},
|
|
74
|
+
{"roof", &generateRoof},
|
|
75
|
+
{"offset", &generateOffset},
|
|
76
|
+
{"surface", &generateSurface},
|
|
77
|
+
{"text", &generateText},
|
|
78
|
+
};
|
|
79
|
+
return table;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const std::vector<std::string>* builtinParamNames(const std::string& name) {
|
|
83
|
+
// Deliberately absent: the builtin *functions* other than the three
|
|
84
|
+
// below. Real OpenSCAD's builtin functions read their arguments
|
|
85
|
+
// positionally without going through Parameters::parse, so `sin(bogus=30)`
|
|
86
|
+
// warns about nothing upstream -- verified against 2022.08.22 -- and
|
|
87
|
+
// warning here would be a divergence, not a fix.
|
|
88
|
+
static const std::unordered_map<std::string, std::vector<std::string>> table = {
|
|
89
|
+
// -- builtin modules ---------------------------------------------
|
|
90
|
+
{"cube", {"size", "center"}},
|
|
91
|
+
{"sphere", {"r", "d"}},
|
|
92
|
+
{"cylinder", {"h", "r1", "r2", "center", "r", "d", "d1", "d2"}},
|
|
93
|
+
{"polyhedron", {"points", "faces", "convexity", "triangles"}},
|
|
94
|
+
{"square", {"size", "center"}},
|
|
95
|
+
{"circle", {"r", "d"}},
|
|
96
|
+
{"polygon", {"points", "paths", "convexity"}},
|
|
97
|
+
{"translate", {"v"}},
|
|
98
|
+
{"rotate", {"a", "v"}},
|
|
99
|
+
{"scale", {"v"}},
|
|
100
|
+
{"mirror", {"v"}},
|
|
101
|
+
{"multmatrix", {"m"}},
|
|
102
|
+
{"resize", {"newsize", "auto", "convexity"}},
|
|
103
|
+
{"color", {"c", "alpha"}},
|
|
104
|
+
{"union", {}},
|
|
105
|
+
{"difference", {}},
|
|
106
|
+
{"intersection", {}},
|
|
107
|
+
{"hull", {}},
|
|
108
|
+
{"minkowski", {"convexity"}},
|
|
109
|
+
{"children", {"index"}},
|
|
110
|
+
{"render", {"convexity"}},
|
|
111
|
+
// "repair" is this port's own addition, not an upstream parameter.
|
|
112
|
+
{"import",
|
|
113
|
+
{"file", "layer", "convexity", "origin", "scale", "width", "height", "filename", "layername", "center", "dpi",
|
|
114
|
+
"id", "repair"}},
|
|
115
|
+
{"linear_extrude", {"height", "v", "scale", "center", "twist", "slices", "segments", "convexity"}},
|
|
116
|
+
{"rotate_extrude", {"angle", "start", "convexity"}},
|
|
117
|
+
{"projection", {"cut", "convexity"}},
|
|
118
|
+
{"roof", {"method", "convexity"}},
|
|
119
|
+
{"offset", {"r", "delta", "chamfer"}},
|
|
120
|
+
{"surface", {"file", "center", "convexity", "invert"}},
|
|
121
|
+
{"text", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
122
|
+
// breakpoint() is this port's own debugger extension, no upstream
|
|
123
|
+
// equivalent to mirror.
|
|
124
|
+
{"breakpoint", {"condition"}},
|
|
125
|
+
|
|
126
|
+
// -- the three builtin FUNCTIONS that do use Parameters::parse ----
|
|
127
|
+
{"textmetrics", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
128
|
+
{"fontmetrics", {"size", "font"}},
|
|
129
|
+
};
|
|
130
|
+
auto it = table.find(name);
|
|
131
|
+
return it == table.end() ? nullptr : &it->second;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
void warnUnexpectedBuiltinArgs(Evaluator& ev, const oscad::ASTNode& callNode) {
|
|
135
|
+
if (callNode.kind() != oscad::NodeKind::ModularCall) return;
|
|
136
|
+
const auto& call = static_cast<const oscad::ModularCall&>(callNode);
|
|
137
|
+
if (const std::vector<std::string>* declared = builtinParamNames(call.name->name)) {
|
|
138
|
+
warnUnexpectedArgs(ev, *declared, call.arguments);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
} // namespace oscadeval
|