openscad-cpp-evaluator 0.15.0__tar.gz → 0.16.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.15.0 → openscad_cpp_evaluator-0.16.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/bindings/CMakeLists.txt +1 -0
- openscad_cpp_evaluator-0.16.0/bindings/ast_to_py.cpp +326 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/bindings/module.cpp +14 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/python/openscad_cpp_evaluator/__init__.py +36 -1
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_python_bindings.py +116 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/text/stb_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/uv.lock +0 -0
|
@@ -15,6 +15,7 @@ find_package(nanobind CONFIG REQUIRED)
|
|
|
15
15
|
# from-source Manifold/Boost rebuild per interpreter in CI.
|
|
16
16
|
nanobind_add_module(_openscad_cpp_evaluator NB_STATIC STABLE_ABI
|
|
17
17
|
module.cpp
|
|
18
|
+
ast_to_py.cpp
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
# The static evaluator lib PUBLIC-links parser + manifold + Boost::polygon,
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// Snapshots the parser's AST into plain Python dicts.
|
|
2
|
+
//
|
|
3
|
+
// Deliberately a COPY rather than wrappers around live ASTNode pointers.
|
|
4
|
+
// The tree is owned by a `std::vector<std::unique_ptr<ASTNode>>` local to
|
|
5
|
+
// whichever binding parsed it, and dies when that call returns; handing
|
|
6
|
+
// Python raw pointers into it would be a use-after-free the moment anything
|
|
7
|
+
// outlived the call, and this project has already shipped one dangling
|
|
8
|
+
// pointer of exactly that shape (the bodyCtx bug fixed in v0.13.1). It also
|
|
9
|
+
// sidesteps the threading problem entirely -- a render worker thread can
|
|
10
|
+
// parse, hand the snapshot to the GUI thread, and exit, with nothing shared.
|
|
11
|
+
//
|
|
12
|
+
// The cost is one walk plus allocation per parse. That is affordable
|
|
13
|
+
// because callers ask for this explicitly (parse_ast()), not on the render
|
|
14
|
+
// path, which never needs it.
|
|
15
|
+
//
|
|
16
|
+
// Every node dict carries at least:
|
|
17
|
+
// kind -- str, the NodeKind name ("NumberLiteral", "ModularCall", ...)
|
|
18
|
+
// position -- dict(origin, line, column, start_offset, end_offset)
|
|
19
|
+
// plus that kind's own fields, named in snake_case. Child nodes are nested
|
|
20
|
+
// dicts; child lists are lists of dicts; an absent optional child is None.
|
|
21
|
+
//
|
|
22
|
+
// `position.start_offset`/`end_offset` are the point of the whole exercise:
|
|
23
|
+
// they let a caller recover the ORIGINAL source text of any subexpression
|
|
24
|
+
// and reuse it verbatim, rather than re-serialising a parsed value and
|
|
25
|
+
// losing how the author wrote it (1.500 -> 1.5, 1e3 -> 1000).
|
|
26
|
+
|
|
27
|
+
#include "openscad_cpp_parser/api.hpp"
|
|
28
|
+
#include "openscad_cpp_parser/ast/ast_node.hpp"
|
|
29
|
+
#include "openscad_cpp_parser/ast/comments.hpp"
|
|
30
|
+
#include "openscad_cpp_parser/ast/declarations.hpp"
|
|
31
|
+
#include "openscad_cpp_parser/ast/expression.hpp"
|
|
32
|
+
#include "openscad_cpp_parser/ast/module_instantiation.hpp"
|
|
33
|
+
#include "openscad_cpp_parser/ast/vector_element.hpp"
|
|
34
|
+
|
|
35
|
+
#include <nanobind/nanobind.h>
|
|
36
|
+
#include <nanobind/stl/string.h>
|
|
37
|
+
|
|
38
|
+
#include <memory>
|
|
39
|
+
#include <vector>
|
|
40
|
+
|
|
41
|
+
namespace nb = nanobind;
|
|
42
|
+
|
|
43
|
+
namespace oscadbind {
|
|
44
|
+
|
|
45
|
+
namespace {
|
|
46
|
+
|
|
47
|
+
nb::dict positionToPy(const oscad::Position& p) {
|
|
48
|
+
nb::dict d;
|
|
49
|
+
// origin is "" for the main file (matching how the evaluator reports
|
|
50
|
+
// it); left as-is rather than mapped to None, so a caller can compare
|
|
51
|
+
// it against a path without a null check.
|
|
52
|
+
d["origin"] = p.origin;
|
|
53
|
+
d["line"] = p.line;
|
|
54
|
+
d["column"] = p.column;
|
|
55
|
+
d["start_offset"] = p.start_offset;
|
|
56
|
+
d["end_offset"] = p.end_offset;
|
|
57
|
+
return d;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
nb::object nodeToPy(const oscad::ASTNode* n);
|
|
61
|
+
|
|
62
|
+
// A null unique_ptr child (e.g. a parameter with no default) becomes None
|
|
63
|
+
// rather than being omitted, so a consumer can index the key unconditionally.
|
|
64
|
+
template <typename T>
|
|
65
|
+
nb::object childToPy(const std::unique_ptr<T>& p) {
|
|
66
|
+
return p ? nodeToPy(p.get()) : nb::none();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
template <typename T>
|
|
70
|
+
nb::list listToPy(const std::vector<std::unique_ptr<T>>& v) {
|
|
71
|
+
nb::list out;
|
|
72
|
+
for (const std::unique_ptr<T>& item : v) out.append(nodeToPy(item.get()));
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
nb::dict baseDict(const oscad::ASTNode* n) {
|
|
77
|
+
nb::dict d;
|
|
78
|
+
d["kind"] = oscad::nodeKindName(n->kind());
|
|
79
|
+
d["position"] = positionToPy(n->position());
|
|
80
|
+
return d;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
nb::object nodeToPy(const oscad::ASTNode* n) {
|
|
84
|
+
if (n == nullptr) return nb::none();
|
|
85
|
+
nb::dict d = baseDict(n);
|
|
86
|
+
|
|
87
|
+
// kind() is authoritative about the concrete type (every leaf class sets
|
|
88
|
+
// its own), so static_cast is safe here and avoids a dynamic_cast per
|
|
89
|
+
// node on what is already an allocation-heavy walk.
|
|
90
|
+
#define OSC_NODE(KindName, Type) case oscad::NodeKind::KindName: { const auto* x = static_cast<const oscad::Type*>(n); (void)x;
|
|
91
|
+
#define OSC_END break; }
|
|
92
|
+
|
|
93
|
+
switch (n->kind()) {
|
|
94
|
+
// -- comments ---------------------------------------------------
|
|
95
|
+
OSC_NODE(CommentLine, CommentLine) d["text"] = x->text; OSC_END
|
|
96
|
+
OSC_NODE(BlankLine, BlankLine) OSC_END
|
|
97
|
+
OSC_NODE(CommentSpan, CommentSpan) d["text"] = x->text; OSC_END
|
|
98
|
+
OSC_NODE(CommentedExpr, CommentedExpr)
|
|
99
|
+
d["leading_comments"] = listToPy(x->leadingComments);
|
|
100
|
+
d["trailing_comments"] = listToPy(x->trailingComments);
|
|
101
|
+
d["expr"] = childToPy(x->expr);
|
|
102
|
+
OSC_END
|
|
103
|
+
|
|
104
|
+
// -- primaries / literals ---------------------------------------
|
|
105
|
+
OSC_NODE(Identifier, Identifier) d["name"] = x->name; OSC_END
|
|
106
|
+
// `val` is the DECODED string minus its quotes; escape sequences
|
|
107
|
+
// are kept raw (a source \n stays two characters). Use the span to
|
|
108
|
+
// recover exactly what was written.
|
|
109
|
+
OSC_NODE(StringLiteral, StringLiteral) d["val"] = x->val; OSC_END
|
|
110
|
+
// Parsed to double, so the source spelling (1.500, 1e3, 0x10) is
|
|
111
|
+
// NOT recoverable from here -- that is what the span is for.
|
|
112
|
+
OSC_NODE(NumberLiteral, NumberLiteral) d["val"] = x->val; OSC_END
|
|
113
|
+
OSC_NODE(BooleanLiteral, BooleanLiteral) d["val"] = x->val; OSC_END
|
|
114
|
+
OSC_NODE(UndefinedLiteral, UndefinedLiteral) OSC_END
|
|
115
|
+
OSC_NODE(RangeLiteral, RangeLiteral)
|
|
116
|
+
d["start"] = childToPy(x->start);
|
|
117
|
+
d["end"] = childToPy(x->end);
|
|
118
|
+
// Never null: the parser defaults an omitted step to 1.
|
|
119
|
+
d["step"] = childToPy(x->step);
|
|
120
|
+
OSC_END
|
|
121
|
+
|
|
122
|
+
// -- declarations / arguments -----------------------------------
|
|
123
|
+
OSC_NODE(ParameterDeclaration, ParameterDeclaration)
|
|
124
|
+
d["name"] = childToPy(x->name);
|
|
125
|
+
d["default_value"] = childToPy(x->defaultValue); // nullable
|
|
126
|
+
d["leading_comments"] = listToPy(x->leadingComments);
|
|
127
|
+
d["trailing_comments"] = listToPy(x->trailingComments);
|
|
128
|
+
OSC_END
|
|
129
|
+
OSC_NODE(PositionalArgument, PositionalArgument) d["expr"] = childToPy(x->expr); OSC_END
|
|
130
|
+
OSC_NODE(NamedArgument, NamedArgument)
|
|
131
|
+
d["name"] = childToPy(x->name);
|
|
132
|
+
d["expr"] = childToPy(x->expr);
|
|
133
|
+
OSC_END
|
|
134
|
+
OSC_NODE(Assignment, Assignment)
|
|
135
|
+
d["name"] = childToPy(x->name);
|
|
136
|
+
d["expr"] = childToPy(x->expr);
|
|
137
|
+
OSC_END
|
|
138
|
+
|
|
139
|
+
// -- prefix expression forms ------------------------------------
|
|
140
|
+
OSC_NODE(LetOp, LetOp)
|
|
141
|
+
d["assignments"] = listToPy(x->assignments);
|
|
142
|
+
d["body"] = childToPy(x->body);
|
|
143
|
+
OSC_END
|
|
144
|
+
OSC_NODE(EchoOp, EchoOp)
|
|
145
|
+
d["arguments"] = listToPy(x->arguments);
|
|
146
|
+
d["body"] = childToPy(x->body);
|
|
147
|
+
OSC_END
|
|
148
|
+
OSC_NODE(AssertOp, AssertOp)
|
|
149
|
+
d["arguments"] = listToPy(x->arguments);
|
|
150
|
+
d["body"] = childToPy(x->body);
|
|
151
|
+
OSC_END
|
|
152
|
+
OSC_NODE(FunctionLiteral, FunctionLiteral)
|
|
153
|
+
d["parameters"] = listToPy(x->parameters);
|
|
154
|
+
d["body"] = childToPy(x->body);
|
|
155
|
+
OSC_END
|
|
156
|
+
|
|
157
|
+
// -- unary operators --------------------------------------------
|
|
158
|
+
#define OSC_UNARY(KindName) OSC_NODE(KindName, KindName) d["expr"] = childToPy(x->expr); OSC_END
|
|
159
|
+
OSC_UNARY(UnaryMinusOp)
|
|
160
|
+
OSC_UNARY(LogicalNotOp)
|
|
161
|
+
OSC_UNARY(BitwiseNotOp)
|
|
162
|
+
#undef OSC_UNARY
|
|
163
|
+
|
|
164
|
+
// -- binary operators -------------------------------------------
|
|
165
|
+
#define OSC_BINARY(KindName) \
|
|
166
|
+
OSC_NODE(KindName, KindName) d["left"] = childToPy(x->left); d["right"] = childToPy(x->right); OSC_END
|
|
167
|
+
OSC_BINARY(AdditionOp)
|
|
168
|
+
OSC_BINARY(SubtractionOp)
|
|
169
|
+
OSC_BINARY(MultiplicationOp)
|
|
170
|
+
OSC_BINARY(DivisionOp)
|
|
171
|
+
OSC_BINARY(ModuloOp)
|
|
172
|
+
OSC_BINARY(ExponentOp)
|
|
173
|
+
OSC_BINARY(BitwiseAndOp)
|
|
174
|
+
OSC_BINARY(BitwiseOrOp)
|
|
175
|
+
OSC_BINARY(BitwiseShiftLeftOp)
|
|
176
|
+
OSC_BINARY(BitwiseShiftRightOp)
|
|
177
|
+
OSC_BINARY(LogicalAndOp)
|
|
178
|
+
OSC_BINARY(LogicalOrOp)
|
|
179
|
+
OSC_BINARY(EqualityOp)
|
|
180
|
+
OSC_BINARY(InequalityOp)
|
|
181
|
+
OSC_BINARY(GreaterThanOp)
|
|
182
|
+
OSC_BINARY(GreaterThanOrEqualOp)
|
|
183
|
+
OSC_BINARY(LessThanOp)
|
|
184
|
+
OSC_BINARY(LessThanOrEqualOp)
|
|
185
|
+
#undef OSC_BINARY
|
|
186
|
+
|
|
187
|
+
OSC_NODE(TernaryOp, TernaryOp)
|
|
188
|
+
d["condition"] = childToPy(x->condition);
|
|
189
|
+
d["true_expr"] = childToPy(x->trueExpr);
|
|
190
|
+
d["false_expr"] = childToPy(x->falseExpr);
|
|
191
|
+
OSC_END
|
|
192
|
+
|
|
193
|
+
// -- postfix ----------------------------------------------------
|
|
194
|
+
OSC_NODE(PrimaryCall, PrimaryCall)
|
|
195
|
+
d["left"] = childToPy(x->left);
|
|
196
|
+
d["arguments"] = listToPy(x->arguments);
|
|
197
|
+
OSC_END
|
|
198
|
+
OSC_NODE(PrimaryIndex, PrimaryIndex)
|
|
199
|
+
d["left"] = childToPy(x->left);
|
|
200
|
+
d["index"] = childToPy(x->index);
|
|
201
|
+
OSC_END
|
|
202
|
+
OSC_NODE(PrimaryMember, PrimaryMember)
|
|
203
|
+
d["left"] = childToPy(x->left);
|
|
204
|
+
d["member"] = childToPy(x->member);
|
|
205
|
+
OSC_END
|
|
206
|
+
|
|
207
|
+
// -- list comprehension clauses ---------------------------------
|
|
208
|
+
OSC_NODE(ListCompLet, ListCompLet)
|
|
209
|
+
d["assignments"] = listToPy(x->assignments);
|
|
210
|
+
d["body"] = childToPy(x->body);
|
|
211
|
+
OSC_END
|
|
212
|
+
OSC_NODE(ListCompEach, ListCompEach) d["body"] = childToPy(x->body); OSC_END
|
|
213
|
+
OSC_NODE(ListCompFor, ListCompFor)
|
|
214
|
+
d["assignments"] = listToPy(x->assignments);
|
|
215
|
+
d["body"] = childToPy(x->body);
|
|
216
|
+
OSC_END
|
|
217
|
+
OSC_NODE(ListCompCFor, ListCompCFor)
|
|
218
|
+
d["inits"] = listToPy(x->inits);
|
|
219
|
+
d["condition"] = childToPy(x->condition);
|
|
220
|
+
d["incrs"] = listToPy(x->incrs);
|
|
221
|
+
d["body"] = childToPy(x->body);
|
|
222
|
+
OSC_END
|
|
223
|
+
OSC_NODE(ListCompIf, ListCompIf)
|
|
224
|
+
d["condition"] = childToPy(x->condition);
|
|
225
|
+
d["true_expr"] = childToPy(x->trueExpr);
|
|
226
|
+
OSC_END
|
|
227
|
+
OSC_NODE(ListCompIfElse, ListCompIfElse)
|
|
228
|
+
d["condition"] = childToPy(x->condition);
|
|
229
|
+
d["true_expr"] = childToPy(x->trueExpr);
|
|
230
|
+
d["false_expr"] = childToPy(x->falseExpr);
|
|
231
|
+
OSC_END
|
|
232
|
+
// Also how a plain vector literal ([1,2,3]) is represented --
|
|
233
|
+
// elements mix comprehension clauses and bare expressions.
|
|
234
|
+
OSC_NODE(ListComprehension, ListComprehension) d["elements"] = listToPy(x->elements); OSC_END
|
|
235
|
+
|
|
236
|
+
// -- module instantiation ---------------------------------------
|
|
237
|
+
OSC_NODE(ModularCall, ModularCall)
|
|
238
|
+
d["name"] = childToPy(x->name);
|
|
239
|
+
d["arguments"] = listToPy(x->arguments);
|
|
240
|
+
d["children"] = listToPy(x->children);
|
|
241
|
+
OSC_END
|
|
242
|
+
OSC_NODE(ModularFor, ModularFor)
|
|
243
|
+
d["assignments"] = listToPy(x->assignments);
|
|
244
|
+
d["body"] = listToPy(x->body);
|
|
245
|
+
OSC_END
|
|
246
|
+
OSC_NODE(ModularIntersectionFor, ModularIntersectionFor)
|
|
247
|
+
d["assignments"] = listToPy(x->assignments);
|
|
248
|
+
d["body"] = listToPy(x->body);
|
|
249
|
+
OSC_END
|
|
250
|
+
OSC_NODE(ModularLet, ModularLet)
|
|
251
|
+
d["assignments"] = listToPy(x->assignments);
|
|
252
|
+
d["children"] = listToPy(x->children);
|
|
253
|
+
OSC_END
|
|
254
|
+
OSC_NODE(ModularEcho, ModularEcho)
|
|
255
|
+
d["arguments"] = listToPy(x->arguments);
|
|
256
|
+
d["children"] = listToPy(x->children);
|
|
257
|
+
OSC_END
|
|
258
|
+
OSC_NODE(ModularAssert, ModularAssert)
|
|
259
|
+
d["arguments"] = listToPy(x->arguments);
|
|
260
|
+
d["children"] = listToPy(x->children);
|
|
261
|
+
OSC_END
|
|
262
|
+
OSC_NODE(ModularIf, ModularIf)
|
|
263
|
+
d["condition"] = childToPy(x->condition);
|
|
264
|
+
d["true_branch"] = listToPy(x->trueBranch);
|
|
265
|
+
OSC_END
|
|
266
|
+
OSC_NODE(ModularIfElse, ModularIfElse)
|
|
267
|
+
d["condition"] = childToPy(x->condition);
|
|
268
|
+
d["true_branch"] = listToPy(x->trueBranch);
|
|
269
|
+
d["false_branch"] = listToPy(x->falseBranch);
|
|
270
|
+
OSC_END
|
|
271
|
+
|
|
272
|
+
// -- modifier wrappers (! # % *) --------------------------------
|
|
273
|
+
#define OSC_MODIFIER(KindName) OSC_NODE(KindName, KindName) d["child"] = childToPy(x->child); OSC_END
|
|
274
|
+
OSC_MODIFIER(ModularModifierShowOnly)
|
|
275
|
+
OSC_MODIFIER(ModularModifierHighlight)
|
|
276
|
+
OSC_MODIFIER(ModularModifierBackground)
|
|
277
|
+
OSC_MODIFIER(ModularModifierDisable)
|
|
278
|
+
#undef OSC_MODIFIER
|
|
279
|
+
|
|
280
|
+
// -- top-level declarations -------------------------------------
|
|
281
|
+
OSC_NODE(ModuleDeclaration, ModuleDeclaration)
|
|
282
|
+
d["name"] = childToPy(x->name);
|
|
283
|
+
d["parameters"] = listToPy(x->parameters);
|
|
284
|
+
d["children"] = listToPy(x->children);
|
|
285
|
+
d["pre_name_comments"] = listToPy(x->preNameComments);
|
|
286
|
+
d["post_name_comments"] = listToPy(x->postNameComments);
|
|
287
|
+
d["post_params_comments"] = listToPy(x->postParamsComments);
|
|
288
|
+
OSC_END
|
|
289
|
+
OSC_NODE(FunctionDeclaration, FunctionDeclaration)
|
|
290
|
+
d["name"] = childToPy(x->name);
|
|
291
|
+
d["parameters"] = listToPy(x->parameters);
|
|
292
|
+
d["expr"] = childToPy(x->expr);
|
|
293
|
+
d["pre_name_comments"] = listToPy(x->preNameComments);
|
|
294
|
+
d["post_name_comments"] = listToPy(x->postNameComments);
|
|
295
|
+
d["post_params_comments"] = listToPy(x->postParamsComments);
|
|
296
|
+
OSC_END
|
|
297
|
+
OSC_NODE(UseStatement, UseStatement) d["filepath"] = childToPy(x->filepath); OSC_END
|
|
298
|
+
OSC_NODE(IncludeStatement, IncludeStatement) d["filepath"] = childToPy(x->filepath); OSC_END
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
#undef OSC_NODE
|
|
302
|
+
#undef OSC_END
|
|
303
|
+
|
|
304
|
+
// No default: above -- the switch is exhaustive over NodeKind, so
|
|
305
|
+
// adding a node kind to the parser without handling it here is a
|
|
306
|
+
// compiler warning rather than a silently field-less dict.
|
|
307
|
+
return d;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
} // namespace
|
|
311
|
+
|
|
312
|
+
nb::list astToPy(const std::vector<std::unique_ptr<oscad::ASTNode>>& ast) {
|
|
313
|
+
nb::list out;
|
|
314
|
+
for (const std::unique_ptr<oscad::ASTNode>& n : ast) out.append(nodeToPy(n.get()));
|
|
315
|
+
return out;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
nb::list parseAstFromFile(const std::string& path, bool includeComments) {
|
|
319
|
+
return astToPy(oscad::getASTFromFile(path, includeComments));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
nb::list parseAstFromString(const std::string& code, bool includeComments) {
|
|
323
|
+
return astToPy(oscad::getASTFromString(code, includeComments));
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
} // namespace oscadbind
|
|
@@ -40,6 +40,14 @@
|
|
|
40
40
|
|
|
41
41
|
namespace nb = nanobind;
|
|
42
42
|
|
|
43
|
+
// Defined in ast_to_py.cpp -- snapshots the parser's AST into plain Python
|
|
44
|
+
// dicts. Declared here rather than in a header since these two entry points
|
|
45
|
+
// are the whole interface and only this file calls them.
|
|
46
|
+
namespace oscadbind {
|
|
47
|
+
nb::list parseAstFromFile(const std::string& path, bool includeComments);
|
|
48
|
+
nb::list parseAstFromString(const std::string& code, bool includeComments);
|
|
49
|
+
} // namespace oscadbind
|
|
50
|
+
|
|
43
51
|
namespace {
|
|
44
52
|
|
|
45
53
|
// Moves a std::vector's storage into a NumPy array that owns it via a
|
|
@@ -649,6 +657,12 @@ NB_MODULE(_openscad_cpp_evaluator, m) {
|
|
|
649
657
|
"Evaluate a .scad file; return (bodies, echoes, id_to_node, csg_tree, profile_result, dyn, dyn_explicit).");
|
|
650
658
|
m.def("parse_decls", &parseDecls, nb::arg("path"),
|
|
651
659
|
"Parse a .scad file; return top-level declaration (namespace, name, start, end, line, column, origin) tuples.");
|
|
660
|
+
m.def("parse_ast", &oscadbind::parseAstFromFile, nb::arg("path"), nb::arg("include_comments") = false,
|
|
661
|
+
"Parse a .scad file; return the AST as a list of plain nested dicts "
|
|
662
|
+
"(kind, position, plus that kind's own fields). A snapshot, not a view -- "
|
|
663
|
+
"safe to keep, share across threads, and outlive the parse.");
|
|
664
|
+
m.def("parse_ast_string", &oscadbind::parseAstFromString, nb::arg("code"), nb::arg("include_comments") = false,
|
|
665
|
+
"As parse_ast(), but parses a source string instead of a file.");
|
|
652
666
|
m.def("debug_evaluate", &debugEvaluate, nb::arg("path"), nb::arg("viewport_params"), nb::arg("debug_hook"),
|
|
653
667
|
nb::arg("error_break"), nb::arg("echo_fn"), nb::arg("manifold_cache") = nullptr,
|
|
654
668
|
nb::arg("return_hook") = nb::none(), nb::arg("fast_continue_signal") = nullptr,
|
|
@@ -18,7 +18,7 @@ from ._openscad_cpp_evaluator import FastContinueSignal, ManifoldCache
|
|
|
18
18
|
__all__ = [
|
|
19
19
|
"Evaluator", "ColoredBody", "EvalError", "ParseError", "OscObject", "parse", "to_renderable_bodies",
|
|
20
20
|
"ManifoldCache", "CallSiteProfile", "ProfileResult", "format_csg_tree", "bodies_from_dicts",
|
|
21
|
-
"FastContinueSignal",
|
|
21
|
+
"FastContinueSignal", "parse_ast", "parse_ast_string",
|
|
22
22
|
]
|
|
23
23
|
|
|
24
24
|
|
|
@@ -256,6 +256,41 @@ def parse(path: str) -> RootScope:
|
|
|
256
256
|
return RootScope(decls)
|
|
257
257
|
|
|
258
258
|
|
|
259
|
+
def parse_ast(path: str, include_comments: bool = False) -> list:
|
|
260
|
+
"""Parse a .scad file; return its AST as a list of plain nested dicts.
|
|
261
|
+
|
|
262
|
+
Each node is `{"kind": str, "position": {...}, **fields}`, where fields
|
|
263
|
+
are that kind's own (e.g. NumberLiteral has "val"; ModularCall has
|
|
264
|
+
"name"/"arguments"/"children"). Child nodes nest as dicts, child lists
|
|
265
|
+
as lists, and an absent optional child is None.
|
|
266
|
+
|
|
267
|
+
`position` carries `start_offset`/`end_offset`, which is the point of
|
|
268
|
+
this API: they let a caller slice the ORIGINAL source text of any
|
|
269
|
+
subexpression and reuse it verbatim, instead of re-serialising a parsed
|
|
270
|
+
value and losing how it was written (`1.500` -> `1.5`, `1e3` -> `1000`).
|
|
271
|
+
|
|
272
|
+
This is a SNAPSHOT, not a view of live parser memory: it is safe to
|
|
273
|
+
keep, mutate, share across threads, and outlive the parse. That costs
|
|
274
|
+
one walk per call, which is why it is a separate entry point rather
|
|
275
|
+
than something evaluate() always pays for.
|
|
276
|
+
|
|
277
|
+
Raises ParseError on a syntax error.
|
|
278
|
+
"""
|
|
279
|
+
try:
|
|
280
|
+
return _ext.parse_ast(path, include_comments)
|
|
281
|
+
except Exception as e:
|
|
282
|
+
raise ParseError(str(e)) from e
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def parse_ast_string(code: str, include_comments: bool = False) -> list:
|
|
286
|
+
"""As `parse_ast`, but parses a source string. `position.origin` is
|
|
287
|
+
"<string>" for every node. Raises ParseError on a syntax error."""
|
|
288
|
+
try:
|
|
289
|
+
return _ext.parse_ast_string(code, include_comments)
|
|
290
|
+
except Exception as e:
|
|
291
|
+
raise ParseError(str(e)) from e
|
|
292
|
+
|
|
293
|
+
|
|
259
294
|
class _MeshShim:
|
|
260
295
|
"""Duck-types a manifold3d mesh: the four arrays the renderer reads."""
|
|
261
296
|
__slots__ = ("vert_properties", "tri_verts", "run_original_id", "run_index", "num_prop")
|
{openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/tests/test_python_bindings.py
RENAMED
|
@@ -232,6 +232,122 @@ def test_role_defaults_to_normal_and_reflects_modifiers():
|
|
|
232
232
|
assert roles == ["highlight", "show_only"]
|
|
233
233
|
|
|
234
234
|
|
|
235
|
+
# -- parse_ast: AST snapshot ---------------------------------------------
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def test_parse_ast_spans_recover_original_number_text():
|
|
239
|
+
# The whole point of exposing spans: a parsed NumberLiteral is a double,
|
|
240
|
+
# so the source spelling is gone from `val` -- but the span still points
|
|
241
|
+
# at it, letting a rewriter reuse the author's own text verbatim.
|
|
242
|
+
from openscad_cpp_evaluator import parse_ast_string
|
|
243
|
+
src = "translate([1.500, 2.250, 1e3]) cube(2);"
|
|
244
|
+
vec = parse_ast_string(src)[0]["arguments"][0]["expr"]
|
|
245
|
+
spellings = [src[e["position"]["start_offset"]:e["position"]["end_offset"]] for e in vec["elements"]]
|
|
246
|
+
assert spellings == ["1.500", "2.250", "1e3"], spellings
|
|
247
|
+
assert [e["val"] for e in vec["elements"]] == [1.5, 2.25, 1000.0]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def test_parse_ast_node_shapes():
|
|
251
|
+
from openscad_cpp_evaluator import parse_ast_string
|
|
252
|
+
ast = parse_ast_string("module m(a, b=2) { cube(a); } m(1, b=3) sphere(2);")
|
|
253
|
+
decl, call = ast
|
|
254
|
+
assert decl["kind"] == "ModuleDeclaration"
|
|
255
|
+
assert decl["name"]["name"] == "m"
|
|
256
|
+
assert [p["name"]["name"] for p in decl["parameters"]] == ["a", "b"]
|
|
257
|
+
# An absent optional child is None, not a missing key.
|
|
258
|
+
assert decl["parameters"][0]["default_value"] is None
|
|
259
|
+
assert decl["parameters"][1]["default_value"]["val"] == 2.0
|
|
260
|
+
assert call["kind"] == "ModularCall"
|
|
261
|
+
assert [a["kind"] for a in call["arguments"]] == ["PositionalArgument", "NamedArgument"]
|
|
262
|
+
assert call["arguments"][1]["name"]["name"] == "b"
|
|
263
|
+
assert [c["kind"] for c in call["children"]] == ["ModularCall"]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def test_parse_ast_covers_every_node_kind_reachable_from_source():
|
|
267
|
+
# Guards the exhaustive switch in ast_to_py.cpp: a node kind added to
|
|
268
|
+
# the parser without a case here would produce a dict with only
|
|
269
|
+
# kind/position, silently losing its fields.
|
|
270
|
+
from openscad_cpp_evaluator import parse_ast_string
|
|
271
|
+
src = """
|
|
272
|
+
include <x.scad>
|
|
273
|
+
use <y.scad>
|
|
274
|
+
A = 1; B = "s"; C = true; D = undef; E = [0:2:10]; F = -A; G = !C; H = ~1;
|
|
275
|
+
I = A+1-2*3/4%5^2; J = A<1 && A>2 || A<=3 && A>=4 && A==5 && A!=6;
|
|
276
|
+
K = A&1 | 2 << 3 >> 4;
|
|
277
|
+
L = C ? A : B; M = [1,2,3][0]; N = let(x=1) x; O = echo("e") 1;
|
|
278
|
+
P = assert(true) 2; Q = function(a) a; R = [for (i=[0:3]) i*2];
|
|
279
|
+
S = [for (i=[0:3]) if (i%2==0) i else -i];
|
|
280
|
+
S2 = [for (i=[0:3]) if (i%2==0) i]; // bare if -> ListCompIf
|
|
281
|
+
T = [for (i=0; i<3; i=i+1) i]; U = [for (v=[[1,2]]) each v];
|
|
282
|
+
V = [let(z=2) for (i=[0:1]) z*i]; W = object(a=1).a;
|
|
283
|
+
function fn(p) = p; module mod(m) { cube(m); children(); }
|
|
284
|
+
mod(1) { sphere(2); }
|
|
285
|
+
for (i=[0:1]) cube(1);
|
|
286
|
+
intersection_for (i=[0:1]) cube(2);
|
|
287
|
+
let (t=1) cube(t); echo("hi") cube(1); assert(true) cube(1);
|
|
288
|
+
if (A>0) cube(1); else sphere(1);
|
|
289
|
+
if (A>0) cube(1); // bare if -> ModularIf
|
|
290
|
+
!cube(1); #cube(1); %cube(1); *cube(1);
|
|
291
|
+
"""
|
|
292
|
+
seen = set()
|
|
293
|
+
|
|
294
|
+
def walk(n):
|
|
295
|
+
if isinstance(n, dict) and "kind" in n:
|
|
296
|
+
seen.add(n["kind"])
|
|
297
|
+
pos = n["position"]
|
|
298
|
+
assert pos["end_offset"] >= pos["start_offset"], n["kind"]
|
|
299
|
+
for k, v in n.items():
|
|
300
|
+
if k not in ("kind", "position"):
|
|
301
|
+
walk(v)
|
|
302
|
+
elif isinstance(n, list):
|
|
303
|
+
for x in n:
|
|
304
|
+
walk(x)
|
|
305
|
+
|
|
306
|
+
for node in parse_ast_string(src, True):
|
|
307
|
+
walk(node)
|
|
308
|
+
# Every kind above, minus the three only produced by comment
|
|
309
|
+
# preservation on a file with comments in the right places.
|
|
310
|
+
expected = {
|
|
311
|
+
"IncludeStatement", "UseStatement", "Assignment", "Identifier", "NumberLiteral", "StringLiteral",
|
|
312
|
+
"BooleanLiteral", "UndefinedLiteral", "RangeLiteral", "UnaryMinusOp", "LogicalNotOp", "BitwiseNotOp",
|
|
313
|
+
"AdditionOp", "SubtractionOp", "MultiplicationOp", "DivisionOp", "ModuloOp", "ExponentOp",
|
|
314
|
+
"BitwiseAndOp", "BitwiseOrOp", "BitwiseShiftLeftOp", "BitwiseShiftRightOp", "LogicalAndOp",
|
|
315
|
+
"LogicalOrOp", "EqualityOp", "InequalityOp", "GreaterThanOp", "GreaterThanOrEqualOp", "LessThanOp",
|
|
316
|
+
"LessThanOrEqualOp", "TernaryOp", "PrimaryCall", "PrimaryIndex", "PrimaryMember", "LetOp", "EchoOp",
|
|
317
|
+
"AssertOp", "FunctionLiteral", "ListComprehension", "ListCompFor", "ListCompIf", "ListCompIfElse",
|
|
318
|
+
"ListCompCFor", "ListCompEach", "ListCompLet", "FunctionDeclaration", "ModuleDeclaration",
|
|
319
|
+
"ParameterDeclaration", "PositionalArgument", "NamedArgument", "ModularCall", "ModularFor",
|
|
320
|
+
"ModularIntersectionFor", "ModularLet", "ModularEcho", "ModularAssert", "ModularIf", "ModularIfElse",
|
|
321
|
+
"ModularModifierShowOnly", "ModularModifierHighlight", "ModularModifierBackground",
|
|
322
|
+
"ModularModifierDisable",
|
|
323
|
+
}
|
|
324
|
+
missing = expected - seen
|
|
325
|
+
assert not missing, f"node kinds not emitted: {sorted(missing)}"
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def test_parse_ast_snapshot_outlives_the_parse():
|
|
329
|
+
# It is a copy, not a view into parser memory -- the point of the
|
|
330
|
+
# snapshot design. Holding it after many further parses (which reuse
|
|
331
|
+
# and free the same arenas) must not corrupt it.
|
|
332
|
+
from openscad_cpp_evaluator import parse_ast_string
|
|
333
|
+
held = parse_ast_string("a = 1.500;")
|
|
334
|
+
for i in range(200):
|
|
335
|
+
parse_ast_string(f"b{i} = [for (j=[0:20]) j*{i}];")
|
|
336
|
+
assert held[0]["expr"]["val"] == 1.5
|
|
337
|
+
assert held[0]["name"]["name"] == "a"
|
|
338
|
+
held[0]["expr"]["val"] = 99.0 # plain dicts: mutable, owned by the caller
|
|
339
|
+
assert held[0]["expr"]["val"] == 99.0
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def test_parse_ast_raises_parse_error_on_bad_syntax():
|
|
343
|
+
from openscad_cpp_evaluator import ParseError, parse_ast_string
|
|
344
|
+
try:
|
|
345
|
+
parse_ast_string("cube(")
|
|
346
|
+
except ParseError:
|
|
347
|
+
return
|
|
348
|
+
raise AssertionError("expected ParseError")
|
|
349
|
+
|
|
350
|
+
|
|
235
351
|
def main():
|
|
236
352
|
tests = [v for k, v in sorted(globals().items()) if k.startswith("test_") and callable(v)]
|
|
237
353
|
failures = []
|
|
File without changes
|
{openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/.github/workflows/wheels.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.15.0 → openscad_cpp_evaluator-0.16.0}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|