openscad-cpp-evaluator 0.43.0__tar.gz → 0.45.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.43.0 → openscad_cpp_evaluator-0.45.0}/CLAUDE.md +15 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/CMakeLists.txt +13 -1
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/evaluator.hpp +7 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/CMakeLists.txt +8 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/function_builtins.cpp +45 -2
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/bytecode_compiler.cpp +22 -10
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/bytecode_vm.cpp +2 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/eval_context.cpp +28 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/expr_eval.cpp +23 -1
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/user_calls.cpp +10 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/CMakeLists.txt +1 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_bytecode_compiler.cpp +7 -7
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_expr_eval.cpp +24 -11
- openscad_cpp_evaluator-0.45.0/tests/test_feature_detection.cpp +162 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_use.cpp +6 -3
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/uv.lock +0 -0
|
@@ -441,6 +441,21 @@ handling in arithmetic, the closure-detection rule for `call_ctx` vs `child_ctx`
|
|
|
441
441
|
verbatim port, not an independent design. Deliberate divergences are called out in code comments —
|
|
442
442
|
grep for `ponytail:`.
|
|
443
443
|
|
|
444
|
+
- **Feature detection** — `$_SUPPORTED_FEATURE` (just `true`; names the CAPABILITY rather than the
|
|
445
|
+
vendor, so any evaluator adding `supported_feature()` is meant to set it, and checking it first
|
|
446
|
+
solves the bootstrapping problem of calling a function you don't know exists. Written
|
|
447
|
+
`!is_undef($_SUPPORTED_FEATURE) && supported_feature(...)` the guard is **silent** in OpenSCAD --
|
|
448
|
+
`is_undef()` is the one way to read an unknown variable there without a warning, and `&&`
|
|
449
|
+
short-circuits past the unknown call; verified against the reference), `$_BELFRYSCAD` (seeded in `EvalContext::makeRoot`, `src/eval_context.cpp`, as
|
|
450
|
+
`[major, minor, patch]` from `OSCAD_EVAL_VERSION_*` compile definitions that the top-level
|
|
451
|
+
`CMakeLists.txt` parses out of `pyproject.toml`, so wheel and local builds cannot disagree and a
|
|
452
|
+
bump needs one edit) and `supported_feature("name")` (`featureLevels()` in
|
|
453
|
+
`src/builtins/function_builtins.cpp`, returning a LEVEL so a feature whose semantics change can
|
|
454
|
+
be told from its earlier self; 0 for unknown names and non-string arguments, deliberately
|
|
455
|
+
silent so probing for a future feature is safe). Both exist because OpenSCAD **silently ignores**
|
|
456
|
+
unknown arguments -- `children(separate=true)` renders the wrong shape there with no warning --
|
|
457
|
+
and both read as `undef` in OpenSCAD, so a guard written against them works in both.
|
|
458
|
+
|
|
444
459
|
- `include/openscad_cpp_evaluator/value.hpp`, `src/value.cpp` — the `Value` variant (OpenSCAD's
|
|
445
460
|
dynamic value type) and its free-function arithmetic/comparison helpers. See the plan's §1 for
|
|
446
461
|
the type-mapping table and why there's no numpy-equivalent library.
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.24)
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
# Read the version straight out of pyproject.toml rather than repeating it
|
|
4
|
+
# here. It reaches C++ as OSCAD_EVAL_VERSION_{MAJOR,MINOR,PATCH} (see
|
|
5
|
+
# src/CMakeLists.txt), which is what seeds $_BELFRYSCAD -- so a released
|
|
6
|
+
# wheel and a local `cmake --build` always report the same numbers, and a
|
|
7
|
+
# version bump needs one edit, not three.
|
|
8
|
+
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml" _oscad_pyproject)
|
|
9
|
+
if(NOT _oscad_pyproject MATCHES "\nversion = \"([0-9]+)\.([0-9]+)\.([0-9]+)\"")
|
|
10
|
+
message(FATAL_ERROR "could not read version = \"X.Y.Z\" from pyproject.toml")
|
|
11
|
+
endif()
|
|
12
|
+
set(OSCAD_EVAL_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
|
13
|
+
|
|
14
|
+
project(openscad_cpp_evaluator VERSION ${OSCAD_EVAL_VERSION} LANGUAGES CXX)
|
|
3
15
|
|
|
4
16
|
# On Apple Silicon, warn (don't fail -- a universal or intentionally-x86_64
|
|
5
17
|
# build is legitimate) if the effective target architecture is x86_64 while
|
|
@@ -372,6 +372,13 @@ public:
|
|
|
372
372
|
// One synthetic `children(index)` statement, owned by syntheticNodes_.
|
|
373
373
|
const oscad::ASTNode* makeChildrenIndexCall(const oscad::ModularCall& origin, size_t index);
|
|
374
374
|
|
|
375
|
+
// The sole argument of `is_undef(x)` when x is a bare identifier, else
|
|
376
|
+
// nullptr. That call is a PROBE -- asking whether a name is defined must
|
|
377
|
+
// not itself complain that it isn't -- so the name is read with
|
|
378
|
+
// warnIfUndef=false. Static and syntactic so the bytecode compiler can
|
|
379
|
+
// ask at compile time and emit LoadFreeNoWarn.
|
|
380
|
+
static const oscad::Identifier* undefProbeTarget(const oscad::PrimaryCall& call);
|
|
381
|
+
|
|
375
382
|
// Syntactic gate: is this statement a `children(..., separate=true)`?
|
|
376
383
|
// Cheap and side-effect-free, so the bytecode compiler can ask it at
|
|
377
384
|
// COMPILE time to decide which opcode to emit, long before the flag's
|
|
@@ -46,6 +46,14 @@ add_library(openscad_cpp_evaluator STATIC
|
|
|
46
46
|
builtins/surface.cpp
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
# Seeds $_BELFRYSCAD (eval_context.cpp). Parsed from pyproject.toml by the
|
|
50
|
+
# top-level CMakeLists so there is one source of truth for the version.
|
|
51
|
+
target_compile_definitions(openscad_cpp_evaluator PRIVATE
|
|
52
|
+
OSCAD_EVAL_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
|
|
53
|
+
OSCAD_EVAL_VERSION_MINOR=${PROJECT_VERSION_MINOR}
|
|
54
|
+
OSCAD_EVAL_VERSION_PATCH=${PROJECT_VERSION_PATCH}
|
|
55
|
+
)
|
|
56
|
+
|
|
49
57
|
target_include_directories(openscad_cpp_evaluator PUBLIC
|
|
50
58
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
|
|
51
59
|
)
|
{openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -449,7 +449,7 @@ bool isBuiltinFunctionName(const std::string& name) {
|
|
|
449
449
|
"acos", "atan", "atan2", "max", "min", "pow", "norm", "cross", "rands", "concat", "len", "str",
|
|
450
450
|
"chr", "ord", "is_undef", "is_num", "is_bool", "is_string", "is_list", "is_function", "is_object",
|
|
451
451
|
"search", "lookup", "has_key", "version", "version_num", "parent_module",
|
|
452
|
-
"object", "textmetrics", "fontmetrics", "dxf_dim", "dxf_cross",
|
|
452
|
+
"object", "textmetrics", "fontmetrics", "dxf_dim", "dxf_cross", "supported_feature",
|
|
453
453
|
};
|
|
454
454
|
return names.count(name) > 0;
|
|
455
455
|
}
|
|
@@ -591,9 +591,39 @@ enum class BuiltinFnId {
|
|
|
591
591
|
TextMetrics, FontMetrics, Abs, Sign, Ceil, Floor, Round, Sqrt, Ln, Log, Exp, Sin, Cos, Tan,
|
|
592
592
|
Asin, Acos, Atan, Atan2, Max, Min, Pow, Norm, Cross, Rands, Concat, Len, Str, Chr, Ord,
|
|
593
593
|
IsUndef, IsNum, IsBool, IsString, IsList, IsFunction, IsObject, Search, Lookup, HasKey,
|
|
594
|
-
Version, VersionNum, ParentModule, DxfDim, DxfCross,
|
|
594
|
+
Version, VersionNum, ParentModule, DxfDim, DxfCross, SupportedFeature,
|
|
595
595
|
};
|
|
596
596
|
|
|
597
|
+
// supported_feature("name") -> the level at which this build implements that
|
|
598
|
+
// feature, or 0 for one it does not implement (and for a name it has never
|
|
599
|
+
// heard of, which is deliberate: probing for a feature from a future release
|
|
600
|
+
// is supposed to be safe).
|
|
601
|
+
//
|
|
602
|
+
// A LEVEL rather than a boolean so a feature whose semantics change later
|
|
603
|
+
// can be told apart from its earlier self. Everything here is 1 today;
|
|
604
|
+
// nothing has changed since this function existed, and a script cannot
|
|
605
|
+
// observe what a build without supported_feature() did anyway.
|
|
606
|
+
//
|
|
607
|
+
// This is the answer to a real hazard: OpenSCAD does not reject arguments or
|
|
608
|
+
// names it doesn't know -- children(separate=true) is silently ignored there
|
|
609
|
+
// -- so a script using an extension runs and quietly renders something else.
|
|
610
|
+
// Guarding on supported_feature() is how a script says so out loud.
|
|
611
|
+
const std::unordered_map<std::string, double>& featureLevels() {
|
|
612
|
+
static const std::unordered_map<std::string, double> levels = {
|
|
613
|
+
{"render-expr", 1.0}, // render() in expression position
|
|
614
|
+
{"polyhedron-vnf", 1.0}, // polyhedron(vnf) / polyhedron(object)
|
|
615
|
+
{"separate-children", 1.0}, // children(..., separate=true)
|
|
616
|
+
{"minkowski-diff", 1.0}, // minkowski_difference()
|
|
617
|
+
{"sphere-styles", 1.0}, // sphere(style=)
|
|
618
|
+
{"export-name", 1.0}, // $export_name
|
|
619
|
+
{"simplify-op", 1.0}, // simplify()
|
|
620
|
+
{"expr-import", 1.0}, // import() in expression position
|
|
621
|
+
{"object-function", 1.0}, // object(), unconditional here
|
|
622
|
+
{"roof-op", 1.0}, // roof(), method="voronoi" only
|
|
623
|
+
};
|
|
624
|
+
return levels;
|
|
625
|
+
}
|
|
626
|
+
|
|
597
627
|
const std::unordered_map<std::string, BuiltinFnId>& builtinFnIds() {
|
|
598
628
|
static const std::unordered_map<std::string, BuiltinFnId> ids = {
|
|
599
629
|
{"textmetrics", BuiltinFnId::TextMetrics}, {"fontmetrics", BuiltinFnId::FontMetrics},
|
|
@@ -614,6 +644,7 @@ const std::unordered_map<std::string, BuiltinFnId>& builtinFnIds() {
|
|
|
614
644
|
{"version", BuiltinFnId::Version}, {"version_num", BuiltinFnId::VersionNum},
|
|
615
645
|
{"parent_module", BuiltinFnId::ParentModule},
|
|
616
646
|
{"dxf_dim", BuiltinFnId::DxfDim}, {"dxf_cross", BuiltinFnId::DxfCross},
|
|
647
|
+
{"supported_feature", BuiltinFnId::SupportedFeature},
|
|
617
648
|
};
|
|
618
649
|
return ids;
|
|
619
650
|
}
|
|
@@ -694,6 +725,7 @@ const std::unordered_map<int, BuiltinCheck>& builtinChecks() {
|
|
|
694
725
|
// warning, so only the too-many case is an arity error.
|
|
695
726
|
add(BuiltinFnId::ParentModule, {0, 1, "1", {kNum}});
|
|
696
727
|
add(BuiltinFnId::HasKey, {-1, -1, nullptr, {{TObj, "object"}, {TStr, "string"}}});
|
|
728
|
+
add(BuiltinFnId::SupportedFeature, {1, 1, "1", {}});
|
|
697
729
|
for (BuiltinFnId id : {BuiltinFnId::IsUndef, BuiltinFnId::IsNum, BuiltinFnId::IsBool,
|
|
698
730
|
BuiltinFnId::IsString, BuiltinFnId::IsList, BuiltinFnId::IsFunction,
|
|
699
731
|
BuiltinFnId::IsObject}) {
|
|
@@ -1008,6 +1040,17 @@ Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs
|
|
|
1008
1040
|
// The OpenSCAD release we track. version_num() is that same
|
|
1009
1041
|
// year/month/day folded as y * 10000 + m * 100 + d, exactly like the
|
|
1010
1042
|
// reference's own builtin_version_num (builtin_functions.cc).
|
|
1043
|
+
case BuiltinFnId::SupportedFeature: {
|
|
1044
|
+
const Value name = getArg(args, 0, "feature", Value{});
|
|
1045
|
+
const std::string* s = std::get_if<std::string>(&name);
|
|
1046
|
+
// A non-string is 0 rather than an error, same as an unknown
|
|
1047
|
+
// name: the whole point of this function is that asking is
|
|
1048
|
+
// always safe.
|
|
1049
|
+
if (!s) return Value{0.0};
|
|
1050
|
+
const auto& levels = featureLevels();
|
|
1051
|
+
const auto it = levels.find(*s);
|
|
1052
|
+
return Value{it == levels.end() ? 0.0 : it->second};
|
|
1053
|
+
}
|
|
1011
1054
|
case BuiltinFnId::Version: return numList({2026.0, 1.0, 1.0});
|
|
1012
1055
|
case BuiltinFnId::VersionNum: {
|
|
1013
1056
|
// The optional vector argument the reference also accepts: with
|
|
@@ -262,7 +262,10 @@ public:
|
|
|
262
262
|
void compileIdentifierLoad(const std::string& name, const oscad::Position& pos, std::vector<Instruction>& out,
|
|
263
263
|
CompileScope& scope, bool warnIfUndef) {
|
|
264
264
|
if (!name.empty() && name[0] == '$') {
|
|
265
|
-
|
|
265
|
+
// `b` is the warn flag -- a $-name reached through the
|
|
266
|
+
// is_undef() probe must stay quiet, same as LoadFreeNoWarn does
|
|
267
|
+
// for a plain one.
|
|
268
|
+
out.push_back({Op::LoadDyn, internName(name), warnIfUndef ? 1 : 0, &pos});
|
|
266
269
|
} else if (auto slot = scope.resolve(name)) {
|
|
267
270
|
out.push_back({Op::LoadLocal, *slot, 0, &pos});
|
|
268
271
|
} else if (auto upvalSlot = resolveEnclosing(name)) {
|
|
@@ -620,15 +623,24 @@ public:
|
|
|
620
623
|
}
|
|
621
624
|
}
|
|
622
625
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
626
|
+
// is_undef(name) probes rather than reads -- the same quiet
|
|
627
|
+
// load the interpreter uses (Evaluator::undefProbeTarget),
|
|
628
|
+
// so the two engines agree on which reads warn.
|
|
629
|
+
if (const oscad::Identifier* undefProbe = Evaluator::undefProbeTarget(n)) {
|
|
630
|
+
compileIdentifierLoad(undefProbe->name, undefProbe->position(), out, scope,
|
|
631
|
+
/*warnIfUndef=*/false);
|
|
632
|
+
site.argNames.push_back(std::nullopt);
|
|
633
|
+
} else {
|
|
634
|
+
for (const auto& argPtr : n.arguments) {
|
|
635
|
+
if (argPtr->kind() == NodeKind::NamedArgument) {
|
|
636
|
+
auto& a = static_cast<const oscad::NamedArgument&>(*argPtr);
|
|
637
|
+
compileExpr(*a.expr, out, scope); // an argument is never tail
|
|
638
|
+
site.argNames.push_back(a.name->name);
|
|
639
|
+
} else {
|
|
640
|
+
auto& a = static_cast<const oscad::PositionalArgument&>(*argPtr);
|
|
641
|
+
compileExpr(*a.expr, out, scope);
|
|
642
|
+
site.argNames.push_back(std::nullopt);
|
|
643
|
+
}
|
|
632
644
|
}
|
|
633
645
|
}
|
|
634
646
|
int siteIdx = static_cast<int>(chunk_.callSites.size());
|
|
@@ -562,6 +562,8 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
562
562
|
} else if (const Value* v = ctx.dyn->find(name)) {
|
|
563
563
|
f.stack.push_back(*v);
|
|
564
564
|
} else {
|
|
565
|
+
// ins.b = warn flag; see compileIdentifierLoad.
|
|
566
|
+
if (ins.b) ev.warn("Ignoring unknown variable '" + name + "'", ins.pos);
|
|
565
567
|
f.stack.push_back(Value{});
|
|
566
568
|
}
|
|
567
569
|
++f.pc;
|
|
@@ -21,6 +21,34 @@ EvalContext EvalContext::makeRoot(const oscad::Scope* rootScope) {
|
|
|
21
21
|
// see undef, take the falsy branch by accident rather than by rule, and
|
|
22
22
|
// warn about an unknown variable while doing it.
|
|
23
23
|
ctx.dyn->set("$preview", Value{false});
|
|
24
|
+
// $_BELFRYSCAD -- present only here, so a script can tell which
|
|
25
|
+
// evaluator it is running under. OpenSCAD leaves it undef, which is the
|
|
26
|
+
// whole point: `if ($_BELFRYSCAD == undef)` is the portable test, and it
|
|
27
|
+
// works because an unknown $-variable is undef rather than an error.
|
|
28
|
+
//
|
|
29
|
+
// Shaped like OpenSCAD's own version() -- a [major, minor, patch] list
|
|
30
|
+
// rather than a string -- so comparisons need no string splitting.
|
|
31
|
+
// Which FEATURES exist is a separate question with a better answer:
|
|
32
|
+
// supported_feature() (function_builtins.cpp).
|
|
33
|
+
// $_SUPPORTED_FEATURE -- "supported_feature() is callable here". Set by
|
|
34
|
+
// any implementation that provides the function, not just this one, so a
|
|
35
|
+
// script can check for the FUNCTION rather than for a vendor:
|
|
36
|
+
//
|
|
37
|
+
// if (!is_undef($_SUPPORTED_FEATURE) && supported_feature("sep..."))
|
|
38
|
+
//
|
|
39
|
+
// Solves the bootstrapping problem -- you cannot safely call
|
|
40
|
+
// supported_feature() without first knowing it exists -- and in that
|
|
41
|
+
// exact form it is SILENT in OpenSCAD: is_undef() is the one way to
|
|
42
|
+
// read an unknown variable there without a warning, and && short-
|
|
43
|
+
// circuits so the unknown function is never reached. Verified against
|
|
44
|
+
// the reference binary: no warning, correct branch.
|
|
45
|
+
// If OpenSCAD ever adds supported_feature(), it sets this too and the
|
|
46
|
+
// same script starts working there with no edit.
|
|
47
|
+
ctx.dyn->set("$_SUPPORTED_FEATURE", Value{true});
|
|
48
|
+
ctx.dyn->set("$_BELFRYSCAD",
|
|
49
|
+
Value{std::make_shared<const ValueList>(ValueList{{Value{double{OSCAD_EVAL_VERSION_MAJOR}},
|
|
50
|
+
Value{double{OSCAD_EVAL_VERSION_MINOR}},
|
|
51
|
+
Value{double{OSCAD_EVAL_VERSION_PATCH}}}})});
|
|
24
52
|
ctx.let_ = TrailView<Value>::makeRoot();
|
|
25
53
|
ctx.dynPositions = TrailView<const oscad::Position*>::makeRoot();
|
|
26
54
|
ctx.childrenNodes = std::make_shared<const ChildrenNodeList>();
|
|
@@ -107,6 +107,16 @@ void Evaluator::warn(const std::string& message, const oscad::Position* position
|
|
|
107
107
|
echoFn_(formatWarning(message, position, callStack_));
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
const oscad::Identifier* Evaluator::undefProbeTarget(const oscad::PrimaryCall& call) {
|
|
111
|
+
if (call.left->kind() != oscad::NodeKind::Identifier) return nullptr;
|
|
112
|
+
if (static_cast<const oscad::Identifier&>(*call.left).name != "is_undef") return nullptr;
|
|
113
|
+
if (call.arguments.size() != 1) return nullptr;
|
|
114
|
+
if (call.arguments[0]->kind() != oscad::NodeKind::PositionalArgument) return nullptr;
|
|
115
|
+
const auto& arg = static_cast<const oscad::PositionalArgument&>(*call.arguments[0]);
|
|
116
|
+
if (arg.expr->kind() != oscad::NodeKind::Identifier) return nullptr;
|
|
117
|
+
return static_cast<const oscad::Identifier*>(arg.expr.get());
|
|
118
|
+
}
|
|
119
|
+
|
|
110
120
|
Value Evaluator::evalIdentifier(const std::string& name, const oscad::Position* position, EvalContext& ctx,
|
|
111
121
|
bool warnIfUndef) {
|
|
112
122
|
if (const Value* v = ctx.let_->find(name)) return *v;
|
|
@@ -128,7 +138,19 @@ Value Evaluator::evalIdentifier(const std::string& name, const oscad::Position*
|
|
|
128
138
|
// $-name anyway (dynamic variables aren't scope-declarable) and
|
|
129
139
|
// exists only for plain identifiers.
|
|
130
140
|
const Value* v = ctx.dyn->find(name);
|
|
131
|
-
|
|
141
|
+
if (v) return *v;
|
|
142
|
+
// Warns like any other unknown name. This used to return silently
|
|
143
|
+
// for EVERY $-read, on the strength of BOSL2's get_slop() --
|
|
144
|
+
// `is_undef($slop) ? 0 : $slop` with $slop never assigned -- being
|
|
145
|
+
// silent in the reference. It is, but for two narrower reasons: the
|
|
146
|
+
// probe does not warn about its own argument (undefProbeTarget), and
|
|
147
|
+
// the else branch never runs when is_undef() is true. A plain
|
|
148
|
+
// `echo($nope)` DOES warn there, in every context checked --
|
|
149
|
+
// assignment, function body, module body, comparison. Real BOSL2
|
|
150
|
+
// (gears, threading, rounded_prism, diff/attach, path_sweep) emits
|
|
151
|
+
// none of these, because it guards its own $-reads.
|
|
152
|
+
if (warnIfUndef) warn("Ignoring unknown variable '" + name + "'", position);
|
|
153
|
+
return Value{};
|
|
132
154
|
}
|
|
133
155
|
|
|
134
156
|
if (name == "PI") return Value{std::numbers::pi};
|
|
@@ -882,6 +882,16 @@ Value Evaluator::evalFunctionCall(const oscad::PrimaryCall& node, EvalContext& c
|
|
|
882
882
|
// exactly (name in _BUILTIN_FN_NAMES gates which branch runs at
|
|
883
883
|
// all).
|
|
884
884
|
if (isBuiltinFunctionName(leftId->name)) {
|
|
885
|
+
// is_undef(name) is a probe: asking whether a name is defined
|
|
886
|
+
// must not itself warn that it isn't. The $-branch of
|
|
887
|
+
// evalIdentifier is already silent for any name, but a PLAIN
|
|
888
|
+
// identifier warned -- so `is_undef(some_flag)` was noisy here
|
|
889
|
+
// and silent in the reference. Verified against OpenSCAD:
|
|
890
|
+
// no warning for either spelling inside is_undef().
|
|
891
|
+
if (const oscad::Identifier* probe = undefProbeTarget(node)) {
|
|
892
|
+
return Value{std::holds_alternative<std::monostate>(
|
|
893
|
+
evalIdentifier(probe->name, &probe->position(), ctx, /*warnIfUndef=*/false))};
|
|
894
|
+
}
|
|
885
895
|
// object() needs the raw argument list, not a pre-resolved
|
|
886
896
|
// CallArgs, to merge positional/named arguments in their exact
|
|
887
897
|
// call-site interleaved order (see builtinObject's own
|
{openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/tests/test_bytecode_compiler.cpp
RENAMED
|
@@ -162,13 +162,13 @@ TEST(BytecodeCompiler, SelfReferentialParameterDefaultResolvesToUndef) {
|
|
|
162
162
|
ScopedVm vm(true);
|
|
163
163
|
// Referencing "x" inside its own default falls all the way through to
|
|
164
164
|
// Scope::lookupVariable finding nothing usable there (a
|
|
165
|
-
// ParameterDeclaration),
|
|
166
|
-
//
|
|
167
|
-
// the
|
|
168
|
-
// that the compiled path reproduces
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
165
|
+
// ParameterDeclaration) -- undef, so the ternary takes the 5. Silent:
|
|
166
|
+
// is_undef() is a probe and does not warn about the name it asks about,
|
|
167
|
+
// matching the reference, which is silent for this exact script. This
|
|
168
|
+
// test's own point is that the compiled path reproduces the interpreter
|
|
169
|
+
// exactly; it used to assert a warning both engines emitted and the
|
|
170
|
+
// reference did not.
|
|
171
|
+
EXPECT_EQ(runCapturingEcho("function foo(x = is_undef(x) ? 5 : x) = x;\necho(foo());"), "ECHO: 5");
|
|
172
172
|
// Caller-supplied value: default expression never runs at all, so no
|
|
173
173
|
// warning either.
|
|
174
174
|
EXPECT_EQ(runCapturingEcho("function foo(x = is_undef(x) ? 5 : x) = x;\necho(foo(10));"), "ECHO: 10");
|
|
@@ -52,21 +52,34 @@ TEST(ExprEvalIdentifiers, UnknownVariableWarnsAndIsUndef) {
|
|
|
52
52
|
EXPECT_NE(lastWarning.find("Ignoring unknown variable 'nope'"), std::string::npos);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
TEST(ExprEvalIdentifiers,
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
55
|
+
TEST(ExprEvalIdentifiers, UndefinedDollarVariableIsUndefAndWarns) {
|
|
56
|
+
// A never-assigned $-name reads as undef and warns, exactly like a
|
|
57
|
+
// never-declared bare identifier.
|
|
58
|
+
//
|
|
59
|
+
// This test used to assert the opposite, on the strength of BOSL2's
|
|
60
|
+
// constants.scad -- `function get_slop() = is_undef($slop) ? 0 : $slop;`
|
|
61
|
+
// with $slop never assigned -- being silent in real OpenSCAD. It is,
|
|
62
|
+
// but not because $-reads are exempt: is_undef() does not warn about the
|
|
63
|
+
// name it probes, and the else branch never runs while is_undef() is
|
|
64
|
+
// true. Measured against the reference, a PLAIN read warns in every
|
|
65
|
+
// context tried -- echo, assignment, function body, module body,
|
|
66
|
+
// comparison -- so the old blanket exemption was over-generalised from
|
|
67
|
+
// one guarded expression.
|
|
65
68
|
std::string lastWarning;
|
|
66
69
|
Evaluator ev([&](const std::string& msg) { lastWarning = msg; });
|
|
67
70
|
Value v = evalSrc("$slop", ev);
|
|
68
71
|
EXPECT_TRUE(std::holds_alternative<std::monostate>(v));
|
|
69
|
-
|
|
72
|
+
EXPECT_NE(lastWarning.find("Ignoring unknown variable '$slop'"), std::string::npos) << lastWarning;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
TEST(ExprEvalIdentifiers, TheBoslGetSlopIdiomStaysSilent) {
|
|
76
|
+
// The case the old exemption existed for, kept as a test in its own
|
|
77
|
+
// right: it must remain silent through the is_undef() probe alone.
|
|
78
|
+
std::string lastWarning;
|
|
79
|
+
Evaluator ev([&](const std::string& msg) { lastWarning = msg; });
|
|
80
|
+
Value v = evalSrc("is_undef($slop) ? 0 : $slop", ev);
|
|
81
|
+
EXPECT_TRUE(lastWarning.empty()) << lastWarning;
|
|
82
|
+
EXPECT_EQ(std::get<double>(v), 0.0);
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
TEST(ExprEvalIdentifiers, ResolvesViaScopeFallbackWhenNotEagerlyBound) {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// $_BELFRYSCAD and supported_feature() -- how a script asks which evaluator
|
|
2
|
+
// it is running under, and what that evaluator can actually do.
|
|
3
|
+
//
|
|
4
|
+
// The hazard they exist for: OpenSCAD does not reject arguments or names it
|
|
5
|
+
// has never heard of. `children(separate=true)` is silently ignored there,
|
|
6
|
+
// so a script using an extension runs and quietly renders something else.
|
|
7
|
+
// Both of these are readable from OpenSCAD too -- an unknown $-variable and
|
|
8
|
+
// an unknown function are undef (with a warning), not errors -- so a guard
|
|
9
|
+
// written against them works in both.
|
|
10
|
+
|
|
11
|
+
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
12
|
+
|
|
13
|
+
#include "test_helpers.hpp"
|
|
14
|
+
|
|
15
|
+
#include <gtest/gtest.h>
|
|
16
|
+
|
|
17
|
+
using namespace oscadeval;
|
|
18
|
+
using namespace oscadeval::test;
|
|
19
|
+
|
|
20
|
+
namespace {
|
|
21
|
+
|
|
22
|
+
class ScopedVm {
|
|
23
|
+
public:
|
|
24
|
+
explicit ScopedVm(bool enabled) { Evaluator::setBytecodeVmEnabledForTesting(enabled); }
|
|
25
|
+
~ScopedVm() { Evaluator::setBytecodeVmEnabledForTesting(std::nullopt); }
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
std::vector<std::string> echoesFrom(const std::string& src) {
|
|
29
|
+
std::vector<std::string> out;
|
|
30
|
+
evalSrc(src, [&](const std::string& m) { out.push_back(m); });
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Every feature name the docs promise. A typo in either direction -- here or
|
|
35
|
+
// in featureLevels() -- shows up as a 0.
|
|
36
|
+
const char* kFeatures[] = {"separate-children", "minkowski-diff", "sphere-styles", "export-name",
|
|
37
|
+
"simplify-op", "expr-import", "object-function", "roof-op",
|
|
38
|
+
"render-expr", "polyhedron-vnf"};
|
|
39
|
+
|
|
40
|
+
} // namespace
|
|
41
|
+
|
|
42
|
+
TEST(FeatureDetection, BelfryscadVariableIsTheEvaluatorVersion) {
|
|
43
|
+
for (bool vm : {false, true}) {
|
|
44
|
+
ScopedVm guard(vm);
|
|
45
|
+
// Shaped like OpenSCAD's own version(): [major, minor, patch], so a
|
|
46
|
+
// comparison needs no string splitting. Read from pyproject.toml at
|
|
47
|
+
// configure time, so this cannot drift from the released version.
|
|
48
|
+
const std::vector<std::string> e = echoesFrom("echo(is_list($_BELFRYSCAD), len($_BELFRYSCAD));");
|
|
49
|
+
ASSERT_EQ(e.size(), 1u) << "vm=" << vm;
|
|
50
|
+
EXPECT_NE(e[0].find("true"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
51
|
+
EXPECT_NE(e[0].find("3"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
TEST(FeatureDetection, BelfryscadVariableHoldsThreeNumbers) {
|
|
56
|
+
for (bool vm : {false, true}) {
|
|
57
|
+
ScopedVm guard(vm);
|
|
58
|
+
const std::vector<std::string> e = echoesFrom(
|
|
59
|
+
"echo(is_num($_BELFRYSCAD[0]), is_num($_BELFRYSCAD[1]), is_num($_BELFRYSCAD[2]));");
|
|
60
|
+
ASSERT_EQ(e.size(), 1u) << "vm=" << vm;
|
|
61
|
+
EXPECT_EQ(e[0].find("false"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
TEST(FeatureDetection, EveryDocumentedFeatureReportsALevel) {
|
|
66
|
+
for (bool vm : {false, true}) {
|
|
67
|
+
ScopedVm guard(vm);
|
|
68
|
+
for (const char* f : kFeatures) {
|
|
69
|
+
const std::vector<std::string> e =
|
|
70
|
+
echoesFrom(std::string("echo(supported_feature(\"") + f + "\"));");
|
|
71
|
+
ASSERT_EQ(e.size(), 1u) << f << ", vm=" << vm;
|
|
72
|
+
EXPECT_NE(e[0].find("1"), std::string::npos) << f << ", vm=" << vm << ", got " << e[0];
|
|
73
|
+
EXPECT_EQ(e[0].find("0"), std::string::npos) << f << " reported unsupported, vm=" << vm;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
TEST(FeatureDetection, AnUnknownFeatureIsZeroAndSilent) {
|
|
79
|
+
// Probing for a feature from a future release has to be safe -- that is
|
|
80
|
+
// the whole point of asking. No warning, no error, just 0.
|
|
81
|
+
for (bool vm : {false, true}) {
|
|
82
|
+
ScopedVm guard(vm);
|
|
83
|
+
const std::vector<std::string> e = echoesFrom("echo(supported_feature(\"time-travel\"));");
|
|
84
|
+
ASSERT_EQ(e.size(), 1u) << "vm=" << vm << " (unexpected warning?)";
|
|
85
|
+
EXPECT_NE(e[0].find("0"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
TEST(FeatureDetection, ANonStringArgumentIsZeroRatherThanAnError) {
|
|
90
|
+
for (bool vm : {false, true}) {
|
|
91
|
+
ScopedVm guard(vm);
|
|
92
|
+
for (const char* arg : {"42", "undef", "[1,2]"}) {
|
|
93
|
+
const std::vector<std::string> e =
|
|
94
|
+
echoesFrom(std::string("echo(supported_feature(") + arg + "));");
|
|
95
|
+
ASSERT_EQ(e.size(), 1u) << arg << ", vm=" << vm;
|
|
96
|
+
EXPECT_NE(e[0].find("0"), std::string::npos) << arg << ", vm=" << vm << ", got " << e[0];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
TEST(FeatureDetection, SupportedFeatureMarkerIsSet) {
|
|
102
|
+
// Vendor-neutral: it says "supported_feature() is callable", not "this is
|
|
103
|
+
// BelfrySCAD". Any implementation adding the function is meant to set it,
|
|
104
|
+
// so a script guards on the capability rather than on who is running it.
|
|
105
|
+
for (bool vm : {false, true}) {
|
|
106
|
+
ScopedVm guard(vm);
|
|
107
|
+
const std::vector<std::string> e = echoesFrom("echo($_SUPPORTED_FEATURE);");
|
|
108
|
+
ASSERT_EQ(e.size(), 1u) << "vm=" << vm;
|
|
109
|
+
EXPECT_NE(e[0].find("true"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
TEST(FeatureDetection, TheMarkerGuardsTheCallItself) {
|
|
114
|
+
// The bootstrapping shape: you cannot safely CALL supported_feature()
|
|
115
|
+
// without first knowing it exists. Checking the marker first solves that,
|
|
116
|
+
// and because && short-circuits, an evaluator lacking both warns once
|
|
117
|
+
// rather than twice -- verified against the reference binary, which
|
|
118
|
+
// reports exactly one warning for this source and takes the else branch.
|
|
119
|
+
for (bool vm : {false, true}) {
|
|
120
|
+
ScopedVm guard(vm);
|
|
121
|
+
const std::vector<std::string> e = echoesFrom(
|
|
122
|
+
"if (!is_undef($_SUPPORTED_FEATURE) && supported_feature(\"separate-children\"))\n"
|
|
123
|
+
" echo(\"extended\");\n"
|
|
124
|
+
"else echo(\"portable\");\n");
|
|
125
|
+
ASSERT_EQ(e.size(), 1u) << "vm=" << vm;
|
|
126
|
+
EXPECT_NE(e[0].find("extended"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
TEST(FeatureDetection, IsUndefDoesNotWarnAboutTheNameItProbes) {
|
|
131
|
+
// Asking whether a name is defined must not itself complain that it
|
|
132
|
+
// isn't -- otherwise the portable guard is noisy here while being
|
|
133
|
+
// silent in OpenSCAD. Both spellings, since only the $-prefixed one
|
|
134
|
+
// used to be quiet.
|
|
135
|
+
for (bool vm : {false, true}) {
|
|
136
|
+
ScopedVm guard(vm);
|
|
137
|
+
for (const char* name : {"$_NO_SUCH_DOLLAR", "no_such_plain"}) {
|
|
138
|
+
const std::vector<std::string> e = echoesFrom(std::string("echo(is_undef(") + name + "));");
|
|
139
|
+
ASSERT_EQ(e.size(), 1u) << name << ", vm=" << vm << " (warned?)";
|
|
140
|
+
EXPECT_NE(e[0].find("true"), std::string::npos) << name << ", vm=" << vm << ", got " << e[0];
|
|
141
|
+
}
|
|
142
|
+
// A plain read of an unknown name still warns -- only the probe is
|
|
143
|
+
// exempt, and only for its own argument.
|
|
144
|
+
const std::vector<std::string> e = echoesFrom("echo(no_such_plain);");
|
|
145
|
+
ASSERT_EQ(e.size(), 2u) << "vm=" << vm;
|
|
146
|
+
EXPECT_NE(e[0].find("Ignoring unknown variable"), std::string::npos) << "vm=" << vm;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
TEST(FeatureDetection, TheGuardIdiomReadsTrueHere) {
|
|
151
|
+
// What a script actually writes. In OpenSCAD $_BELFRYSCAD is undef and
|
|
152
|
+
// supported_feature() is an unknown function returning undef -- both
|
|
153
|
+
// falsy -- so the same source takes the other branch there.
|
|
154
|
+
for (bool vm : {false, true}) {
|
|
155
|
+
ScopedVm guard(vm);
|
|
156
|
+
const std::vector<std::string> e = echoesFrom(
|
|
157
|
+
"if ($_BELFRYSCAD == undef) echo(\"portable\");\n"
|
|
158
|
+
"else if (supported_feature(\"separate-children\")) echo(\"extended\");\n");
|
|
159
|
+
ASSERT_EQ(e.size(), 1u) << "vm=" << vm;
|
|
160
|
+
EXPECT_NE(e[0].find("extended"), std::string::npos) << "vm=" << vm << ", got " << e[0];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -52,11 +52,14 @@ TEST(UseStatement, InjectsFunctionAndModuleButNotVariables) {
|
|
|
52
52
|
std::vector<std::string> echoed;
|
|
53
53
|
UseEvaluated e = evalFile(main, [&](const std::string& m) { echoed.push_back(m); });
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
// Two, not three: is_undef() is a probe and does not warn about the name
|
|
56
|
+
// it is asking about -- matching the reference, which is silent for this
|
|
57
|
+
// exact script. `ECHO: true` is what proves lib_var wasn't injected; the
|
|
58
|
+
// warning this used to also assert was our own divergence, not the point.
|
|
59
|
+
ASSERT_EQ(echoed.size(), 2u);
|
|
56
60
|
EXPECT_EQ(echoed[0], "ECHO: 103"); // 1 + 2 + lib_var(100) -- proves lib_add's body resolves
|
|
57
61
|
// lib_var from *its own* file's scope (reanchoring)
|
|
58
|
-
|
|
59
|
-
EXPECT_EQ(echoed[2], "ECHO: true"); // is_undef(lib_var) in main's own scope
|
|
62
|
+
EXPECT_EQ(echoed[1], "ECHO: true"); // is_undef(lib_var) in main's own scope -- NOT injected
|
|
60
63
|
EXPECT_EQ(e.bodies.size(), 1u); // lib_cube(5) still produced geometry
|
|
61
64
|
std::filesystem::remove(lib);
|
|
62
65
|
std::filesystem::remove(main);
|
|
File without changes
|
{openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.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
|
|
File without changes
|
{openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.43.0 → openscad_cpp_evaluator-0.45.0}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|